Obtaining a handle to a USB WebCam (Windows 10/CPP) - driver

I'm trying to obtain a handle to my USB WebCam (Microsoft LifeCam HD-3000 ) device.
I dont want to use it in a conventional way so usage of any multimedia framework are not considerable.
I need to be able (if possible) to send to it IRP's via DeviceIoControl etc.
Reversing its driver written in KMDF I found a call to WdfDeviceCreateDeviceInterface
and GUID passed as an argument:
v1 = WdfDeviceCreateDeviceInterface(WdfDriverGlobals, device, &stru_FFFFF807650740C8, 0i64);
.rdata:FFFFF807650740C8 stru_FFFFF807650740C8 dd 0B94D388Ah ; Data1
.rdata:FFFFF807650740C8 ; DATA XREF: internalEvtDeviceAdd+351↓o
.rdata:FFFFF807650740C8 dw 7331h ; Data2
.rdata:FFFFF807650740C8 dw 4E5Eh ; Data3
.rdata:FFFFF807650740C8 db 8Bh, 0Fh, 8, 16h, 0Eh, 0A1h, 0F7h, 6; Data4
Python>getGUID(0xFFFFF807650740C8)
b94d388a-7331-4e5e-8b0f-08160ea1f706
Having an interface GUID I used the WinObjEx64 to find a symlink to created device:
With symlink I attempted to open a handle:
int main()
{
LPWSTR errormsg = NULL;
DWORD errorCode;
HANDLE h = CreateFile(L"\\\\.\\USB#VID_045E&PID_0779&MI_00#6&2bd7a9d&0&0000#{b94d388a-7331-4e5e-8b0f-08160ea1f706}",
GENERIC_READ, // Only read access
0, // FILE_SHARE_READ | FILE_SHARE_WRITE
NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING,// No special create flags
0, // No special attributes
NULL); // No template file
errorCode = GetLastError();
printf("Error code: 0x%x\n", errorCode);
if (h == INVALID_HANDLE_VALUE)
{
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
0,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&errormsg,
0, NULL);
wprintf(L"Error : %s\n", errormsg);
}
return 0;
}
Output:
Error code: 0x2
Error : The system cannot find the file specified.
With such result I decided to obtain a dev path using SetupDi* APIs
void GetInterfaceDevicePath(GUID* guid) {
DWORD requiredSize;
int MemberIdx = 0;
HDEVINFO hDeviceInfoset = SetupDiGetClassDevs(guid, NULL, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hDeviceInfoset != INVALID_HANDLE_VALUE) {
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData = { 0 };
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
while (SetupDiEnumDeviceInterfaces(hDeviceInfoset, NULL, guid, MemberIdx, &DeviceInterfaceData)) {
MemberIdx++;
SP_DEVINFO_DATA DeviceInfoData = { 0 };
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
SetupDiGetDeviceInterfaceDetail(hDeviceInfoset, &DeviceInterfaceData, NULL, 0, &requiredSize, NULL);
SP_DEVICE_INTERFACE_DETAIL_DATA* DevIntfDetailData = (SP_DEVICE_INTERFACE_DETAIL_DATA*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
requiredSize);
DevIntfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (SetupDiGetDeviceInterfaceDetail(hDeviceInfoset, &DeviceInterfaceData,
DevIntfDetailData, requiredSize, &requiredSize, &DeviceInfoData)) {
printf("DevicePath: %S\n", (TCHAR*)DevIntfDetailData->DevicePath);
HANDLE h = CreateFileW(DevIntfDetailData->DevicePath,
0,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
LPWSTR errormsg = NULL;
DWORD error = GetLastError();
printf("Error code: 0x%x\n", error);
if (h == INVALID_HANDLE_VALUE)
{
FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
0,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPWSTR)&errormsg,
0, NULL);
wprintf(L"Error : %s\n", errormsg);
}
}
HeapFree(GetProcessHeap(), 0, DevIntfDetailData);
}
SetupDiDestroyDeviceInfoList(hDeviceInfoset);
}
}
int main()
{
GUID deviceGUID;
CLSIDFromString(L"{b94d388a-7331-4e5e-8b0f-08160ea1f706}", (LPCLSID)&deviceGUID);
GetInterfaceDevicePath(&deviceGUID);
return 0;
}
Unfortunately that also failed:
DevicePath: \\?\usb#vid_045e&pid_0779&mi_00#6&2bd7a9d&0&0000#{b94d388a-7331-4e5e-8b0f-08160ea1f706}
Error code: 0x2
Error : The system cannot find the file specified.
Output from livekd about how this driver is attached to the driver/device stack:
||1:lkd> !drvobj \Driver\LifeCamTrueColor
Driver object (ffffc60eba506750) is for:
\Driver\LifeCamTrueColor
Driver Extension List: (id , addr)
(fffff80684f87330 ffffc60eb19f75f0)
Device Object list:
ffffc60eb82f54e0
||1:lkd> !devobj ffffc60eb82f54e0
Device object (ffffc60eb82f54e0) is for:
\Driver\LifeCamTrueColor DriverObject ffffc60eba506750
Current Irp 00000000 RefCount 0 Type 0000002f Flags 00002000
SecurityDescriptor ffffdb888d07e660 DevExt ffffc60ec0deffb0 DevObjExt ffffc60eb82f5658
ExtensionFlags (0000000000)
Characteristics (0x00000100) FILE_DEVICE_SECURE_OPEN
AttachedDevice (Upper) ffffc60eaba48b40 \Driver\ksthunk
AttachedTo (Lower) ffffc60ec2cdadf0 \Driver\usbvideo
Device queue is not busy.
||1:lkd> !drvobj \Driver\usbvideo
Driver object (ffffc60ebfde7e30) is for:
\Driver\usbvideo
Driver Extension List: (id , addr)
(fffff8069aa2d130 ffffc60eb19f7560)
Device Object list:
ffffc60ec2cdadf0
||1:lkd> !devobj ffffc60ec2cdadf0
Device object (ffffc60ec2cdadf0) is for:
\Driver\usbvideo DriverObject ffffc60ebfde7e30
Current Irp 00000000 RefCount 0 Type 0000002f Flags 00002000
SecurityDescriptor ffffdb888d07e660 DevExt ffffc60ec2cdaf60 DevObjExt ffffc60ec2cdaf68
ExtensionFlags (0000000000)
Characteristics (0x00000100) FILE_DEVICE_SECURE_OPEN
AttachedDevice (Upper) ffffc60eb82f54e0 \Driver\LifeCamTrueColor
AttachedTo (Lower) ffffc60eb60e60a0 \Driver\usbccgp
Device queue is not busy.
||1:lkd> !drvobj \Driver\ksthunk
Driver object (ffffc60ea7777df0) is for:
\Driver\ksthunk
Driver Extension List: (id , addr)
(fffff806993f80a0 ffffc60ea772e580)
Device Object list:
ffffc60eaf67c7b0 ffffc60eaba48b40 ffffc60ea7bc4e10 ffffc60ea79a8e00
ffffc60ea7a15de0 ffffc60ea771bdf0
||1:lkd> !devobj ffffc60eaba48b40
Device object (ffffc60eaba48b40) is for:
000000d4 \Driver\ksthunk DriverObject ffffc60ea7777df0
Current Irp 00000000 RefCount 0 Type 0000002f Flags 00002040
SecurityDescriptor ffffdb888d07e660 DevExt ffffc60eaba48c90 DevObjExt ffffc60eaba48c98
ExtensionFlags (0000000000)
Characteristics (0x00000100) FILE_DEVICE_SECURE_OPEN
AttachedTo (Lower) ffffc60eb82f54e0 \Driver\LifeCamTrueColor
Device queue is not busy.
Also a screens from DeviceTree
Thanks!

Related

Error 87 in WriteFile function (NDIS) when using EtherType 0x88A4 (EtherCat)

I am trying to send a Raw Ethernet frame over layer 2, using the prottest.c example code for the NDIS driver, in C.
The example works without problem, but when I modify the Ether Type (0x88A4 EtherCat)
and adapt the frame with the necessary structure and information, the Writefile function always returns Error 87 (Incorrect parameters).
Is it not possible to write with this function on Layer 2, in Raw, without the TCP/IP stack, what could be wrong?
Thanks for your help.
Best regards.
VOID
DoWriteProc(
HANDLE Handle
)
{
PUCHAR pWriteBuf = NULL;
PUCHAR pData;
INT SendCount;
PETH_HEADER pEthHeader;
DWORD BytesWritten;
BOOLEAN bSuccess;
DEBUGP(("DoWriteProc\n"));
SendCount = 0;
do
{
pWriteBuf = malloc(PacketLength);
if (pWriteBuf == NULL)
{
DEBUGP(("DoWriteProc: Failed to malloc %d bytes\n", PacketLength));
break;
}
pEthHeader = (PETH_HEADER)pWriteBuf;
pEthHeader->EthType = EthType;
if (bUseFakeAddress)
{
memcpy(pEthHeader->SrcAddr, FakeSrcMacAddr, MAC_ADDR_LEN);
}
else
{
memcpy(pEthHeader->SrcAddr, SrcMacAddr, MAC_ADDR_LEN);
}
memcpy(pEthHeader->DstAddr, DstMacAddr, MAC_ADDR_LEN);
pData = (PUCHAR)(pEthHeader + 1);
*pData++ = (UCHAR)0x8C; //Lenght
*pData++ = (UCHAR)0x45; //Res & Type
*pData++ = (UCHAR)0xD0; //Publisher
*pData++ = (UCHAR)0x50;
*pData++ = (UCHAR)0x99;
*pData++ = (UCHAR)0x45;
*pData++ = (UCHAR)0x34;
*pData++ = (UCHAR)0x9D;
*pData++ = (UCHAR)0x01; //Count
*pData++ = (UCHAR)0x00;
*pData++ = (UCHAR)0x00; //Cycle
*pData++ = (UCHAR)0x00;
*pData++ = (UCHAR)0x00; //Res
*pData++ = (UCHAR)0x28; //EAP_SM
*pData++ = (UCHAR)0x04; //PD ID
*pData++ = (UCHAR)0x00;
*pData++ = (UCHAR)0x00; //Version
*pData++ = (UCHAR)0x00;
*pData++ = (UCHAR)0x78; //Lenght
*pData++ = (UCHAR)0x05;
*pData++ = (UCHAR)0x00; //Quality
*pData++ = (UCHAR)0x00;
unsigned char j = 0;
for (int k = 0; k < 1400; k++) //Data
{
*pData++ = (UCHAR)j;
j++;
if (j > 0xFF)
{
j = 0;
}
}
SendCount = 0;
while (TRUE)
{
bSuccess = (BOOLEAN)WriteFile(
Handle,
pWriteBuf,
PacketLength,
&BytesWritten,
NULL);
DWORD err = GetLastError();
printf("ERROR: %i", err);
if (!bSuccess)
{
PRINTF(("DoWriteProc: WriteFile failed on Handle %p\n", Handle));
break;
}
SendCount++;
DEBUGP(("DoWriteProc: sent %d bytes\n", BytesWritten));
if ((NumberOfPackets != -1) && (SendCount == NumberOfPackets))
{
break;
}
}
} while (FALSE);
if (pWriteBuf)
{
free(pWriteBuf);
}
PRINTF(("DoWriteProc: finished sending %d packets of %d bytes each\n",
SendCount, PacketLength));}
HANDLE
OpenHandle(_In_ PSTR pDeviceName){
DWORD DesiredAccess;
DWORD ShareMode;
LPSECURITY_ATTRIBUTES lpSecurityAttributes = NULL;
DWORD CreationDistribution;
DWORD FlagsAndAttributes;
HANDLE Handle;
DWORD BytesReturned;
DesiredAccess = GENERIC_READ | GENERIC_WRITE;
ShareMode = 0;
CreationDistribution = OPEN_EXISTING;
FlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
Handle = CreateFileA(
pDeviceName,
DesiredAccess,
ShareMode,
lpSecurityAttributes,
CreationDistribution,
FlagsAndAttributes,
NULL
);
if (Handle == INVALID_HANDLE_VALUE)
{
DEBUGP(("Creating file failed, error %x\n", GetLastError()));
return Handle;
}
//
// Wait for the driver to finish binding.
//
if (!DeviceIoControl(
Handle,
IOCTL_NDISPROT_BIND_WAIT,
NULL,
0,
NULL,
0,
&BytesReturned,
NULL))
{
DEBUGP(("IOCTL_NDISIO_BIND_WAIT failed, error %x\n", GetLastError()));
CloseHandle(Handle);
Handle = INVALID_HANDLE_VALUE;
}
return (Handle);
}
For security, the driver refuses to send these types of packets by default.
Of course, since you have the source code to the driver, you are free to modify this restriction however you like — it's your driver. You can add a line to specifically allow the 0x88A4 EtherType, or delete the entire if-statement to allow all EtherTypes. You can require the usermode process to be running as Administrator if it wants to send "suspicious" network frames.
A bit more detail on the security angle. If you allow untrusted users/programs to place arbitrary data onto the network, that may compromise or weaken network security. This is why the sample driver (and Windows in general) does not allow arbitrary programs to put arbitrary data on the network.
For example, a malicious program that has unrestricted access to the Ethernet layer can advertise a malicious DHCP server that points clients to a malicious DNS server, conduct ARP poisoning attacks on your switch, DoS a switch (with, for example, 802.3x PAUSE frames, or with LLDPDUs that undermine the QoS policy), or circumvent any firewall policies you might have.
These potential attacks aren't necessarily a deal-breaker: consider that this is roughly the equivalent of allowing someone to plug an arbitrary unmanaged device into an Ethernet jack on your network. If your network already has measures in place to defend against hostile Ethernet endpoints, then removing restrictions from the sample driver not making things much worse. Alternatively, if you have some level of trust for all the users & code on the PCs that will run your driver, then modifying the driver won't matter. Or if your threat model already assumes the network is hostile and unreliable, then removing these restrictions will only help fulfill your threat model's expectations. ;)

How to set up a UNIX domain socket in iOS?

I am trying to set up a UNIX domain socket in iOS. According to https://iphonedevwiki.net/index.php/Unix_sockets, this is the code that I used to set up the socket on the server side:
const char *socket_path = "/var/run/myserver.socket";
// setup socket
struct sockaddr_un local;
strcpy(local.sun_path, socket_path);
unlink(local.sun_path);
local.sun_family = AF_UNIX;
int listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
printf("listenfd: %d\n", listenfd);
// start the server
int r = -1;
while(r != 0) {
r = bind(listenfd, (struct sockaddr*)&local, sizeof(local));
printf("bind: %d\n", r);
usleep(200 * 1000);
}
int one = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
// start listening for new connections
r = -1;
while(r != 0) {
r = listen(listenfd, 20);
printf("listen: %d\n", r);
usleep(200 * 1000);
}
// wait for new connection, and then process it
int connfd = -1;
while(true) {
if(connfd == -1) {
// wait for new connection
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
printf("new connfd: %d\n", connfd);
}
// process incoming data
char buffer[4096];
int len = recv(connfd, buffer, sizeof(buffer), 0);
if(len == 0) {
printf("connfd %d disconnected!\n", connfd);
connfd = -1;
continue;
} else {
printf("connfd %d recieved data: %s", connfd, buffer);
// send some data back (optional)
const char *response = "got it!\n";
send(connfd, response, strlen(response) + 1, 0);
}
}
However, when I run this code on my iPhone, I got this in the console:
listenfd: 3
bind: -1
bind: -1
bind: -1
bind: -1
bind: -1
...
It looks like there is a problem when we do bind() as it returns -1, I want to know what I am doing wrong in the code?
The errno is 1, which is OPERATION_NOT_PERMITTED
You are not allowed to create objects in /var/run on iOS. You need to put the socket in a directory where you are allowed to create objects, like FileManager.shared.temporaryDirectory.

Using winsock2, comparing two characters that seem to be equal comes out not equal

Hello fine community at stackoverflow! I've been lurking around using the site for about a year now, and just have come to the need to post a question.
I'm a bit of a klutz when it comes to coding, so go easy on me.
Here's the code (most of it is the sample winsock MSDN code :P):
Client:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
// Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")
void clarify(char *recvdata);
char mdata[7];
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "10150"
int main(int argc, char **argv)
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("173.21.56.58", DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
// Send an initial buffer
char sendbuf[512];
std::cin.getline(sendbuf, 512);
iResult = send( ConnectSocket, sendbuf, 512, 0 );
if (iResult == SOCKET_ERROR) {
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
std::cout<<"sendbuf: "<<sendbuf<<"\n";
std::cout<<"strlen(sendbuf): "<<strlen(sendbuf)<<"\n";
printf("Bytes Sent: %ld\n", iResult);
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
std::cout<<"recvbuf: "<<recvbuf<<"\n";
std::cout<<"recvbuflen: "<<recvbuflen<<"\n";
std::cout<<"strlen(recvbuf): "<<strlen(recvbuf)<<"\n";
std::cout<<recvbuf[0]<<"\n";
std::cout<<recvbuf[1]<<"\n";
std::cout<<recvbuf[2]<<"\n";
std::cout<<recvbuf[3]<<"\n";
std::cout<<recvbuf[4]<<"\n";
std::cout<<recvbuf[5]<<"\n";
std::cout<<recvbuf[6]<<"\n";
std::cout<<recvbuf[7]<<"\n";
std::cout<<recvbuf[8]<<"\n";
std::cout<<recvbuf[9]<<"\n";
std::cout<<recvbuf[10]<<"\n";
std::cout<<recvbuf[11]<<"\n";
std::cout<<recvbuf[12]<<"\n";
clarify(recvbuf);
std::cout<<"mdata(main()): "<<mdata<<"\n";
if (mdata == "anarchy") {std::cout<<"This is Anarchy. :)";}
else {std::cout<<"Nope. :( ";}
} while( iResult > 0 );
std::cin.ignore();
// shutdown the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
void clarify(char *recvdata)
{
std::cout<<"recvdata: "<<recvdata<<"\n";
for (int i=0; i<(strlen(recvdata)); i++) {
mdata[i]=recvdata[i];
std::cout<<mdata[i]<<"\n";
}
std::cout<<"mdata(clarify()): "<<mdata<<"\n";
}
And the server code is the sample MSDN winsock code.
I realize the code has a bunch of sloppy extras added in, but rest assured, those are for my own thoughts and reminders. So, please don't bother telling me other places I could clean up. I'll take care of that when I get closer to finishing my project (a long way away :) ).
So, I'm having issues comparing the "mdata" variable with the characters "anarchy".
Even when I send "anarchy" through winsock, it comes back as "anarchy", and I run it through "clarify()" just for good measure, it still doesn't seem to equal "anarchy".
I'm sure it's a noob mistake I'm making here, so please go easy on me...
EDIT:
Here's the output after typing "anarchy" for the "sendbuf" input:
anarchy
sendbuf: anarchy
strlen(sendbuf): 7
bytes sent: 512
bytes recieved: 512
recvbuf: anarchy
recvbuflen: 512
strlen(recvbuf): 7
a
n
a
r
c
h
y
f
4
i
w
,
recvdata: anarchy
a
n
a
r
c
h
y
mdata(clarify()): anarchy
mdata(main()): anarchy
Nope :(
You're comparing the address of a c-string literal to the address stored in mdata.
if (mdata == "anarchy") {std::cout<<"This is Anarchy. :)";}
"anarchy" is a string literal, and has an address. You're comparing that arbitrary address with the address stored in the mdata variable. They're not the same addresses, so the equality check fails.
You don't mean to compare the addresses of where your two strings are stored, you mean to compare the characters stored at those strings.
strncmp is your friend here.

an error occurs after GetQueuedCompletionStatus returns, error number is ERROR_INVALID_NETNAME

GetQueuedCompletionStatus fails with ERROR_INVALID_NETNAME. What does this mean? I tried looking in MSDN.
First step: connect to the server using ConnectEx. ConnectEx succeeds, with error code 997 (ERROR_IO_PENDING):
DWORD bytes = 0;
sockaddr_in addr = {0};
iocp_data_t * iocp = (iocp_data_t *)module->data;
addr.sin_addr.s_addr = ip;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if(!iocp->tcp_connectex(event->fd, (const sockaddr*)&addr, sizeof(sockaddr_in),
NULL, 0, NULL, &event->connect.overlap))
{
if(!ERR_RW_RETRIABLE(socket_geterror(event->fd)))
{
return false;
}
}
return true;
GetQueuedCompletionStatus returns after the ConnectEx call finishes, but with error code 1214 (ERROR_INVALID_NETNAME):
fd_event_t * fd_event;
iocp_data_t * iocp = (iocp_data_t *)module->data;
rc = GetQueuedCompletionStatus(iocp->iocp, &bytes, (PULONG_PTR)&fd_event,
(LPOVERLAPPED *) &event, (u_long) 1);
if(event == NULL)
{
return;
}
DWORD err = GetLastError(); // err = 1214
event = containing_record(event,event_t,overlap);
if(event->in_used)
{
if(event->event_handler != NULL)
{
event->event_handler(module,fd_event,event->type,event->user);
}
iocp_add_event(module,fd_event,event->type,event->event_handler,event->user);
}
A couple things to check:
Where does ip come from? You might need to use htonl.
How is the socket created? Perhaps your particular socket can't deal with IPv4 addresses (e.g. it's an IPv6 socket).
Also, make sure GetQueuedCompletionStatus returns FALSE before calling GetLastError. GetQueuedCompletionStatus has three possible outcomes:
Return value of TRUE:
Completion packet dequeued successfully, and the I/O finished successfully.
Return value of FALSE, with the OVERLAPPED set to NULL:
GetQueuedCompletionStatus itself failed to dequeue a completion (e.g. timed out).
Return value of FALSE, with the OVERLAPPED not NULL:
Completion packet dequeued, but the I/O it represents failed.

Port availability check on remote system

How can I tell if a given port is available or not on a local or remote system, in an NSIS page?
Abuot COM ports:
They cannot be detected directly from NSIS so write simple plug-in in C which will detect port by it's number.
This is my basic idea:
void GetListOfLocalPorts(CList<CString, CString>& o_lstPorts)
{
for( int i = 1; i <= 99; i++ )
{
DCB dcb;
HANDLE hCom = NULL;
BYTE byPort = (BYTE)i;
CString strPort;
strPort.Format("COM%d", i);
CString strCom = (CString)"\\\\.\\" + strPort;
SetErrorMode(SEM_FAILCRITICALERRORS);
try
{
hCom = CreateFile(strCom, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hCom == INVALID_HANDLE_VALUE)
continue;
BOOL fSuccess = GetCommState(hCom, &dcb);
CloseHandle(hCom);
if (!fSuccess)
continue;
// Port exists on this machine
o_lstPorts.AddTail(strPort);
}
catch(...)
{
}
}
}

Resources