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.

442 lines
9.6 KiB

  1. /*** osdet.cpp - OS Platform detection dll for V3
  2. *
  3. * Created 11/18/98
  4. *
  5. * MODIFICATION HISTORY
  6. * This currently just detects the client platform and returns it. As we detemine
  7. * what platform detection needs to do this module will change.
  8. *
  9. */
  10. #include <windows.h>
  11. #include <objbase.h>
  12. #include <tchar.h>
  13. #include <osdet.h>
  14. #include <wuv3cdm.h>
  15. #include <ar.h>
  16. static enumV3Platform DetectClientPlatform(void);
  17. static BOOL GetIEVersion(DWORD* dwMajor, DWORD* dwMinor);
  18. static WORD CorrectGetACP(void);
  19. static WORD CorrectGetOEMCP(void);
  20. static LANGID MapLangID(LANGID langid);
  21. static bool FIsNECMachine();
  22. const LANGID LANGID_ENGLISH = MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT); // 0x0409
  23. const LANGID LANGID_GREEK = MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT); // 0x0408
  24. const LANGID LANGID_JAPANESE = MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT); // 0x0411
  25. const LANGID LANGID_ARABIC = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA); // 0x0401
  26. const LANGID LANGID_HEBREW = MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT); // 0x040D
  27. const LANGID LANGID_THAI = MAKELANGID(LANG_THAI, SUBLANG_DEFAULT); // 0x041E
  28. const TCHAR Win98_REGPATH_MACHLCID[] = _T("Control Panel\\Desktop\\ResourceLocale");
  29. const TCHAR REGPATH_CODEPAGE[] = _T("SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage");
  30. const TCHAR REGKEY_OEMCP[] = _T("OEMCP");
  31. const TCHAR REGKEY_ACP[] = _T("ACP");
  32. const TCHAR REGKEY_LOCALE[] = _T("Locale");
  33. const WORD CODEPAGE_ARABIC = 1256;
  34. const WORD CODEPAGE_HEBREW = 1255;
  35. const WORD CODEPAGE_THAI = 874;
  36. const WORD CODEPAGE_GREEK_MS = 737;
  37. const WORD CODEPAGE_GREEK_IBM = 869;
  38. #define REGKEY_WUV3TEST _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\wuv3test")
  39. // Registry keys to determine NEC machines
  40. const TCHAR NT5_REGPATH_MACHTYPE[] = _T("HARDWARE\\DESCRIPTION\\System");
  41. const TCHAR NT5_REGKEY_MACHTYPE[] = _T("Identifier");
  42. const TCHAR REGVAL_MACHTYPE_AT[] = _T("AT/AT COMPATIBLE");
  43. const TCHAR REGVAL_MACHTYPE_NEC[] = _T("NEC PC-98");
  44. #define LOOKUP_OEMID(keybdid) HIBYTE(LOWORD((keybdid)))
  45. #define PC98_KEYBOARD_ID 0x0D
  46. BOOL APIENTRY DllMain(
  47. HANDLE hModule,
  48. DWORD ul_reason_for_call,
  49. LPVOID lpReserved
  50. )
  51. {
  52. switch (ul_reason_for_call)
  53. {
  54. case DLL_PROCESS_ATTACH:
  55. case DLL_THREAD_ATTACH:
  56. case DLL_THREAD_DETACH:
  57. case DLL_PROCESS_DETACH:
  58. break;
  59. }
  60. return TRUE;
  61. }
  62. //We have not defined what goes here yet. This will be the method called
  63. //by the V3 control to determine platform ids that are then used with
  64. //the catalog inventory.plt and bitmask.plt files.
  65. void WINAPI V3_Detection(
  66. PINT *ppiPlatformIDs,
  67. PINT piTotalIDs
  68. )
  69. {
  70. //We use coTaskMemAlloc in order to be compatible with the V3 memory allocator.
  71. //We don't want the V3 memory exception handling in this dll.
  72. *ppiPlatformIDs = (PINT)CoTaskMemAlloc(sizeof(INT));
  73. if ( !*ppiPlatformIDs )
  74. {
  75. *piTotalIDs = 0;
  76. }
  77. else
  78. {
  79. #ifdef _WUV3TEST
  80. auto_hkey hkey;
  81. if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUV3TEST, 0, KEY_READ, &hkey))
  82. {
  83. DWORD dwPlatform = 0;
  84. DWORD dwSize = sizeof(dwPlatform);
  85. if (NO_ERROR == RegQueryValueEx(hkey, _T("Platform"), 0, 0, (LPBYTE)&dwPlatform, &dwSize))
  86. {
  87. *ppiPlatformIDs[0] = (int)dwPlatform;
  88. *piTotalIDs = 1;
  89. return;
  90. }
  91. }
  92. #endif
  93. *ppiPlatformIDs[0] = (int)DetectClientPlatform();
  94. *piTotalIDs = 1;
  95. }
  96. }
  97. static LANGID MapLangID(LANGID langid)
  98. {
  99. switch (PRIMARYLANGID(langid))
  100. {
  101. case LANG_ARABIC:
  102. langid = MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA);
  103. break;
  104. case LANG_CHINESE:
  105. if (SUBLANGID(langid) != SUBLANG_CHINESE_TRADITIONAL)
  106. langid = MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED);
  107. break;
  108. case LANG_DUTCH:
  109. langid = MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH);
  110. break;
  111. case LANG_GERMAN:
  112. langid = MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN);
  113. break;
  114. case LANG_ENGLISH:
  115. //if (SUBLANGID(langid) != SUBLANG_ENGLISH_UK)
  116. langid = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
  117. break;
  118. case LANG_FRENCH:
  119. langid = MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH);
  120. break;
  121. case LANG_ITALIAN:
  122. langid = MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN);
  123. break;
  124. case LANG_KOREAN:
  125. langid = MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN);
  126. break;
  127. case LANG_NORWEGIAN:
  128. langid = MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL);
  129. break;
  130. case LANG_PORTUGUESE:
  131. // We support both SUBLANG_PORTUGUESE and SUBLANG_PORTUGUESE_BRAZILIAN
  132. break;
  133. case LANG_SPANISH:
  134. langid = MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH);
  135. break;
  136. case LANG_SWEDISH:
  137. langid = MAKELANGID(LANG_SWEDISH, SUBLANG_SWEDISH);
  138. break;
  139. };
  140. return langid;
  141. }
  142. // return V3 language ID
  143. DWORD WINAPI V3_GetLangID()
  144. {
  145. #ifdef _WUV3TEST
  146. // language spoofing
  147. auto_hkey hkey;
  148. if (NO_ERROR == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_WUV3TEST, 0, KEY_READ, &hkey)) {
  149. DWORD dwLangID = 0;
  150. DWORD dwSize = sizeof(dwLangID);
  151. if (NO_ERROR == RegQueryValueEx(hkey, _T("LangID"), 0, 0, (LPBYTE)&dwLangID, &dwSize))
  152. {
  153. return dwLangID;
  154. }
  155. }
  156. #endif
  157. WORD wCodePage = 0;
  158. LANGID langidCurrent = GetSystemDefaultUILanguage();
  159. //
  160. // special handling for languages
  161. //
  162. switch (langidCurrent)
  163. {
  164. case LANGID_ENGLISH:
  165. // enabled langauges
  166. wCodePage = CorrectGetACP();
  167. if (CODEPAGE_ARABIC != wCodePage &&
  168. CODEPAGE_HEBREW != wCodePage &&
  169. CODEPAGE_THAI != wCodePage)
  170. {
  171. wCodePage = 0;
  172. }
  173. break;
  174. case LANGID_GREEK:
  175. // Greek IBM?
  176. wCodePage = CorrectGetOEMCP();
  177. if (wCodePage != CODEPAGE_GREEK_IBM)
  178. {
  179. // if its not Greek IBM we assume its MS. The language code for Greek MS does not include
  180. // the code page
  181. wCodePage = 0;
  182. }
  183. break;
  184. case LANGID_JAPANESE:
  185. if (FIsNECMachine())
  186. {
  187. wCodePage = 1;
  188. }
  189. break;
  190. default:
  191. // map language to the ones we support
  192. langidCurrent = MapLangID(langidCurrent);
  193. break;
  194. }
  195. return MAKELONG(langidCurrent, wCodePage);
  196. }
  197. DWORD WINAPI V3_GetUserLangID()
  198. {
  199. WORD wCodePage = 0;
  200. LANGID langidCurrent = GetUserDefaultUILanguage();
  201. //
  202. // special handling for languages
  203. // (NOTE: duplicated above - can probably be optimized by putting this code into MapLangID
  204. //
  205. switch (langidCurrent)
  206. {
  207. case LANGID_ENGLISH:
  208. // enabled langauges
  209. wCodePage = CorrectGetACP();
  210. if (CODEPAGE_ARABIC != wCodePage &&
  211. CODEPAGE_HEBREW != wCodePage &&
  212. CODEPAGE_THAI != wCodePage)
  213. {
  214. wCodePage = 0;
  215. }
  216. break;
  217. case LANGID_GREEK:
  218. // Greek IBM?
  219. wCodePage = CorrectGetOEMCP();
  220. if (wCodePage != CODEPAGE_GREEK_IBM)
  221. {
  222. // if its not Greek IBM we assume its MS. The language code for Greek MS does not include
  223. // the code page
  224. wCodePage = 0;
  225. }
  226. break;
  227. case LANGID_JAPANESE:
  228. if (FIsNECMachine())
  229. {
  230. wCodePage = 1;
  231. }
  232. break;
  233. default:
  234. // map language to the ones we support
  235. langidCurrent = MapLangID(langidCurrent);
  236. break;
  237. }
  238. return MAKELONG(langidCurrent, wCodePage);
  239. }
  240. static enumV3Platform DetectClientPlatform(void)
  241. {
  242. #ifdef _WIN64
  243. return enV3_Wistler64;
  244. #else
  245. return enV3_Wistler;
  246. #endif
  247. }
  248. static BOOL GetIEVersion(DWORD* dwMajor, DWORD* dwMinor)
  249. {
  250. HKEY hSubKey;
  251. DWORD dwType;
  252. ULONG nLen;
  253. TCHAR szValue[MAX_PATH];
  254. BOOL bResult = FALSE;
  255. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\Internet Explorer"),
  256. 0, KEY_READ, &hSubKey) == NO_ERROR)
  257. {
  258. nLen = MAX_PATH;
  259. if (RegQueryValueEx(hSubKey, _T("Version"), NULL, &dwType, (LPBYTE)szValue, &nLen) == NO_ERROR)
  260. {
  261. if ((nLen > 0) && (dwType == REG_SZ))
  262. {
  263. *dwMajor = (DWORD)szValue[0] - (DWORD)'0';
  264. if (nLen >= 3)
  265. *dwMinor = (DWORD)szValue[2] - (DWORD)'0';
  266. else
  267. *dwMinor = 0;
  268. return TRUE;
  269. }
  270. }
  271. RegCloseKey(hSubKey);
  272. }
  273. return FALSE;
  274. }
  275. static int aton(LPCTSTR ptr)
  276. {
  277. int i = 0;
  278. while ('0' <= *ptr && *ptr <= '9')
  279. {
  280. i = 10 * i + (int)(*ptr - '0');
  281. ptr ++;
  282. }
  283. return i;
  284. }
  285. static WORD CorrectGetACP(void)
  286. {
  287. WORD wCodePage = 0;
  288. auto_hkey hkey;
  289. RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGPATH_CODEPAGE, 0, KEY_QUERY_VALUE, &hkey);
  290. DWORD type;
  291. TCHAR szCodePage[MAX_PATH];
  292. DWORD size = sizeof(szCodePage);
  293. if (NO_ERROR == RegQueryValueEx(hkey, REGKEY_ACP, 0, &type, (BYTE *)szCodePage, &size) &&
  294. type == REG_SZ)
  295. {
  296. wCodePage = (WORD)aton(szCodePage);
  297. }
  298. return wCodePage;
  299. }
  300. static WORD CorrectGetOEMCP(void)
  301. {
  302. WORD wCodePage = 0;
  303. auto_hkey hkey;
  304. RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGPATH_CODEPAGE, 0, KEY_QUERY_VALUE, &hkey);
  305. DWORD type;
  306. TCHAR szCodePage[MAX_PATH];
  307. DWORD size = sizeof(szCodePage);
  308. if (NO_ERROR == RegQueryValueEx(hkey, REGKEY_OEMCP, 0, &type, (BYTE *)szCodePage, &size) &&
  309. type == REG_SZ)
  310. {
  311. wCodePage = (WORD)aton(szCodePage);
  312. }
  313. return wCodePage;
  314. }
  315. static bool FIsNECMachine()
  316. {
  317. bool fNEC = false;
  318. OSVERSIONINFO osverinfo;
  319. osverinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  320. if (GetVersionEx(&osverinfo))
  321. {
  322. if (osverinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  323. {
  324. HKEY hKey;
  325. DWORD type;
  326. TCHAR tszMachineType[50];
  327. DWORD size = sizeof(tszMachineType);
  328. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  329. NT5_REGPATH_MACHTYPE,
  330. 0,
  331. KEY_QUERY_VALUE,
  332. &hKey) == ERROR_SUCCESS)
  333. {
  334. if (RegQueryValueEx(hKey,
  335. NT5_REGKEY_MACHTYPE,
  336. 0,
  337. &type,
  338. (BYTE *)tszMachineType,
  339. &size) == ERROR_SUCCESS)
  340. {
  341. if (type == REG_SZ)
  342. {
  343. if (lstrcmp(tszMachineType, REGVAL_MACHTYPE_NEC) == 0)
  344. {
  345. fNEC = true;
  346. }
  347. }
  348. }
  349. RegCloseKey(hKey);
  350. }
  351. }
  352. else // enOSWin98
  353. {
  354. // All NEC machines have NEC keyboards for Win98. NEC
  355. // machine detection is based on this.
  356. if (LOOKUP_OEMID(GetKeyboardType(1)) == PC98_KEYBOARD_ID)
  357. {
  358. fNEC = true;
  359. }
  360. }
  361. }
  362. return fNEC;
  363. }