Reputation: 324
I wanna get client ip address or host name. I'm using VS6.0 & VS2010 on Windows 7 Ultimate.
CreateNamedPipe(...)
on Server is as follows :
SECURITY_ATTRIBUTES sa = {0};
hPipe = CreateNamedPipe(
_T("\\\\.\\pipe\\AnonymousPipe"), // pipe name
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES,
0xD000,
0xD000,
NMPWAIT_USE_DEFAULT_WAIT,
&sa);
if (hPipe == INVALID_HANDLE_VALUE)
{
_tprintf(TEXT("CreateNamedPipe failed, GLE=%d.\n"), GetLastError());
return -1;
}
fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (fConnected)
{
printf("Client connected, creating a processing thread.\n");
// Get Information Of Connected Client.
// Client Ip Address or Hostname.
}
How can I detect which client connected to server?
I can see the connection between server and client using netstat
cmd line.
netstat -an|find "445"
TCP 0.0.0.0:445 0.0.0.0:0 LISTENING
TCP 0.0.0.0:445 192.168.125.115:4124 ESTABLISHED
TCP 0.0.0.0:445 192.168.125.192:4882 ESTABLISHED
String "192.168.125.115"&"192.168.125.192" is my target. But I cannot find a way to detect connected client ip in programmatically in VS6.0.
Someone told me that use GetNamedPipeClientComputerName() to solve this problem. But
GetNamedPipeClientComputerName()
Minimum supported client Windows Vista [desktop apps only] Minimum supported server Windows Server 2008 [desktop apps only]
Many client still using Windows XP.
I have searched a lot to solve the problem, but I could not find the code describing for this.
Thank you for all viewers.
Upvotes: 0
Views: 805
Reputation: 33744
how already answered in comments GetNamedPipeClientComputerName
can be used for this. it available from Windows Vista. if want it on xp also it can be implemented in next way:
ULONG AltGetNamedPipeClientComputerName(HANDLE Pipe, PWSTR ClientComputerName, ULONG ClientComputerNameLength)
{
static const char AttributeName[] = "ClientComputerName";
if (HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL))
{
IO_STATUS_BLOCK iosb;
NTSTATUS status = NtFsControlFile(Pipe,
hEvent,
NULL,
NULL,
&iosb,
FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE,
(void*)AttributeName,
sizeof(AttributeName),
ClientComputerName,
ClientComputerNameLength*sizeof(WCHAR));
if (status == STATUS_PENDING)
{
WaitForSingleObject(hEvent, INFINITE);
status = iosb.Status;
}
CloseHandle(hEvent);
return status == STATUS_NOT_FOUND ? ERROR_PIPE_LOCAL : RtlNtStatusToDosError(status);
}
return GetLastError();
}
this is general how really GetNamedPipeClientComputerName
implemented internal. however if we use synchronous pipes (so created without FILE_FLAG_OVERLAPPED
) we can simplify function - not need create event - NtFsControlFile
never return STATUS_PENDING
for synchronous handle.
ULONG AltGetNamedPipeClientComputerNameSync(HANDLE Pipe, PWSTR ClientComputerName, ULONG ClientComputerNameLength)
{
static const char AttributeName[] = "ClientComputerName";
IO_STATUS_BLOCK iosb;
NTSTATUS status = NtFsControlFile(Pipe,
hEvent,
NULL,
NULL,
&iosb,
FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE,
(void*)AttributeName,
sizeof(AttributeName),
ClientComputerName,
ClientComputerNameLength*sizeof(WCHAR));
return status == STATUS_NOT_FOUND ? ERROR_PIPE_LOCAL : RtlNtStatusToDosError(status);
}
from another side if we use asynchronous pipe - we can and not wait when FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE
completed, but handle it asyncronous like other requests, which you handle async
one very important note - we can not use DeviceIoControl
here, but only NtFsControlFile
- this is because DeviceIoControl
internally check dwIoControlCode
and if it for FILE_DEVICE_FILE_SYSTEM
call NtFsControlFile
otherwise NtDeviceIoControlFile
. the FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE
defined in ntifs.h
(from wdk) as
#define FSCTL_PIPE_GET_CONNECTION_ATTRIBUTE CTL_CODE(FILE_DEVICE_NAMED_PIPE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
for FILE_DEVICE_NAMED_PIPE
DeviceIoControl
call NtDeviceIoControlFile
but we need NtFsControlFile
exactly.
note that this worked only for server side pipe end (created by CreateNamedPipe
) and in case client is remote. otherwise STATUS_NOT_FOUND
will be returned from NtFsControlFile
. the GetNamedPipeClientComputerName
implementation special check for this code and convert it to ERROR_PIPE_LOCAL
Upvotes: 1