Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

264 lines
8.2 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. lpccreat.c
  5. Abstract:
  6. Local Inter-Process Communication (LPC) connection system services.
  7. Author:
  8. Steve Wood (stevewo) 15-May-1989
  9. Revision History:
  10. --*/
  11. #include "lpcp.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE,NtCreatePort)
  14. #endif
  15. NTSTATUS
  16. NtCreatePort(
  17. OUT PHANDLE PortHandle,
  18. IN POBJECT_ATTRIBUTES ObjectAttributes,
  19. IN ULONG MaxConnectionInfoLength,
  20. IN ULONG MaxMessageLength,
  21. IN ULONG MaxPoolUsage
  22. )
  23. /*++
  24. Routine Description:
  25. A server process can create a named connection port with the
  26. NtCreatePort service.
  27. A connection port is created with the name and SECURITY_DESCRIPTOR specified in the
  28. ObjectAttributes structure. A handle to the connection port object
  29. is returned in the location pointed to by the PortHandle parameter.
  30. The returned handle can then be used to listen for connection
  31. requests to that port name, using the NtListenPort service.
  32. The standard object architecture defined desired access parameter is
  33. not necessary since this service can only create a new port, not
  34. access an existing port.
  35. Connection ports cannot be used to send and receive messages. They
  36. are only valid as a parameter to the NtListenPort service.
  37. Arguments:
  38. PortHandle - A pointer to a variable that will receive the
  39. connection port object handle value.
  40. ObjectAttributes - A pointer to a structure that specifies the
  41. name of the object, an access control list (SECURITY_DESCRIPTOR) to be applied
  42. to the object, and a set of object attribute flags.
  43. !b !u ObjectAttributes Structure
  44. PSTRING !f ObjectName - An optional pointer to a null terminated
  45. port name string. The form of the name is
  46. [\name...\name]\port_name. If no name is specified
  47. then an unconnected communication port is created rather
  48. than a connection port. This is useful for sending and
  49. receiving messages between threads of a single process.
  50. PSECURITY_DESCRIPTOR !f AccessControlList - An optional pointer to an SECURITY_DESCRIPTOR.
  51. If an SECURITY_DESCRIPTOR is specified then it will be used to control
  52. access to the port object. If no SECURITY_DESCRIPTOR is specified, then
  53. any process will be allowed to access the port.
  54. ULONG !f Attributes - A set of flags that control the port
  55. object attributes.
  56. !_ None of the standard values are relevant for this call. !_-
  57. Connection ports cannot be inherited, are always placed in
  58. the system handle table and are exclusive to the creating
  59. process. This field must be zero. Future implementations
  60. might support specifying the !c OBJ_PERMANENT attribute.
  61. MaxMessageLength - Specifies the maximum length of messages sent or
  62. received on communication ports created from this connection
  63. port. The value of this parameter cannot exceed
  64. MAX_PORTMSG_LENGTH bytes.
  65. MaxPoolUsage - Specifies the maximum amount of NonPaged pool used for
  66. message storage.
  67. Return Value:
  68. return-value - Description of conditions needed to return value. - or -
  69. None.
  70. --*/
  71. {
  72. PLPCP_PORT_OBJECT ConnectionPort;
  73. HANDLE Handle;
  74. KPROCESSOR_MODE PreviousMode;
  75. NTSTATUS Status;
  76. BOOLEAN UnNamedPort;
  77. PAGED_CODE();
  78. //
  79. // Get previous processor mode and probe output arguments if necessary.
  80. //
  81. PreviousMode = KeGetPreviousMode();
  82. UnNamedPort = FALSE;
  83. if (PreviousMode != KernelMode) {
  84. try {
  85. ProbeForWriteHandle( PortHandle );
  86. if (ObjectAttributes->ObjectName == NULL ||
  87. ObjectAttributes->ObjectName->Length == 0 ||
  88. ObjectAttributes->ObjectName->Buffer == NULL
  89. ) {
  90. UnNamedPort = TRUE;
  91. }
  92. }
  93. except( EXCEPTION_EXECUTE_HANDLER ) {
  94. return( GetExceptionCode() );
  95. }
  96. }
  97. else {
  98. if (ObjectAttributes->ObjectName == NULL ||
  99. ObjectAttributes->ObjectName->Length == 0 ||
  100. ObjectAttributes->ObjectName->Buffer == NULL
  101. ) {
  102. UnNamedPort = TRUE;
  103. }
  104. }
  105. //
  106. // Allocate and initialize a port object. If an object name was
  107. // specified, then this is a connection port. Otherwise this is an
  108. // unconnected communication port that a process can use to communicate
  109. // between threads.
  110. //
  111. Status = ObCreateObject( PreviousMode,
  112. LpcPortObjectType,
  113. ObjectAttributes,
  114. PreviousMode,
  115. NULL,
  116. (ULONG)sizeof( LPCP_PORT_OBJECT ),
  117. 0,
  118. 0,
  119. (PVOID *)&ConnectionPort
  120. );
  121. if (!NT_SUCCESS( Status )) {
  122. return( Status );
  123. }
  124. RtlZeroMemory( ConnectionPort, (ULONG)sizeof( LPCP_PORT_OBJECT ) );
  125. ConnectionPort->Length = sizeof( LPCP_PORT_OBJECT );
  126. ConnectionPort->ConnectionPort = ConnectionPort;
  127. ConnectionPort->Creator = PsGetCurrentThread()->Cid;
  128. InitializeListHead( &ConnectionPort->LpcReplyChainHead );
  129. InitializeListHead( &ConnectionPort->LpcDataInfoChainHead );
  130. //
  131. // Named ports get a connection message queue.
  132. //
  133. if (UnNamedPort) {
  134. ConnectionPort->Flags = UNCONNECTED_COMMUNICATION_PORT;
  135. ConnectionPort->ConnectedPort = ConnectionPort;
  136. }
  137. else {
  138. ConnectionPort->Flags = SERVER_CONNECTION_PORT;
  139. }
  140. //
  141. // All ports get a request message queue.
  142. //
  143. Status = LpcpInitializePortQueue( ConnectionPort );
  144. if (!NT_SUCCESS(Status)) {
  145. ObDereferenceObject( ConnectionPort );
  146. return(Status);
  147. }
  148. //
  149. // Initialize the port zone
  150. //
  151. ConnectionPort->MaxMessageLength =
  152. LpcpZone.Zone.BlockSize - FIELD_OFFSET( LPCP_MESSAGE, Request );
  153. ConnectionPort->MaxConnectionInfoLength =
  154. ConnectionPort->MaxMessageLength -
  155. sizeof( PORT_MESSAGE ) -
  156. sizeof( LPCP_CONNECTION_MESSAGE );
  157. #if DBG
  158. LpcpTrace(( "Created port %ws (%x) - MaxMsgLen == %x MaxConnectInfoLen == %x\n",
  159. UnNamedPort ? L"** UnNamed **" : ObjectAttributes->ObjectName->Buffer,
  160. ConnectionPort,
  161. ConnectionPort->MaxMessageLength,
  162. ConnectionPort->MaxConnectionInfoLength
  163. ));
  164. #endif
  165. if (ConnectionPort->MaxMessageLength < MaxMessageLength) {
  166. #if DBG
  167. LpcpPrint(( "MaxMessageLength granted is %x but requested %x\n",
  168. ConnectionPort->MaxMessageLength,
  169. MaxMessageLength
  170. ));
  171. DbgBreakPoint();
  172. #endif
  173. ObDereferenceObject( ConnectionPort );
  174. return STATUS_INVALID_PARAMETER_4;
  175. }
  176. if (ConnectionPort->MaxConnectionInfoLength < MaxConnectionInfoLength) {
  177. #if DBG
  178. LpcpPrint(( "MaxConnectionInfoLength granted is %x but requested %x\n",
  179. ConnectionPort->MaxConnectionInfoLength,
  180. MaxConnectionInfoLength
  181. ));
  182. DbgBreakPoint();
  183. #endif
  184. ObDereferenceObject( ConnectionPort );
  185. return STATUS_INVALID_PARAMETER_3;
  186. }
  187. //
  188. // Insert connection port object in specified object table. Set port
  189. // handle value if successful. If not successful, then the port will
  190. // have been dereferenced, which will cause it to be freed, after our
  191. // delete procedure is called. The delete procedure will undo the work
  192. // done to initialize the port. Finally, return the system server status.
  193. //
  194. Status = ObInsertObject( ConnectionPort,
  195. NULL,
  196. PORT_ALL_ACCESS,
  197. 0,
  198. (PVOID *)NULL,
  199. &Handle
  200. );
  201. if (NT_SUCCESS( Status )) {
  202. try {
  203. *PortHandle = Handle;
  204. }
  205. except( EXCEPTION_EXECUTE_HANDLER ) {
  206. NtClose( Handle );
  207. Status = GetExceptionCode();
  208. }
  209. }
  210. return( Status );
  211. }