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.

604 lines
18 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. dllinit.c
  5. Abstract:
  6. This module contains the initialization code for the Client-Server (CS)
  7. Client DLL.
  8. Author:
  9. Steve Wood (stevewo) 8-Oct-1990
  10. Environment:
  11. User Mode only
  12. Revision History:
  13. --*/
  14. #include "csrdll.h"
  15. #include "ldrp.h"
  16. BOOLEAN
  17. CsrDllInitialize(
  18. IN PVOID DllHandle,
  19. IN ULONG Reason,
  20. IN PCONTEXT Context OPTIONAL
  21. )
  22. /*++
  23. Routine Description:
  24. This function is the DLL initialization routine for the Client DLL
  25. This function gets control when the application links to this DLL
  26. are snapped.
  27. Arguments:
  28. Context - Supplies an optional context buffer that will be restore
  29. after all DLL initialization has been completed. If this
  30. parameter is NULL then this is a dynamic snap of this module.
  31. Otherwise this is a static snap prior to the user process
  32. gaining control.
  33. Return Value:
  34. Status value.
  35. --*/
  36. {
  37. Context;
  38. if (Reason != DLL_PROCESS_ATTACH) {
  39. return( TRUE );
  40. }
  41. //
  42. // Remember our DLL handle in a global variable.
  43. //
  44. CsrDllHandle = DllHandle;
  45. return( TRUE );
  46. }
  47. NTSTATUS
  48. CsrOneTimeInitialize( VOID )
  49. {
  50. NTSTATUS Status;
  51. //
  52. // Save away system information in a global variable
  53. //
  54. Status = NtQuerySystemInformation( SystemBasicInformation,
  55. &CsrNtSysInfo,
  56. sizeof( CsrNtSysInfo ),
  57. NULL
  58. );
  59. if (!NT_SUCCESS( Status )) {
  60. return( Status );
  61. }
  62. //
  63. // Use the process heap for memory allocation.
  64. //
  65. CsrHeap = RtlProcessHeap();
  66. CsrInitOnceDone = TRUE;
  67. return( STATUS_SUCCESS );
  68. }
  69. NTSTATUS
  70. CsrClientConnectToServer(
  71. IN PWSTR ObjectDirectory,
  72. IN ULONG ServerDllIndex,
  73. IN PCSR_CALLBACK_INFO CallbackInformation OPTIONAL,
  74. IN PVOID ConnectionInformation,
  75. IN OUT PULONG ConnectionInformationLength OPTIONAL,
  76. OUT PBOOLEAN CalledFromServer OPTIONAL
  77. )
  78. /*++
  79. Routine Description:
  80. This function is called by the client side DLL to connect with its
  81. server side DLL.
  82. Arguments:
  83. ObjectDirectory - Points to a null terminate string that is the same
  84. as the value of the ObjectDirectory= argument passed to the CSRSS
  85. program.
  86. ServerDllIndex - Index of the server DLL that is being connected to.
  87. It should match one of the ServerDll= arguments passed to the CSRSS
  88. program.
  89. CallbackInformation - An optional pointer to a structure that contains
  90. a pointer to the client callback function dispatch table.
  91. ConnectionInformation - An optional pointer to uninterpreted data.
  92. This data is intended for clients to pass package, version and
  93. protocol identification information to the server to allow the
  94. server to determine if it can satisify the client before
  95. accepting the connection. Upon return to the client, the
  96. ConnectionInformation data block contains any information passed
  97. back from the server DLL by its call to the
  98. CsrCompleteConnection call. The output data overwrites the
  99. input data.
  100. ConnectionInformationLength - Pointer to the length of the
  101. ConnectionInformation data block. The output value is the
  102. length of the data stored in the ConnectionInformation data
  103. block by the server's call to the NtCompleteConnectPort
  104. service. This parameter is OPTIONAL only if the
  105. ConnectionInformation parameter is NULL, otherwise it is
  106. required.
  107. CalledFromServer - On output, TRUE if the dll has been called from
  108. a server process.
  109. Return Value:
  110. Status value.
  111. --*/
  112. {
  113. NTSTATUS Status;
  114. CSR_API_MSG m;
  115. PCSR_CLIENTCONNECT_MSG a = &m.u.ClientConnect;
  116. PCSR_CAPTURE_HEADER CaptureBuffer;
  117. HANDLE CsrServerModuleHandle;
  118. STRING ProcedureName;
  119. ANSI_STRING DllName;
  120. UNICODE_STRING DllName_U;
  121. PIMAGE_NT_HEADERS NtHeaders;
  122. if (ARGUMENT_PRESENT( ConnectionInformation ) &&
  123. (!ARGUMENT_PRESENT( ConnectionInformationLength ) ||
  124. *ConnectionInformationLength == 0
  125. )
  126. ) {
  127. return( STATUS_INVALID_PARAMETER );
  128. }
  129. if (!CsrInitOnceDone) {
  130. Status = CsrOneTimeInitialize();
  131. if (!NT_SUCCESS( Status )) {
  132. return( Status );
  133. }
  134. }
  135. if (ARGUMENT_PRESENT( CallbackInformation )) {
  136. CsrLoadedClientDll[ ServerDllIndex ] = RtlAllocateHeap( CsrHeap, MAKE_TAG( CSR_TAG ), sizeof(CSR_CALLBACK_INFO) );
  137. CsrLoadedClientDll[ ServerDllIndex ]->ApiNumberBase =
  138. CallbackInformation->ApiNumberBase;
  139. CsrLoadedClientDll[ ServerDllIndex ]->MaxApiNumber =
  140. CallbackInformation->MaxApiNumber;
  141. CsrLoadedClientDll[ ServerDllIndex ]->CallbackDispatchTable =
  142. CallbackInformation->CallbackDispatchTable;
  143. }
  144. //
  145. // if we are being called by a server process, skip lpc port initialization
  146. // and call to server connect routine and just initialize heap. the
  147. // dll initialization routine will do any necessary initialization. this
  148. // stuff only needs to be done for the first connect.
  149. //
  150. if ( CsrServerProcess == TRUE ) {
  151. *CalledFromServer = CsrServerProcess;
  152. return STATUS_SUCCESS;
  153. }
  154. //
  155. // If the image is an NT Native image, we are running in the
  156. // context of the server.
  157. //
  158. NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
  159. CsrServerProcess =
  160. (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) ? TRUE : FALSE;
  161. if ( CsrServerProcess ) {
  162. extern PVOID NtDllBase;
  163. RtlInitAnsiString( &DllName, "csrsrv" );
  164. Status = RtlAnsiStringToUnicodeString(&DllName_U, &DllName, TRUE);
  165. ASSERT(NT_SUCCESS(Status));
  166. LdrDisableThreadCalloutsForDll(NtDllBase);
  167. Status = LdrGetDllHandle(
  168. UNICODE_NULL,
  169. NULL,
  170. &DllName_U,
  171. (PVOID *)&CsrServerModuleHandle
  172. );
  173. RtlFreeUnicodeString(&DllName_U);
  174. CsrServerProcess = TRUE;
  175. RtlInitString(&ProcedureName,"CsrCallServerFromServer");
  176. Status = LdrGetProcedureAddress(
  177. CsrServerModuleHandle,
  178. &ProcedureName,
  179. 0L,
  180. (PVOID *)&CsrServerApiRoutine
  181. );
  182. ASSERT(NT_SUCCESS(Status));
  183. RtlInitString(&ProcedureName, "CsrLocateThreadInProcess");
  184. Status = LdrGetProcedureAddress(
  185. CsrServerModuleHandle,
  186. &ProcedureName,
  187. 0L,
  188. (PVOID *)&CsrpLocateThreadInProcess
  189. );
  190. ASSERT(NT_SUCCESS(Status));
  191. ASSERT (CsrPortHeap==NULL);
  192. CsrPortHeap = RtlProcessHeap();
  193. CsrPortBaseTag = RtlCreateTagHeap( CsrPortHeap,
  194. 0,
  195. L"CSRPORT!",
  196. L"CAPTURE\0"
  197. );
  198. if (ARGUMENT_PRESENT(CalledFromServer)) {
  199. *CalledFromServer = CsrServerProcess;
  200. }
  201. return STATUS_SUCCESS;
  202. }
  203. if ( ARGUMENT_PRESENT(ConnectionInformation) ) {
  204. CsrServerProcess = FALSE;
  205. if (CsrPortHandle == NULL) {
  206. Status = CsrpConnectToServer( ObjectDirectory );
  207. if (!NT_SUCCESS( Status )) {
  208. return( Status );
  209. }
  210. }
  211. a->ServerDllIndex = ServerDllIndex;
  212. a->ConnectionInformationLength = *ConnectionInformationLength;
  213. if (ARGUMENT_PRESENT( ConnectionInformation )) {
  214. CaptureBuffer = CsrAllocateCaptureBuffer( 1,
  215. 0,
  216. a->ConnectionInformationLength
  217. );
  218. if (CaptureBuffer == NULL) {
  219. return( STATUS_NO_MEMORY );
  220. }
  221. CsrAllocateMessagePointer( CaptureBuffer,
  222. a->ConnectionInformationLength,
  223. (PVOID *)&a->ConnectionInformation
  224. );
  225. RtlMoveMemory( a->ConnectionInformation,
  226. ConnectionInformation,
  227. a->ConnectionInformationLength
  228. );
  229. *ConnectionInformationLength = a->ConnectionInformationLength;
  230. }
  231. else {
  232. CaptureBuffer = NULL;
  233. }
  234. Status = CsrClientCallServer( &m,
  235. CaptureBuffer,
  236. CSR_MAKE_API_NUMBER( CSRSRV_SERVERDLL_INDEX,
  237. CsrpClientConnect
  238. ),
  239. sizeof( *a )
  240. );
  241. if (CaptureBuffer != NULL) {
  242. if (ARGUMENT_PRESENT( ConnectionInformation )) {
  243. RtlMoveMemory( ConnectionInformation,
  244. a->ConnectionInformation,
  245. *ConnectionInformationLength
  246. );
  247. }
  248. CsrFreeCaptureBuffer( CaptureBuffer );
  249. }
  250. }
  251. else {
  252. Status = STATUS_SUCCESS;
  253. }
  254. if (ARGUMENT_PRESENT(CalledFromServer)) {
  255. *CalledFromServer = CsrServerProcess;
  256. }
  257. return( Status );
  258. }
  259. BOOLEAN
  260. xProtectHandle(
  261. HANDLE hObject
  262. )
  263. {
  264. NTSTATUS Status;
  265. OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
  266. Status = NtQueryObject( hObject,
  267. ObjectHandleFlagInformation,
  268. &HandleInfo,
  269. sizeof( HandleInfo ),
  270. NULL
  271. );
  272. if (NT_SUCCESS( Status )) {
  273. HandleInfo.ProtectFromClose = TRUE;
  274. Status = NtSetInformationObject( hObject,
  275. ObjectHandleFlagInformation,
  276. &HandleInfo,
  277. sizeof( HandleInfo )
  278. );
  279. if (NT_SUCCESS( Status )) {
  280. return TRUE;
  281. }
  282. }
  283. return FALSE;
  284. }
  285. NTSTATUS
  286. CsrpConnectToServer(
  287. IN PWSTR ObjectDirectory
  288. )
  289. {
  290. NTSTATUS Status;
  291. REMOTE_PORT_VIEW ServerView;
  292. ULONG MaxMessageLength;
  293. ULONG ConnectionInformationLength;
  294. CSR_API_CONNECTINFO ConnectionInformation;
  295. SECURITY_QUALITY_OF_SERVICE DynamicQos;
  296. HANDLE PortSection;
  297. PORT_VIEW ClientView;
  298. ULONG n;
  299. LARGE_INTEGER SectionSize;
  300. //
  301. // Create the port name string by combining the passed in object directory
  302. // name with the port name.
  303. //
  304. n = ((wcslen( ObjectDirectory ) + 1) * sizeof( WCHAR )) +
  305. sizeof( CSR_API_PORT_NAME );
  306. CsrPortName.Length = 0;
  307. CsrPortName.MaximumLength = (USHORT)n;
  308. CsrPortName.Buffer = RtlAllocateHeap( CsrHeap, MAKE_TAG( CSR_TAG ), n );
  309. if (CsrPortName.Buffer == NULL) {
  310. return( STATUS_NO_MEMORY );
  311. }
  312. RtlAppendUnicodeToString( &CsrPortName, ObjectDirectory );
  313. RtlAppendUnicodeToString( &CsrPortName, L"\\" );
  314. RtlAppendUnicodeToString( &CsrPortName, CSR_API_PORT_NAME );
  315. //
  316. // Set up the security quality of service parameters to use over the
  317. // port. Use the most efficient (least overhead) - which is dynamic
  318. // rather than static tracking.
  319. //
  320. DynamicQos.ImpersonationLevel = SecurityImpersonation;
  321. DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  322. DynamicQos.EffectiveOnly = TRUE;
  323. //
  324. // Create a section to contain the Port Memory. Port Memory is private
  325. // memory that is shared between the client and server processes.
  326. // This allows data that is too large to fit into an API request message
  327. // to be passed to the server.
  328. //
  329. SectionSize.LowPart = CSR_PORT_MEMORY_SIZE;
  330. SectionSize.HighPart = 0;
  331. Status = NtCreateSection( &PortSection,
  332. SECTION_ALL_ACCESS,
  333. NULL,
  334. &SectionSize,
  335. PAGE_READWRITE,
  336. SEC_RESERVE,
  337. NULL
  338. );
  339. if (!NT_SUCCESS( Status )) {
  340. return( Status );
  341. }
  342. //
  343. // Connect to the server. This includes a description of the Port Memory
  344. // section so that the LPC connection logic can make the section visible
  345. // to both the client and server processes. Also pass information the
  346. // server needs in the connection information structure.
  347. //
  348. ClientView.Length = sizeof( ClientView );
  349. ClientView.SectionHandle = PortSection;
  350. ClientView.SectionOffset = 0;
  351. ClientView.ViewSize = SectionSize.LowPart;
  352. ClientView.ViewBase = 0;
  353. ClientView.ViewRemoteBase = 0;
  354. ServerView.Length = sizeof( ServerView );
  355. ServerView.ViewSize = 0;
  356. ServerView.ViewBase = 0;
  357. ConnectionInformationLength = sizeof( ConnectionInformation );
  358. ConnectionInformation.ExpectedVersion = CSR_VERSION;
  359. Status = NtConnectPort( &CsrPortHandle,
  360. &CsrPortName,
  361. &DynamicQos,
  362. &ClientView,
  363. &ServerView,
  364. (PULONG)&MaxMessageLength,
  365. (PVOID)&ConnectionInformation,
  366. (PULONG)&ConnectionInformationLength
  367. );
  368. NtClose( PortSection );
  369. if (!NT_SUCCESS( Status )) {
  370. IF_DEBUG {
  371. DbgPrint( "CSRDLL: Unable to connect to %wZ Server - Status == %X\n",
  372. &CsrPortName,
  373. Status
  374. );
  375. }
  376. return( Status );
  377. }
  378. xProtectHandle(CsrPortHandle);
  379. NtCurrentPeb()->ReadOnlySharedMemoryBase = ConnectionInformation.SharedSectionBase;
  380. NtCurrentPeb()->ReadOnlySharedMemoryHeap = ConnectionInformation.SharedSectionHeap;
  381. NtCurrentPeb()->ReadOnlyStaticServerData = (PVOID *)ConnectionInformation.SharedStaticServerData;
  382. #if DBG
  383. CsrDebug = ConnectionInformation.DebugFlags;
  384. #endif
  385. CsrObjectDirectory = ConnectionInformation.ObjectDirectory;
  386. CsrPortMemoryRemoteDelta = (ULONG)ClientView.ViewRemoteBase -
  387. (ULONG)ClientView.ViewBase;
  388. IF_CSR_DEBUG( LPC ) {
  389. DbgPrint( "CSRDLL: ClientView: Base=%lX RemoteBase=%lX Delta: %lX Size=%lX\n",
  390. (ULONG)ClientView.ViewBase,
  391. (ULONG)ClientView.ViewRemoteBase,
  392. CsrPortMemoryRemoteDelta,
  393. (ULONG)ClientView.ViewSize
  394. );
  395. }
  396. //
  397. // Create a sparse heap in the share memory section. Initially
  398. // commit just one page.
  399. //
  400. CsrPortHeap = RtlCreateHeap( HEAP_CLASS_8, // Flags
  401. ClientView.ViewBase, // HeapBase
  402. ClientView.ViewSize, // ReserveSize
  403. CsrNtSysInfo.PageSize, // CommitSize
  404. 0, // Reserved
  405. 0 // GrowthThreshold
  406. );
  407. if (CsrPortHeap == NULL) {
  408. NtClose( CsrPortHandle );
  409. CsrPortHandle = NULL;
  410. return( STATUS_NO_MEMORY );
  411. }
  412. CsrPortBaseTag = RtlCreateTagHeap( CsrPortHeap,
  413. 0,
  414. L"CSRPORT!",
  415. L"!CSRPORT\0"
  416. L"CAPTURE\0"
  417. );
  418. return( STATUS_SUCCESS );
  419. }
  420. ULONG
  421. CsrNullApiCall(
  422. IN LONG CountArguments,
  423. IN PCHAR *Arguments OPTIONAL
  424. )
  425. /*++
  426. Routine Description:
  427. This function is present to test the overhead associated with
  428. communicating with the OS/2 Subsystem.
  429. Arguments:
  430. CountArguments - Number of string arguments to pass to the server
  431. via Port Memory.
  432. Arguments - Optional pointer to an array of ASCIZ string pointers.
  433. Return Value:
  434. Random 32-bit number
  435. --*/
  436. {
  437. CSR_API_MSG m;
  438. PCSR_NULLAPICALL_MSG a = &m.u.NullApiCall;
  439. PCSR_CAPTURE_HEADER CaptureBuffer;
  440. ULONG Size;
  441. LONG i;
  442. a->CountArguments = CountArguments;
  443. if (CountArguments > 0) {
  444. Size = CountArguments * sizeof( PCHAR );
  445. for (i=0; i<CountArguments; i++) {
  446. Size += (strlen( Arguments[ i ] ) + 1) & ~3;
  447. }
  448. CaptureBuffer = CsrAllocateCaptureBuffer( 1,
  449. CountArguments,
  450. Size
  451. );
  452. CsrAllocateMessagePointer( CaptureBuffer,
  453. CountArguments * sizeof( PCHAR ),
  454. (PVOID *)&a->Arguments
  455. );
  456. for (i=0; i<CountArguments; i++) {
  457. Size = strlen( Arguments[ i ] ) + 1;
  458. CsrAllocateCapturePointer( CaptureBuffer,
  459. Size,
  460. (PVOID *)&a->Arguments[ i ]
  461. );
  462. RtlMoveMemory( a->Arguments[ i ], Arguments[ i ], Size );
  463. }
  464. }
  465. else {
  466. CaptureBuffer = NULL;
  467. CountArguments = -CountArguments;
  468. ASSERT(sizeof(ULONG) == sizeof(PVOID));
  469. for (i=0; i<CountArguments; i++) {
  470. a->FastArguments[ i ] = (ULONG)Arguments[ i ];
  471. }
  472. }
  473. CsrClientCallServer( &m,
  474. CaptureBuffer,
  475. CSR_MAKE_API_NUMBER( CSRSRV_SERVERDLL_INDEX,
  476. CsrpNullApiCall
  477. ),
  478. sizeof( *a )
  479. );
  480. if (CaptureBuffer != NULL) {
  481. CsrFreeCaptureBuffer( CaptureBuffer );
  482. }
  483. return( (NTSTATUS) m.ReturnValue );
  484. }