Windows IT Pro
Windows IT Library
  - Advertise        
Windows IT Pro Logo

  Home  |   Books  |   Chapters  |   Topics  |   Authors  |   Book Reviews  |   Whitepapers  |   About Us  |   Contact Us  |   ITTV  |   IT Jobs

search for  on    power search   help
 






Local Procedure Call
View the book table of contents
Author: Prasad Dabak
Milind Borate
Sandeep Phadke
Published: October 1999
Copyright: 1999
Publisher: M&T Books
 


NtConnectPort
int _stdcall

NtConnectPort(

PHANDLE PortHandle,

PUNICODE_STRING PortName,

PVOID Unknown1,

LPCSECTIONINFO sectionInfo,

PLPCSECTIONMAPINFO mapInfo,

PVOID Unknown2,

PVOID ConnectInfo,

PDWORD pConnectInfoLength);
The client uses this function to establish LPC communication with the server. The name of the port to connect to is specified as a Unicode string in the PortName parameter. The second parameter, unknown at this time, cannot pass as NULL because the function fails the validation checks otherwise. The third parameter operates only when you use the shared section LPC. It is a pointer to a structure, described as follows:
 typedef struct LpcSectionInfo {

        DWORD Length;

        HANDLE SectionHandle;

        DWORD Param1;

        DWORD SectionSize;

        DWORD ClientBaseAddress;

        DWORD ServerBaseAddress;

} LPCSECTIONINFO, *PLPCSECTIONINFO;
The Length field in this structure specifies the size of the structure; it is always set to 24. The caller of this function–the client–fills the SectionHandle and SectionSize fields, apart from the Length. The CreateFileMapping() function can create a shared section of required size. Upon return from the NtConnectPort() function, the ClientBaseAddress and ServerBaseAddress fields, in the LPCSECTIONINFO structure, contain the addresses where the section is mapped in the client address space and the server address space, respectively.

The next parameter to the NtConnectPort() function–mapInfo–also functions only for the shared section LPC. This parameter is a pointer to a structure described as follows:
typedef struct LpcSectionMapInfo

{

        DWORD Length;

        DWORD SectionSize;

        DWORD ServerBaseAddress;

} LPCSECTIONMAPINFO, *PLPCSECTIONMAPINFO;
This structure duplicates the information in the LPCSECTIONINFO structure. The client needs to fill only the Length field, which it always sets to 12–the size of the structure. We have not been able to decipher the significance of passing this structure to the NtConnectPort() function. Still, you have to pass a valid structure; if you pass a NULL pointer, the function fails. We have observed that the two members of the structure, namely, SectionSize and ServerBaseAddress, zero out on return from the function.

We do not know the next parameter sent to the NtConnectPort() function, so set it as NULL.

The client can send some information to the server with the connection request. The server receives this information via the LPC message, which it gets from the NtReplyWaitReceivePort() function in case of a connection request. The ConnectInfo parameter points to this connection information. The size of the connection information passes through the pConnectInfoLength parameter that is a pointer to a double word. The server, also, can send back some information to the client at connection time. This information returns in the same ConnectInfo buffer, and the pConnectInfoLength is set to indicate the length of the returned connection information.

NtReplyWaitReceivePort
int _stdcall

NtReplyWaitReceivePort(

HANDLE PortHandle,

PDWORD Unknown,

PLPCMESSAGE pLpcMessageOut,

PLPCMESSAGE pLpcMessageIn);
This function is used by the server side of LPC to receive requests from clients and reply to them. The first parameter is the port handle obtained from the NtCreatePort() function. The second parameter, currently unknown, can be passed as NULL. The third parameter is the message that serves as a reply to the previous client request. This parameter can be NULL, in which case the function simply accepts a request from the client. The fourth parameter, a pointer to a LpcMessage structure, fills, on return from the function, with the request information. Both the third and the fourth parameters are pointers to the LpcMessage structure, which we display here.
typedef struct LpcMessage {

/* LPC Message Header */

WORD  ActualMessageLength;

WORD  TotalMessageLength;

DWORD MessageType;

DWORD ClientProcessId;

DWORD ClientThreadId;

DWORD MessageId;

DWORD SharedSectionSize;

BYTE  MessageData[MAX_MESSAGE_DATA];

} LPCMESSAGE, *PLPCMESSAGE;
The ActualMessageLength field is set to the size of the actual message stored in the MessageData field, whereas the TotalMessageLength is set to the size of the entire LpcMessage structure along with the MessageData. The system, not the client-server, sets the MessageType field. There are several message types. We detail the important ones:

LPC_REQUESTThe server receives this type of message when a client sends a request using the NtRequestWaitReplyPort() function. The server should reply to this message using the NtReplyPort() function or the NtReplyWaitReceivePort() function. The server should not reply to any messages other than the LPC_REQUEST messages. The NtRequestWaitReplyPort() function waits until it gets the reply from the server and then returns the reply message to the client. Effectively, the client thread that calls the NtRequestWaitReplyPort() function hangs if the server does not send a reply message.
LPC_REPLYThe client receives this type of message from the NtRequestWaitReplyPort() function, when the server replies to the request.
LPC_DATAGRAMThe server receives this type of message when a client sends a request using the NtRequestPort() function. As the name of the message type implies, the client does not get a reply from the server for this kind of message. If the server tries to reply to this message using the NtReplyPort() function or the NtReplyWaitReceivePort() function, the function fails and returns an error.
LPC_PORT_CLOSEDThe server receives this type of message when a client closes the port handle. If a client dies without closing the port handle, the operating system closes the handle on behalf of the client. Thus, the server gets the LPC_PORT_CLOSED message in any case and can use it to free the per-client resources it allocates.
LPC_CLIENT_DIEDThe server receives this type of message when a client dies. Refer to the description of the NtRegisterThreadTerminatePort() function for more information.
LPC_CONNECTION_REQUESTThe corresponding server receives this type of message when a client tries to connect to a port using the NtConnectPort() function.

The next fields in the LpcMessage structure are set, by the system, to the client’s process ID and thread ID, respectively. The next field is set to the unique message ID generated by the system. The server can rely on these fields because the operating system, not the client, sets them. These fields do not make sense in the messages received by the client and therefore are set to zero in the messages returned by the NtRequestWaitReplyPort() function.

Only the shared section LPC uses the SharedSectionSize field. The system sets this field to the size of the shared section when it passes a LPC_CONNECTION_REQUEST type of message to the server.

The last field is the actual message and is a variable length field. The client-server can choose to allocate only enough memory space to hold the structure parameters and the actual message. When passing a pointer to this structure for receiving a message, you must allocate enough memory space to fit the message the process can send at the other end of the port. If you fail to do it, you will receive an “Invalid Access” or similar kind of fault. To be on the safer side, you should always allocate for the maximum-sized message while passing a pointer for receiving a message.

NtAcceptConnectPort
int _stdcall

NtAcceptConnectPort(

PHANDLE PortHandle,

DWORD Unknown1,

PLPCMESSAGE pLpcMessage,

DWORD acceptIt,

DWORD Unknown3,

PLPCSECTIONMAPINFO mapInfo);
Whenever the server receives a connection request, it follows a connection establishment procedure by first calling the NtAcceptConnectPort() function and then the NtCompleteConnectPort() function. This sequence of operations establishes a communication channel between the client and the server. The client end of the channel represents the handle that it gets from the NtConnectPort() function. The first parameter to NtAcceptConnectPort() is a port handle pointer set to another handle to the message port on return. This handle is the server-side end of the communication channel, although the server can use the handle returned from the NtCreatePort() function to accept requests from all clients. The server can close the handle, returned by the NtAcceptConnectPort() function, when it no longer wants to accept requests using the particular communication channel. Any further requests by the client on a closed communication channel will fail.

We have not been able to decipher the second parameter–generally set to zero. The third parameter is the LPC message returned to the client as the connection information from the server. The fourth parameter, named acceptIt, is passed as 0 if the server cannot accept the connection request. The server passes acceptIt as a nonzero value if it can accept the connection request. The fifth parameter, not deciphered yet, can be set to zero. The last parameter is a pointer to the LpcSectionMapInfo structure, which fills with appropriate data upon return. We already explained the members of this structure. This structure supplies shared-section information for future use by the server for communicating with the client.

NtCompleteConnectPort
int _stdcall

NtCompleteConnectPort(

HANDLE PortHandle);
The server finishes the connection procedure with the NtCompleteConnectPort() function. The only parameter to this function is the port handle returned by the previous call to the NtAcceptConnectPort() function. The client waits in the NtCon-nectPort() function until the server completes the connection procedure by calling the NtCompleteConnectPort() function.

NtRequestWaitReplyPort
int _stdcall

NtRequestWaitReplyPort(

HANDLE PortHandle,

PLPCMESSAGE pLpcMessageIn,

PLPCMESSAGE pLpcMessageOut);
The client uses this function to send a request and wait for a reply to/from the server. The first parameter is the port handle obtained via a previous call to the NtConnectPort() function. The pLpcMessageIn parameter is a pointer to a LPC request message sent to the server. The last parameter is a pointer to another LPC message structure that fills with the reply message from the server, on return from the function.

NtListenPort
int _stdcall

NtListenPort(

HANDLE PortHandle,

PLPCMESSAGE pLpcMessage);
This very small function internally uses the NtReplyWaitReceivePort() function. Here we present the pseudocode of this function:
NtListenPort(HANDLE PortHandle,

PLPCMESSAGE pLpcMessage)

{

while(1) {

rc = NtReplyWaitReceivePort(

PortHandle,

NULL,

NULL

pLpcMessage);

if (rc == 0)

if(pLpcMessage->MessageType ==

LPC_CONNECTION_REQUEST)

break;

}

return rc;

}
As you can see from this pseudocode, the NtListenPort() function ignores all messages except connection requests. You cannot use this function if servicing multiple clients. While servicing multiple clients, a server gets a mix of connection requests and other client requests. The server needs to sort out the connection requests from the other requests and perform appropriate processing. If only a single client can connect at a time, the server can get the connection request using the NtListenPort() function and then start a loop to accept and process other client requests.

NtRequestPort
int _stdcall

NtRequestPort(

HANDLE PortHandle,

PLPCMESSAGE pLpcMessage);
This function just sends a message on the port and returns. The server thread waiting on this port gets the message and does the required processing. The server thread need not return the results to the caller. In this case, the message type in the header is LPC_DATAGRAM. A message sent using this function resembles a datagram in the sense that the sender does not receive an acknowledgment.

NtReplyPort
int _stdcall

NtReplyPort(

HANDLE PortHandle,

PLPCMESSAGE pLpcMessage);
The server uses this function if it wants to send a reply to the client and does not want to be blocked for the next request from the client. The first parameter to this function is the port handle, and the second parameter is the reply message sent to the client.

NtRegisterThreadTerminatePort
int _stdcall

NtRegisterThreadTerminatePort(

HANDLE PortHandle);
If a client calls this function after connecting to a port, then the operating system sends the LPC_CLIENT_DIED message to the server when the client dies. Even if the client closes the port handle and keeps running, the system maintains a reference to the port. Therefore, the operating system sends the LPC_PORT_CLOSED message after the LPC_CLIENT_DIED message and not after the client closes the port handle.

NtSetDefaultHardErrorPort
int _stdcall

NtSetDefaultHardErrorPort(

HANDLE PortHandle);
The CSRSS subsystem calls this function during its initialization. The NtRaiseHardError() function, called in case of serious system errors, sends a message to the registered hard error port. Hence, the CSRSS subsystem can pop up the message when application startup problems appear. The kernel houses only one set of global variables. These variables store the pointer to the hard error port so only one process can capture system errors. On Windows NT, this happens to be the Win32 subsystem. Calling this function requires special privilege.

Here, we present the pseudocode for this function:
NtSetDefaultHardErrorPort(HANDLE PortHandle)

{

if (PrivilegeNotHeld)

return STATUS_PRIVILEGE_NOT_HELD);

if (ExReadyForErrors == 0) {

Get a pointer to the kernel port object from

PortHandle;

ExpDefaultErrorPort =

pointer to kernel port object;

ExpDefaultErrorPortProcess = CurrentProcess;

ExReadyForErrors = 1;

} else {

return STATUS_UNSUCCESSFUL

}

return STATUS_SUCCESS;

}


Page: 1, 2, 3, 4, 5, 6

next page



Windows IT Pro Home Register FAQ for Windows WinInfo News
Europe Edition About Us Contact Us/Customer Service Media Kit Affiliates / Licensing  
SQL Server Magazine Office & SharePoint Pro Windows Dev Pro IT Job Hound ITTV
IT Library Technology Resource Directory Connected Home Windows Excavator Windows SuperSite 
 
 Windows IT Pro is a Division of Penton Media Inc.
 Copyright © 2008 Penton Media, Inc., All rights reserved. Terms and Use | Privacy Statement | Reprints and Licensing