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.

687 lines
18 KiB

  1. #include "pch.h"
  2. #include "loader.h"
  3. #include <stdlib.h>
  4. #pragma hdrstop
  5. #define ISNT() (g_VersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  6. #define ISOSR2() (LOWORD(g_VersionInfo.dwBuildNumber) > 1080)
  7. #define BUILDNUM() (g_VersionInfo.dwBuildNumber)
  8. //
  9. // Global variables defined here
  10. //
  11. //
  12. // TargetNativeLangID : this is native language ID of running system
  13. //
  14. LANGID TargetNativeLangID;
  15. //
  16. // SourceNativeLangID : this is native language ID of new NT you want to install
  17. //
  18. LANGID SourceNativeLangID;
  19. //
  20. // g_IsLanguageMatched : if source and target language are matched (or compatible)
  21. //
  22. // 1. if SourceNativeLangID == TargetNativeLangID
  23. //
  24. // 2. if SourceNativeLangID's alternative ID == TargetNativeLangID
  25. //
  26. BOOL g_IsLanguageMatched;
  27. typedef struct _tagAltSourceLocale {
  28. LANGID LangId;
  29. LANGID AltLangId;
  30. DWORD MajorOs;
  31. DWORD MinorOs;
  32. DWORD ExcludedOs;
  33. } ALTSOURCELOCALE, *PALTSOURCELOCALE;
  34. ALTSOURCELOCALE g_AltSourceLocale [] = {{0x00000C04, 0x00000409, 0x0200, 0xFFFFFFFF, 0xFFFFFFFF},
  35. {0x0000040D, 0x00000409, 0x0200, 0xFFFFFFFF, 0xFFFFFFFF},
  36. {0x00000401, 0x00000409, 0x0200, 0xFFFFFFFF, 0xFFFFFFFF},
  37. {0x0000041E, 0x00000409, 0x0200, 0xFFFFFFFF, 0xFFFFFFFF},
  38. {0x00000809, 0x00000409, 0x00FF, 0xFFFFFFFF, 0xFFFFFFFF},
  39. {0x0000080A, 0x00000C0A, 0x00FF, 0xFFFFFFFF, 0xFFFFFFFF},
  40. {0x0000040A, 0x00000C0A, 0x0300, 0xFFFFFFFF, 0xFFFFFFFF},
  41. {0x00000425, 0x00000409, 0x00FF, 0xFFFFFFFF, 0xFFFFFFFF},
  42. {0x00000801, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  43. {0x00000c01, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  44. {0x00001001, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  45. {0x00001401, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  46. {0x00001801, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  47. {0x00001c01, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  48. {0x00002001, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  49. {0x00002401, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  50. {0x00002801, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  51. {0x00002c01, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  52. {0x00003001, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  53. {0x00003401, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  54. {0x00003801, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  55. {0x00003c01, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  56. {0x00004001, 0x00000401, 0x0001, 0xFFFFFFFF, 0xFFFFFFFF},
  57. {0, 0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}};
  58. typedef struct _tagTrustedSourceLocale {
  59. LANGID LangId;
  60. DWORD MajorOs;
  61. DWORD MinorOs;
  62. DWORD ExcludedOs;
  63. } TRUSTEDSOURCELOCALE, *PTRUSTEDSOURCELOCALE;
  64. TRUSTEDSOURCELOCALE g_TrustedSourceLocale [] = {{0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}};
  65. typedef struct _tagOSVERSIONMAJORID {
  66. PCTSTR Name;
  67. DWORD MajorId;
  68. DWORD Platform;
  69. DWORD Major;
  70. DWORD Minor;
  71. } OSVERSIONMAJORID, *POSVERSIONMAJORID;
  72. OSVERSIONMAJORID g_OsVersionMajorId [] = {{TEXT("Win95"), 0x0001, 1, 4, 0},
  73. {TEXT("Win98"), 0x0002, 1, 4, 10},
  74. {TEXT("WinME"), 0x0004, 1, 4, 90},
  75. {TEXT("WinNT351"), 0x0100, 2, 3, 51},
  76. {TEXT("WinNT40"), 0x0200, 2, 4, 0},
  77. {NULL, 0, 0, 0, 0}};
  78. typedef struct _tagOSVERSIONMINORID {
  79. PCTSTR Name;
  80. DWORD MajorId;
  81. DWORD MinorId;
  82. DWORD Platform;
  83. DWORD Major;
  84. DWORD Minor;
  85. DWORD Build;
  86. PCTSTR CSDVer;
  87. } OSVERSIONMINORID, *POSVERSIONMINORID;
  88. OSVERSIONMINORID g_OsVersionMinorId [] = {{NULL, 0, 0, 0, 0, 0, 0, NULL}};
  89. typedef struct _tagLANGINFO {
  90. LANGID LangID;
  91. INT Count;
  92. } LANGINFO,*PLANGINFO;
  93. BOOL
  94. TrustedDefaultUserLocale (
  95. LANGID LangID
  96. );
  97. BOOL
  98. CALLBACK
  99. EnumLangProc(
  100. HANDLE hModule, // resource-module handle
  101. LPCTSTR lpszType, // pointer to resource type
  102. LPCTSTR lpszName, // pointer to resource name
  103. WORD wIDLanguage, // resource language identifier
  104. LONG_PTR lParam // application-defined parameter
  105. )
  106. /*++
  107. Routine Description:
  108. Callback that counts versions stamps.
  109. Arguments:
  110. Details of version enumerated version stamp. (Ignore.)
  111. Return Value:
  112. Indirectly thru lParam: count, langID
  113. --*/
  114. {
  115. PLANGINFO LangInfo;
  116. LangInfo = (PLANGINFO) lParam;
  117. LangInfo->Count++;
  118. //
  119. // for localized build contains multiple resource,
  120. // it usually contains 0409 as backup lang.
  121. //
  122. // if LangInfo->LangID != 0 means we already assigned an ID to it
  123. //
  124. // so when wIDLanguage == 0x409, we keep the one we got from last time
  125. //
  126. if ((wIDLanguage == 0x409) && (LangInfo->LangID != 0)) {
  127. return TRUE;
  128. }
  129. LangInfo->LangID = wIDLanguage;
  130. return TRUE; // continue enumeration
  131. }
  132. LANGID
  133. GetNTDLLNativeLangID (
  134. VOID
  135. )
  136. /*++
  137. Routine Description:
  138. This function is designed specifically for getting native lang of ntdll.dll
  139. This is not a generic function to get other module's language
  140. the assumption is:
  141. 1. if only one language in resource then return this lang
  142. 2. if two languages in resource then return non-US language
  143. 3. if more than two languages, it's invalid in our case, but returns the last one.
  144. Arguments:
  145. None
  146. Return Value:
  147. Native lang ID in ntdll.dll
  148. --*/
  149. {
  150. LPCTSTR Type = (LPCTSTR) RT_VERSION;
  151. LPCTSTR Name = (LPCTSTR) 1;
  152. LANGINFO LangInfo;
  153. ZeroMemory(&LangInfo,sizeof(LangInfo));
  154. EnumResourceLanguages (
  155. GetModuleHandle(TEXT("ntdll.dll")),
  156. Type,
  157. Name,
  158. EnumLangProc,
  159. (LONG_PTR) &LangInfo
  160. );
  161. if ((LangInfo.Count > 2) || (LangInfo.Count < 1) ) {
  162. //
  163. // put error log here
  164. //
  165. // so far, for NT 3.51, only JPN has two language resources
  166. }
  167. return LangInfo.LangID;
  168. }
  169. BOOL
  170. IsHongKongVersion (
  171. VOID
  172. )
  173. /*++
  174. Routine Description:
  175. Try to identify HongKong NT 4.0
  176. It based on:
  177. NTDLL's language is English and build is 1381 and
  178. pImmReleaseContext return TRUE
  179. Arguments:
  180. Return Value:
  181. Language ID of running system
  182. --*/
  183. {
  184. HMODULE hMod;
  185. BOOL bRet=FALSE;
  186. typedef BOOL (*IMMRELEASECONTEXT) (HWND,HANDLE);
  187. IMMRELEASECONTEXT pImmReleaseContext;
  188. LANGID TmpID = GetNTDLLNativeLangID();
  189. if ((g_VersionInfo.dwBuildNumber == 1381) &&
  190. (TmpID == 0x0409)){
  191. hMod = LoadLibrary(TEXT("imm32.dll"));
  192. if (hMod) {
  193. pImmReleaseContext = (IMMRELEASECONTEXT) GetProcAddress(hMod,"ImmReleaseContext");
  194. if (pImmReleaseContext) {
  195. bRet = pImmReleaseContext(NULL,NULL);
  196. }
  197. FreeLibrary(hMod);
  198. }
  199. }
  200. return (bRet);
  201. }
  202. LANGID
  203. GetDefaultUserLangID (
  204. VOID
  205. )
  206. {
  207. LONG dwErr;
  208. HKEY hkey;
  209. DWORD dwSize;
  210. CHAR buffer[512];
  211. LANGID langid = 0;
  212. dwErr = RegOpenKeyEx( HKEY_USERS,
  213. TEXT(".DEFAULT\\Control Panel\\International"),
  214. 0,
  215. KEY_READ,
  216. &hkey );
  217. if( dwErr == ERROR_SUCCESS ) {
  218. dwSize = sizeof(buffer);
  219. dwErr = RegQueryValueExA(hkey,
  220. "Locale",
  221. NULL, //reserved
  222. NULL, //type
  223. buffer,
  224. &dwSize );
  225. if(dwErr == ERROR_SUCCESS) {
  226. langid = LANGIDFROMLCID(strtoul(buffer,NULL,16));
  227. }
  228. RegCloseKey(hkey);
  229. }
  230. return langid;
  231. }
  232. LANGID
  233. GetTargetNativeLangID (
  234. VOID
  235. )
  236. /*++
  237. Routine Description:
  238. Applies different rules to different platforms
  239. NT
  240. build number <= 1840 : check ntdll's language,
  241. we scaned all 3.51's ntdll on boneyard\intl,
  242. it looks like we can trust them.
  243. build number > 1840 : user MUI language
  244. Win9x
  245. use default user's resource language
  246. Arguments:
  247. Return Value:
  248. Language ID of running system
  249. --*/
  250. {
  251. LONG dwErr;
  252. HKEY hkey;
  253. DWORD dwSize;
  254. CHAR buffer[512];
  255. LANGID rcLang;
  256. LANGID langid = 0;
  257. // Find out if we are running on NT or WIN9X
  258. if( ISNT() ) {
  259. //
  260. // We're on NT, but which version? GetSystemDefaultUILanguage() was broke until 1840...
  261. //
  262. if( g_VersionInfo.dwBuildNumber > 1840 ) {
  263. FARPROC NT5API;
  264. //
  265. // Use the API to find out our locale.
  266. //
  267. if( NT5API = GetProcAddress( GetModuleHandle(TEXT("kernel32.dll")), "GetSystemDefaultUILanguage") ) {
  268. rcLang = (LANGID)NT5API();
  269. //
  270. // need to convert decimal to hex, LANGID to chr.
  271. //
  272. langid = rcLang;
  273. }
  274. } else {
  275. //
  276. // by looking into \\boneyard\intl, almost every ntdll.dll marked correct lang ID
  277. // so get langID from ntdll.dll
  278. //
  279. langid = GetNTDLLNativeLangID();
  280. if (langid == 0x0409) {
  281. if (IsHongKongVersion()) {
  282. langid = 0x0C04;
  283. } else {
  284. //
  285. // if default user's locale is in [TrustedDefaultUserLocale]
  286. //
  287. // then this is a backdoor for some localized build that its ntdll.dll marked
  288. //
  289. // as English but can't be upgrade by US version.
  290. //
  291. LANGID DefaultUserLangID = GetDefaultUserLangID();
  292. if (DefaultUserLangID &&
  293. TrustedDefaultUserLocale (DefaultUserLangID)) {
  294. langid = DefaultUserLangID;
  295. }
  296. }
  297. }
  298. }
  299. } else {
  300. //
  301. // We're on Win9x.
  302. //
  303. dwErr = RegOpenKeyEx( HKEY_USERS,
  304. TEXT(".Default\\Control Panel\\desktop\\ResourceLocale"),
  305. 0,
  306. KEY_READ,
  307. &hkey );
  308. if (dwErr == ERROR_SUCCESS) {
  309. dwSize = sizeof(buffer);
  310. dwErr = RegQueryValueExA( hkey,
  311. "",
  312. NULL, //reserved
  313. NULL, //type
  314. buffer,
  315. &dwSize );
  316. if(dwErr == ERROR_SUCCESS) {
  317. langid = LANGIDFROMLCID(strtoul(buffer,NULL,16));
  318. }
  319. RegCloseKey(hkey);
  320. }
  321. if ( dwErr != ERROR_SUCCESS ) {
  322. // Check HKLM\System\CurrentControlSet\Control\Nls\Locale
  323. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  324. TEXT("System\\CurrentControlSet\\Control\\Nls\\Locale"),
  325. 0,
  326. KEY_READ,
  327. &hkey );
  328. if (dwErr == ERROR_SUCCESS) {
  329. dwSize = sizeof(buffer);
  330. dwErr = RegQueryValueExA( hkey,
  331. "",
  332. NULL, //reserved
  333. NULL, //type
  334. buffer,
  335. &dwSize );
  336. if (dwErr == ERROR_SUCCESS) {
  337. langid = LANGIDFROMLCID(strtoul(buffer,NULL,16));
  338. }
  339. RegCloseKey(hkey);
  340. }
  341. }
  342. }
  343. return (langid);
  344. }
  345. LANGID
  346. GetSourceNativeLangID (
  347. VOID
  348. )
  349. /*++
  350. Routine Description:
  351. [DefaultValues]
  352. Locale = xxxx
  353. every localized build has it's own Locale in intl.inf,
  354. so we use this value to identify source languag
  355. Arguments:
  356. Return Value:
  357. Language ID of source
  358. --*/
  359. {
  360. // BUGBUG - implement this by reading our own version info.
  361. LPCTSTR Type = (LPCTSTR) RT_VERSION;
  362. LPCTSTR Name = (LPCTSTR) 1;
  363. LANGINFO LangInfo;
  364. ZeroMemory(&LangInfo,sizeof(LangInfo));
  365. EnumResourceLanguages (
  366. NULL, // our own module
  367. Type,
  368. Name,
  369. EnumLangProc,
  370. (LONG_PTR) &LangInfo
  371. );
  372. if ((LangInfo.Count > 2) || (LangInfo.Count < 1) ) {
  373. //
  374. // put error log here
  375. //
  376. // so far, for NT 3.51, only JPN has two language resources
  377. }
  378. return LangInfo.LangID;
  379. }
  380. DWORD
  381. GetOsMajorId (
  382. VOID
  383. )
  384. {
  385. POSVERSIONMAJORID p = g_OsVersionMajorId;
  386. while (p->Name) {
  387. if ((p->Platform == g_VersionInfo.dwPlatformId) &&
  388. (p->Major == g_VersionInfo.dwMajorVersion) &&
  389. (p->Minor == g_VersionInfo.dwMinorVersion)
  390. ) {
  391. return p->MajorId;
  392. }
  393. p++;
  394. }
  395. return 0;
  396. }
  397. DWORD
  398. GetOsMinorId (
  399. VOID
  400. )
  401. {
  402. POSVERSIONMINORID p = g_OsVersionMinorId;
  403. while (p->Name) {
  404. if ((p->Platform == g_VersionInfo.dwPlatformId) &&
  405. (p->Major == g_VersionInfo.dwMajorVersion) &&
  406. (p->Minor == g_VersionInfo.dwMinorVersion) &&
  407. (p->Build == g_VersionInfo.dwBuildNumber) &&
  408. ((p->CSDVer == NULL) || _tcsicmp (p->CSDVer, g_VersionInfo.szCSDVersion))
  409. ) {
  410. return p->MinorId;
  411. }
  412. p++;
  413. }
  414. return 0;
  415. }
  416. BOOL
  417. TrustedDefaultUserLocale (
  418. LANGID LangID
  419. )
  420. {
  421. PTRUSTEDSOURCELOCALE p = g_TrustedSourceLocale;
  422. while (p->LangId) {
  423. if ((!(p->ExcludedOs & GetOsMinorId ())) &&
  424. ((p->MinorOs & GetOsMinorId ()) || (p->MajorOs & GetOsMajorId ()))
  425. ) {
  426. return TRUE;
  427. }
  428. p++;
  429. }
  430. return FALSE;
  431. }
  432. BOOL
  433. CheckLanguageVersion (
  434. LANGID SourceLangID,
  435. LANGID TargetLangID
  436. )
  437. /*++
  438. Routine Description:
  439. Check if the language of source NT is same as target NT or ,at least,
  440. compatibile
  441. Arguments:
  442. Inf handle of intl.inf
  443. Return Value:
  444. TRUE They are same or compatibile
  445. FALSE They are different
  446. --*/
  447. {
  448. PALTSOURCELOCALE p = g_AltSourceLocale;
  449. TCHAR TargetLangIDStr[9];
  450. LANGID SrcLANGID;
  451. LANGID DstLANGID;
  452. LANGID AltSourceLangID;
  453. //
  454. // If either one is 0, allow the upgrade. This is Windows 2000 Beta3 behavior.
  455. //
  456. if (SourceLangID == 0 || TargetLangID == 0) {
  457. return TRUE;
  458. }
  459. if (SourceLangID == TargetLangID) {
  460. return TRUE;
  461. }
  462. //
  463. // if Src != Dst, then we need to look up inf file to see
  464. //
  465. // if we can open a backdoor for Target language
  466. //
  467. //
  468. // use TargetLangID as key to find alternative SourceLangID
  469. //
  470. while (p->LangId) {
  471. //
  472. // Check if we found alternative locale
  473. //
  474. AltSourceLangID = LANGIDFROMLCID(p->AltLangId);
  475. if ((TargetLangID == p->LangId) &&
  476. (SourceLangID == AltSourceLangID)
  477. ) {
  478. //
  479. // We are here if we found alternative source lang,
  480. //
  481. // now check the version criteria
  482. //
  483. if ((!(p->ExcludedOs & GetOsMinorId ())) &&
  484. ((p->MinorOs & GetOsMinorId ()) || (p->MajorOs & GetOsMajorId ()))
  485. ) {
  486. return TRUE;
  487. }
  488. }
  489. p++;
  490. }
  491. return FALSE;
  492. }
  493. BOOL
  494. InitLanguageDetection (
  495. VOID
  496. )
  497. /*++
  498. Routine Description:
  499. Initialize language detection and put the result in 3 global variables
  500. SourceNativeLangID - LANGID of Source (NT is going to be installed)
  501. TargetNativeLangID - LANGID of Target (OS system which is running)
  502. g_IsLanguageMatched - If language is not matched, then blocks upgrade
  503. Arguments:
  504. None
  505. Return Value:
  506. TRUE init correctly
  507. FALSE init failed
  508. --*/
  509. {
  510. //
  511. // Init Global Variables
  512. //
  513. SourceNativeLangID = GetSourceNativeLangID();
  514. TargetNativeLangID = GetTargetNativeLangID();
  515. g_IsLanguageMatched = CheckLanguageVersion(SourceNativeLangID,TargetNativeLangID);
  516. if (!g_IsLanguageMatched) {
  517. if (SourceNativeLangID == 0x00000409) {
  518. // This is a localized system running an English wizard.
  519. // We want to allow that.
  520. g_IsLanguageMatched = TRUE;
  521. }
  522. }
  523. return TRUE;
  524. }