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.

656 lines
18 KiB

  1. /*++
  2. Copyright (c) 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. ULONG BaseDllTag;
  13. BOOLEAN BaseRunningInServerProcess;
  14. UINT_PTR SystemRangeStart;
  15. #if defined(_WIN64) || defined(BUILD_WOW6432)
  16. SYSTEM_BASIC_INFORMATION SysInfo;
  17. SYSTEM_PROCESSOR_INFORMATION NativeProcessorInfo;
  18. #endif
  19. WCHAR BaseDefaultPathBuffer[ 3072 ];
  20. extern const WCHAR PsapiDllString[] = L"psapi.dll";
  21. UNICODE_STRING BaseDefaultPath;
  22. UNICODE_STRING BaseDefaultPathAppend;
  23. PWSTR BaseCSDVersion;
  24. WORD BaseCSDNumber;
  25. WORD BaseRCNumber;
  26. UNICODE_STRING BaseUnicodeCommandLine;
  27. ANSI_STRING BaseAnsiCommandLine;
  28. LPSTARTUPINFOA BaseAnsiStartupInfo;
  29. PBASE_STATIC_SERVER_DATA BaseStaticServerData;
  30. ULONG BaseIniFileUpdateCount;
  31. RTL_CRITICAL_SECTION gcsAppCert;
  32. LIST_ENTRY BasepAppCertDllsList;
  33. RTL_CRITICAL_SECTION gcsAppCompat;
  34. PTERMSRVFORMATOBJECTNAME gpTermsrvFormatObjectName;
  35. PTERMSRVGETCOMPUTERNAME gpTermsrvGetComputerName;
  36. PTERMSRVADJUSTPHYMEMLIMITS gpTermsrvAdjustPhyMemLimits;
  37. PTERMSRVGETWINDOWSDIRECTORYA gpTermsrvGetWindowsDirectoryA;
  38. PTERMSRVGETWINDOWSDIRECTORYW gpTermsrvGetWindowsDirectoryW;
  39. PTERMSRVCONVERTSYSROOTTOUSERDIR gpTermsrvConvertSysRootToUserDir;
  40. PTERMSRVBUILDINIFILENAME gpTermsrvBuildIniFileName;
  41. PTERMSRVCORINIFILE gpTermsrvCORIniFile;
  42. PTERMSRVUPDATEALLUSERMENU gpTermsrvUpdateAllUserMenu;
  43. PGETTERMSRCOMPATFLAGS gpGetTermsrCompatFlags;
  44. PTERMSRVBUILDSYSINIPATH gpTermsrvBuildSysIniPath;
  45. PTERMSRVCOPYINIFILE gpTermsrvCopyIniFile;
  46. PTERMSRVGETSTRING gpTermsrvGetString;
  47. PTERMSRVLOGINSTALLINIFILE gpTermsrvLogInstallIniFile;
  48. HANDLE BaseDllHandle;
  49. HANDLE BaseNamedObjectDirectory;
  50. PVOID BaseHeap;
  51. RTL_HANDLE_TABLE BaseHeapHandleTable;
  52. UNICODE_STRING BaseWindowsDirectory;
  53. UNICODE_STRING BaseWindowsSystemDirectory;
  54. UNICODE_STRING BaseDllDirectory = { 0, 0, NULL };
  55. RTL_CRITICAL_SECTION BaseDllDirectoryLock;
  56. RTL_CRITICAL_SECTION BaseLZSemTable;
  57. #ifdef WX86
  58. UNICODE_STRING BaseWindowsSys32x86Directory;
  59. #endif
  60. //
  61. // Dispatch functions for Oem/Ansi sensitive conversions
  62. //
  63. NTSTATUS (*Basep8BitStringToUnicodeString)(
  64. PUNICODE_STRING DestinationString,
  65. PANSI_STRING SourceString,
  66. BOOLEAN AllocateDestinationString
  67. ) = RtlAnsiStringToUnicodeString;
  68. NTSTATUS (*BasepUnicodeStringTo8BitString)(
  69. PANSI_STRING DestinationString,
  70. PUNICODE_STRING SourceString,
  71. BOOLEAN AllocateDestinationString
  72. ) = RtlUnicodeStringToAnsiString;
  73. ULONG (*BasepUnicodeStringTo8BitSize)(
  74. PUNICODE_STRING UnicodeString
  75. ) = BasepUnicodeStringToAnsiSize;
  76. ULONG (*Basep8BitStringToUnicodeSize)(
  77. PANSI_STRING AnsiString
  78. ) = BasepAnsiStringToUnicodeSize;
  79. VOID
  80. WINAPI
  81. SetFileApisToOEM(
  82. VOID
  83. )
  84. {
  85. Basep8BitStringToUnicodeString = RtlOemStringToUnicodeString;
  86. BasepUnicodeStringTo8BitString = RtlUnicodeStringToOemString;
  87. BasepUnicodeStringTo8BitSize = BasepUnicodeStringToOemSize;
  88. Basep8BitStringToUnicodeSize = BasepOemStringToUnicodeSize;
  89. }
  90. VOID
  91. WINAPI
  92. SetFileApisToANSI(
  93. VOID
  94. )
  95. {
  96. Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
  97. BasepUnicodeStringTo8BitString = RtlUnicodeStringToAnsiString;
  98. BasepUnicodeStringTo8BitSize = BasepUnicodeStringToAnsiSize;
  99. Basep8BitStringToUnicodeSize = BasepAnsiStringToUnicodeSize;
  100. }
  101. BOOL
  102. WINAPI
  103. AreFileApisANSI(
  104. VOID
  105. )
  106. {
  107. return Basep8BitStringToUnicodeString == RtlAnsiStringToUnicodeString;
  108. }
  109. BOOLEAN
  110. ConDllInitialize(
  111. IN ULONG Reason,
  112. IN PWSTR pObjectDirectory OPTIONAL
  113. );
  114. BOOLEAN
  115. NlsDllInitialize(
  116. IN PVOID DllHandle,
  117. IN ULONG Reason,
  118. IN PBASE_STATIC_SERVER_DATA BaseStaticServerData
  119. );
  120. VOID
  121. NlsThreadCleanup(
  122. VOID);
  123. #if DBG
  124. VOID
  125. WINAPI
  126. AssertDelayLoadFailureMapsAreSorted (
  127. VOID
  128. );
  129. #endif
  130. extern const UNICODE_STRING BasePathVariableName = RTL_CONSTANT_STRING(L"PATH");
  131. extern const UNICODE_STRING BaseUserProfileVariableName = RTL_CONSTANT_STRING(L"USERPROFILE");
  132. extern const UNICODE_STRING BaseTmpVariableName = RTL_CONSTANT_STRING(L"TMP");
  133. extern const UNICODE_STRING BaseTempVariableName = RTL_CONSTANT_STRING(L"TEMP");
  134. extern const UNICODE_STRING BaseDotVariableName = RTL_CONSTANT_STRING(L".");
  135. extern const UNICODE_STRING BaseDotTmpSuffixName = RTL_CONSTANT_STRING(L".tmp");
  136. extern const UNICODE_STRING BaseDotComSuffixName = RTL_CONSTANT_STRING(L".com");
  137. extern const UNICODE_STRING BaseDotPifSuffixName = RTL_CONSTANT_STRING(L".pif");
  138. extern const UNICODE_STRING BaseDotExeSuffixName = RTL_CONSTANT_STRING(L".exe");
  139. extern const UNICODE_STRING BaseConsoleInput = RTL_CONSTANT_STRING(L"CONIN$");
  140. extern const UNICODE_STRING BaseConsoleOutput = RTL_CONSTANT_STRING(L"CONOUT$");
  141. extern const UNICODE_STRING BaseConsoleGeneric = RTL_CONSTANT_STRING(L"CON");
  142. BOOLEAN
  143. BaseDllInitialize(
  144. IN PVOID DllHandle,
  145. IN ULONG Reason,
  146. IN PCONTEXT Context OPTIONAL
  147. )
  148. /*++
  149. Routine Description:
  150. This function implements Win32 base dll initialization.
  151. It's primary purpose is to create the Base heap.
  152. Arguments:
  153. DllHandle - Saved in BaseDllHandle global variable
  154. Context - Not Used
  155. Return Value:
  156. STATUS_SUCCESS
  157. --*/
  158. {
  159. BOOLEAN Success;
  160. NTSTATUS Status;
  161. PPEB Peb;
  162. LPWSTR p, p1;
  163. BOOLEAN ServerProcess;
  164. HANDLE hNlsCacheMutant;
  165. USHORT Size;
  166. #if !defined(BUILD_WOW6432)
  167. ULONG SizeMutant;
  168. #endif
  169. WCHAR szSessionDir[MAX_SESSION_PATH];
  170. Peb = NtCurrentPeb();
  171. SessionId = Peb->SessionId;
  172. BaseDllHandle = DllHandle;
  173. Success = TRUE;
  174. switch ( Reason ) {
  175. case DLL_PROCESS_ATTACH:
  176. Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
  177. RtlSetThreadPoolStartFunc( BaseCreateThreadPoolThread,
  178. BaseExitThreadPoolThread );
  179. LdrSetDllManifestProber(&BasepProbeForDllManifest);
  180. BaseDllTag = RtlCreateTagHeap( RtlProcessHeap(),
  181. 0,
  182. L"BASEDLL!",
  183. L"TMP\0"
  184. L"BACKUP\0"
  185. L"INI\0"
  186. L"FIND\0"
  187. L"GMEM\0"
  188. L"LMEM\0"
  189. L"ENV\0"
  190. L"RES\0"
  191. L"VDM\0"
  192. );
  193. BaseIniFileUpdateCount = 0;
  194. BaseDllInitializeMemoryManager();
  195. BaseDefaultPath.Length = 0;
  196. BaseDefaultPath.MaximumLength = 0;
  197. BaseDefaultPath.Buffer = NULL;
  198. //
  199. // Connect to BASESRV.DLL in the server process
  200. //
  201. #if !defined(BUILD_WOW6432)
  202. SizeMutant = sizeof(hNlsCacheMutant);
  203. #endif
  204. if ( SessionId == 0 ) {
  205. //
  206. // Console Session
  207. //
  208. wcscpy(szSessionDir, WINSS_OBJECT_DIRECTORY_NAME);
  209. } else {
  210. swprintf(szSessionDir,L"%ws\\%ld%ws",SESSION_ROOT,SessionId,WINSS_OBJECT_DIRECTORY_NAME);
  211. }
  212. #if defined(BUILD_WOW6432) || defined(_WIN64)
  213. Status = NtQuerySystemInformation(SystemBasicInformation,
  214. &SysInfo,
  215. sizeof(SYSTEM_BASIC_INFORMATION),
  216. NULL
  217. );
  218. if (!NT_SUCCESS(Status)) {
  219. return FALSE;
  220. }
  221. Status = RtlGetNativeSystemInformation(
  222. SystemProcessorInformation,
  223. &NativeProcessorInfo,
  224. sizeof(SYSTEM_PROCESSOR_INFORMATION),
  225. NULL
  226. );
  227. if (!NT_SUCCESS(Status)) {
  228. return FALSE;
  229. }
  230. #endif
  231. #if defined(BUILD_WOW6432)
  232. Status = CsrBaseClientConnectToServer(szSessionDir,
  233. &hNlsCacheMutant,
  234. &ServerProcess
  235. );
  236. #else
  237. Status = CsrClientConnectToServer( szSessionDir,
  238. BASESRV_SERVERDLL_INDEX,
  239. &hNlsCacheMutant,
  240. &SizeMutant,
  241. &ServerProcess
  242. );
  243. #endif
  244. if (!NT_SUCCESS( Status )) {
  245. return FALSE;
  246. }
  247. BaseStaticServerData = BASE_SHARED_SERVER_DATA;
  248. if (!ServerProcess) {
  249. CsrNewThread();
  250. BaseRunningInServerProcess = FALSE;
  251. }
  252. else {
  253. BaseRunningInServerProcess = TRUE;
  254. }
  255. BaseCSDVersion = BaseStaticServerData->CSDVersion;
  256. BaseCSDNumber = BaseStaticServerData->CSDNumber;
  257. BaseRCNumber = BaseStaticServerData->RCNumber;
  258. if ((BaseCSDVersion) &&
  259. (!Peb->CSDVersion.Buffer)) {
  260. RtlInitUnicodeString(&Peb->CSDVersion, BaseCSDVersion);
  261. }
  262. BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsDirectory, &BaseStaticServerData->WindowsDirectory);
  263. BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsSystemDirectory, &BaseStaticServerData->WindowsSystemDirectory);
  264. #ifdef WX86
  265. BASE_SERVER_STR_TO_LOCAL_STR(&BaseWindowsSys32x86Directory, &BaseStaticServerData->WindowsSys32x86Directory);
  266. #endif
  267. BaseUnicodeCommandLine = Peb->ProcessParameters->CommandLine;
  268. Status = RtlUnicodeStringToAnsiString(
  269. &BaseAnsiCommandLine,
  270. &BaseUnicodeCommandLine,
  271. TRUE
  272. );
  273. if ( !NT_SUCCESS(Status) ){
  274. BaseAnsiCommandLine.Buffer = NULL;
  275. BaseAnsiCommandLine.Length = 0;
  276. BaseAnsiCommandLine.MaximumLength = 0;
  277. }
  278. p = BaseDefaultPathBuffer;
  279. p1 = BaseWindowsSystemDirectory.Buffer;
  280. while( *p = *p1++) {
  281. p++;
  282. }
  283. *p++ = L';';
  284. #ifdef WX86
  285. //
  286. // Wx86 system dir follows 32 bit system dir
  287. //
  288. p1 = BaseWindowsSys32x86Directory.Buffer;
  289. while( *p = *p1++) {
  290. p++;
  291. }
  292. *p++ = L';';
  293. #endif
  294. //
  295. // 16bit system directory follows 32bit system directory
  296. //
  297. p1 = BaseWindowsDirectory.Buffer;
  298. while( *p = *p1++) {
  299. p++;
  300. }
  301. p1 = L"\\system";
  302. while( *p = *p1++) {
  303. p++;
  304. }
  305. *p++ = L';';
  306. p1 = BaseWindowsDirectory.Buffer;
  307. while( *p = *p1++) {
  308. p++;
  309. }
  310. *p++ = L';';
  311. if (IsTerminalServer()) {
  312. WCHAR TermSrvWindowsPath[MAX_PATH];
  313. SIZE_T TermSrvWindowsPathLength = 0;
  314. NTSTATUS TermSrvWindowsPathStatus;
  315. TermSrvWindowsPathStatus = GetPerUserWindowsDirectory(
  316. TermSrvWindowsPath,
  317. RTL_NUMBER_OF(TermSrvWindowsPath),
  318. &TermSrvWindowsPathLength
  319. );
  320. if (NT_SUCCESS(TermSrvWindowsPathStatus)
  321. && TermSrvWindowsPathLength != 0
  322. ) {
  323. RtlCopyMemory(p, TermSrvWindowsPath, (TermSrvWindowsPathLength * sizeof(p[0])));
  324. p += TermSrvWindowsPathLength;
  325. *p++ = L';';
  326. }
  327. }
  328. *p = UNICODE_NULL;
  329. BaseDefaultPath.Buffer = BaseDefaultPathBuffer;
  330. BaseDefaultPath.Length = (USHORT)((ULONG_PTR)p - (ULONG_PTR)BaseDefaultPathBuffer);
  331. BaseDefaultPath.MaximumLength = sizeof( BaseDefaultPathBuffer );
  332. BaseDefaultPathAppend.Buffer = p;
  333. BaseDefaultPathAppend.Length = 0;
  334. BaseDefaultPathAppend.MaximumLength = (USHORT)
  335. (BaseDefaultPath.MaximumLength - BaseDefaultPath.Length);
  336. if (!NT_SUCCESS(RtlInitializeCriticalSection(&BaseDllDirectoryLock))) {
  337. return FALSE;
  338. }
  339. if (!NT_SUCCESS(RtlInitializeCriticalSection(&BaseLZSemTable))) {
  340. return FALSE;
  341. }
  342. BaseDllInitializeIniFileMappings( BaseStaticServerData );
  343. if ( Peb->ProcessParameters ) {
  344. if ( Peb->ProcessParameters->Flags & RTL_USER_PROC_PROFILE_USER ) {
  345. LoadLibraryW(PsapiDllString);
  346. }
  347. if (Peb->ProcessParameters->DebugFlags) {
  348. DbgBreakPoint();
  349. }
  350. }
  351. //
  352. // call the NLS API initialization routine
  353. //
  354. if ( !NlsDllInitialize( DllHandle,
  355. Reason,
  356. BaseStaticServerData ) )
  357. {
  358. return FALSE;
  359. }
  360. //
  361. // call the console initialization routine
  362. //
  363. if ( !ConDllInitialize(Reason,szSessionDir) ) {
  364. return FALSE;
  365. }
  366. InitializeListHead( &BasepAppCertDllsList );
  367. if (!NT_SUCCESS(RtlInitializeCriticalSection(&gcsAppCert))) {
  368. return FALSE;
  369. }
  370. if (!NT_SUCCESS(RtlInitializeCriticalSection(&gcsAppCompat))) {
  371. return(FALSE);
  372. }
  373. #if DBG
  374. AssertDelayLoadFailureMapsAreSorted ();
  375. #endif
  376. break;
  377. case DLL_PROCESS_DETACH:
  378. //
  379. // Make sure any open registry keys are closed.
  380. //
  381. if (BaseIniFileUpdateCount != 0) {
  382. WriteProfileStringW( NULL, NULL, NULL );
  383. }
  384. break;
  385. case DLL_THREAD_ATTACH:
  386. //
  387. // call the console initialization routine
  388. //
  389. if ( !ConDllInitialize(Reason,NULL) ) {
  390. return FALSE;
  391. }
  392. break;
  393. case DLL_THREAD_DETACH:
  394. //
  395. // Delete the thread NLS cache, if exists.
  396. //
  397. NlsThreadCleanup();
  398. break;
  399. default:
  400. break;
  401. }
  402. return Success;
  403. }
  404. NTSTATUS
  405. NTAPI
  406. BaseProcessInitPostImport()
  407. /*
  408. Routine Description:
  409. Called by the ntdll process initialization code after all of the
  410. import tables for the static imports of the EXE have been processed,
  411. but before any DLL_PROCESS_ATTACHes are sent with the exception of
  412. kernel32.dll's.
  413. Needed for the terminal server app compat hooks.
  414. */
  415. {
  416. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  417. //
  418. // Intialize TerminalServer(Hydra) hook function pointers for app compatibility
  419. //
  420. if (IsTerminalServer()) {
  421. Status = BasepInitializeTermsrvFpns();
  422. if (!NT_SUCCESS(Status)) {
  423. goto Exit;
  424. }
  425. }
  426. Status = STATUS_SUCCESS;
  427. Exit:
  428. return Status;
  429. }
  430. HANDLE
  431. BaseGetNamedObjectDirectory(
  432. VOID
  433. )
  434. {
  435. OBJECT_ATTRIBUTES Obja;
  436. NTSTATUS Status;
  437. const static UNICODE_STRING RestrictedObjectDirectory = RTL_CONSTANT_STRING(L"Restricted");
  438. ACCESS_MASK DirAccess = DIRECTORY_ALL_ACCESS &
  439. ~(DELETE | WRITE_DAC | WRITE_OWNER);
  440. HANDLE hRootNamedObject;
  441. HANDLE BaseHandle;
  442. HANDLE Token, NewToken;
  443. if ( BaseNamedObjectDirectory != NULL) {
  444. return BaseNamedObjectDirectory;
  445. }
  446. if (NtCurrentTeb()->IsImpersonating) {
  447. //
  448. // If we're impersonating, save the impersonation token, and
  449. // revert to self for the duration of the directory creation.
  450. //
  451. Status = NtOpenThreadToken(NtCurrentThread(),
  452. TOKEN_IMPERSONATE,
  453. TRUE,
  454. &Token);
  455. if (! NT_SUCCESS(Status)) {
  456. return BaseNamedObjectDirectory;
  457. }
  458. NewToken = NULL;
  459. Status = NtSetInformationThread(NtCurrentThread(),
  460. ThreadImpersonationToken,
  461. (PVOID) &NewToken,
  462. (ULONG) sizeof(NewToken));
  463. if (! NT_SUCCESS(Status)) {
  464. NtClose(Token);
  465. return BaseNamedObjectDirectory;
  466. }
  467. } else {
  468. Token = NULL;
  469. }
  470. RtlAcquirePebLock();
  471. if ( !BaseNamedObjectDirectory ) {
  472. BASE_READ_REMOTE_STR_TEMP(TempStr);
  473. InitializeObjectAttributes( &Obja,
  474. BASE_READ_REMOTE_STR(BaseStaticServerData->NamedObjectDirectory, TempStr),
  475. OBJ_CASE_INSENSITIVE,
  476. NULL,
  477. NULL
  478. );
  479. Status = NtOpenDirectoryObject( &BaseHandle,
  480. DirAccess,
  481. &Obja
  482. );
  483. // if the intial open failed, try again with just traverse, and
  484. // open the restricted subdirectory
  485. if ( !NT_SUCCESS(Status) ) {
  486. Status = NtOpenDirectoryObject( &hRootNamedObject,
  487. DIRECTORY_TRAVERSE,
  488. &Obja
  489. );
  490. if ( NT_SUCCESS(Status) ) {
  491. InitializeObjectAttributes( &Obja,
  492. (PUNICODE_STRING)&RestrictedObjectDirectory,
  493. OBJ_CASE_INSENSITIVE,
  494. hRootNamedObject,
  495. NULL
  496. );
  497. Status = NtOpenDirectoryObject( &BaseHandle,
  498. DirAccess,
  499. &Obja
  500. );
  501. NtClose( hRootNamedObject );
  502. }
  503. }
  504. if ( NT_SUCCESS(Status) ) {
  505. BaseNamedObjectDirectory = BaseHandle;
  506. }
  507. }
  508. RtlReleasePebLock();
  509. if (Token) {
  510. NtSetInformationThread(NtCurrentThread(),
  511. ThreadImpersonationToken,
  512. (PVOID) &Token,
  513. (ULONG) sizeof(Token));
  514. NtClose(Token);
  515. }
  516. return BaseNamedObjectDirectory;
  517. }