ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

reply.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.