Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenreply.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/lpc/reply.c 00005 * PURPOSE: Local Procedure Call: Receive (Replies) 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* PRIVATE FUNCTIONS *********************************************************/ 00016 00017 VOID 00018 NTAPI 00019 LpcpFreeDataInfoMessage(IN PLPCP_PORT_OBJECT Port, 00020 IN ULONG MessageId, 00021 IN ULONG CallbackId, 00022 IN CLIENT_ID ClientId) 00023 { 00024 PLPCP_MESSAGE Message; 00025 PLIST_ENTRY ListHead, NextEntry; 00026 00027 /* Check if the port we want is the connection port */ 00028 if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT) 00029 { 00030 /* Use it */ 00031 Port = Port->ConnectionPort; 00032 if (!Port) return; 00033 } 00034 00035 /* Loop the list */ 00036 ListHead = &Port->LpcDataInfoChainHead; 00037 NextEntry = ListHead->Flink; 00038 while (ListHead != NextEntry) 00039 { 00040 /* Get the message */ 00041 Message = CONTAINING_RECORD(NextEntry, LPCP_MESSAGE, Entry); 00042 00043 /* Make sure it matches */ 00044 if ((Message->Request.MessageId == MessageId) && 00045 (Message->Request.ClientId.UniqueThread == ClientId.UniqueThread) && 00046 (Message->Request.ClientId.UniqueProcess == ClientId.UniqueProcess)) 00047 { 00048 /* Unlink and free it */ 00049 RemoveEntryList(&Message->Entry); 00050 InitializeListHead(&Message->Entry); 00051 LpcpFreeToPortZone(Message, 1); 00052 break; 00053 } 00054 00055 /* Go to the next entry */ 00056 NextEntry = NextEntry->Flink; 00057 } 00058 } 00059 00060 VOID 00061 NTAPI 00062 LpcpSaveDataInfoMessage(IN PLPCP_PORT_OBJECT Port, 00063 IN PLPCP_MESSAGE Message, 00064 IN ULONG LockHeld) 00065 { 00066 PAGED_CODE(); 00067 00068 /* Acquire the lock */ 00069 if (!LockHeld) KeAcquireGuardedMutex(&LpcpLock); 00070 00071 /* Check if the port we want is the connection port */ 00072 if ((Port->Flags & LPCP_PORT_TYPE_MASK) > LPCP_UNCONNECTED_PORT) 00073 { 00074 /* Use it */ 00075 Port = Port->ConnectionPort; 00076 if (!Port) 00077 { 00078 /* Release the lock and return */ 00079 if (!LockHeld) KeReleaseGuardedMutex(&LpcpLock); 00080 return; 00081 } 00082 } 00083 00084 /* Link the message */ 00085 InsertTailList(&Port->LpcDataInfoChainHead, &Message->Entry); 00086 00087 /* Release the lock */ 00088 if (!LockHeld) KeReleaseGuardedMutex(&LpcpLock); 00089 } 00090 00091 VOID 00092 NTAPI 00093 LpcpMoveMessage(IN PPORT_MESSAGE Destination, 00094 IN PPORT_MESSAGE Origin, 00095 IN PVOID Data, 00096 IN ULONG MessageType, 00097 IN PCLIENT_ID ClientId) 00098 { 00099 /* Set the Message size */ 00100 LPCTRACE((LPC_REPLY_DEBUG | LPC_SEND_DEBUG), 00101 "Destination/Origin: %p/%p. Data: %p. Length: %lx\n", 00102 Destination, 00103 Origin, 00104 Data, 00105 Origin->u1.Length); 00106 Destination->u1.Length = Origin->u1.Length; 00107 00108 /* Set the Message Type */ 00109 Destination->u2.s2.Type = !MessageType ? 00110 Origin->u2.s2.Type : MessageType & 0xFFFF; 00111 00112 /* Check if we have a Client ID */ 00113 if (ClientId) 00114 { 00115 /* Set the Client ID */ 00116 Destination->ClientId.UniqueProcess = ClientId->UniqueProcess; 00117 Destination->ClientId.UniqueThread = ClientId->UniqueThread; 00118 } 00119 else 00120 { 00121 /* Otherwise, copy it */ 00122 Destination->ClientId.UniqueProcess = Origin->ClientId.UniqueProcess; 00123 Destination->ClientId.UniqueThread = Origin->ClientId.UniqueThread; 00124 } 00125 00126 /* Copy the MessageId and ClientViewSize */ 00127 Destination->MessageId = Origin->MessageId; 00128 Destination->ClientViewSize = Origin->ClientViewSize; 00129 00130 /* Copy the Message Data */ 00131 RtlCopyMemory(Destination + 1, 00132 Data, 00133 ((Destination->u1.Length & 0xFFFF) + 3) &~3); 00134 } 00135 00136 /* PUBLIC FUNCTIONS **********************************************************/ 00137 00138 /* 00139 * @implemented 00140 */ 00141 NTSTATUS 00142 NTAPI 00143 NtReplyPort(IN HANDLE PortHandle, 00144 IN PPORT_MESSAGE ReplyMessage) 00145 { 00146 PLPCP_PORT_OBJECT Port, ConnectionPort = NULL; 00147 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); 00148 NTSTATUS Status; 00149 PLPCP_MESSAGE Message; 00150 PETHREAD Thread = PsGetCurrentThread(), WakeupThread; 00151 //PORT_MESSAGE CapturedReplyMessage; 00152 00153 PAGED_CODE(); 00154 LPCTRACE(LPC_REPLY_DEBUG, 00155 "Handle: %lx. Message: %p.\n", 00156 PortHandle, 00157 ReplyMessage); 00158 00159 if (KeGetPreviousMode() == UserMode) 00160 { 00161 _SEH2_TRY 00162 { 00163 ProbeForRead(ReplyMessage, sizeof(PORT_MESSAGE), sizeof(ULONG)); 00164 /*RtlCopyMemory(&CapturedReplyMessage, ReplyMessage, sizeof(PORT_MESSAGE)); 00165 ReplyMessage = &CapturedReplyMessage;*/ 00166 } 00167 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00168 { 00169 DPRINT1("SEH crash [1]\n"); 00170 DbgBreakPoint(); 00171 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00172 } 00173 _SEH2_END; 00174 } 00175 00176 /* Validate its length */ 00177 if (((ULONG)ReplyMessage->u1.s1.DataLength + sizeof(PORT_MESSAGE)) > 00178 (ULONG)ReplyMessage->u1.s1.TotalLength) 00179 { 00180 /* Fail */ 00181 return STATUS_INVALID_PARAMETER; 00182 } 00183 00184 /* Make sure it has a valid ID */ 00185 if (!ReplyMessage->MessageId) return STATUS_INVALID_PARAMETER; 00186 00187 /* Get the Port object */ 00188 Status = ObReferenceObjectByHandle(PortHandle, 00189 0, 00190 LpcPortObjectType, 00191 PreviousMode, 00192 (PVOID*)&Port, 00193 NULL); 00194 if (!NT_SUCCESS(Status)) return Status; 00195 00196 /* Validate its length in respect to the port object */ 00197 if (((ULONG)ReplyMessage->u1.s1.TotalLength > Port->MaxMessageLength) || 00198 ((ULONG)ReplyMessage->u1.s1.TotalLength <= 00199 (ULONG)ReplyMessage->u1.s1.DataLength)) 00200 { 00201 /* Too large, fail */ 00202 ObDereferenceObject(Port); 00203 return STATUS_PORT_MESSAGE_TOO_LONG; 00204 } 00205 00206 /* Get the ETHREAD corresponding to it */ 00207 Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId, 00208 NULL, 00209 &WakeupThread); 00210 if (!NT_SUCCESS(Status)) 00211 { 00212 /* No thread found, fail */ 00213 ObDereferenceObject(Port); 00214 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00215 return Status; 00216 } 00217 00218 /* Allocate a message from the port zone */ 00219 Message = LpcpAllocateFromPortZone(); 00220 if (!Message) 00221 { 00222 /* Fail if we couldn't allocate a message */ 00223 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00224 ObDereferenceObject(WakeupThread); 00225 ObDereferenceObject(Port); 00226 return STATUS_NO_MEMORY; 00227 } 00228 00229 /* Keep the lock acquired */ 00230 KeAcquireGuardedMutex(&LpcpLock); 00231 00232 /* Make sure this is the reply the thread is waiting for */ 00233 if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId) || 00234 ((LpcpGetMessageFromThread(WakeupThread)) && 00235 (LpcpGetMessageType(&LpcpGetMessageFromThread(WakeupThread)-> 00236 Request) != LPC_REQUEST))) 00237 { 00238 /* It isn't, fail */ 00239 LpcpFreeToPortZone(Message, 3); 00240 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00241 ObDereferenceObject(WakeupThread); 00242 ObDereferenceObject(Port); 00243 return STATUS_REPLY_MESSAGE_MISMATCH; 00244 } 00245 00246 /* Copy the message */ 00247 _SEH2_TRY 00248 { 00249 LpcpMoveMessage(&Message->Request, 00250 ReplyMessage, 00251 ReplyMessage + 1, 00252 LPC_REPLY, 00253 NULL); 00254 } 00255 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00256 { 00257 /* Fail */ 00258 LpcpFreeToPortZone(Message, 3); 00259 ObDereferenceObject(WakeupThread); 00260 ObDereferenceObject(Port); 00261 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00262 } 00263 _SEH2_END; 00264 00265 /* Reference the thread while we use it */ 00266 ObReferenceObject(WakeupThread); 00267 Message->RepliedToThread = WakeupThread; 00268 00269 /* Set this as the reply message */ 00270 WakeupThread->LpcReplyMessageId = 0; 00271 WakeupThread->LpcReplyMessage = (PVOID)Message; 00272 00273 /* Check if we have messages on the reply chain */ 00274 if (!(WakeupThread->LpcExitThreadCalled) && 00275 !(IsListEmpty(&WakeupThread->LpcReplyChain))) 00276 { 00277 /* Remove us from it and reinitialize it */ 00278 RemoveEntryList(&WakeupThread->LpcReplyChain); 00279 InitializeListHead(&WakeupThread->LpcReplyChain); 00280 } 00281 00282 /* Check if this is the message the thread had received */ 00283 if ((Thread->LpcReceivedMsgIdValid) && 00284 (Thread->LpcReceivedMessageId == ReplyMessage->MessageId)) 00285 { 00286 /* Clear this data */ 00287 Thread->LpcReceivedMessageId = 0; 00288 Thread->LpcReceivedMsgIdValid = FALSE; 00289 } 00290 00291 /* Free any data information */ 00292 LpcpFreeDataInfoMessage(Port, 00293 ReplyMessage->MessageId, 00294 ReplyMessage->CallbackId, 00295 ReplyMessage->ClientId); 00296 00297 /* Release the lock and release the LPC semaphore to wake up waiters */ 00298 KeReleaseGuardedMutex(&LpcpLock); 00299 LpcpCompleteWait(&WakeupThread->LpcReplySemaphore); 00300 00301 /* Now we can let go of the thread */ 00302 ObDereferenceObject(WakeupThread); 00303 00304 /* Dereference port object */ 00305 ObDereferenceObject(Port); 00306 return Status; 00307 } 00308 00309 /* 00310 * @implemented 00311 */ 00312 NTSTATUS 00313 NTAPI 00314 NtReplyWaitReceivePortEx(IN HANDLE PortHandle, 00315 OUT PVOID *PortContext OPTIONAL, 00316 IN PPORT_MESSAGE ReplyMessage OPTIONAL, 00317 OUT PPORT_MESSAGE ReceiveMessage, 00318 IN PLARGE_INTEGER Timeout OPTIONAL) 00319 { 00320 PLPCP_PORT_OBJECT Port, ReceivePort, ConnectionPort = NULL; 00321 KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(), WaitMode = PreviousMode; 00322 NTSTATUS Status; 00323 PLPCP_MESSAGE Message; 00324 PETHREAD Thread = PsGetCurrentThread(), WakeupThread; 00325 PLPCP_CONNECTION_MESSAGE ConnectMessage; 00326 ULONG ConnectionInfoLength; 00327 //PORT_MESSAGE CapturedReplyMessage; 00328 LARGE_INTEGER CapturedTimeout; 00329 00330 PAGED_CODE(); 00331 LPCTRACE(LPC_REPLY_DEBUG, 00332 "Handle: %lx. Messages: %p/%p. Context: %p\n", 00333 PortHandle, 00334 ReplyMessage, 00335 ReceiveMessage, 00336 PortContext); 00337 00338 if (KeGetPreviousMode() == UserMode) 00339 { 00340 _SEH2_TRY 00341 { 00342 if (ReplyMessage != NULL) 00343 { 00344 ProbeForRead(ReplyMessage, sizeof(PORT_MESSAGE), sizeof(ULONG)); 00345 /*RtlCopyMemory(&CapturedReplyMessage, ReplyMessage, sizeof(PORT_MESSAGE)); 00346 ReplyMessage = &CapturedReplyMessage;*/ 00347 } 00348 00349 if (Timeout != NULL) 00350 { 00351 ProbeForReadLargeInteger(Timeout); 00352 RtlCopyMemory(&CapturedTimeout, Timeout, sizeof(LARGE_INTEGER)); 00353 Timeout = &CapturedTimeout; 00354 } 00355 00356 if (PortContext != NULL) 00357 ProbeForWritePointer(PortContext); 00358 } 00359 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00360 { 00361 DPRINT1("SEH crash [1]\n"); 00362 DbgBreakPoint(); 00363 _SEH2_YIELD(return _SEH2_GetExceptionCode()); 00364 } 00365 _SEH2_END; 00366 } 00367 else 00368 { 00369 /* If this is a system thread, then let it page out its stack */ 00370 if (Thread->SystemThread) WaitMode = UserMode; 00371 } 00372 00373 /* Check if caller has a reply message */ 00374 if (ReplyMessage) 00375 { 00376 /* Validate its length */ 00377 if (((ULONG)ReplyMessage->u1.s1.DataLength + sizeof(PORT_MESSAGE)) > 00378 (ULONG)ReplyMessage->u1.s1.TotalLength) 00379 { 00380 /* Fail */ 00381 return STATUS_INVALID_PARAMETER; 00382 } 00383 00384 /* Make sure it has a valid ID */ 00385 if (!ReplyMessage->MessageId) return STATUS_INVALID_PARAMETER; 00386 } 00387 00388 /* Get the Port object */ 00389 Status = ObReferenceObjectByHandle(PortHandle, 00390 0, 00391 LpcPortObjectType, 00392 PreviousMode, 00393 (PVOID*)&Port, 00394 NULL); 00395 if (!NT_SUCCESS(Status)) return Status; 00396 00397 /* Check if the caller has a reply message */ 00398 if (ReplyMessage) 00399 { 00400 /* Validate its length in respect to the port object */ 00401 if (((ULONG)ReplyMessage->u1.s1.TotalLength > Port->MaxMessageLength) || 00402 ((ULONG)ReplyMessage->u1.s1.TotalLength <= 00403 (ULONG)ReplyMessage->u1.s1.DataLength)) 00404 { 00405 /* Too large, fail */ 00406 ObDereferenceObject(Port); 00407 return STATUS_PORT_MESSAGE_TOO_LONG; 00408 } 00409 } 00410 00411 /* Check if this is anything but a client port */ 00412 if ((Port->Flags & LPCP_PORT_TYPE_MASK) != LPCP_CLIENT_PORT) 00413 { 00414 /* Check if this is the connection port */ 00415 if (Port->ConnectionPort == Port) 00416 { 00417 /* Use this port */ 00418 ConnectionPort = ReceivePort = Port; 00419 ObReferenceObject(ConnectionPort); 00420 } 00421 else 00422 { 00423 /* Acquire the lock */ 00424 KeAcquireGuardedMutex(&LpcpLock); 00425 00426 /* Get the port */ 00427 ConnectionPort = ReceivePort = Port->ConnectionPort; 00428 if (!ConnectionPort) 00429 { 00430 /* Fail */ 00431 KeReleaseGuardedMutex(&LpcpLock); 00432 ObDereferenceObject(Port); 00433 return STATUS_PORT_DISCONNECTED; 00434 } 00435 00436 /* Release lock and reference */ 00437 ObReferenceObject(ConnectionPort); 00438 KeReleaseGuardedMutex(&LpcpLock); 00439 } 00440 } 00441 else 00442 { 00443 /* Otherwise, use the port itself */ 00444 ReceivePort = Port; 00445 } 00446 00447 /* Check if the caller gave a reply message */ 00448 if (ReplyMessage) 00449 { 00450 /* Get the ETHREAD corresponding to it */ 00451 Status = PsLookupProcessThreadByCid(&ReplyMessage->ClientId, 00452 NULL, 00453 &WakeupThread); 00454 if (!NT_SUCCESS(Status)) 00455 { 00456 /* No thread found, fail */ 00457 ObDereferenceObject(Port); 00458 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00459 return Status; 00460 } 00461 00462 /* Allocate a message from the port zone */ 00463 Message = LpcpAllocateFromPortZone(); 00464 if (!Message) 00465 { 00466 /* Fail if we couldn't allocate a message */ 00467 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00468 ObDereferenceObject(WakeupThread); 00469 ObDereferenceObject(Port); 00470 return STATUS_NO_MEMORY; 00471 } 00472 00473 /* Keep the lock acquired */ 00474 KeAcquireGuardedMutex(&LpcpLock); 00475 00476 /* Make sure this is the reply the thread is waiting for */ 00477 if ((WakeupThread->LpcReplyMessageId != ReplyMessage->MessageId) || 00478 ((LpcpGetMessageFromThread(WakeupThread)) && 00479 (LpcpGetMessageType(&LpcpGetMessageFromThread(WakeupThread)-> 00480 Request) != LPC_REQUEST))) 00481 { 00482 /* It isn't, fail */ 00483 LpcpFreeToPortZone(Message, 3); 00484 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00485 ObDereferenceObject(WakeupThread); 00486 ObDereferenceObject(Port); 00487 return STATUS_REPLY_MESSAGE_MISMATCH; 00488 } 00489 00490 /* Copy the message */ 00491 LpcpMoveMessage(&Message->Request, 00492 ReplyMessage, 00493 ReplyMessage + 1, 00494 LPC_REPLY, 00495 NULL); 00496 00497 /* Reference the thread while we use it */ 00498 ObReferenceObject(WakeupThread); 00499 Message->RepliedToThread = WakeupThread; 00500 00501 /* Set this as the reply message */ 00502 WakeupThread->LpcReplyMessageId = 0; 00503 WakeupThread->LpcReplyMessage = (PVOID)Message; 00504 00505 /* Check if we have messages on the reply chain */ 00506 if (!(WakeupThread->LpcExitThreadCalled) && 00507 !(IsListEmpty(&WakeupThread->LpcReplyChain))) 00508 { 00509 /* Remove us from it and reinitialize it */ 00510 RemoveEntryList(&WakeupThread->LpcReplyChain); 00511 InitializeListHead(&WakeupThread->LpcReplyChain); 00512 } 00513 00514 /* Check if this is the message the thread had received */ 00515 if ((Thread->LpcReceivedMsgIdValid) && 00516 (Thread->LpcReceivedMessageId == ReplyMessage->MessageId)) 00517 { 00518 /* Clear this data */ 00519 Thread->LpcReceivedMessageId = 0; 00520 Thread->LpcReceivedMsgIdValid = FALSE; 00521 } 00522 00523 /* Free any data information */ 00524 LpcpFreeDataInfoMessage(Port, 00525 ReplyMessage->MessageId, 00526 ReplyMessage->CallbackId, 00527 ReplyMessage->ClientId); 00528 00529 /* Release the lock and release the LPC semaphore to wake up waiters */ 00530 KeReleaseGuardedMutex(&LpcpLock); 00531 LpcpCompleteWait(&WakeupThread->LpcReplySemaphore); 00532 00533 /* Now we can let go of the thread */ 00534 ObDereferenceObject(WakeupThread); 00535 } 00536 00537 /* Now wait for someone to reply to us */ 00538 LpcpReceiveWait(ReceivePort->MsgQueue.Semaphore, WaitMode); 00539 if (Status != STATUS_SUCCESS) goto Cleanup; 00540 00541 /* Wait done, get the LPC lock */ 00542 KeAcquireGuardedMutex(&LpcpLock); 00543 00544 /* Check if we've received nothing */ 00545 if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead)) 00546 { 00547 /* Check if this was a waitable port and wake it */ 00548 if (ReceivePort->Flags & LPCP_WAITABLE_PORT) 00549 { 00550 /* Reset its event */ 00551 KeResetEvent(&ReceivePort->WaitEvent); 00552 } 00553 00554 /* Release the lock and fail */ 00555 KeReleaseGuardedMutex(&LpcpLock); 00556 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00557 ObDereferenceObject(Port); 00558 return STATUS_UNSUCCESSFUL; 00559 } 00560 00561 /* Get the message on the queue */ 00562 Message = CONTAINING_RECORD(RemoveHeadList(&ReceivePort-> 00563 MsgQueue.ReceiveHead), 00564 LPCP_MESSAGE, 00565 Entry); 00566 00567 /* Check if the queue is empty now */ 00568 if (IsListEmpty(&ReceivePort->MsgQueue.ReceiveHead)) 00569 { 00570 /* Check if this was a waitable port */ 00571 if (ReceivePort->Flags & LPCP_WAITABLE_PORT) 00572 { 00573 /* Reset its event */ 00574 KeResetEvent(&ReceivePort->WaitEvent); 00575 } 00576 } 00577 00578 /* Re-initialize the message's list entry */ 00579 InitializeListHead(&Message->Entry); 00580 00581 /* Set this as the received message */ 00582 Thread->LpcReceivedMessageId = Message->Request.MessageId; 00583 Thread->LpcReceivedMsgIdValid = TRUE; 00584 00585 _SEH2_TRY 00586 { 00587 /* Check if this was a connection request */ 00588 if (LpcpGetMessageType(&Message->Request) == LPC_CONNECTION_REQUEST) 00589 { 00590 /* Get the connection message */ 00591 ConnectMessage = (PLPCP_CONNECTION_MESSAGE)(Message + 1); 00592 LPCTRACE(LPC_REPLY_DEBUG, 00593 "Request Messages: %p/%p\n", 00594 Message, 00595 ConnectMessage); 00596 00597 /* Get its length */ 00598 ConnectionInfoLength = Message->Request.u1.s1.DataLength - 00599 sizeof(LPCP_CONNECTION_MESSAGE); 00600 00601 /* Return it as the receive message */ 00602 *ReceiveMessage = Message->Request; 00603 00604 /* Clear our stack variable so the message doesn't get freed */ 00605 Message = NULL; 00606 00607 /* Setup the receive message */ 00608 ReceiveMessage->u1.s1.TotalLength = (CSHORT)(sizeof(LPCP_MESSAGE) + 00609 ConnectionInfoLength); 00610 ReceiveMessage->u1.s1.DataLength = (CSHORT)ConnectionInfoLength; 00611 RtlCopyMemory(ReceiveMessage + 1, 00612 ConnectMessage + 1, 00613 ConnectionInfoLength); 00614 00615 /* Clear the port context if the caller requested one */ 00616 if (PortContext) *PortContext = NULL; 00617 } 00618 else if (LpcpGetMessageType(&Message->Request) != LPC_REPLY) 00619 { 00620 /* Otherwise, this is a new message or event */ 00621 LPCTRACE(LPC_REPLY_DEBUG, 00622 "Non-Reply Messages: %p/%p\n", 00623 &Message->Request, 00624 (&Message->Request) + 1); 00625 00626 /* Copy it */ 00627 LpcpMoveMessage(ReceiveMessage, 00628 &Message->Request, 00629 (&Message->Request) + 1, 00630 0, 00631 NULL); 00632 00633 /* Return its context */ 00634 if (PortContext) *PortContext = Message->PortContext; 00635 00636 /* And check if it has data information */ 00637 if (Message->Request.u2.s2.DataInfoOffset) 00638 { 00639 /* It does, save it, and don't free the message below */ 00640 LpcpSaveDataInfoMessage(Port, Message, 1); 00641 Message = NULL; 00642 } 00643 } 00644 else 00645 { 00646 /* This is a reply message, should never happen! */ 00647 ASSERT(FALSE); 00648 } 00649 } 00650 _SEH2_EXCEPT(ExSystemExceptionFilter()) 00651 { 00652 DPRINT1("SEH crash [2]\n"); 00653 DbgBreakPoint(); 00654 Status = _SEH2_GetExceptionCode(); 00655 } 00656 _SEH2_END; 00657 00658 /* Check if we have a message pointer here */ 00659 if (Message) 00660 { 00661 /* Free it and release the lock */ 00662 LpcpFreeToPortZone(Message, 3); 00663 } 00664 else 00665 { 00666 /* Just release the lock */ 00667 KeReleaseGuardedMutex(&LpcpLock); 00668 } 00669 00670 Cleanup: 00671 /* All done, dereference the port and return the status */ 00672 LPCTRACE(LPC_REPLY_DEBUG, 00673 "Port: %p. Status: %p\n", 00674 Port, 00675 Status); 00676 if (ConnectionPort) ObDereferenceObject(ConnectionPort); 00677 ObDereferenceObject(Port); 00678 return Status; 00679 } 00680 00681 /* 00682 * @implemented 00683 */ 00684 NTSTATUS 00685 NTAPI 00686 NtReplyWaitReceivePort(IN HANDLE PortHandle, 00687 OUT PVOID *PortContext OPTIONAL, 00688 IN PPORT_MESSAGE ReplyMessage OPTIONAL, 00689 OUT PPORT_MESSAGE ReceiveMessage) 00690 { 00691 /* Call the newer API */ 00692 return NtReplyWaitReceivePortEx(PortHandle, 00693 PortContext, 00694 ReplyMessage, 00695 ReceiveMessage, 00696 NULL); 00697 } 00698 00699 /* 00700 * @unimplemented 00701 */ 00702 NTSTATUS 00703 NTAPI 00704 NtReplyWaitReplyPort(IN HANDLE PortHandle, 00705 IN PPORT_MESSAGE ReplyMessage) 00706 { 00707 UNIMPLEMENTED; 00708 return STATUS_NOT_IMPLEMENTED; 00709 } 00710 00711 /* 00712 * @unimplemented 00713 */ 00714 NTSTATUS 00715 NTAPI 00716 NtReadRequestData(IN HANDLE PortHandle, 00717 IN PPORT_MESSAGE Message, 00718 IN ULONG Index, 00719 IN PVOID Buffer, 00720 IN ULONG BufferLength, 00721 OUT PULONG Returnlength) 00722 { 00723 UNIMPLEMENTED; 00724 return STATUS_NOT_IMPLEMENTED; 00725 } 00726 00727 /* 00728 * @unimplemented 00729 */ 00730 NTSTATUS 00731 NTAPI 00732 NtWriteRequestData(IN HANDLE PortHandle, 00733 IN PPORT_MESSAGE Message, 00734 IN ULONG Index, 00735 IN PVOID Buffer, 00736 IN ULONG BufferLength, 00737 OUT PULONG ReturnLength) 00738 { 00739 UNIMPLEMENTED; 00740 return STATUS_NOT_IMPLEMENTED; 00741 } 00742 00743 /* EOF */ Generated on Sun May 27 2012 04:33:26 for ReactOS by
1.7.6.1
|