/* * @implemented */ NTSTATUS NTAPI NtListenPort(IN HANDLE PortHandle, OUT PPORT_MESSAGE ConnectMessage) { NTSTATUS Status; PAGED_CODE(); LPCTRACE(LPC_LISTEN_DEBUG, "Handle: %lx\n", PortHandle); /* Wait forever for a connection request. */ for (;;) { /* Do the wait */ Status = NtReplyWaitReceivePort(PortHandle, NULL, NULL, ConnectMessage); /* Accept only LPC_CONNECTION_REQUEST requests. */ if ((Status != STATUS_SUCCESS) || (LpcpGetMessageType(ConnectMessage) == LPC_CONNECTION_REQUEST)) { /* Break out */ break; } } /* Return status */ return Status; }
VOID SepServerGetNextMessage( VOID ) { // // Wait for the next message to come in... // Status = NtReplyWaitReceivePort( EarPort, NULL, NULL, &RequestMessage ); SEASSERT_SUCCESS(Status); RequestCount += 1; return; }
NTSTATUS NtListenPort ( __in HANDLE PortHandle, __out PPORT_MESSAGE ConnectionRequest ) /*++ Routine Description: A server thread can listen for connection requests from client threads using the NtReplyWaitReceivePort service and looking for an LPC_CONNECTION_REQUEST message type. This call will loop, calling the NtReplyWaitReceivePort service, and return when it sees a message of type LPC_CONNECTION_REQUEST Arguments: PortHandle - Specifies the connection port to listen for connection requests to. ConnectionRequest - Pointer to a structure that describes the connection request the client is making: Return Value: NTSTATUS - An appropriate status value --*/ { NTSTATUS Status; PAGED_CODE(); // // Keep on looping until we get a connection request on the lpc port // while (TRUE) { Status = NtReplyWaitReceivePort( PortHandle, NULL, NULL, ConnectionRequest ); // // We'll return from this procedure if ever we get back non success // or the message is a connection request. We still need to protect // the testing of ConnectionRequest because it is a user supplied // buffer. // try { if ((Status != STATUS_SUCCESS) || ((ConnectionRequest->u2.s2.Type & ~LPC_KERNELMODE_MESSAGE) == LPC_CONNECTION_REQUEST)) { break; } } except( EXCEPTION_EXECUTE_HANDLER ) { Status = GetExceptionCode(); break; } } // // And return to our caller // return Status; }
/*++ * @name CsrSbApiRequestThread * * The CsrSbApiRequestThread routine handles incoming messages or connection * requests on the SM API LPC Port. * * @param Parameter * System-default user-defined parameter. Unused. * * @return The thread exit code, if the thread is terminated. * * @remarks Before listening on the port, the routine will first attempt * to connect to the user subsystem. * *--*/ VOID NTAPI CsrSbApiRequestThread(IN PVOID Parameter) { NTSTATUS Status; SB_API_MSG ReceiveMsg; PSB_API_MSG ReplyMsg = NULL; PVOID PortContext; ULONG MessageType; /* Start the loop */ while (TRUE) { /* Wait for a message to come in */ Status = NtReplyWaitReceivePort(CsrSbApiPort, &PortContext, &ReplyMsg->h, &ReceiveMsg.h); /* Check if we didn't get success */ if (Status != STATUS_SUCCESS) { /* If we only got a warning, keep going */ if (NT_SUCCESS(Status)) continue; /* We failed big time, so start out fresh */ ReplyMsg = NULL; DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status); continue; } /* Save the message type */ MessageType = ReceiveMsg.h.u2.s2.Type; /* Check if this is a connection request */ if (MessageType == LPC_CONNECTION_REQUEST) { /* Handle connection request */ CsrSbApiHandleConnectionRequest(&ReceiveMsg); /* Start over */ ReplyMsg = NULL; continue; } /* Check if the port died */ if (MessageType == LPC_PORT_CLOSED) { /* Close the handle if we have one */ if (PortContext) NtClose((HANDLE)PortContext); /* Client died, start over */ ReplyMsg = NULL; continue; } else if (MessageType == LPC_CLIENT_DIED) { /* Client died, start over */ ReplyMsg = NULL; continue; } /* * It's an API Message, check if it's within limits. If it's not, the * NT Behaviour is to set this to the Maximum API. */ if (ReceiveMsg.ApiNumber > SbpMaxApiNumber) { ReceiveMsg.ApiNumber = SbpMaxApiNumber; DPRINT1("CSRSS: %lx is invalid Sb ApiNumber\n", ReceiveMsg.ApiNumber); } /* Reuse the message */ ReplyMsg = &ReceiveMsg; /* Make sure that the message is supported */ if (ReceiveMsg.ApiNumber < SbpMaxApiNumber) { /* Call the API */ if (!CsrServerSbApiDispatch[ReceiveMsg.ApiNumber](&ReceiveMsg)) { /* It failed, so return nothing */ ReplyMsg = NULL; } } else { /* We don't support this API Number */ ReplyMsg->ReturnValue = STATUS_NOT_IMPLEMENTED; } } }
NTSTATUS SmpApiLoop ( IN PVOID ThreadParameter ) /*++ Routine Description: This is the main Session Manager API Loop. It services session manager API requests. Arguments: ThreadParameter - Supplies a handle to the API port used to receive session manager API requests. Return Value: None. --*/ { PSMAPIMSG SmApiReplyMsg; SMMESSAGE_SIZE MsgBuf; PSMAPIMSG SmApiMsg; NTSTATUS Status; HANDLE ConnectionPort; PSMP_CLIENT_CONTEXT ClientContext; PSMPKNOWNSUBSYS KnownSubSys; ConnectionPort = (HANDLE) ThreadParameter; SmApiMsg = (PSMAPIMSG)&MsgBuf; SmApiReplyMsg = NULL; try { for(;;) { Status = NtReplyWaitReceivePort( ConnectionPort, (PVOID *) &ClientContext, (PPORT_MESSAGE) SmApiReplyMsg, (PPORT_MESSAGE) SmApiMsg ); if ( !NT_SUCCESS(Status) ) { SmApiReplyMsg = NULL; continue; } else if ( SmApiMsg->h.u2.s2.Type == LPC_CONNECTION_REQUEST ) { SmpHandleConnectionRequest( ConnectionPort, (PSBAPIMSG) SmApiMsg ); SmApiReplyMsg = NULL; } else if ( SmApiMsg->h.u2.s2.Type == LPC_DEBUG_EVENT ) { ASSERT(SmpDbgSsLoaded); DbgSsHandleKmApiMsg((PDBGKM_APIMSG)SmApiMsg,NULL); SmApiReplyMsg = NULL; } else if ( SmApiMsg->h.u2.s2.Type == LPC_PORT_CLOSED ) { SmApiReplyMsg = NULL; } else { KnownSubSys = ClientContext->KnownSubSys; SmApiMsg->ReturnedStatus = STATUS_PENDING; #if DBG && 0 if (SmApiMsg->ApiNumber >= SmMaxApiNumber ) { SmApiMsg->ApiNumber = SmMaxApiNumber; } KdPrint(( "SMSS: %s Api Request received from %lx.%lx\n", SmpApiName[ SmApiMsg->ApiNumber ], SmApiMsg->h.ClientId.UniqueProcess, SmApiMsg->h.ClientId.UniqueThread )); #endif // DBG if (SmApiMsg->ApiNumber >= SmMaxApiNumber ) { Status = STATUS_NOT_IMPLEMENTED; } else { switch (SmApiMsg->ApiNumber) { case SmExecPgmApi : Status = (SmpApiDispatch[SmApiMsg->ApiNumber])( SmApiMsg, ClientContext, ConnectionPort); break; case SmLoadDeferedSubsystemApi : Status = (SmpApiDispatch[SmApiMsg->ApiNumber])( SmApiMsg, ClientContext, ConnectionPort); break; case SmCreateForeignSessionApi : case SmSessionCompleteApi : case SmTerminateForeignSessionApi : if (!KnownSubSys) { Status = STATUS_INVALID_PARAMETER; } else { Status = (SmpApiDispatch[SmApiMsg->ApiNumber])( SmApiMsg, ClientContext, ConnectionPort); } break; } } SmApiMsg->ReturnedStatus = Status; SmApiReplyMsg = SmApiMsg; } } } except (DbgpUnhandledExceptionFilter( GetExceptionInformation() )) { ; } // // Make the compiler happy // return STATUS_UNSUCCESSFUL; }
int security_reference_monitor_t::run() { const int maxlen = 0x100; //dprintf("starting kthread %p p = %p\n", this, process); current = static_cast<thread_t*>( this ); //dprintf("current->process = %p\n", current->process); object_attributes_t rm_oa( (PCWSTR) L"\\SeRmCommandPort" ); HANDLE port = 0, client = 0; NTSTATUS r = NtCreatePort( &port, &rm_oa, 0x100, 0x100, 0 ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) die("NtCreatePort(SeRmCommandPort) failed r = %08lx\n", r); BYTE buf[maxlen]; LPC_MESSAGE *req = (LPC_MESSAGE*) buf; r = NtListenPort( port, req ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) die("NtListenPort(SeRmCommandPort) failed r = %08lx\n", r); HANDLE conn_port = 0; r = NtAcceptConnectPort( &conn_port, 0, req, TRUE, NULL, NULL ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) die("NtAcceptConnectPort(SeRmCommandPort) failed r = %08lx\n", r); r = NtCompleteConnectPort( conn_port ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) die("NtCompleteConnectPort(SeRmCommandPort) failed r = %08lx\n", r); unicode_string_t lsa; lsa.copy( (PCWSTR) L"\\SeLsaCommandPort" ); SECURITY_QUALITY_OF_SERVICE qos; qos.Length = sizeof(qos); qos.ImpersonationLevel = SecurityAnonymous; qos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; qos.EffectiveOnly = TRUE; r = NtConnectPort( &client, &lsa, &qos, NULL, NULL, NULL, NULL, NULL ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) die("NtConnectPort(SeLsaCommandPort) failed r = %08lx\n", r); while (!terminated) { ULONG client_handle; r = NtReplyWaitReceivePort( port, &client_handle, 0, req ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) die("NtReplyWaitReceivePort(SeRmCommandPort) failed r = %08lx\n", r); dprintf("got message %ld\n", req->MessageId ); // send something back... r = NtReplyPort( port, req ); if (r == STATUS_THREAD_IS_TERMINATING) return 0; if (r < STATUS_SUCCESS) die("NtReplyPort(SeRmCommandPort) failed r = %08lx\n", r); } dprintf("done\n"); return 0; }
ULONG NTAPI SmpApiLoop(IN PVOID Parameter) { HANDLE SmApiPort = (HANDLE)Parameter; NTSTATUS Status; PSMP_CLIENT_CONTEXT ClientContext; PSM_API_MSG ReplyMsg = NULL; SM_API_MSG RequestMsg; PROCESS_BASIC_INFORMATION ProcessInformation; LARGE_INTEGER Timeout; /* Increase the number of API threads for throttling code for later */ _InterlockedExchangeAdd(&SmTotalApiThreads, 1); /* Mark us critical */ RtlSetThreadIsCritical(TRUE, NULL, TRUE); /* Set the PID of the SM process itself for later checking */ NtQueryInformationProcess(NtCurrentProcess(), ProcessBasicInformation, &ProcessInformation, sizeof(ProcessInformation), NULL); SmUniqueProcessId = (HANDLE)ProcessInformation.UniqueProcessId; /* Now process incoming messages */ while (TRUE) { /* Begin waiting on a request */ Status = NtReplyWaitReceivePort(SmApiPort, (PVOID*)&ClientContext, &ReplyMsg->h, &RequestMsg.h); if (Status == STATUS_NO_MEMORY) { /* Ran out of memory, so do a little timeout and try again */ if (ReplyMsg) DPRINT1("SMSS: Failed to reply to calling thread, retrying.\n"); Timeout.QuadPart = -50000000; NtDelayExecution(FALSE, &Timeout); continue; } /* Check what kind of request we received */ switch (RequestMsg.h.u2.s2.Type) { /* A new connection */ case LPC_CONNECTION_REQUEST: /* Create the right structures for it */ SmpHandleConnectionRequest(SmApiPort, (PSB_API_MSG)&RequestMsg); ReplyMsg = NULL; break; /* A closed connection */ case LPC_PORT_CLOSED: /* Destroy any state we had for this client */ DPRINT1("Port closed\n"); //if (ClientContext) SmpPushDeferredClientContext(ClientContext); ReplyMsg = NULL; break; /* An actual API message */ default: if (!ClientContext) { ReplyMsg = NULL; break; } RequestMsg.ReturnValue = STATUS_PENDING; /* Check if the API is valid */ if (RequestMsg.ApiNumber >= SmpMaxApiNumber) { /* It isn't, fail */ DPRINT1("Invalid API: %lx\n", RequestMsg.ApiNumber); Status = STATUS_NOT_IMPLEMENTED; } else if ((RequestMsg.ApiNumber <= SmpTerminateForeignSessionApi) && !(ClientContext->Subsystem)) { /* It's valid, but doesn't have a subsystem with it */ DPRINT1("Invalid session API\n"); Status = STATUS_INVALID_PARAMETER; } else { /* It's totally okay, so call the dispatcher for it */ Status = SmpApiDispatch[RequestMsg.ApiNumber](&RequestMsg, ClientContext, SmApiPort); } /* Write the result valud and return the message back */ RequestMsg.ReturnValue = Status; ReplyMsg = &RequestMsg; break; } } return STATUS_SUCCESS; }
/********************************************************************** * ApiPortListener/1 * * DESCRIPTION * The thread to process messages from the \POSIX+\ApiPort * LPC port. Mostly used by PSXDLL.DLL. */ VOID STDCALL ApiPortListener (PVOID pArg) { ULONG ulIndex = (ULONG) pArg; NTSTATUS Status; LPC_TYPE RequestType; ULONG PortIdentifier; PSX_MAX_MESSAGE Request; PPSX_MAX_MESSAGE Reply = NULL; BOOL NullReply = FALSE; debug_print (L"PSXSS: ->%s pArg=%d", __FUNCTION__, ulIndex); while (TRUE) { Reply = NULL; NullReply = FALSE; while (!NullReply) { Status = NtReplyWaitReceivePort ( Server.Port[ulIndex].hObject, 0, (PLPC_MESSAGE) Reply, (PLPC_MESSAGE) & Request ); if (!NT_SUCCESS(Status)) { break; } RequestType = PORT_MESSAGE_TYPE(Request); switch (RequestType) { case LPC_CONNECTION_REQUEST: ProcessConnectionRequest ((PLPC_MAX_MESSAGE) & Request); NullReply = TRUE; continue; case LPC_CLIENT_DIED: case LPC_PORT_CLOSED: case LPC_DEBUG_EVENT: case LPC_ERROR_EVENT: case LPC_EXCEPTION: NullReply = TRUE; continue; default: if (RequestType != LPC_REQUEST) { NullReply = TRUE; continue; } } Reply = & Request; Reply->PsxHeader.Status = ProcessRequest (& Request); NullReply = FALSE; } if ((STATUS_INVALID_HANDLE == Status) || (STATUS_OBJECT_TYPE_MISMATCH == Status)) { break; } } #ifdef __PSXSS_ON_W32__ TerminateThread(GetCurrentThread(),Status); #else NtTerminateThread(NtCurrentThread(),Status); #endif }
NTSTATUS AcceptLpcConnect(PLPC_PORT LpcPort, BOOL AcceptConnection, BYTE *reply, WORD replyLength) { NTSTATUS status; LPC_MESSAGE reqMsg, repMsg; PSERVER_LPC_PORT serverPort; HANDLE hPort = INVALID_HANDLE_VALUE; PHANDLE phPort = &hPort; BOOL stopFlag = FALSE; log("Wait for connection..."); serverPort = (PSERVER_LPC_PORT) LpcPort; while (!stopFlag) { status = NtReplyWaitReceivePort( LpcPort->hPort, (PVOID *) &phPort, NULL, (PLPC_MESSAGE_HEADER) &reqMsg ); log("status: %x\n", status); log("Message type: %x\n", reqMsg.header.MessageType); switch (reqMsg.header.MessageType) { case LPC_CONNECTION_REQUEST: status = NtAcceptConnectPort( &hPort, NULL, (PLPC_MESSAGE_HEADER) &reqMsg, AcceptConnection, NULL, NULL ); log("NtAcceptConnectPort: %x\n", status); status = NtCompleteConnectPort(hPort); log("NtCompleteConnectPort: %x\n", status); break; case LPC_REQUEST: case LPC_DATAGRAM: memset(&repMsg, 0, sizeof(repMsg)); memcpy(&(repMsg.header), &(reqMsg.header), sizeof(repMsg.header)); memcpy(repMsg.data, reply, replyLength); repMsg.header.DataLength = replyLength; repMsg.header.TotalLength = replyLength + sizeof(repMsg.header); log("SERVER: request: %s\n", reqMsg.data); log("SERVER: reply: %s\n", repMsg.data); status = NtReplyPort(hPort, (PLPC_MESSAGE_HEADER) &repMsg); log("NtReplyPort: %x\n", status); status = NtCompleteConnectPort(hPort); //log("NtCompleteConnectPort: %x\n", status); stopFlag = TRUE; break; case LPC_PORT_CLOSED: log("LPC_PORT_CLOSED\n"); break; default: break; }; } return status; }
static DWORD WINAPI LsapRmServerThread( PVOID StartContext) { LSAP_RM_API_MESSAGE Message; PPORT_MESSAGE ReplyMessage; REMOTE_PORT_VIEW RemotePortView; HANDLE MessagePort, DummyPortHandle; NTSTATUS Status; /* Initialize the port message */ Message.Header.u1.s1.TotalLength = sizeof(Message); Message.Header.u1.s1.DataLength = 0; /* Listen on the LSA command port */ Status = NtListenPort(SeLsaCommandPort, &Message.Header); if (!NT_SUCCESS(Status)) { ERR("LsapRmServerThread - Port Listen failed 0x%lx\n", Status); return Status; } /* Setup the Port View Structure */ RemotePortView.Length = sizeof(REMOTE_PORT_VIEW); RemotePortView.ViewSize = 0; RemotePortView.ViewBase = NULL; /* Accept the connection */ Status = NtAcceptConnectPort(&MessagePort, 0, &Message.Header, TRUE, NULL, &RemotePortView); if (!NT_SUCCESS(Status)) { ERR("LsapRmServerThread - Port Accept Connect failed 0x%lx\n", Status); return Status; } /* Complete the connection */ Status = NtCompleteConnectPort(MessagePort); if (!NT_SUCCESS(Status)) { ERR("LsapRmServerThread - Port Complete Connect failed 0x%lx\n", Status); return Status; } /* No reply yet */ ReplyMessage = NULL; /* Start looping */ while (TRUE) { /* Wait for a message */ Status = NtReplyWaitReceivePort(MessagePort, NULL, ReplyMessage, &Message.Header); if (!NT_SUCCESS(Status)) { ERR("LsapRmServerThread - Failed to get message: 0x%lx", Status); ReplyMessage = NULL; continue; } /* Check if this is a connection request */ if (Message.Header.u2.s2.Type == LPC_CONNECTION_REQUEST) { /* Reject connection request */ NtAcceptConnectPort(&DummyPortHandle, NULL, &Message.Header, FALSE, NULL, NULL); /* Start over */ ReplyMessage = NULL; continue; } /* Check if this is an actual request */ if (Message.Header.u2.s2.Type == LPC_REQUEST) { ReplyMessage = &Message.Header; switch (Message.ApiNumber) { case LsapAdtWriteLogApi: LsapAdtWriteLog(&Message); break; case LsapAsyncApi: LsapAsync(&Message); break; case LsapComponentTestApi: LsapComponentTest(&Message); break; default: ERR("LsapRmServerThread - invalid API number: 0x%lx\n", Message.ApiNumber); ReplyMessage = NULL; } continue; } ERR("LsapRmServerThread - unexpected message type: 0x%lx\n", Message.Header.u2.s2.Type); /* Start over */ ReplyMessage = NULL; } }
NTSTATUS PhSvcApiRequestThreadStart( __in PVOID Parameter ) { NTSTATUS status; PHSVC_THREAD_CONTEXT threadContext; HANDLE portHandle; PVOID portContext; PHSVC_API_MSG receiveMessage; PPHSVC_API_MSG replyMessage; CSHORT messageType; PPHSVC_CLIENT client; threadContext.CurrentClient = NULL; threadContext.OldClient = NULL; TlsSetValue(PhSvcApiThreadContextTlsIndex, &threadContext); portHandle = PhSvcApiPortHandle; replyMessage = NULL; while (TRUE) { status = NtReplyWaitReceivePort( portHandle, &portContext, (PPORT_MESSAGE)replyMessage, (PPORT_MESSAGE)&receiveMessage ); portHandle = PhSvcApiPortHandle; replyMessage = NULL; if (!NT_SUCCESS(status)) { // Client probably died. continue; } messageType = receiveMessage.h.u2.s2.Type; if (messageType == LPC_CONNECTION_REQUEST) { PhSvcHandleConnectionRequest(&receiveMessage); continue; } if (!portContext) continue; client = (PPHSVC_CLIENT)portContext; threadContext.CurrentClient = client; if (messageType == LPC_REQUEST) { PhSvcDispatchApiCall(client, &receiveMessage, &replyMessage, &portHandle); } else if (messageType == LPC_PORT_CLOSED) { PhDereferenceObject(client); if (_InterlockedDecrement(&PhSvcApiNumberOfClients) == 0) { NtSetEvent(PhSvcTimeoutStandbyEventHandle, NULL); } } assert(!threadContext.OldClient); } }
UdbgTest1() { NTSTATUS st; HANDLE ExitThread, SpinThread, DebugProcess; CLIENT_ID ExitClientId, SpinClientId; DBGKM_APIMSG m; PDBGKM_CREATE_THREAD CreateThreadArgs; PDBGKM_CREATE_PROCESS CreateProcessArgs; PDBGKM_EXIT_THREAD ExitThreadArgs; PDBGKM_EXIT_PROCESS ExitProcessArgs; ULONG Psp; DbgPrint("UdbgTest1: (1)...\n"); // // Verify that a process can be created with a debug // port. // st = NtCreateProcess( &DebugProcess, PROCESS_ALL_ACCESS, NULL, NtCurrentProcess(), FALSE, NULL, DebugPort, NULL ); ASSERT(NT_SUCCESS(st)); st = RtlCreateUserThread( DebugProcess, NULL, TRUE, 0L, 0L, 0L, ThreadThatExits, (PVOID) STATUS_ABANDONED, &ExitThread, &ExitClientId ); ASSERT(NT_SUCCESS(st)); st = RtlCreateUserThread( DebugProcess, NULL, TRUE, 0L, 0L, 0L, ThreadThatSpins, NULL, &SpinThread, &SpinClientId ); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest1: (2)...\n"); // // Verify that CreateProcess Messages Arrive, and that // they are correct // st = NtResumeThread(SpinThread,NULL); ASSERT(NT_SUCCESS(st)); st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmCreateProcessApi); CreateThreadArgs = &m.u.CreateProcess.InitialThread; CreateProcessArgs = &m.u.CreateProcess; ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatSpins ); ASSERT( CreateProcessArgs->SubSystemKey == 0); DbgPrint("UdbgTest1: (3)...\n"); // // Verify that other threads in the process are properly suspended // st = NtSuspendThread(ExitThread,&Psp); ASSERT(NT_SUCCESS(st) && Psp == 2); st = NtResumeThread(ExitThread,&Psp); ASSERT(NT_SUCCESS(st) && Psp == 3); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest1: (4)...\n"); // // Verify that CreateThread Messages Arrive, and that // they are correct // st = NtResumeThread(ExitThread,&Psp); ASSERT(NT_SUCCESS(st)); st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmCreateThreadApi); CreateThreadArgs = &m.u.CreateThread; ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExits ); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest1: (5)...\n"); // // Verify that ExitThread Messages Arrive, and that // they are correct // st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmExitThreadApi); ExitThreadArgs = &m.u.ExitThread; ASSERT( ExitThreadArgs->ExitStatus == STATUS_ABANDONED ); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); st = NtWaitForSingleObject(ExitThread,FALSE,NULL); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest1: (6)...\n"); // // Verify that ExitThread Messages Arrive, and that // they are correct // st = NtTerminateProcess(DebugProcess,STATUS_REPARSE); ASSERT(NT_SUCCESS(st)); st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmExitThreadApi); ExitThreadArgs = &m.u.ExitThread; ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE ); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest1: (7)...\n"); // // Verify that ExitProcess Messages Arrive, and that // they are correct // st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmExitProcessApi); ExitProcessArgs = &m.u.ExitProcess; ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE ); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); st = NtWaitForSingleObject(ExitThread,FALSE,NULL); ASSERT(NT_SUCCESS(st)); st = NtWaitForSingleObject(DebugProcess,FALSE,NULL); ASSERT(NT_SUCCESS(st)); NtClose(ExitThread); NtClose(SpinThread); NtClose(DebugProcess); DbgPrint("UdbgTest1: END OF TEST ***\n"); }
UdbgTest2() { NTSTATUS st; HANDLE ExceptionThread, DebugProcess; DBGKM_APIMSG m; PDBGKM_CREATE_THREAD CreateThreadArgs; PDBGKM_CREATE_PROCESS CreateProcessArgs; PDBGKM_EXIT_THREAD ExitThreadArgs; PDBGKM_EXIT_PROCESS ExitProcessArgs; PDBGKM_EXCEPTION ExceptionArgs; ULONG Psp; DbgPrint("UdbgTest2: (1)...\n"); // // Verify that a process can be created with a debug // port. // st = NtCreateProcess( &DebugProcess, PROCESS_ALL_ACCESS, NULL, NtCurrentProcess(), FALSE, NULL, DebugPort, NULL ); ASSERT(NT_SUCCESS(st)); st = RtlCreateUserThread( DebugProcess, NULL, TRUE, 0L, 0L, 0L, ThreadThatExcepts, (PVOID) STATUS_ABANDONED, &ExceptionThread, NULL ); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest2: (2)...\n"); // // Verify that CreateThread Messages Arrive, and that // they are correct // st = NtResumeThread(ExceptionThread,NULL); ASSERT(NT_SUCCESS(st)); st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmCreateProcessApi); CreateThreadArgs = &m.u.CreateProcess.InitialThread; CreateProcessArgs = &m.u.CreateProcess; ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExcepts ); ASSERT( CreateProcessArgs->SubSystemKey == 0); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest2: (3)...\n"); // // Verify that First Chance Exception Messages Arrive, and that // they are correct // st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmExceptionApi); ExceptionArgs = &m.u.Exception; ASSERT( ExceptionArgs->FirstChance == TRUE ); m.ReturnedStatus = DBG_EXCEPTION_NOT_HANDLED; st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest2: (4)...\n"); // // Verify that First Chance Exception Messages Arrive, and that // they are correct // st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmExceptionApi); ExceptionArgs = &m.u.Exception; ASSERT( ExceptionArgs->FirstChance == FALSE ); m.ReturnedStatus = DBG_EXCEPTION_HANDLED; skip4: st = NtTerminateProcess(DebugProcess,STATUS_REPARSE); ASSERT(NT_SUCCESS(st)); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmExitThreadApi); ExitThreadArgs = &m.u.ExitThread; ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE ); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); DbgPrint("UdbgTest2: (5)...\n"); // // Verify that ExitProcess Messages Arrive, and that // they are correct // st = NtReplyWaitReceivePort( DebugPort, NULL, NULL, (PPORT_MESSAGE)&m ); ASSERT(NT_SUCCESS(st)); ASSERT(m.ApiNumber == DbgKmExitProcessApi); ExitProcessArgs = &m.u.ExitProcess; ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE ); st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m); ASSERT(NT_SUCCESS(st)); st = NtWaitForSingleObject(ExceptionThread,FALSE,NULL); ASSERT(NT_SUCCESS(st)); st = NtWaitForSingleObject(DebugProcess,FALSE,NULL); ASSERT(NT_SUCCESS(st)); NtClose(ExceptionThread); NtClose(DebugProcess); DbgPrint("UdbgTest2: END OF TEST ***\n"); }
/*++ * @name CsrApiRequestThread * * The CsrApiRequestThread routine handles incoming messages or connection * requests on the CSR API LPC Port. * * @param Parameter * System-default user-defined parameter. Unused. * * @return The thread exit code, if the thread is terminated. * * @remarks Before listening on the port, the routine will first attempt * to connect to the user subsystem. * *--*/ NTSTATUS NTAPI CsrApiRequestThread(IN PVOID Parameter) { PTEB Teb = NtCurrentTeb(); LARGE_INTEGER TimeOut; PCSR_THREAD CurrentThread, CsrThread; NTSTATUS Status; CSR_REPLY_CODE ReplyCode; PCSR_API_MESSAGE ReplyMsg; CSR_API_MESSAGE ReceiveMsg; PCSR_PROCESS CsrProcess; PHARDERROR_MSG HardErrorMsg; PVOID PortContext; PCSR_SERVER_DLL ServerDll; PCLIENT_DIED_MSG ClientDiedMsg; PDBGKM_MSG DebugMessage; ULONG ServerId, ApiId, MessageType, i; HANDLE ReplyPort; /* Setup LPC loop port and message */ ReplyMsg = NULL; ReplyPort = CsrApiPort; /* Connect to user32 */ while (!CsrConnectToUser()) { /* Set up the timeout for the connect (30 seconds) */ TimeOut.QuadPart = -30 * 1000 * 1000 * 10; /* Keep trying until we get a response */ Teb->Win32ClientInfo[0] = 0; NtDelayExecution(FALSE, &TimeOut); } /* Get our thread */ CurrentThread = Teb->CsrClientThread; /* If we got an event... */ if (Parameter) { /* Set it, to let stuff waiting on us load */ Status = NtSetEvent((HANDLE)Parameter, NULL); ASSERT(NT_SUCCESS(Status)); /* Increase the Thread Counts */ InterlockedIncrementUL(&CsrpStaticThreadCount); InterlockedIncrementUL(&CsrpDynamicThreadTotal); } /* Now start the loop */ while (TRUE) { /* Make sure the real CID is set */ Teb->RealClientId = Teb->ClientId; /* Debug check */ if (Teb->CountOfOwnedCriticalSections) { DPRINT1("CSRSRV: FATAL ERROR. CsrThread is Idle while holding %lu critical sections\n", Teb->CountOfOwnedCriticalSections); DPRINT1("CSRSRV: Last Receive Message %lx ReplyMessage %lx\n", &ReceiveMsg, ReplyMsg); DbgBreakPoint(); } /* Wait for a message to come through */ Status = NtReplyWaitReceivePort(ReplyPort, &PortContext, &ReplyMsg->Header, &ReceiveMsg.Header); /* Check if we didn't get success */ if (Status != STATUS_SUCCESS) { /* Was it a failure or another success code? */ if (!NT_SUCCESS(Status)) { /* Check for specific status cases */ if ((Status != STATUS_INVALID_CID) && (Status != STATUS_UNSUCCESSFUL) && ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort))) { /* Notify the debugger */ DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status); DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort); } /* We failed big time, so start out fresh */ ReplyMsg = NULL; ReplyPort = CsrApiPort; continue; } else { /* A strange "success" code, just try again */ DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status); continue; } } /* Use whatever Client ID we got */ Teb->RealClientId = ReceiveMsg.Header.ClientId; /* Get the Message Type */ MessageType = ReceiveMsg.Header.u2.s2.Type; /* Handle connection requests */ if (MessageType == LPC_CONNECTION_REQUEST) { /* Handle the Connection Request */ CsrApiHandleConnectionRequest(&ReceiveMsg); ReplyMsg = NULL; ReplyPort = CsrApiPort; continue; } /* It's some other kind of request. Get the lock for the lookup */ CsrAcquireProcessLock(); /* Now do the lookup to get the CSR_THREAD */ CsrThread = CsrLocateThreadByClientId(&CsrProcess, &ReceiveMsg.Header.ClientId); /* Did we find a thread? */ if (!CsrThread) { /* This wasn't a CSR Thread, release lock */ CsrReleaseProcessLock(); /* If this was an exception, handle it */ if (MessageType == LPC_EXCEPTION) { ReplyMsg = &ReceiveMsg; ReplyPort = CsrApiPort; ReplyMsg->Status = DBG_CONTINUE; } else if (MessageType == LPC_PORT_CLOSED || MessageType == LPC_CLIENT_DIED) { /* The Client or Port are gone, loop again */ ReplyMsg = NULL; ReplyPort = CsrApiPort; } else if (MessageType == LPC_ERROR_EVENT) { /* If it's a hard error, handle this too */ HardErrorMsg = (PHARDERROR_MSG)&ReceiveMsg; /* Default it to unhandled */ HardErrorMsg->Response = ResponseNotHandled; /* Check if there are free api threads */ CsrpCheckRequestThreads(); if (CsrpStaticThreadCount) { /* Loop every Server DLL */ for (i = 0; i < CSR_SERVER_DLL_MAX; i++) { /* Get the Server DLL */ ServerDll = CsrLoadedServerDll[i]; /* Check if it's valid and if it has a Hard Error Callback */ if ((ServerDll) && (ServerDll->HardErrorCallback)) { /* Call it */ ServerDll->HardErrorCallback(NULL /* == CsrThread */, HardErrorMsg); /* If it's handled, get out of here */ if (HardErrorMsg->Response != ResponseNotHandled) break; } } } /* Increase the thread count */ InterlockedIncrementUL(&CsrpStaticThreadCount); /* If the response was 0xFFFFFFFF, we'll ignore it */ if (HardErrorMsg->Response == 0xFFFFFFFF) { ReplyMsg = NULL; ReplyPort = CsrApiPort; } else { ReplyMsg = &ReceiveMsg; ReplyPort = CsrApiPort; } } else if (MessageType == LPC_REQUEST) { /* This is an API Message coming from a non-CSR Thread */ ReplyMsg = &ReceiveMsg; ReplyPort = CsrApiPort; ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION; } else if (MessageType == LPC_DATAGRAM) { /* This is an API call, get the Server ID */ ServerId = CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg.ApiNumber); /* Make sure that the ID is within limits, and the Server DLL loaded */ ServerDll = NULL; if ((ServerId >= CSR_SERVER_DLL_MAX) || (!(ServerDll = CsrLoadedServerDll[ServerId]))) { /* We are beyond the Maximum Server ID */ DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll); // DbgBreakPoint(); ReplyMsg = NULL; ReplyPort = CsrApiPort; continue; } /* Get the API ID, normalized with our Base ID */ ApiId = CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber) - ServerDll->ApiBase; /* Make sure that the ID is within limits, and the entry exists */ if (ApiId >= ServerDll->HighestApiSupported) { /* We are beyond the Maximum API ID, or it doesn't exist */ DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n", CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber), &ServerDll->Name); ReplyPort = CsrApiPort; ReplyMsg = NULL; continue; } #ifdef CSR_DBG if (CsrDebug & 2) { DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n", Teb->ClientId.UniqueThread, ReceiveMsg.Header.ClientId.UniqueProcess, ReceiveMsg.Header.ClientId.UniqueThread, ServerDll->NameTable[ApiId], NULL); } #endif /* Assume success */ ReceiveMsg.Status = STATUS_SUCCESS; /* Validation complete, start SEH */ _SEH2_TRY { /* Make sure we have enough threads */ CsrpCheckRequestThreads(); /* Call the API and get the reply code */ ReplyMsg = NULL; ReplyPort = CsrApiPort; ServerDll->DispatchTable[ApiId](&ReceiveMsg, &ReplyCode); /* Increase the static thread count */ InterlockedIncrementUL(&CsrpStaticThreadCount); } _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation())) { ReplyMsg = NULL; ReplyPort = CsrApiPort; } _SEH2_END; } else {
NTSTATUS PhSvcApiRequestThreadStart( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; NTSTATUS status; PHSVC_THREAD_CONTEXT threadContext; HANDLE portHandle; PVOID portContext; SIZE_T messageSize; PPORT_MESSAGE receiveMessage; PPORT_MESSAGE replyMessage; CSHORT messageType; PPHSVC_CLIENT client; PPHSVC_API_PAYLOAD payload; PhInitializeAutoPool(&autoPool); threadContext.CurrentClient = NULL; threadContext.OldClient = NULL; TlsSetValue(PhSvcApiThreadContextTlsIndex, &threadContext); portHandle = PhSvcApiPortHandle; messageSize = PhIsExecutingInWow64() ? sizeof(PHSVC_API_MSG64) : sizeof(PHSVC_API_MSG); receiveMessage = PhAllocate(messageSize); replyMessage = NULL; while (TRUE) { status = NtReplyWaitReceivePort( portHandle, &portContext, replyMessage, receiveMessage ); portHandle = PhSvcApiPortHandle; replyMessage = NULL; if (!NT_SUCCESS(status)) { // Client probably died. continue; } messageType = receiveMessage->u2.s2.Type; if (messageType == LPC_CONNECTION_REQUEST) { PhSvcHandleConnectionRequest(receiveMessage); continue; } if (!portContext) continue; client = portContext; threadContext.CurrentClient = client; PhWaitForEvent(&client->ReadyEvent, NULL); if (messageType == LPC_REQUEST) { if (PhIsExecutingInWow64()) payload = &((PPHSVC_API_MSG64)receiveMessage)->p; else payload = &((PPHSVC_API_MSG)receiveMessage)->p; PhSvcDispatchApiCall(client, payload, &portHandle); replyMessage = receiveMessage; } else if (messageType == LPC_PORT_CLOSED) { PhDereferenceObject(client); if (_InterlockedDecrement(&PhSvcApiNumberOfClients) == 0) { NtSetEvent(PhSvcTimeoutStandbyEventHandle, NULL); } } assert(!threadContext.OldClient); PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); }
NTSTATUS CsrSbApiRequestThread( IN PVOID Parameter ) { NTSTATUS Status; SBAPIMSG ReceiveMsg; PSBAPIMSG ReplyMsg; ReplyMsg = NULL; while (TRUE) { IF_CSR_DEBUG( LPC ) { DbgPrint( "CSRSS: Sb Api Request Thread waiting...\n" ); } Status = NtReplyWaitReceivePort( CsrSbApiPort, NULL, (PPORT_MESSAGE)ReplyMsg, (PPORT_MESSAGE)&ReceiveMsg ); if (Status != 0) { if (NT_SUCCESS( Status )) { continue; // Try again if alerted or a failure } else { IF_DEBUG { DbgPrint( "CSRSS: ReceivePort failed - Status == %X\n", Status ); } break; } } // // Check to see if this is a connection request and handle // if (ReceiveMsg.h.u2.s2.Type == LPC_CONNECTION_REQUEST) { CsrSbApiHandleConnectionRequest( &ReceiveMsg ); ReplyMsg = NULL; continue; } if ((ULONG)ReceiveMsg.ApiNumber >= SbMaxApiNumber) { IF_DEBUG { DbgPrint( "CSRSS: %lx is invalid Sb ApiNumber\n", ReceiveMsg.ApiNumber ); } ReceiveMsg.ApiNumber = SbMaxApiNumber; } #if DBG IF_CSR_DEBUG( LPC ) { DbgPrint( "CSRSS: %s Sb Api Request received from %lx.%lx\n", CsrServerSbApiName[ ReceiveMsg.ApiNumber ], ReceiveMsg.h.ClientId.UniqueProcess, ReceiveMsg.h.ClientId.UniqueThread ); } #endif // DBG ReplyMsg = &ReceiveMsg; if (ReceiveMsg.ApiNumber < SbMaxApiNumber) { if (!(*CsrServerSbApiDispatch[ ReceiveMsg.ApiNumber ])( &ReceiveMsg )) { ReplyMsg = NULL; } } else { ReplyMsg->ReturnedStatus = STATUS_NOT_IMPLEMENTED; } #if DBG IF_CSR_DEBUG( LPC ) { if (ReplyMsg != NULL) { DbgPrint( "CSRSS: %s Sb Api sending %lx status reply to %lx.%lx\n", CsrServerSbApiName[ ReceiveMsg.ApiNumber ], ReplyMsg->ReturnedStatus, ReplyMsg->h.ClientId.UniqueProcess, ReplyMsg->h.ClientId.UniqueThread ); } } #endif // DBG }
NTSTATUS WINAPI AuthPortThreadRoutine(PVOID Param) { PLSAP_LOGON_CONTEXT LogonContext; PLSA_API_MSG ReplyMsg = NULL; LSA_API_MSG RequestMsg; NTSTATUS Status; TRACE("AuthPortThreadRoutine() called\n"); Status = STATUS_SUCCESS; for (;;) { TRACE("Reply: %p\n", ReplyMsg); Status = NtReplyWaitReceivePort(AuthPortHandle, (PVOID*)&LogonContext, (PPORT_MESSAGE)ReplyMsg, (PPORT_MESSAGE)&RequestMsg); if (!NT_SUCCESS(Status)) { TRACE("NtReplyWaitReceivePort() failed (Status %lx)\n", Status); break; } TRACE("Received message\n"); switch (RequestMsg.h.u2.s2.Type) { case LPC_CONNECTION_REQUEST: TRACE("Port connection request\n"); Status = LsapHandlePortConnection(&RequestMsg); ReplyMsg = NULL; break; case LPC_PORT_CLOSED: TRACE("Port closed\n"); ReplyMsg = NULL; break; case LPC_CLIENT_DIED: TRACE("Client died\n"); ReplyMsg = NULL; break; default: TRACE("Received request (ApiNumber: %lu)\n", RequestMsg.ApiNumber); switch (RequestMsg.ApiNumber) { case LSASS_REQUEST_CALL_AUTHENTICATION_PACKAGE: RequestMsg.Status = LsapCallAuthenticationPackage(&RequestMsg, LogonContext); ReplyMsg = &RequestMsg; break; case LSASS_REQUEST_DEREGISTER_LOGON_PROCESS: ReplyMsg = &RequestMsg; RequestMsg.Status = STATUS_SUCCESS; NtReplyPort(AuthPortHandle, &ReplyMsg->h); LsapDeregisterLogonProcess(&RequestMsg, LogonContext); ReplyMsg = NULL; break; case LSASS_REQUEST_LOGON_USER: RequestMsg.Status = LsapLogonUser(&RequestMsg, LogonContext); ReplyMsg = &RequestMsg; break; case LSASS_REQUEST_LOOKUP_AUTHENTICATION_PACKAGE: RequestMsg.Status = LsapLookupAuthenticationPackage(&RequestMsg, LogonContext); ReplyMsg = &RequestMsg; break; case LSASS_REQUEST_ENUM_LOGON_SESSIONS: RequestMsg.Status = LsapEnumLogonSessions(&RequestMsg); ReplyMsg = &RequestMsg; break; case LSASS_REQUEST_GET_LOGON_SESSION_DATA: RequestMsg.Status = LsapGetLogonSessionData(&RequestMsg); ReplyMsg = &RequestMsg; break; case LSASS_REQUEST_POLICY_CHANGE_NOTIFY: RequestMsg.Status = LsapRegisterNotification(&RequestMsg); ReplyMsg = &RequestMsg; break; default: RequestMsg.Status = STATUS_INVALID_SYSTEM_SERVICE; ReplyMsg = &RequestMsg; break; } break; } } return STATUS_SUCCESS; }
NTSTATUS DbgSspSrvApiLoop( IN PVOID ThreadParameter ) /*++ Routine Description: This loop services Dbg Subsystem server originated messages. Arguments: ThreadParameter - Not used. Return Value: None. --*/ { DBGSRV_APIMSG DbgSrvApiMsg; PDBGSS_CONTINUE_KEY ContinueKey; NTSTATUS st; for(;;) { st = NtReplyWaitReceivePort( DbgSspApiPort, NULL, NULL, (PPORT_MESSAGE) &DbgSrvApiMsg ); if (!NT_SUCCESS( st )) { continue; } ASSERT(DbgSrvApiMsg.ApiNumber < DbgSrvMaxApiNumber); switch (DbgSrvApiMsg.ApiNumber ) { case DbgSrvContinueApi : // // Might want to implement continue status based callout // like DBG_TERMINATE_PROCESS/THREAD // ContinueKey = (PDBGSS_CONTINUE_KEY) DbgSrvApiMsg.ContinueKey; ContinueKey->KmApiMsg.ReturnedStatus = DbgSrvApiMsg.ReturnedStatus; if ( ContinueKey->ReplyEvent ) { st = NtSetEvent(ContinueKey->ReplyEvent,NULL); } else { st = NtReplyPort(DbgSspKmReplyPort, (PPORT_MESSAGE) &ContinueKey->KmApiMsg ); } RtlFreeHeap(RtlProcessHeap(), 0, ContinueKey); break; default : ASSERT(FALSE); } } // // Make the compiler happy // return st; }