Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

lpccreat.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 lpccreat.c 00008 00009 Abstract: 00010 00011 Local Inter-Process Communication (LPC) connection system services. 00012 00013 Author: 00014 00015 Steve Wood (stevewo) 15-May-1989 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "lpcp.h" 00022 00023 // 00024 // Local procedure prototype 00025 // 00026 00027 NTSTATUS 00028 LpcpCreatePort ( 00029 OUT PHANDLE PortHandle, 00030 IN POBJECT_ATTRIBUTES ObjectAttributes, 00031 IN ULONG MaxConnectionInfoLength, 00032 IN ULONG MaxMessageLength, 00033 IN ULONG MaxPoolUsage, 00034 IN BOOLEAN Waitable 00035 ); 00036 00037 #ifdef ALLOC_PRAGMA 00038 #pragma alloc_text(PAGE,NtCreatePort) 00039 #pragma alloc_text(PAGE,NtCreateWaitablePort) 00040 #pragma alloc_text(PAGE,LpcpCreatePort) 00041 #endif 00042 00043 00044 NTSTATUS 00045 NtCreatePort ( 00046 OUT PHANDLE PortHandle, 00047 IN POBJECT_ATTRIBUTES ObjectAttributes, 00048 IN ULONG MaxConnectionInfoLength, 00049 IN ULONG MaxMessageLength, 00050 IN ULONG MaxPoolUsage 00051 ) 00052 00053 /*++ 00054 00055 Routine Description: 00056 00057 See LpcpCreatePort. 00058 00059 Arguments: 00060 00061 See LpcpCreatePort. 00062 00063 Return Value: 00064 00065 NTSTATUS - An appropriate status value 00066 00067 --*/ 00068 00069 { 00070 NTSTATUS Status; 00071 00072 PAGED_CODE(); 00073 00074 Status = LpcpCreatePort( PortHandle, 00075 ObjectAttributes, 00076 MaxConnectionInfoLength, 00077 MaxMessageLength, 00078 MaxPoolUsage, 00079 FALSE ); 00080 00081 return Status ; 00082 00083 } 00084 00085 00086 NTSTATUS 00087 NtCreateWaitablePort ( 00088 OUT PHANDLE PortHandle, 00089 IN POBJECT_ATTRIBUTES ObjectAttributes, 00090 IN ULONG MaxConnectionInfoLength, 00091 IN ULONG MaxMessageLength, 00092 IN ULONG MaxPoolUsage 00093 ) 00094 00095 /*++ 00096 00097 Routine Description: 00098 00099 Same as NtCreatePort. 00100 00101 The only difference between this call and NtCreatePort is that the 00102 working KEVENT that can be used to wait for LPC messages to arrive 00103 asynchronously. 00104 00105 Arguments: 00106 00107 See LpcpCreatePort. 00108 00109 Return Value: 00110 00111 NTSTATUS - An appropriate status value 00112 00113 --*/ 00114 00115 { 00116 NTSTATUS Status ; 00117 00118 PAGED_CODE(); 00119 00120 Status = LpcpCreatePort( PortHandle, 00121 ObjectAttributes, 00122 MaxConnectionInfoLength, 00123 MaxMessageLength, 00124 MaxPoolUsage, 00125 TRUE ); 00126 00127 return Status ; 00128 } 00129 00130 00131 // 00132 // Local support routine 00133 // 00134 00135 NTSTATUS 00136 LpcpCreatePort ( 00137 OUT PHANDLE PortHandle, 00138 IN POBJECT_ATTRIBUTES ObjectAttributes, 00139 IN ULONG MaxConnectionInfoLength, 00140 IN ULONG MaxMessageLength, 00141 IN ULONG MaxPoolUsage, 00142 IN BOOLEAN Waitable 00143 ) 00144 00145 /*++ 00146 00147 Routine Description: 00148 00149 A server process can create a named connection port with the NtCreatePort 00150 service. 00151 00152 A connection port is created with the name and SECURITY_DESCRIPTOR 00153 specified in the ObjectAttributes structure. A handle to the connection 00154 port object is returned in the location pointed to by the PortHandle 00155 parameter. The returned handle can then be used to listen for connection 00156 requests to that port name, using the NtListenPort service. 00157 00158 The standard object architecture defined desired access parameter is not 00159 necessary since this service can only create a new port, not access an 00160 existing port. 00161 00162 Connection ports cannot be used to send and receive messages. They are 00163 only valid as a parameter to the NtListenPort service. 00164 00165 Arguments: 00166 00167 PortHandle - A pointer to a variable that will receive the connection port 00168 object handle value. 00169 00170 ObjectAttributes - A pointer to a structure that specifies the name of the 00171 object, an access control list (SECURITY_DESCRIPTOR) to be applied to 00172 the object, and a set of object attribute flags. 00173 00174 PUNICODE_STRING ObjectName - An optional pointer to a null terminated 00175 port name string. The form of the name is 00176 [\name...\name]\port_name. If no name is specified then an 00177 unconnected communication port is created rather than a connection 00178 port. This is useful for sending and receiving messages between 00179 threads of a single process. 00180 00181 ULONG Attributes - A set of flags that control the port object 00182 attributes. 00183 00184 None of the standard values are relevant for this call. 00185 Connection ports cannot be inherited, are always placed in the 00186 system handle table and are exclusive to the creating process. 00187 This field must be zero. Future implementations might support 00188 specifying the OBJ_PERMANENT attribute. 00189 00190 MaxMessageLength - Specifies the maximum length of messages sent or 00191 received on communication ports created from this connection 00192 port. The value of this parameter cannot exceed 00193 MAX_PORTMSG_LENGTH bytes. 00194 00195 MaxPoolUsage - Specifies the maximum amount of NonPaged pool used for 00196 message storage. 00197 00198 Waitable - Specifies if the event used by the port can be use to wait 00199 for LPC messages to arrive asynchronously. 00200 00201 Return Value: 00202 00203 NTSTATUS - An appropriate status value 00204 00205 --*/ 00206 00207 { 00208 PLPCP_PORT_OBJECT ConnectionPort; 00209 HANDLE Handle; 00210 KPROCESSOR_MODE PreviousMode; 00211 NTSTATUS Status; 00212 PUNICODE_STRING NamePtr; 00213 UNICODE_STRING CapturedObjectName; 00214 00215 PAGED_CODE(); 00216 00217 // 00218 // Get previous processor mode and probe output arguments if necessary. 00219 // 00220 00221 PreviousMode = KeGetPreviousMode(); 00222 RtlInitUnicodeString( &CapturedObjectName, NULL ); 00223 00224 if (PreviousMode != KernelMode) { 00225 00226 try { 00227 00228 ProbeForWriteHandle( PortHandle ); 00229 00230 ProbeForRead( ObjectAttributes, 00231 sizeof( OBJECT_ATTRIBUTES ), 00232 sizeof( ULONG )); 00233 00234 NamePtr = ObjectAttributes->ObjectName; 00235 00236 if (NamePtr != NULL) { 00237 00238 CapturedObjectName = ProbeAndReadStructure( NamePtr, 00239 UNICODE_STRING ); 00240 } 00241 00242 } except( EXCEPTION_EXECUTE_HANDLER ) { 00243 00244 return( GetExceptionCode() ); 00245 } 00246 00247 } else { 00248 00249 if (ObjectAttributes->ObjectName != NULL) { 00250 00251 CapturedObjectName = *(ObjectAttributes->ObjectName); 00252 } 00253 } 00254 00255 // 00256 // Make the null buffer indicate an unspecified port name 00257 // 00258 00259 if (CapturedObjectName.Length == 0) { 00260 00261 CapturedObjectName.Buffer = NULL; 00262 } 00263 00264 // 00265 // Allocate and initialize a port object. If an object name was 00266 // specified, then this is a connection port. Otherwise this is an 00267 // unconnected communication port that a process can use to communicate 00268 // between threads. 00269 // 00270 00271 Status = ObCreateObject( PreviousMode, 00272 (Waitable ? LpcWaitablePortObjectType 00273 : LpcPortObjectType), 00274 ObjectAttributes, 00275 PreviousMode, 00276 NULL, 00277 (ULONG)sizeof( LPCP_PORT_OBJECT ), 00278 0, 00279 0, 00280 (PVOID *)&ConnectionPort ); 00281 00282 if (!NT_SUCCESS( Status )) { 00283 00284 return( Status ); 00285 } 00286 00287 // 00288 // Zero out the connection port object and then initialize its fields 00289 // 00290 00291 RtlZeroMemory( ConnectionPort, (ULONG)sizeof( LPCP_PORT_OBJECT )); 00292 00293 ConnectionPort->Length = sizeof( LPCP_PORT_OBJECT ); 00294 ConnectionPort->ConnectionPort = ConnectionPort; 00295 ConnectionPort->Creator = PsGetCurrentThread()->Cid; 00296 00297 InitializeListHead( &ConnectionPort->LpcReplyChainHead ); 00298 00299 InitializeListHead( &ConnectionPort->LpcDataInfoChainHead ); 00300 00301 // 00302 // Named ports get a connection message queue. 00303 // 00304 00305 if (CapturedObjectName.Buffer == NULL) { 00306 00307 ConnectionPort->Flags = UNCONNECTED_COMMUNICATION_PORT; 00308 ConnectionPort->ConnectedPort = ConnectionPort; 00309 ConnectionPort->ServerProcess = NULL; 00310 00311 } else { 00312 00313 ConnectionPort->Flags = SERVER_CONNECTION_PORT; 00314 00315 ObReferenceObject( PsGetCurrentProcess() ); 00316 ConnectionPort->ServerProcess = PsGetCurrentProcess(); 00317 } 00318 00319 if ( Waitable ) { 00320 00321 ConnectionPort->Flags |= PORT_WAITABLE; 00322 } 00323 00324 // 00325 // All ports get a request message queue. 00326 // 00327 00328 Status = LpcpInitializePortQueue( ConnectionPort ); 00329 00330 if (!NT_SUCCESS(Status)) { 00331 00332 ObDereferenceObject( ConnectionPort ); 00333 00334 return(Status); 00335 } 00336 00337 // 00338 // For a waitable port, create the KEVENT that will 00339 // be used to signal clients 00340 // 00341 00342 if (ConnectionPort->Flags & PORT_WAITABLE) { 00343 00344 KeInitializeEvent( &ConnectionPort->WaitEvent, 00345 NotificationEvent, 00346 FALSE ); 00347 } 00348 00349 // 00350 // Set the maximum message length and connection info length based on the 00351 // zone block size less the structs overhead. 00352 // 00353 00354 ConnectionPort->MaxMessageLength = LpcpZone.Zone.BlockSize - 00355 FIELD_OFFSET( LPCP_MESSAGE, Request ); 00356 00357 ConnectionPort->MaxConnectionInfoLength = ConnectionPort->MaxMessageLength - 00358 sizeof( PORT_MESSAGE ) - 00359 sizeof( LPCP_CONNECTION_MESSAGE ); 00360 00361 #if DBG 00362 LpcpTrace(( "Created port %ws (%x) - MaxMsgLen == %x MaxConnectInfoLen == %x\n", 00363 CapturedObjectName.Buffer == NULL ? L"** UnNamed **" : ObjectAttributes->ObjectName->Buffer, 00364 ConnectionPort, 00365 ConnectionPort->MaxMessageLength, 00366 ConnectionPort->MaxConnectionInfoLength )); 00367 #endif 00368 00369 // 00370 // Sanity check that the max message length being asked for is not 00371 // greater than the max message length possible in the system 00372 // 00373 00374 if (ConnectionPort->MaxMessageLength < MaxMessageLength) { 00375 00376 #if DBG 00377 LpcpPrint(( "MaxMessageLength granted is %x but requested %x\n", 00378 ConnectionPort->MaxMessageLength, 00379 MaxMessageLength )); 00380 DbgBreakPoint(); 00381 #endif 00382 00383 ObDereferenceObject( ConnectionPort ); 00384 00385 return STATUS_INVALID_PARAMETER_4; 00386 } 00387 00388 // 00389 // Save the MaxMessageLength to the connection port 00390 // 00391 00392 ConnectionPort->MaxMessageLength = MaxMessageLength; 00393 00394 // 00395 // Sanity check that the max connection info length being asked for is 00396 // not greater than the maximum possible in the system 00397 // 00398 00399 if (ConnectionPort->MaxConnectionInfoLength < MaxConnectionInfoLength) { 00400 00401 #if DBG 00402 LpcpPrint(( "MaxConnectionInfoLength granted is %x but requested %x\n", 00403 ConnectionPort->MaxConnectionInfoLength, 00404 MaxConnectionInfoLength )); 00405 DbgBreakPoint(); 00406 #endif 00407 00408 ObDereferenceObject( ConnectionPort ); 00409 00410 return STATUS_INVALID_PARAMETER_3; 00411 } 00412 00413 // 00414 // Insert connection port object in specified object table. Set port 00415 // handle value if successful. If not successful, then the port will 00416 // have been dereferenced, which will cause it to be freed, after our 00417 // delete procedure is called. The delete procedure will undo the work 00418 // done to initialize the port. Finally, return the system server status. 00419 // 00420 00421 Status = ObInsertObject( ConnectionPort, 00422 NULL, 00423 PORT_ALL_ACCESS, 00424 0, 00425 (PVOID *)NULL, 00426 &Handle ); 00427 00428 if (NT_SUCCESS( Status )) { 00429 00430 // 00431 // Set the output variable protected against access faults 00432 // 00433 00434 try { 00435 00436 *PortHandle = Handle; 00437 00438 } except( EXCEPTION_EXECUTE_HANDLER ) { 00439 00440 NtClose( Handle ); 00441 00442 Status = GetExceptionCode(); 00443 } 00444 } 00445 00446 // 00447 // And return to our caller 00448 // 00449 00450 return Status; 00451 } 00452 00453

Generated on Sat May 15 19:40:39 2004 for test by doxygen 1.3.7