Leaked source code of windows server 2003
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.

542 lines
15 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 "ldrp.h"
  15. #include "csrdll.h"
  16. BOOLEAN
  17. ProtectHandle (
  18. HANDLE hObject
  19. );
  20. BOOLEAN
  21. UnProtectHandle (
  22. HANDLE hObject
  23. );
  24. BOOLEAN
  25. CsrDllInitialize (
  26. IN PVOID DllHandle,
  27. IN ULONG Reason,
  28. IN PCONTEXT Context OPTIONAL
  29. )
  30. /*++
  31. Routine Description:
  32. This function is the DLL initialization routine for the Client DLL
  33. This function gets control when the application links to this DLL
  34. are snapped.
  35. Arguments:
  36. Context - Supplies an optional context buffer that will be restored
  37. after all DLL initialization has been completed. If this
  38. parameter is NULL then this is a dynamic snap of this module.
  39. Otherwise this is a static snap prior to the user process
  40. gaining control.
  41. Return Value:
  42. Status value.
  43. --*/
  44. {
  45. UNREFERENCED_PARAMETER (Context);
  46. if (Reason == DLL_PROCESS_ATTACH) {
  47. //
  48. // Remember our DLL handle in a global variable.
  49. //
  50. CsrDllHandle = DllHandle;
  51. }
  52. return TRUE;
  53. }
  54. NTSTATUS
  55. CsrOneTimeInitialize (
  56. VOID
  57. )
  58. {
  59. NTSTATUS Status;
  60. //
  61. // Save away system information in a global variable.
  62. //
  63. Status = NtQuerySystemInformation (SystemBasicInformation,
  64. &CsrNtSysInfo,
  65. sizeof (CsrNtSysInfo),
  66. NULL);
  67. if (!NT_SUCCESS (Status)) {
  68. return Status;
  69. }
  70. //
  71. // Use the process heap for memory allocations.
  72. //
  73. CsrHeap = RtlProcessHeap ();
  74. CsrInitOnceDone = TRUE;
  75. return STATUS_SUCCESS;
  76. }
  77. NTSTATUS
  78. CsrClientConnectToServer (
  79. IN PWSTR ObjectDirectory,
  80. IN ULONG ServerDllIndex,
  81. IN PVOID ConnectionInformation,
  82. IN OUT PULONG ConnectionInformationLength OPTIONAL,
  83. OUT PBOOLEAN CalledFromServer OPTIONAL
  84. )
  85. /*++
  86. Routine Description:
  87. This function is called by the client side DLL to connect with its
  88. server side DLL.
  89. Arguments:
  90. ObjectDirectory - Points to a null terminated string that is the same
  91. as the value of the ObjectDirectory= argument passed to the CSRSS
  92. program.
  93. ServerDllIndex - Index of the server DLL that is being connected to.
  94. It should match one of the ServerDll= arguments passed to the CSRSS
  95. program.
  96. ConnectionInformation - An optional pointer to uninterpreted data.
  97. This data is intended for clients to pass package, version and
  98. protocol identification information to the server to allow the
  99. server to determine if it can satisfy the client before
  100. accepting the connection. Upon return to the client, the
  101. ConnectionInformation data block contains any information passed
  102. back from the server DLL by its call to the
  103. CsrCompleteConnection call. The output data overwrites the
  104. input data.
  105. ConnectionInformationLength - Pointer to the length of the
  106. ConnectionInformation data block. The output value is the
  107. length of the data stored in the ConnectionInformation data
  108. block by the server's call to the NtCompleteConnectPort
  109. service. This parameter is OPTIONAL only if the
  110. ConnectionInformation parameter is NULL, otherwise it is
  111. required.
  112. CalledFromServer - On output, TRUE if the dll has been called from
  113. a server process.
  114. Return Value:
  115. Status value.
  116. --*/
  117. {
  118. NTSTATUS Status;
  119. CSR_API_MSG m;
  120. PCSR_CLIENTCONNECT_MSG a = &m.u.ClientConnect;
  121. PCSR_CAPTURE_HEADER CaptureBuffer;
  122. HANDLE CsrServerModuleHandle;
  123. STRING ProcedureName;
  124. UNICODE_STRING DllName_U;
  125. PIMAGE_NT_HEADERS NtHeaders;
  126. if ((ARGUMENT_PRESENT (ConnectionInformation)) &&
  127. (!ARGUMENT_PRESENT (ConnectionInformationLength) ||
  128. *ConnectionInformationLength == 0)) {
  129. return STATUS_INVALID_PARAMETER;
  130. }
  131. if (!CsrInitOnceDone) {
  132. Status = CsrOneTimeInitialize();
  133. if (!NT_SUCCESS (Status)) {
  134. return Status;
  135. }
  136. }
  137. //
  138. // If we are being called by a server process, skip LPC port initialization
  139. // and call to server connect routine and just initialize the heap. The
  140. // dll initialization routine will do any necessary initialization. This
  141. // stuff only needs to be done for the first connect.
  142. //
  143. if (CsrServerProcess == TRUE) {
  144. if (ARGUMENT_PRESENT (CalledFromServer)) {
  145. *CalledFromServer = CsrServerProcess;
  146. }
  147. return STATUS_SUCCESS;
  148. }
  149. //
  150. // If the image is an NT native image, we are running in the
  151. // context of the server.
  152. //
  153. NtHeaders = RtlImageNtHeader (NtCurrentPeb()->ImageBaseAddress);
  154. if (!NtHeaders) {
  155. return STATUS_INVALID_IMAGE_FORMAT;
  156. }
  157. CsrServerProcess =
  158. (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE) ? TRUE : FALSE;
  159. if (CsrServerProcess) {
  160. extern PVOID NtDllBase;
  161. DllName_U.Buffer = L"csrsrv";
  162. DllName_U.Length = sizeof (L"csrsrv") - sizeof (WCHAR);
  163. DllName_U.MaximumLength = sizeof(L"csrsrv");
  164. Status = LdrDisableThreadCalloutsForDll (NtDllBase);
  165. if (!NT_SUCCESS (Status)) {
  166. return Status;
  167. }
  168. Status = LdrGetDllHandle (NULL,
  169. NULL,
  170. &DllName_U,
  171. (PVOID *)&CsrServerModuleHandle);
  172. if (!NT_SUCCESS (Status)) {
  173. return Status;
  174. }
  175. RtlInitString (&ProcedureName,"CsrCallServerFromServer");
  176. Status = LdrGetProcedureAddress (CsrServerModuleHandle,
  177. &ProcedureName,
  178. 0L,
  179. (PVOID *)&CsrServerApiRoutine);
  180. if (!NT_SUCCESS (Status)) {
  181. return Status;
  182. }
  183. ASSERT (NT_SUCCESS(Status));
  184. ASSERT (CsrPortHeap == NULL);
  185. CsrPortHeap = RtlProcessHeap();
  186. CsrPortBaseTag = RtlCreateTagHeap (CsrPortHeap,
  187. 0,
  188. L"CSRPORT!",
  189. L"CAPTURE\0");
  190. if (ARGUMENT_PRESENT(CalledFromServer)) {
  191. *CalledFromServer = CsrServerProcess;
  192. }
  193. return STATUS_SUCCESS;
  194. }
  195. if (ARGUMENT_PRESENT(ConnectionInformation)) {
  196. if (CsrPortHandle == NULL) {
  197. Status = CsrpConnectToServer (ObjectDirectory);
  198. if (!NT_SUCCESS(Status)) {
  199. return Status;
  200. }
  201. }
  202. Status = STATUS_SUCCESS;
  203. //
  204. // For basesrv this is one big noop.
  205. //
  206. if (ServerDllIndex != BASESRV_SERVERDLL_INDEX) {
  207. a->ServerDllIndex = ServerDllIndex;
  208. a->ConnectionInformationLength = *ConnectionInformationLength;
  209. CaptureBuffer = CsrAllocateCaptureBuffer (1,
  210. a->ConnectionInformationLength);
  211. if (CaptureBuffer == NULL) {
  212. return STATUS_NO_MEMORY;
  213. }
  214. CsrAllocateMessagePointer (CaptureBuffer,
  215. a->ConnectionInformationLength,
  216. (PVOID *)&a->ConnectionInformation);
  217. RtlCopyMemory (a->ConnectionInformation,
  218. ConnectionInformation,
  219. a->ConnectionInformationLength);
  220. *ConnectionInformationLength = a->ConnectionInformationLength;
  221. Status = CsrClientCallServer (&m,
  222. CaptureBuffer,
  223. CSR_MAKE_API_NUMBER (CSRSRV_SERVERDLL_INDEX,
  224. CsrpClientConnect),
  225. sizeof (*a));
  226. if (CaptureBuffer != NULL) {
  227. RtlCopyMemory (ConnectionInformation,
  228. a->ConnectionInformation,
  229. *ConnectionInformationLength);
  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. NTSTATUS
  242. CsrpConnectToServer (
  243. IN PWSTR ObjectDirectory
  244. )
  245. {
  246. NTSTATUS Status;
  247. REMOTE_PORT_VIEW ServerView;
  248. ULONG MaxMessageLength;
  249. ULONG ConnectionInformationLength;
  250. CSR_API_CONNECTINFO ConnectionInformation;
  251. SECURITY_QUALITY_OF_SERVICE DynamicQos;
  252. HANDLE PortSection;
  253. PORT_VIEW ClientView;
  254. SIZE_T n;
  255. LARGE_INTEGER SectionSize;
  256. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  257. PSID SystemSid;
  258. PPEB Peb;
  259. SIZE_T Odl;
  260. PWCHAR p;
  261. //
  262. // Create the port name string by combining the passed in object directory
  263. // name with the port name.
  264. //
  265. Odl = wcslen (ObjectDirectory);
  266. n = ((Odl + 1) * sizeof (WCHAR)) +
  267. sizeof (CSR_API_PORT_NAME) - sizeof (WCHAR);
  268. if (n > MAXUSHORT) {
  269. return STATUS_NAME_TOO_LONG;
  270. }
  271. CsrPortName.Buffer = p = RtlAllocateHeap (CsrHeap, MAKE_TAG (CSR_TAG), n);
  272. if (CsrPortName.Buffer == NULL) {
  273. return STATUS_NO_MEMORY;
  274. }
  275. RtlCopyMemory (p, ObjectDirectory, Odl * sizeof (WCHAR));
  276. p += Odl;
  277. *p++ = L'\\';
  278. RtlCopyMemory (p, CSR_API_PORT_NAME, sizeof (CSR_API_PORT_NAME) - sizeof (WCHAR));
  279. CsrPortName.Length = (USHORT) n;
  280. //
  281. // Set up the security quality of service parameters to use over the
  282. // port. Use the most efficient (least overhead) - which is dynamic
  283. // rather than static tracking.
  284. //
  285. DynamicQos.ImpersonationLevel = SecurityImpersonation;
  286. DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  287. DynamicQos.EffectiveOnly = TRUE;
  288. //
  289. // Create a section to contain the Port Memory. Port Memory is private
  290. // memory that is shared between the client and server processes.
  291. // This allows data that is too large to fit into an API request message
  292. // to be passed to the server.
  293. //
  294. SectionSize.LowPart = CSR_PORT_MEMORY_SIZE;
  295. SectionSize.HighPart = 0;
  296. Status = NtCreateSection (&PortSection,
  297. SECTION_ALL_ACCESS,
  298. NULL,
  299. &SectionSize,
  300. PAGE_READWRITE,
  301. SEC_RESERVE,
  302. NULL);
  303. if (!NT_SUCCESS (Status)) {
  304. return Status;
  305. }
  306. //
  307. // Connect to the server. This includes a description of the Port Memory
  308. // section so that the LPC connection logic can make the section visible
  309. // to both the client and server processes. Also pass information the
  310. // server needs in the connection information structure.
  311. //
  312. ClientView.Length = sizeof (ClientView);
  313. ClientView.SectionHandle = PortSection;
  314. ClientView.SectionOffset = 0;
  315. ClientView.ViewSize = SectionSize.LowPart;
  316. ClientView.ViewBase = 0;
  317. ClientView.ViewRemoteBase = 0;
  318. ServerView.Length = sizeof (ServerView);
  319. ServerView.ViewSize = 0;
  320. ServerView.ViewBase = 0;
  321. ConnectionInformationLength = sizeof (ConnectionInformation);
  322. SystemSid = NULL;
  323. Status = RtlAllocateAndInitializeSid (&NtAuthority,
  324. 1,
  325. SECURITY_LOCAL_SYSTEM_RID,
  326. 0,
  327. 0,
  328. 0,
  329. 0,
  330. 0,
  331. 0,
  332. 0,
  333. &SystemSid);
  334. if (!NT_SUCCESS (Status)) {
  335. NtClose (PortSection);
  336. return Status;
  337. }
  338. #if DBG
  339. ConnectionInformation.DebugFlags = 0;
  340. #endif
  341. Status = NtSecureConnectPort (&CsrPortHandle,
  342. &CsrPortName,
  343. &DynamicQos,
  344. &ClientView,
  345. SystemSid,
  346. &ServerView,
  347. (PULONG)&MaxMessageLength,
  348. (PVOID)&ConnectionInformation,
  349. (PULONG)&ConnectionInformationLength);
  350. RtlFreeSid (SystemSid);
  351. NtClose (PortSection);
  352. if (!NT_SUCCESS (Status)) {
  353. IF_DEBUG {
  354. DbgPrint ("CSRDLL: Unable to connect to %wZ Server - Status == %X\n",
  355. &CsrPortName,
  356. Status);
  357. }
  358. return Status;
  359. }
  360. #if DBG
  361. ProtectHandle (CsrPortHandle);
  362. #endif
  363. Peb = NtCurrentPeb();
  364. Peb->ReadOnlySharedMemoryBase = ConnectionInformation.SharedSectionBase;
  365. Peb->ReadOnlySharedMemoryHeap = ConnectionInformation.SharedSectionHeap;
  366. Peb->ReadOnlyStaticServerData = (PVOID *)ConnectionInformation.SharedStaticServerData;
  367. CsrProcessId = ConnectionInformation.ServerProcessId;
  368. #if DBG
  369. CsrDebug = ConnectionInformation.DebugFlags;
  370. #endif
  371. CsrPortMemoryRemoteDelta = (ULONG_PTR)ClientView.ViewRemoteBase -
  372. (ULONG_PTR)ClientView.ViewBase;
  373. IF_CSR_DEBUG( LPC ) {
  374. DbgPrint ("CSRDLL: ClientView: Base=%p RemoteBase=%p Delta: %lX Size=%lX\n",
  375. ClientView.ViewBase,
  376. ClientView.ViewRemoteBase,
  377. CsrPortMemoryRemoteDelta,
  378. (ULONG)ClientView.ViewSize);
  379. }
  380. //
  381. // Create a sparse heap in the shared memory section. Initially
  382. // commit just one page.
  383. //
  384. CsrPortHeap = RtlCreateHeap (HEAP_CLASS_8, // Flags
  385. ClientView.ViewBase, // HeapBase
  386. ClientView.ViewSize, // ReserveSize
  387. CsrNtSysInfo.PageSize, // CommitSize
  388. 0, // Reserved
  389. 0); // GrowthThreshold
  390. if (CsrPortHeap == NULL) {
  391. #if DBG
  392. UnProtectHandle (CsrPortHandle);
  393. #endif
  394. NtClose (CsrPortHandle);
  395. CsrPortHandle = NULL;
  396. return STATUS_NO_MEMORY;
  397. }
  398. CsrPortBaseTag = RtlCreateTagHeap (CsrPortHeap,
  399. 0,
  400. L"CSRPORT!",
  401. L"!CSRPORT\0"
  402. L"CAPTURE\0");
  403. return STATUS_SUCCESS;
  404. }