Windows API: find process for a file mapping handle - winapi

I created an SSH agent (similar to PuTTY's pageant.exe) which has a predefined protocol: Authentication requests are sent to the agent window via WM_COPYDATA containing the name of a file mapping:
// mapname is supplied via WM_COPYDATA
HANDLE filemap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, mapname);
Is it possible to find out which process (ultimatively, the process name) created a particular file mapping?
I can use GetSecurityInfo on "filemap" to get the security attributes (SID, GID, ...) but how to I get the process itself?
Important note: It is NOT possible to change the protocol (e.g. add information about the sender to WM_COPYDATA) because this is the predefined protocol used by all PuTTY-like applications!

Don't try to find the process by file handle, it's complicated you need to enumerate process to find open handles for each. The WM_COPYDATA message send you the handle of the sender window, a call to GetWindowThreadProcessId should give your answer. Keep in mind that WM_COPYDATA is a way to communicate between 32 and 64 bits process so your process maybe in different space than the caller.
Edit-->
You receive the sender HWND in the WM_COPYDATA you only have to use that HWND to get the process ID
switch (uiMsg)
{
case WM_COPYDATA:
{
DWORD theProcessID;
GetWindowThreadProcessId((HWND) wParam, &theProcessID);
COPYDATASTRUCT *pMyCDS = (PCOPYDATASTRUCT) lParam;
/*...*/
}
/*...*/
}

Related

win32 PostMessage WM_APPCOMMAND sends multiple messages instead of one

I'm writing a small accessibility app which simulates certain keyboard gestures, such as volume up\down.
The goal is to send a single command.
In practice, the volume goes all the way up to 100%, as if user pressed a button for couple seconds or as if the message was dispatched multiple times.
This behavior is the same with both PostMessage and SendMessage, in both C and C# (using PInvoke)
C:
PostMessage(0xffff, 0x0319, 0, 0xa0000)
C#:
PostMessage(new IntPtr(0xffff), WindowMessage.WM_APPCOMMAND, (void*)0, (void*)0xa0000);
The meaning of parameters: send to all windows, message, no source, volume up
Question: How do I issue a command which would result in Windows adjusting volume by the smallest increment?
Additionally, I attempted using WP_KEYUP and WP_KEYDOWN, without success
// dispatch to all apps, message, wparam: virtual key, lparam: repeat count = 1
User32.PostMessage(new IntPtr(0xffff), User32.WindowMessage.WM_KEYDOWN, new IntPtr(0xaf000), new IntPtr(1));
User32.PostMessage(new IntPtr(0xffff), User32.WindowMessage.WM_KEYUP, new IntPtr(0xaf000), new IntPtr(1));
The reason why the command is sent multiple times is, as pointed by Hans in the comment, I broadcasted it to all windows using 0xffff as first parameter. Every window handled it by increasing volume by a notch.
The solution to sending multiple messages is to send the message to either
The shell handle GetShellWindow()
The foreground window handle GetForegroundWindow()
Both handles adjusted the volume by one notch. GetDesktopWindow() did not work, though.

Can I call multiple IOCTL's at the same time? (Windows Driver)

I have searched widely, I am writing a network filter and I am putting my registry filter in the same driver. Can I call multiple IOCTL's of the same driver at the same time? Would it be better if I separated my network filter and registry filter?
Open the device using FILE_FLAG_OVERLAPPED.
Then, when sending the IOCTL, use the Overlapped argument. Then the call will return immediately (async) and you can either wait (using WaitForSingleObject), call more things, or do whatever. Beware that the way the data is returned may have some gotchas in this case, depending on the use case.
OVERLAPPED async_data = { 0 };
async_data.hEvent = event_handle;
if (DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, &async_data)
{
// do stuff, more deviceiocontrol if you want
WaitForSingleObjects(async_data.hEvent, INFINITE);
// We wait until it finishes
}
// Handle error

How to reregister for IO Completion ports for a handle

I have a Windows named pipe that I create with CreateFile (the server side was created using CreateNamedPipe). I use IO completion ports to read/write data asynchronously on both ends.
I need to send these handles to other processes after they've been opened. I tried to call CloseHandle on the handle returned from CreateIoCompletionPort, and then in the other process call CreateIoCompletionPort again. However it always fails and GetLastError returns 87 (ERROR_INVALID_PARAMETER).
I can also reproduce this in just one process, see below. Note there are no outstanding reads/write to the object before I send it.
std::wstring pipe_name = L"\\\\.\\pipe\\test.12345";
HANDLE server = CreateNamedPipeW(
pipe_name.c_str(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
1,
4096,
4096,
10000,
NULL);
SECURITY_ATTRIBUTES security_attributes = {
sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
HANDLE client = CreateFileW(
pipe_name.c_str(), GENERIC_READ | GENERIC_WRITE,
0,
&security_attributes,
OPEN_EXISTING,
SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS | FILE_FLAG_OVERLAPPED,
NULL);
ULONG_PTR key = 1;
HANDLE comp_port = CreateIoCompletionPort(client, NULL, key, 1);
BOOL b1 = CloseHandle(comp_port);
comp_port = CreateIoCompletionPort(client, NULL, key, 1);
if (comp_port == NULL) {
int last_err = GetLastError();
}
Referring to the documentation for CreateIoCompletionPort:
A handle can be associated with only one I/O completion port, and after the association is made, the handle remains associated with that I/O completion port until it [the handle] is closed.
[...] The I/O completion port handle and every file handle associated with that particular I/O completion port are known as references to the I/O completion port. The I/O completion port is released when there are no more references to it.
In other words, closing the I/O completion port handle doesn't achieve anything. The I/O completion port still exists and is permanently associated with the pipe handle. What you're attempting simply isn't possible; you will need to rearchitecture.
Note also:
It is best not to share a file handle associated with an I/O completion port by using either handle inheritance or a call to the DuplicateHandle function. Operations performed with such duplicate handles generate completion notifications. Careful consideration is advised.
The documentation for CreateIoCompletionPort suggests what you're trying to accomplish isn't possible. All handles associated with an I/O completion port refer to the port and as long one is still open the port remains alive:
The I/O completion port handle and every file handle associated with that particular I/O completion port are known as references to the I/O completion port. The I/O completion port is released when there are no more references to it. Therefore, all of these handles must be properly closed to release the I/O completion port and its associated system resources. After these conditions are satisfied, close the I/O completion port handle by calling the CloseHandle function.
It should work if you create a new handle that's not associated with the I/O completion port with CreateFile and then pass it to the other processes with DuplicateHandle. Or just call CreateFile in the other process directly.

Obtaining a HANDLE to a named pipe opened in an external process (win32)

I have a logging facility (descendent of SS_Log) that consists of an independent log viewer and a C++ lib to send messages via a named pipe.
The log viewer is launched by the client through the C++ lib, when the 1st message is logged, and does
HANDLE hPipe = CreateNamedPipe( szPipeName,
PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE|PIPE_WAIT|PIPE_READMODE_MESSAGE,
PIPE_UNLIMITED_INSTANCES,
SSLOG_MAX_MESSAGE_LENGTH,
0, 5000, &sa );
pView->Pipe(hPipe);
if( pView->Pipe() == INVALID_HANDLE_VALUE )
{
pView->MessageBox( _T("Could not create the pipe for incoming messages. No messages can be received. "),
_T("Fatal Error"), MB_OK|MB_ICONSTOP );
return FALSE;
}
// now we loop forever, waiting for messages. As they come in, send them
// to the SS_Log_WindowView::EraseLog() and SS_Log_WindowView::WriteLog()
// functions as appropriate.
while( TRUE )
{
ConnectNamedPipe( pView->Pipe(), NULL );
...
}
When the client wants to send a message, it does
BOOL bResult = WaitNamedPipe(WindowPipeName(), 20000);
bResult = CallNamedPipe(WindowPipeName(), (LPVOID)szFinalBuffer,
_tcslen(szFinalBuffer)+1, (LPVOID)NULL,
0, &dwBytesRead,
5000);
I would like to obtain a HANDLE that corresponds to this named pipe. The documentation suggests I could just make one using CreateFile( WindowPipeName(), GENERIC_READ|GENERIC_WRITE,...OPEN_EXISTING,...). When I do that something clearly starts to block, and the log viewer no longer receives any messages. And that's even without doing anything with that HANDLE.
Is it possible to do what I want, and if so, how?
The log viewer's loop starts with a call to ConnectNamedPipe. So it waits for a client to connect, reads a message, returns to the top of the loop and waits for a client to connect again.
This works with CallNamedPipe because that function connects and disconnects every time it sends a message.
But if the client creates a persistent connection by opening a handle to the pipe with CreateFile then it is only connecting once. In the server, the second call to ConnectNamedPipe will hang waiting for another client to connect.
If you want the log viewer to handle only a single client with a persistent connection you can have a loop that calls ConnectNamedPipe followed by an inner loop that handles messages from the client until the pipe is closed.
If you want to handle multiple clients then your current solution is much simpler than attempting to handle multiple simultaneous connections.

Checking Win32 file streams for available input

I have a simple tunnel program that needs to simultaneously block on standard input and a socket. I currently have a program that looks like this (error handling and boiler plate stuff omitted):
HANDLE host = GetStdHandle(STD_INPUT_HANDLE);
SOCKET peer = ...; // socket(), connect()...
WSAEVENT gate = WSACreateEvent();
OVERLAPPED xfer;
ZeroMemory(&xfer, sizeof(xfer));
xfer.hEvent = gate;
WSABUF pbuf = ...; // allocate memory, set size.
// start an asynchronous transfer.
WSARecv(peer, &pbuf, 1, 0, &xfer, 0);
while ( running )
{
// wait until standard input has available data or the event
// is signaled to inform that socket read operation completed.
HANDLE handles[2] = { host, gate };
const DWORD which = WaitForMultipleObjects
(2, handles, FALSE, INFINITE) - WAIT_OBJECT_0;
if (which == 0)
{
// read stuff from standard input.
ReadFile(host, ...);
// process stuff received from host.
// ...
}
if (which == 1)
{
// process stuff received from peer.
// ...
// start another asynchronous transfer.
WSARecv(peer, &pbuf, 1, 0, &xfer, 0);
}
}
The program works like a charm, I can transfer stuff through this tunnel program without a hitch. The thing is that it has a subtle bug.
If I start this program in interactive mode from cmd.exe and standard input is attached to the keyboard, pressing a key that does not produce input (e.g. the Ctrl key) makes this program block and ignore data received on the socket. I managed to realize that this is because pressing any key signals the standard input handle and WaitForMultipleObjects() returns. As expected, control enters the if (which == 0) block and the call to ReadFile() blocks because there is no input available.
Is there a means to detect how much input is available on a Win32 stream? If so, I could use this to check if any input is available before calling ReadFile() to avoid blocking.
I know of a few solutions for specific types of streams (notably ClearCommError() for serial ports and ioctlsocket(socket,FIONBIO,&count) for sockets), but none that I know of works with the CONIN$ stream.
Use overlapped I/O. Then test the event attached to the I/O operation, instead of the handle.
For CONIN$ specifically, you might also look at the Console Input APIs, such as PeekConsoleInput and GetNumberOfConsoleInputEvents
But I really recommend using OVERLAPPED (background) reads wherever possible and not trying to treat WaitForMultipleObjects like select.
Since the console can't be overlapped in overlapped mode, your simplest options are to wait on the console handle and use ReadConsoleInput (then you have to process control sequences manually), or spawn a dedicated worker thread for synchronous ReadFile. If you choose a worker thread, you may want to then connect a pipe between that worker and the main I/O loop, using overlapped pipe reads.
Another possibility, which I've never tried, would be to wait on the console handle and use PeekConsoleInput to find out whether to call ReadFile or ReadConsoleInput. That way you should be able to get non-blocking along with the cooked terminal processing. OTOH, passing control sequences to ReadConsoleInput might inhibit the buffer-manipulation actions they were supposed to take.
If the two streams are processed independently, or nearly so, it may make more sense to start a thread for each one. Then you can use a blocking read from standard input.

Resources