Source code of Windows XP (NT5)
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.

548 lines
16 KiB

  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 PVOID ConnectionInformation,
  74. IN OUT PULONG ConnectionInformationLength OPTIONAL,
  75. OUT PBOOLEAN CalledFromServer OPTIONAL
  76. )
  77. /*++
  78. Routine Description:
  79. This function is called by the client side DLL to connect with its
  80. server side DLL.
  81. Arguments:
  82. ObjectDirectory - Points to a null terminate string that is the same
  83. as the value of the ObjectDirectory= argument passed to the CSRSS
  84. program.
  85. ServerDllIndex - Index of the server DLL that is being connected to.
  86. It should match one of the ServerDll= arguments passed to the CSRSS
  87. program.
  88. ConnectionInformation - An optional pointer to uninterpreted data.
  89. This data is intended for clients to pass package, version and
  90. protocol identification information to the server to allow the
  91. server to determine if it can satisify the client before
  92. accepting the connection. Upon return to the client, the
  93. ConnectionInformation data block contains any information passed
  94. back from the server DLL by its call to the
  95. CsrCompleteConnection call. The output data overwrites the
  96. input data.
  97. ConnectionInformationLength - Pointer to the length of the
  98. ConnectionInformation data block. The output value is the
  99. length of the data stored in the ConnectionInformation data
  100. block by the server's call to the NtCompleteConnectPort
  101. service. This parameter is OPTIONAL only if the
  102. ConnectionInformation parameter is NULL, otherwise it is
  103. required.
  104. CalledFromServer - On output, TRUE if the dll has been called from
  105. a server process.
  106. Return Value:
  107. Status value.
  108. --*/
  109. {
  110. NTSTATUS Status;
  111. CSR_API_MSG m;
  112. PCSR_CLIENTCONNECT_MSG a = &m.u.ClientConnect;
  113. PCSR_CAPTURE_HEADER CaptureBuffer;
  114. HANDLE CsrServerModuleHandle;
  115. STRING ProcedureName;
  116. ANSI_STRING DllName;
  117. UNICODE_STRING DllName_U;
  118. PIMAGE_NT_HEADERS NtHeaders;
  119. if (ARGUMENT_PRESENT( ConnectionInformation ) &&
  120. (!ARGUMENT_PRESENT( ConnectionInformationLength ) ||
  121. *ConnectionInformationLength == 0
  122. )
  123. ) {
  124. return( STATUS_INVALID_PARAMETER );
  125. }
  126. if (!CsrInitOnceDone) {
  127. Status = CsrOneTimeInitialize();
  128. if (!NT_SUCCESS( Status )) {
  129. return( Status );
  130. }
  131. }
  132. //
  133. // if we are being called by a server process, skip lpc port initialization
  134. // and call to server connect routine and just initialize heap. the
  135. // dll initialization routine will do any necessary initialization. this
  136. // stuff only needs to be done for the first connect.
  137. //
  138. if ( CsrServerProcess == TRUE ) {
  139. *CalledFromServer = CsrServerProcess;
  140. return STATUS_SUCCESS;
  141. }
  142. //
  143. // If the image is an NT Native image, we are running in the
  144. // context of the server.
  145. //
  146. NtHeaders = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
  147. if (! NtHeaders) {
  148. return STATUS_INVALID_IMAGE_FORMAT;
  149. }
  150. CsrServerProcess =
  151. (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) ? TRUE : FALSE;
  152. if ( CsrServerProcess ) {
  153. extern PVOID NtDllBase;
  154. RtlInitAnsiString( &DllName, "csrsrv" );
  155. Status = RtlAnsiStringToUnicodeString(&DllName_U, &DllName, TRUE);
  156. ASSERT(NT_SUCCESS(Status));
  157. LdrDisableThreadCalloutsForDll(NtDllBase);
  158. Status = LdrGetDllHandle(
  159. UNICODE_NULL,
  160. NULL,
  161. &DllName_U,
  162. (PVOID *)&CsrServerModuleHandle
  163. );
  164. RtlFreeUnicodeString(&DllName_U);
  165. CsrServerProcess = TRUE;
  166. RtlInitString(&ProcedureName,"CsrCallServerFromServer");
  167. Status = LdrGetProcedureAddress(
  168. CsrServerModuleHandle,
  169. &ProcedureName,
  170. 0L,
  171. (PVOID *)&CsrServerApiRoutine
  172. );
  173. ASSERT(NT_SUCCESS(Status));
  174. ASSERT (CsrPortHeap==NULL);
  175. CsrPortHeap = RtlProcessHeap();
  176. CsrPortBaseTag = RtlCreateTagHeap( CsrPortHeap,
  177. 0,
  178. L"CSRPORT!",
  179. L"CAPTURE\0"
  180. );
  181. if (ARGUMENT_PRESENT(CalledFromServer)) {
  182. *CalledFromServer = CsrServerProcess;
  183. }
  184. return STATUS_SUCCESS;
  185. }
  186. if ( ARGUMENT_PRESENT(ConnectionInformation) ) {
  187. CsrServerProcess = FALSE;
  188. if (CsrPortHandle == NULL) {
  189. Status = CsrpConnectToServer( ObjectDirectory );
  190. if (!NT_SUCCESS( Status )) {
  191. return( Status );
  192. }
  193. }
  194. a->ServerDllIndex = ServerDllIndex;
  195. a->ConnectionInformationLength = *ConnectionInformationLength;
  196. if (ARGUMENT_PRESENT( ConnectionInformation )) {
  197. CaptureBuffer = CsrAllocateCaptureBuffer( 1,
  198. a->ConnectionInformationLength
  199. );
  200. if (CaptureBuffer == NULL) {
  201. return( STATUS_NO_MEMORY );
  202. }
  203. CsrAllocateMessagePointer( CaptureBuffer,
  204. a->ConnectionInformationLength,
  205. (PVOID *)&a->ConnectionInformation
  206. );
  207. RtlMoveMemory( a->ConnectionInformation,
  208. ConnectionInformation,
  209. a->ConnectionInformationLength
  210. );
  211. *ConnectionInformationLength = a->ConnectionInformationLength;
  212. }
  213. else {
  214. CaptureBuffer = NULL;
  215. }
  216. Status = CsrClientCallServer( &m,
  217. CaptureBuffer,
  218. CSR_MAKE_API_NUMBER( CSRSRV_SERVERDLL_INDEX,
  219. CsrpClientConnect
  220. ),
  221. sizeof( *a )
  222. );
  223. if (CaptureBuffer != NULL) {
  224. if (ARGUMENT_PRESENT( ConnectionInformation )) {
  225. RtlMoveMemory( ConnectionInformation,
  226. a->ConnectionInformation,
  227. *ConnectionInformationLength
  228. );
  229. }
  230. CsrFreeCaptureBuffer( CaptureBuffer );
  231. }
  232. }
  233. else {
  234. Status = STATUS_SUCCESS;
  235. }
  236. if (ARGUMENT_PRESENT(CalledFromServer)) {
  237. *CalledFromServer = CsrServerProcess;
  238. }
  239. return( Status );
  240. }
  241. BOOLEAN
  242. xProtectHandle(
  243. HANDLE hObject
  244. )
  245. {
  246. NTSTATUS Status;
  247. OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
  248. Status = NtQueryObject( hObject,
  249. ObjectHandleFlagInformation,
  250. &HandleInfo,
  251. sizeof( HandleInfo ),
  252. NULL
  253. );
  254. if (NT_SUCCESS( Status )) {
  255. HandleInfo.ProtectFromClose = TRUE;
  256. Status = NtSetInformationObject( hObject,
  257. ObjectHandleFlagInformation,
  258. &HandleInfo,
  259. sizeof( HandleInfo )
  260. );
  261. if (NT_SUCCESS( Status )) {
  262. return TRUE;
  263. }
  264. }
  265. return FALSE;
  266. }
  267. BOOLEAN
  268. xUnProtectHandle(
  269. HANDLE hObject
  270. )
  271. {
  272. NTSTATUS Status;
  273. OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
  274. Status = NtQueryObject( hObject,
  275. ObjectHandleFlagInformation,
  276. &HandleInfo,
  277. sizeof( HandleInfo ),
  278. NULL
  279. );
  280. if (NT_SUCCESS( Status )) {
  281. HandleInfo.ProtectFromClose = FALSE;
  282. Status = NtSetInformationObject( hObject,
  283. ObjectHandleFlagInformation,
  284. &HandleInfo,
  285. sizeof( HandleInfo )
  286. );
  287. if (NT_SUCCESS( Status )) {
  288. return TRUE;
  289. }
  290. }
  291. return FALSE;
  292. }
  293. NTSTATUS
  294. CsrpConnectToServer(
  295. IN PWSTR ObjectDirectory
  296. )
  297. {
  298. NTSTATUS Status;
  299. REMOTE_PORT_VIEW ServerView;
  300. ULONG MaxMessageLength;
  301. ULONG ConnectionInformationLength;
  302. CSR_API_CONNECTINFO ConnectionInformation;
  303. SECURITY_QUALITY_OF_SERVICE DynamicQos;
  304. HANDLE PortSection;
  305. PORT_VIEW ClientView;
  306. ULONG n;
  307. LARGE_INTEGER SectionSize;
  308. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  309. PSID SystemSid;
  310. //
  311. // Create the port name string by combining the passed in object directory
  312. // name with the port name.
  313. //
  314. n = ((wcslen( ObjectDirectory ) + 1) * sizeof( WCHAR )) +
  315. sizeof( CSR_API_PORT_NAME );
  316. CsrPortName.Length = 0;
  317. CsrPortName.MaximumLength = (USHORT)n;
  318. CsrPortName.Buffer = RtlAllocateHeap( CsrHeap, MAKE_TAG( CSR_TAG ), n );
  319. if (CsrPortName.Buffer == NULL) {
  320. return( STATUS_NO_MEMORY );
  321. }
  322. RtlAppendUnicodeToString( &CsrPortName, ObjectDirectory );
  323. RtlAppendUnicodeToString( &CsrPortName, L"\\" );
  324. RtlAppendUnicodeToString( &CsrPortName, CSR_API_PORT_NAME );
  325. //
  326. // Set up the security quality of service parameters to use over the
  327. // port. Use the most efficient (least overhead) - which is dynamic
  328. // rather than static tracking.
  329. //
  330. DynamicQos.ImpersonationLevel = SecurityImpersonation;
  331. DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  332. DynamicQos.EffectiveOnly = TRUE;
  333. //
  334. // Create a section to contain the Port Memory. Port Memory is private
  335. // memory that is shared between the client and server processes.
  336. // This allows data that is too large to fit into an API request message
  337. // to be passed to the server.
  338. //
  339. SectionSize.LowPart = CSR_PORT_MEMORY_SIZE;
  340. SectionSize.HighPart = 0;
  341. Status = NtCreateSection( &PortSection,
  342. SECTION_ALL_ACCESS,
  343. NULL,
  344. &SectionSize,
  345. PAGE_READWRITE,
  346. SEC_RESERVE,
  347. NULL
  348. );
  349. if (!NT_SUCCESS( Status )) {
  350. return( Status );
  351. }
  352. //
  353. // Connect to the server. This includes a description of the Port Memory
  354. // section so that the LPC connection logic can make the section visible
  355. // to both the client and server processes. Also pass information the
  356. // server needs in the connection information structure.
  357. //
  358. ClientView.Length = sizeof( ClientView );
  359. ClientView.SectionHandle = PortSection;
  360. ClientView.SectionOffset = 0;
  361. ClientView.ViewSize = SectionSize.LowPart;
  362. ClientView.ViewBase = 0;
  363. ClientView.ViewRemoteBase = 0;
  364. ServerView.Length = sizeof( ServerView );
  365. ServerView.ViewSize = 0;
  366. ServerView.ViewBase = 0;
  367. ConnectionInformationLength = sizeof( ConnectionInformation );
  368. ConnectionInformation.ExpectedVersion = CSR_VERSION;
  369. SystemSid = NULL;
  370. Status = RtlAllocateAndInitializeSid( &NtAuthority,
  371. 1,
  372. SECURITY_LOCAL_SYSTEM_RID,
  373. 0, 0, 0, 0, 0, 0, 0,
  374. &SystemSid
  375. );
  376. if (!NT_SUCCESS( Status )) {
  377. return( Status );
  378. }
  379. Status = NtSecureConnectPort( &CsrPortHandle,
  380. &CsrPortName,
  381. &DynamicQos,
  382. &ClientView,
  383. SystemSid,
  384. &ServerView,
  385. (PULONG)&MaxMessageLength,
  386. (PVOID)&ConnectionInformation,
  387. (PULONG)&ConnectionInformationLength
  388. );
  389. RtlFreeSid( SystemSid );
  390. NtClose( PortSection );
  391. if (!NT_SUCCESS( Status )) {
  392. IF_DEBUG {
  393. DbgPrint( "CSRDLL: Unable to connect to %wZ Server - Status == %X\n",
  394. &CsrPortName,
  395. Status
  396. );
  397. }
  398. return( Status );
  399. }
  400. xProtectHandle(CsrPortHandle);
  401. NtCurrentPeb()->ReadOnlySharedMemoryBase = ConnectionInformation.SharedSectionBase;
  402. NtCurrentPeb()->ReadOnlySharedMemoryHeap = ConnectionInformation.SharedSectionHeap;
  403. NtCurrentPeb()->ReadOnlyStaticServerData = (PVOID *)ConnectionInformation.SharedStaticServerData;
  404. CsrProcessId = ConnectionInformation.ServerProcessId;
  405. #if DBG
  406. CsrDebug = ConnectionInformation.DebugFlags;
  407. #endif
  408. CsrObjectDirectory = ConnectionInformation.ObjectDirectory;
  409. CsrPortMemoryRemoteDelta = (ULONG_PTR)ClientView.ViewRemoteBase -
  410. (ULONG_PTR)ClientView.ViewBase;
  411. IF_CSR_DEBUG( LPC ) {
  412. DbgPrint( "CSRDLL: ClientView: Base=%p RemoteBase=%p Delta: %lX Size=%lX\n",
  413. ClientView.ViewBase,
  414. ClientView.ViewRemoteBase,
  415. CsrPortMemoryRemoteDelta,
  416. (ULONG)ClientView.ViewSize
  417. );
  418. }
  419. //
  420. // Create a sparse heap in the share memory section. Initially
  421. // commit just one page.
  422. //
  423. CsrPortHeap = RtlCreateHeap( HEAP_CLASS_8, // Flags
  424. ClientView.ViewBase, // HeapBase
  425. ClientView.ViewSize, // ReserveSize
  426. CsrNtSysInfo.PageSize, // CommitSize
  427. 0, // Reserved
  428. 0 // GrowthThreshold
  429. );
  430. if (CsrPortHeap == NULL) {
  431. xUnProtectHandle(CsrPortHandle);
  432. NtClose( CsrPortHandle );
  433. CsrPortHandle = NULL;
  434. return( STATUS_NO_MEMORY );
  435. }
  436. CsrPortBaseTag = RtlCreateTagHeap( CsrPortHeap,
  437. 0,
  438. L"CSRPORT!",
  439. L"!CSRPORT\0"
  440. L"CAPTURE\0"
  441. );
  442. return( STATUS_SUCCESS );
  443. }