VOID PhSvcHandleConnectionRequest( __in PPHSVC_API_MSG Message ) { NTSTATUS status; PPHSVC_CLIENT client; HANDLE portHandle; REMOTE_PORT_VIEW clientView; client = PhSvcCreateClient(&Message->h.ClientId); if (!client) { NtAcceptConnectPort(&portHandle, NULL, &Message->h, FALSE, NULL, NULL); return; } Message->ConnectInfo.ServerProcessId = NtCurrentProcessId(); clientView.Length = sizeof(REMOTE_PORT_VIEW); clientView.ViewSize = 0; clientView.ViewBase = NULL; status = NtAcceptConnectPort( &portHandle, client, &Message->h, TRUE, NULL, &clientView ); if (!NT_SUCCESS(status)) { PhDereferenceObject(client); return; } client->PortHandle = portHandle; client->ClientViewBase = clientView.ViewBase; client->ClientViewLimit = (PCHAR)clientView.ViewBase + clientView.ViewSize; status = NtCompleteConnectPort(portHandle); if (!NT_SUCCESS(status)) { PhDereferenceObject(client); return; } if (_InterlockedIncrement(&PhSvcApiNumberOfClients) == 1) { NtSetEvent(PhSvcTimeoutCancelEventHandle, NULL); } }
VOID PhSvcHandleConnectionRequest( _In_ PPORT_MESSAGE PortMessage ) { NTSTATUS status; PPHSVC_API_MSG message; PPHSVC_API_MSG64 message64; CLIENT_ID clientId; PPHSVC_CLIENT client; HANDLE portHandle; REMOTE_PORT_VIEW clientView; REMOTE_PORT_VIEW64 clientView64; PREMOTE_PORT_VIEW actualClientView; message = (PPHSVC_API_MSG)PortMessage; message64 = (PPHSVC_API_MSG64)PortMessage; if (PhIsExecutingInWow64()) { clientId.UniqueProcess = (HANDLE)message64->h.ClientId.UniqueProcess; clientId.UniqueThread = (HANDLE)message64->h.ClientId.UniqueThread; } else { PPH_STRING referenceFileName; PPH_STRING remoteFileName; clientId = message->h.ClientId; // Make sure that the remote process is Process Hacker itself and not some other program. referenceFileName = NULL; PhGetProcessImageFileNameByProcessId(NtCurrentProcessId(), &referenceFileName); PH_AUTO(referenceFileName); remoteFileName = NULL; PhGetProcessImageFileNameByProcessId(clientId.UniqueProcess, &remoteFileName); PH_AUTO(remoteFileName); if (!referenceFileName || !remoteFileName || !PhEqualString(referenceFileName, remoteFileName, TRUE)) { NtAcceptConnectPort(&portHandle, NULL, PortMessage, FALSE, NULL, NULL); return; } } client = PhSvcCreateClient(&clientId); if (!client) { NtAcceptConnectPort(&portHandle, NULL, PortMessage, FALSE, NULL, NULL); return; } if (PhIsExecutingInWow64()) { message64->p.ConnectInfo.ServerProcessId = HandleToUlong(NtCurrentProcessId()); clientView64.Length = sizeof(REMOTE_PORT_VIEW64); clientView64.ViewSize = 0; clientView64.ViewBase = 0; actualClientView = (PREMOTE_PORT_VIEW)&clientView64; } else { message->p.ConnectInfo.ServerProcessId = HandleToUlong(NtCurrentProcessId()); clientView.Length = sizeof(REMOTE_PORT_VIEW); clientView.ViewSize = 0; clientView.ViewBase = NULL; actualClientView = &clientView; } status = NtAcceptConnectPort( &portHandle, client, PortMessage, TRUE, NULL, actualClientView ); if (!NT_SUCCESS(status)) { PhDereferenceObject(client); return; } // IMPORTANT: Since Vista, NtCompleteConnectPort does not do anything and simply returns STATUS_SUCCESS. // We will call it anyway (for completeness), but we need to use an event to ensure that other threads don't try // to process requests before we have finished setting up the client object. client->PortHandle = portHandle; if (PhIsExecutingInWow64()) { client->ClientViewBase = (PVOID)clientView64.ViewBase; client->ClientViewLimit = PTR_ADD_OFFSET(clientView64.ViewBase, clientView64.ViewSize); } else { client->ClientViewBase = clientView.ViewBase; client->ClientViewLimit = PTR_ADD_OFFSET(clientView.ViewBase, clientView.ViewSize); } NtCompleteConnectPort(portHandle); PhSetEvent(&client->ReadyEvent); if (_InterlockedIncrement(&PhSvcApiNumberOfClients) == 1) { NtSetEvent(PhSvcTimeoutCancelEventHandle, NULL); } }