00147 :
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
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
00257
00258
00259
if (CapturedObjectName.Length == 0) {
00260
00261 CapturedObjectName.Buffer =
NULL;
00262 }
00263
00264
00265
00266
00267
00268
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
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
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
00326
00327
00328
Status =
LpcpInitializePortQueue( ConnectionPort );
00329
00330
if (!
NT_SUCCESS(Status)) {
00331
00332
ObDereferenceObject( ConnectionPort );
00333
00334
return(
Status);
00335 }
00336
00337
00338
00339
00340
00341
00342
if (ConnectionPort->
Flags &
PORT_WAITABLE) {
00343
00344
KeInitializeEvent( &ConnectionPort->
WaitEvent,
00345 NotificationEvent,
00346 FALSE );
00347 }
00348
00349
00350
00351
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
00371
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
00390
00391
00392 ConnectionPort->
MaxMessageLength = MaxMessageLength;
00393
00394
00395
00396
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
00415
00416
00417
00418
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
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
00448
00449
00450
return Status;
00451 }