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.

556 lines
14 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. baseinit.c
  5. Abstract:
  6. This module implements Win32 base initialization
  7. Author:
  8. Mark Lucovsky (markl) 26-Sep-1990
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. //
  13. // Divides by 10000
  14. //
  15. BOOLEAN BaseRunningInServerProcess;
  16. UINT_PTR SystemRangeStart;
  17. #if defined(_WIN64) || defined(BUILD_WOW6432)
  18. SYSTEM_BASIC_INFORMATION SysInfo;
  19. #endif
  20. WCHAR BaseDefaultPathBuffer[ 3072 ];
  21. WCHAR PsapiDllString[] = L"psapi.dll";
  22. ULONG
  23. GetPerUserWindowsDirectory(PWCHAR TermSrvWindowsPath, ULONG len);
  24. //
  25. // Dispatch functions for Oem/Ansi sensitive conversions
  26. //
  27. NTSTATUS (*Basep8BitStringToUnicodeString)(
  28. PUNICODE_STRING DestinationString,
  29. PANSI_STRING SourceString,
  30. BOOLEAN AllocateDestinationString
  31. ) = RtlAnsiStringToUnicodeString;
  32. NTSTATUS (*BasepUnicodeStringTo8BitString)(
  33. PANSI_STRING DestinationString,
  34. PUNICODE_STRING SourceString,
  35. BOOLEAN AllocateDestinationString
  36. ) = RtlUnicodeStringToAnsiString;
  37. ULONG (*BasepUnicodeStringTo8BitSize)(
  38. PUNICODE_STRING UnicodeString
  39. ) = BasepUnicodeStringToAnsiSize;
  40. ULONG (*Basep8BitStringToUnicodeSize)(
  41. PANSI_STRING AnsiString
  42. ) = BasepAnsiStringToUnicodeSize;
  43. VOID
  44. WINAPI
  45. SetFileApisToOEM(
  46. VOID
  47. )
  48. {
  49. Basep8BitStringToUnicodeString = RtlOemStringToUnicodeString;
  50. BasepUnicodeStringTo8BitString = RtlUnicodeStringToOemString;
  51. BasepUnicodeStringTo8BitSize = BasepUnicodeStringToOemSize;
  52. Basep8BitStringToUnicodeSize = BasepOemStringToUnicodeSize;
  53. }
  54. VOID
  55. WINAPI
  56. SetFileApisToANSI(
  57. VOID
  58. )
  59. {
  60. Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
  61. BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
  62. BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
  63. Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
  64. }
  65. BOOL
  66. WINAPI
  67. AreFileApisANSI(
  68. VOID
  69. )
  70. {
  71. return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString;
  72. }
  73. BOOLEAN
  74. ConDllInitialize(
  75. IN ULONG Reason,
  76. IN PWSTR pObjectDirectory OPTIONAL
  77. );
  78. BOOLEAN
  79. NlsDllInitialize(
  80. IN PVOID DllHandle,
  81. IN ULONG Reason,
  82. IN PBASE_STATIC_SERVER_DATA BaseStaticServerData
  83. );
  84. BOOLEAN
  85. NlsThreadCleanup(void);
  86. #if DBG
  87. VOID
  88. WINAPI
  89. AssertDelayLoadFailureMapsAreSorted (
  90. VOID
  91. );
  92. #endif
  93. UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
  94. UNICODE_STRING BaseUserProfileVariableName = RTL_CONSTANT_STRING(L"USERPROFILE");
  95. UNICODE_STRING BaseTmpVariableName = RTL_CONSTANT_STRING(L"TMP");
  96. UNICODE_STRING BaseTempVariableName = RTL_CONSTANT_STRING(L"TEMP");
  97. UNICODE_STRING BaseDotVariableName = RTL_CONSTANT_STRING(L".");
  98. UNICODE_STRING BaseDotTmpSuffixName = RTL_CONSTANT_STRING(L".tmp");
  99. UNICODE_STRING BaseDotComSuffixName = RTL_CONSTANT_STRING(L".com");
  100. UNICODE_STRING BaseDotPifSuffixName = RTL_CONSTANT_STRING(L".pif");
  101. UNICODE_STRING BaseDotExeSuffixName = RTL_CONSTANT_STRING(L".exe");
  102. UNICODE_STRING BaseConsoleInput = RTL_CONSTANT_STRING(L"CONIN$");
  103. UNICODE_STRING BaseConsoleOutput = RTL_CONSTANT_STRING(L"CONOUT$");
  104. UNICODE_STRING BaseConsoleGeneric = RTL_CONSTANT_STRING(L"CON");
  105. BOOLEAN
  106. BaseDllInitialize(
  107. IN PVOID DllHandle,
  108. IN ULONG Reason,
  109. IN PCONTEXT Context OPTIONAL
  110. )
  111. /*++
  112. Routine Description:
  113. This function implements Win32 base dll initialization.
  114. It's primary purpose is to create the Base heap.
  115. Arguments:
  116. DllHandle - Saved in BaseDllHandle global variable
  117. Context - Not Used
  118. Return Value:
  119. STATUS_SUCCESS
  120. --*/
  121. {
  122. BOOLEAN Success;
  123. NTSTATUS Status;
  124. PPEB Peb;
  125. LPWSTR p, p1;
  126. BOOLEAN ServerProcess;
  127. HANDLE hNlsCacheMutant;
  128. USHORT Size;
  129. #if !defined(BUILD_WOW6432)
  130. ULONG SizeMutant;
  131. #endif
  132. WCHAR szSessionDir[MAX_SESSION_PATH];
  133. SessionId = NtCurrentPeb()->SessionId;
  134. BaseDllHandle = DllHandle;
  135. Success = TRUE;
  136. Peb = NtCurrentPeb();
  137. switch ( Reason ) {
  138. case DLL_PROCESS_ATTACH:
  139. Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
  140. RtlSetThreadPoolStartFunc( BaseCreateThreadPoolThread,
  141. BaseExitThreadPoolThread );
  142. LdrSetDllManifestProber(&BasepProbeForDllManifest);
  143. BaseDllTag = RtlCreateTagHeap( RtlProcessHeap(),
  144. 0,
  145. L"BASEDLL!",
  146. L"TMP\0"
  147. L"BACKUP\0"
  148. L"INI\0"
  149. L"FIND\0"
  150. L"GMEM\0"
  151. L"LMEM\0"
  152. L"ENV\0"
  153. L"RES\0"
  154. L"VDM\0"
  155. );
  156. BaseIniFileUpdateCount = 0;
  157. BaseDllInitializeMemoryManager();
  158. RtlInitUnicodeString( &BaseDefaultPath, NULL );
  159. //
  160. // Connect to BASESRV.DLL in the server process
  161. //
  162. #if !defined(BUILD_WOW6432)
  163. SizeMutant = sizeof(hNlsCacheMutant);
  164. #endif
  165. if ( SessionId == 0 ) {
  166. //
  167. // Console Session
  168. //
  169. wcscpy(szSessionDir, WINSS_OBJECT_DIRECTORY_NAME);
  170. } else {
  171. swprintf(szSessionDir,L"%ws\\%ld%ws",SESSION_ROOT,SessionId,WINSS_OBJECT_DIRECTORY_NAME);
  172. }
  173. #if defined(BUILD_WOW6432) || defined(_WIN64)
  174. Status = NtQuerySystemInformation(SystemBasicInformation,
  175. &SysInfo,
  176. sizeof(SYSTEM_BASIC_INFORMATION),
  177. NULL
  178. );
  179. if (!NT_SUCCESS(Status)) {
  180. return FALSE;
  181. }
  182. #endif
  183. #if defined(BUILD_WOW6432)
  184. Status = CsrBaseClientConnectToServer(szSessionDir,
  185. &hNlsCacheMutant,
  186. &ServerProcess
  187. );
  188. #else
  189. Status = CsrClientConnectToServer( szSessionDir,
  190. BASESRV_SERVERDLL_INDEX,
  191. &hNlsCacheMutant,
  192. &SizeMutant,
  193. &ServerProcess
  194. );
  195. #endif
  196. if (!NT_SUCCESS( Status )) {
  197. return FALSE;
  198. }
  199. BaseStaticServerData = BASE_SHARED_SERVER_DATA;
  200. if (!ServerProcess) {
  201. CsrNewThread();
  202. BaseRunningInServerProcess = FALSE;
  203. }
  204. else {
  205. BaseRunningInServerProcess = TRUE;
  206. }
  207. BaseCSDVersion = BaseStaticServerData->CSDVersion;
  208. BaseCSDNumber = BaseStaticServerData->CSDNumber;
  209. BaseRCNumber = BaseStaticServerData->RCNumber;
  210. if ((BaseCSDVersion) &&
  211. (!Peb->CSDVersion.Buffer)) {
  212. RtlInitUnicodeString(&Peb->CSDVersion, BaseCSDVersion);
  213. }
  214. BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsDirectory, &BaseStaticServerData->WindowsDirectory);
  215. BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsSystemDirectory, &BaseStaticServerData->WindowsSystemDirectory);
  216. #ifdef WX86
  217. BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsSys32x86Directory, &BaseStaticServerData->WindowsSys32x86Directory);
  218. #endif
  219. BaseUnicodeCommandLine = NtCurrentPeb()->ProcessParameters->CommandLine;
  220. Status = RtlUnicodeStringToAnsiString(
  221. &BaseAnsiCommandLine,
  222. &BaseUnicodeCommandLine,
  223. TRUE
  224. );
  225. if ( !NT_SUCCESS(Status) ){
  226. BaseAnsiCommandLine.Buffer = NULL;
  227. BaseAnsiCommandLine.Length = 0;
  228. BaseAnsiCommandLine.MaximumLength = 0;
  229. }
  230. p = BaseDefaultPathBuffer;
  231. p1 = BaseWindowsSystemDirectory.Buffer;
  232. while( *p = *p1++) {
  233. p++;
  234. }
  235. *p++ = L';';
  236. #ifdef WX86
  237. //
  238. // Wx86 system dir follows 32 bit system dir
  239. //
  240. p1 = BaseWindowsSys32x86Directory.Buffer;
  241. while( *p = *p1++) {
  242. p++;
  243. }
  244. *p++ = L';';
  245. #endif
  246. //
  247. // 16bit system directory follows 32bit system directory
  248. //
  249. p1 = BaseWindowsDirectory.Buffer;
  250. while( *p = *p1++) {
  251. p++;
  252. }
  253. p1 = L"\\system";
  254. while( *p = *p1++) {
  255. p++;
  256. }
  257. *p++ = L';';
  258. p1 = BaseWindowsDirectory.Buffer;
  259. while( *p = *p1++) {
  260. p++;
  261. }
  262. *p++ = L';';
  263. if (IsTerminalServer()) {
  264. WCHAR TermSrvWindowsPath[MAX_PATH];
  265. if (GetPerUserWindowsDirectory(TermSrvWindowsPath, MAX_PATH)) {
  266. p1 = TermSrvWindowsPath;
  267. while( *p = *p1++) {
  268. p++;
  269. }
  270. *p++ = L';';
  271. }
  272. }
  273. *p = UNICODE_NULL;
  274. BaseDefaultPath.Buffer = BaseDefaultPathBuffer;
  275. BaseDefaultPath.Length = (USHORT)((ULONG_PTR)p - (ULONG_PTR)BaseDefaultPathBuffer);
  276. BaseDefaultPath.MaximumLength = sizeof( BaseDefaultPathBuffer );
  277. BaseDefaultPathAppend.Buffer = p;
  278. BaseDefaultPathAppend.Length = 0;
  279. BaseDefaultPathAppend.MaximumLength = (USHORT)
  280. (BaseDefaultPath.MaximumLength - BaseDefaultPath.Length);
  281. if (!NT_SUCCESS(RtlInitializeCriticalSection(&BaseDllDirectoryLock))) {
  282. return FALSE;
  283. }
  284. BaseDllInitializeIniFileMappings( BaseStaticServerData );
  285. if ( Peb->ProcessParameters ) {
  286. if ( Peb->ProcessParameters->Flags & RTL_USER_PROC_PROFILE_USER ) {
  287. LoadLibraryW(PsapiDllString);
  288. }
  289. if (Peb->ProcessParameters->DebugFlags) {
  290. DbgBreakPoint();
  291. }
  292. }
  293. //
  294. // call the NLS API initialization routine
  295. //
  296. if ( !NlsDllInitialize( DllHandle,
  297. Reason,
  298. BaseStaticServerData ) )
  299. {
  300. return FALSE;
  301. }
  302. //
  303. // call the console initialization routine
  304. //
  305. if ( !ConDllInitialize(Reason,szSessionDir) ) {
  306. return FALSE;
  307. }
  308. InitializeListHead( &BasepAppCertDllsList );
  309. if (!NT_SUCCESS(RtlInitializeCriticalSection(&gcsAppCert))) {
  310. return FALSE;
  311. }
  312. if (!NT_SUCCESS(RtlInitializeCriticalSection(&gcsAppCompat))) {
  313. return(FALSE);
  314. }
  315. #if DBG
  316. AssertDelayLoadFailureMapsAreSorted ();
  317. #endif
  318. break;
  319. case DLL_PROCESS_DETACH:
  320. //
  321. // Make sure any open registry keys are closed.
  322. //
  323. if (BaseIniFileUpdateCount != 0) {
  324. WriteProfileStringW( NULL, NULL, NULL );
  325. }
  326. break;
  327. case DLL_THREAD_ATTACH:
  328. //
  329. // call the console initialization routine
  330. //
  331. if ( !ConDllInitialize(Reason,NULL) ) {
  332. return FALSE;
  333. }
  334. break;
  335. case DLL_THREAD_DETACH:
  336. //
  337. // Delete the thread NLS cache, if exists.
  338. //
  339. NlsThreadCleanup();
  340. break;
  341. default:
  342. break;
  343. }
  344. return Success;
  345. }
  346. NTSTATUS
  347. NTAPI
  348. BaseProcessInitPostImport()
  349. /*
  350. Routine Description:
  351. Called by the ntdll process initialization code after all of the
  352. import tables for the static imports of the EXE have been processed,
  353. but before any DLL_PROCESS_ATTACHes are sent with the exception of
  354. kernel32.dll's.
  355. Needed for the terminal server app compat hooks.
  356. */
  357. {
  358. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  359. //
  360. // Intialize TerminalServer(Hydra) hook function pointers for app compatibility
  361. //
  362. if (IsTerminalServer())
  363. InitializeTermsrvFpns();
  364. Status = STATUS_SUCCESS;
  365. // Exit:
  366. return Status;
  367. }
  368. HANDLE
  369. BaseGetNamedObjectDirectory(
  370. VOID
  371. )
  372. {
  373. OBJECT_ATTRIBUTES Obja;
  374. NTSTATUS Status;
  375. UNICODE_STRING RestrictedObjectDirectory;
  376. ACCESS_MASK DirAccess = DIRECTORY_ALL_ACCESS &
  377. ~(DELETE | WRITE_DAC | WRITE_OWNER);
  378. HANDLE hRootNamedObject;
  379. HANDLE BaseHandle;
  380. if ( BaseNamedObjectDirectory != NULL) {
  381. return BaseNamedObjectDirectory;
  382. }
  383. RtlAcquirePebLock();
  384. if ( !BaseNamedObjectDirectory ) {
  385. BASE_READ_REMOTE_STR_TEMP(TempStr);
  386. InitializeObjectAttributes( &Obja,
  387. BASE_READ_REMOTE_STR(BaseStaticServerData->NamedObjectDirectory, TempStr),
  388. OBJ_CASE_INSENSITIVE,
  389. NULL,
  390. NULL
  391. );
  392. Status = NtOpenDirectoryObject( &BaseHandle,
  393. DirAccess,
  394. &Obja
  395. );
  396. // if the intial open failed, try again with just traverse, and
  397. // open the restricted subdirectory
  398. if ( !NT_SUCCESS(Status) ) {
  399. Status = NtOpenDirectoryObject( &hRootNamedObject,
  400. DIRECTORY_TRAVERSE,
  401. &Obja
  402. );
  403. if ( NT_SUCCESS(Status) ) {
  404. RtlInitUnicodeString( &RestrictedObjectDirectory, L"Restricted");
  405. InitializeObjectAttributes( &Obja,
  406. &RestrictedObjectDirectory,
  407. OBJ_CASE_INSENSITIVE,
  408. hRootNamedObject,
  409. NULL
  410. );
  411. Status = NtOpenDirectoryObject( &BaseHandle,
  412. DirAccess,
  413. &Obja
  414. );
  415. NtClose( hRootNamedObject );
  416. }
  417. }
  418. if ( NT_SUCCESS(Status) ) {
  419. BaseNamedObjectDirectory = BaseHandle;
  420. }
  421. }
  422. RtlReleasePebLock();
  423. return BaseNamedObjectDirectory;
  424. }