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.

381 lines
9.5 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 POSIX Subsystem
  7. Client DLL.
  8. Author:
  9. Mark Lucovsky (markl) 27-Jun-1989
  10. Environment:
  11. User Mode only
  12. Revision History:
  13. Ellen Aycock-Wright (ellena) 03-Jan-1991
  14. Converted to DLL initialization routine.
  15. --*/
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include "psxdll.h"
  19. extern void ClientOpen(int);
  20. ULONG_PTR PsxPortMemoryRemoteDelta;
  21. PVOID PsxPortMemoryBase;
  22. BOOLEAN
  23. PsxDllInitialize(
  24. IN PVOID DllHandle,
  25. IN ULONG Reason,
  26. IN PCONTEXT Context OPTIONAL
  27. )
  28. /*++
  29. Routine Description:
  30. This function is the DLL initialization routine for the POSIX Emulation
  31. Subsystem Client DLL. This function gets control when the applications
  32. links to this DLL are snapped.
  33. Arguments:
  34. Context - Supplies an optional context buffer that will be restored
  35. after all DLL initialization has been completed. If this
  36. parameter is NULL then this is a dynamic snap of this module.
  37. Otherwise this is a static snap prior to the user process
  38. gaining control.
  39. Return Value:
  40. False if initialization failed.
  41. --*/
  42. {
  43. PPEB Peb;
  44. PPEB_PSX_DATA PebPsxData;
  45. NTSTATUS Status;
  46. if (Reason != DLL_PROCESS_ATTACH) {
  47. return TRUE;
  48. }
  49. //
  50. // Remember our DLL handle in a global variable.
  51. //
  52. PsxDllHandle = DllHandle;
  53. PdxHeap = RtlCreateHeap( HEAP_GROWABLE | HEAP_NO_SERIALIZE,
  54. NULL,
  55. 64 * 1024, // Initial size of heap is 64K
  56. 4 * 1024,
  57. 0,
  58. NULL
  59. );
  60. if (PdxHeap == NULL) {
  61. return FALSE;
  62. }
  63. Status = PsxInitDirectories();
  64. if ( !NT_SUCCESS( Status )) {
  65. return FALSE;
  66. }
  67. Status = PsxConnectToServer();
  68. if (!NT_SUCCESS(Status)) {
  69. return FALSE;
  70. }
  71. Peb = NtCurrentPeb();
  72. //
  73. // This is not really an ANSI_STRING but an undocumented data
  74. // structure. Read crt32psx\startup\crt0.c for the code that
  75. // interprets this.
  76. //
  77. PsxAnsiCommandLine = *(PANSI_STRING)&(Peb->ProcessParameters->CommandLine);
  78. if (ARGUMENT_PRESENT(Context)) {
  79. PebPsxData = (PPEB_PSX_DATA)Peb->SubSystemData;
  80. PebPsxData->ClientStartAddress = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(Context);
  81. PROGRAM_COUNTER_TO_CONTEXT(Context, (ULONG_PTR) PdxProcessStartup);
  82. }
  83. return TRUE;
  84. }
  85. NTSTATUS
  86. PsxInitDirectories()
  87. {
  88. PdxDirectoryPrefix.NtCurrentWorkingDirectory.Buffer =
  89. RtlAllocateHeap(PdxHeap, 0,2*PATH_MAX);
  90. PdxDirectoryPrefix.NtCurrentWorkingDirectory.Length = 0;
  91. PdxDirectoryPrefix.NtCurrentWorkingDirectory.MaximumLength = 2*PATH_MAX;
  92. PdxDirectoryPrefix.PsxCurrentWorkingDirectory.Buffer =
  93. RtlAllocateHeap(PdxHeap, 0,PATH_MAX+1);
  94. PdxDirectoryPrefix.PsxCurrentWorkingDirectory.Length = 0;
  95. PdxDirectoryPrefix.PsxCurrentWorkingDirectory.MaximumLength = PATH_MAX+1;
  96. PdxDirectoryPrefix.PsxRoot.Buffer = RtlAllocateHeap(PdxHeap, 0,2*PATH_MAX);
  97. PdxDirectoryPrefix.PsxRoot.Length = 0;
  98. PdxDirectoryPrefix.PsxRoot.MaximumLength = 2*PATH_MAX;
  99. //
  100. // Check that memory allocations worked. If not, then bail out
  101. //
  102. ASSERT(PdxDirectoryPrefix.NtCurrentWorkingDirectory.Buffer);
  103. ASSERT(PdxDirectoryPrefix.PsxCurrentWorkingDirectory.Buffer);
  104. ASSERT(PdxDirectoryPrefix.PsxRoot.Buffer);
  105. if ( (PdxDirectoryPrefix.NtCurrentWorkingDirectory.Buffer == NULL) ||
  106. (PdxDirectoryPrefix.PsxCurrentWorkingDirectory.Buffer == NULL) ||
  107. (PdxDirectoryPrefix.PsxRoot.Buffer == NULL) ) {
  108. return ( STATUS_NO_MEMORY );
  109. }
  110. return ( STATUS_SUCCESS );
  111. }
  112. NTSTATUS
  113. PsxConnectToServer(VOID)
  114. {
  115. UNICODE_STRING PsxPortName;
  116. PSX_API_CONNECTINFO ConnectionInformation;
  117. ULONG ConnectionInformationLength;
  118. PULONG AmIBeingDebugged;
  119. REMOTE_PORT_VIEW ServerView;
  120. HANDLE PortSection;
  121. PPEB Peb;
  122. PPEB_PSX_DATA PebPsxData;
  123. PORT_VIEW ClientView;
  124. LARGE_INTEGER SectionSize;
  125. SECURITY_QUALITY_OF_SERVICE DynamicQos;
  126. NTSTATUS Status;
  127. ConnectionInformationLength = sizeof(ConnectionInformation);
  128. //
  129. // Create a section to contain the Port Memory. Port Memory is private
  130. // memory that is shared between the POSIX client and server processes.
  131. // This allows data that is too large to fit into an API request message
  132. // to be passed to the POSIX server.
  133. //
  134. SectionSize.LowPart = PSX_CLIENT_PORT_MEMORY_SIZE;
  135. SectionSize.HighPart = 0;
  136. // SEC_RESERVE
  137. Status = NtCreateSection(&PortSection, SECTION_ALL_ACCESS, NULL,
  138. &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL);
  139. if (!NT_SUCCESS(Status)) {
  140. KdPrint(("PSXDLL: NtCreateSection: 0x%x\n", Status));
  141. return Status;
  142. }
  143. //
  144. // Get the Peb address. Allocate the POSIX subsystem specific portion
  145. // within the Peb. This structure will be filled in by the server
  146. // process as part of the connect logic.
  147. //
  148. Peb = NtCurrentPeb();
  149. Peb->SubSystemData = RtlAllocateHeap(Peb->ProcessHeap, 0,
  150. sizeof(PEB_PSX_DATA));
  151. if (! Peb->SubSystemData) {
  152. NtClose(PortSection);
  153. return STATUS_NO_MEMORY;
  154. }
  155. PebPsxData = (PPEB_PSX_DATA)Peb->SubSystemData;
  156. PebPsxData->Length = sizeof(PEB_PSX_DATA);
  157. //
  158. // Connect to the POSIX Emulation Subsystem server. This includes a
  159. // description of the Port Memory section so that the LPC connection
  160. // logic can make the section visible to both the client and server
  161. // processes. Also pass information the POSIX server needs in the
  162. // connection information structure.
  163. //
  164. ClientView.Length = sizeof(ClientView);
  165. ClientView.SectionHandle = PortSection;
  166. ClientView.SectionOffset = 0;
  167. ClientView.ViewSize = SectionSize.LowPart;
  168. ClientView.ViewBase = 0;
  169. ClientView.ViewRemoteBase = 0;
  170. ServerView.Length = sizeof(ServerView);
  171. ServerView.ViewSize = 0;
  172. ServerView.ViewBase = 0;
  173. ConnectionInformation.SignalDeliverer = _PdxSignalDeliverer;
  174. ConnectionInformation.NullApiCaller = _PdxNullApiCaller;
  175. ConnectionInformation.DirectoryPrefix = &PdxDirectoryPrefix;
  176. ConnectionInformation.InitialPebPsxData.Length = PebPsxData->Length;
  177. //
  178. // Set up the security quality of service parameters to use over the
  179. // port.
  180. //
  181. DynamicQos.ImpersonationLevel = SecurityImpersonation;
  182. DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  183. DynamicQos.EffectiveOnly = TRUE;
  184. PSX_GET_SESSION_OBJECT_NAME(&PsxPortName, PSX_SS_API_PORT_NAME);
  185. Status = NtConnectPort(&PsxPortHandle, &PsxPortName, &DynamicQos,
  186. &ClientView, &ServerView, NULL,
  187. (PVOID)&ConnectionInformation,
  188. (PULONG)&ConnectionInformationLength);
  189. NtClose(PortSection);
  190. if (!NT_SUCCESS(Status)) {
  191. KdPrint(("PSXDLL: Unable to connect to Posix server: %lx\n",
  192. Status));
  193. return Status;
  194. }
  195. Status = NtRegisterThreadTerminatePort(PsxPortHandle);
  196. ASSERT(NT_SUCCESS(Status));
  197. PsxPortMemoryBase = ClientView.ViewBase;
  198. PsxPortMemoryRemoteDelta = (ULONG_PTR)ClientView.ViewRemoteBase -
  199. (ULONG_PTR)ClientView.ViewBase;
  200. RtlMoveMemory((PVOID)PebPsxData,
  201. (PVOID)&ConnectionInformation.InitialPebPsxData,
  202. PebPsxData->Length);
  203. PdxPortHeap = RtlCreateHeap( HEAP_NO_SERIALIZE,
  204. ClientView.ViewBase,
  205. ClientView.ViewSize,
  206. ClientView.ViewSize,
  207. 0,
  208. 0
  209. );
  210. if (PdxPortHeap == NULL) {
  211. KdPrint(("PsxConnectToServer: RtlCreateHeap failed\n"));
  212. return STATUS_NO_MEMORY;
  213. }
  214. //
  215. // Connect to the session console port and
  216. // set the port handle in the PEB.
  217. //
  218. Status = PsxInitializeSessionPort(HandleToUlong(PebPsxData->SessionPortHandle));
  219. if (!NT_SUCCESS(Status)) {
  220. KdPrint(("PsxConnectToServer: PsxInitSessionPort failed\n"));
  221. return Status;
  222. }
  223. return STATUS_SUCCESS;
  224. }
  225. //
  226. // User mode process entry point.
  227. //
  228. VOID
  229. PdxProcessStartup(
  230. IN PPEB Peb
  231. )
  232. {
  233. PPEB_PSX_DATA PebPsxData;
  234. PFNPROCESS StartAddress;
  235. int ReturnCodeFromMain;
  236. PebPsxData = (PPEB_PSX_DATA)Peb->SubSystemData;
  237. StartAddress = (PFNPROCESS)(PebPsxData->ClientStartAddress);
  238. ReturnCodeFromMain = (*StartAddress) (0, NULL);
  239. _exit(ReturnCodeFromMain);
  240. NtTerminateProcess(NtCurrentProcess(),STATUS_ACCESS_DENIED);
  241. }
  242. VOID
  243. PdxNullApiCaller(
  244. IN PCONTEXT Context
  245. )
  246. {
  247. PdxNullPosixApi();
  248. #ifdef _X86_
  249. Context->Eax = 0;
  250. #endif
  251. NtContinue(Context,FALSE);
  252. //NOTREACHED
  253. }
  254. VOID
  255. PdxSignalDeliverer (
  256. IN PCONTEXT Context,
  257. IN sigset_t PreviousBlockMask,
  258. IN int Signal,
  259. IN _handler Handler
  260. )
  261. {
  262. (Handler)(Signal);
  263. sigprocmask(SIG_SETMASK, &PreviousBlockMask, NULL);
  264. #ifdef _X86_
  265. Context->Eax = 0;
  266. #endif
  267. NtContinue(Context, FALSE);
  268. //NOTREACHED
  269. }
  270. VOID
  271. __PdxInitializeData(
  272. IN int *perrno,
  273. IN char ***penviron
  274. )
  275. /*++
  276. Routine Description:
  277. This function is called from the RTL startup code to notify the DLL of
  278. the location of the variable 'errno'. Necessary because DLLs cannot
  279. export data.
  280. Arguments:
  281. perrno - Supplies the address of errno - declared in rtl/startup.c
  282. Return Value:
  283. None.
  284. --*/
  285. {
  286. Errno = perrno;
  287. Environ = penviron;
  288. }