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.

558 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2000.
  5. //
  6. // File: weblcid.hxx
  7. //
  8. // Contents: WEB CGI escape & unescape classes
  9. //
  10. // History: 96/Jan/3 DwightKr Created
  11. // 97/Jan/7 AlanW Split from cgiesc.cxx,
  12. // made non-destructive
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include <mlang.h>
  18. #include <weblcid.hxx>
  19. //+---------------------------------------------------------------------------
  20. //----------------------------------------------------------------------------
  21. struct tagHTTPLocale
  22. {
  23. WCHAR * wcsHttpAcceptLanguage;
  24. DWORD dwLocaleCode; // encoded form for searching
  25. LCID lcid;
  26. };
  27. const struct tagHTTPLocale aHTTPLocale[] =
  28. {
  29. L"EN", 'EN', MAKELCID( MAKELANGID(LANG_ENGLISH, // English
  30. SUBLANG_ENGLISH_US),
  31. SORT_DEFAULT ),
  32. L"EN-US", 'ENUS', MAKELCID( MAKELANGID(LANG_ENGLISH, // English-United States
  33. SUBLANG_ENGLISH_US),
  34. SORT_DEFAULT ),
  35. L"ZH", 'ZH', MAKELCID( MAKELANGID(LANG_CHINESE, // Chinese
  36. SUBLANG_CHINESE_SIMPLIFIED),
  37. SORT_CHINESE_UNICODE ),
  38. L"ZH-CN", 'ZHCN', MAKELCID( MAKELANGID(LANG_CHINESE, // Chinese/china
  39. SUBLANG_CHINESE_SIMPLIFIED),
  40. SORT_CHINESE_UNICODE ),
  41. L"ZH-TW", 'ZHTW', MAKELCID( MAKELANGID(LANG_CHINESE, // Chinese/taiwan
  42. SUBLANG_CHINESE_TRADITIONAL),
  43. SORT_CHINESE_UNICODE ),
  44. L"NL", 'NL', MAKELCID( MAKELANGID(LANG_DUTCH, // Dutch
  45. SUBLANG_DUTCH),
  46. SORT_DEFAULT ),
  47. //
  48. // Alphabetical from here
  49. //
  50. L"BG", 'BG', MAKELCID( MAKELANGID(LANG_BULGARIAN, // Bulgarian
  51. SUBLANG_DEFAULT),
  52. SORT_DEFAULT ),
  53. L"HR", 'HR', MAKELCID( MAKELANGID(LANG_CROATIAN, // Croatian
  54. SUBLANG_DEFAULT),
  55. SORT_DEFAULT ),
  56. L"CS", 'CS', MAKELCID( MAKELANGID(LANG_CZECH, // Czech
  57. SUBLANG_DEFAULT),
  58. SORT_DEFAULT ),
  59. L"DA", 'DA', MAKELCID( MAKELANGID(LANG_DANISH, // Danish
  60. SUBLANG_DEFAULT),
  61. SORT_DEFAULT ),
  62. L"FI", 'FI', MAKELCID( MAKELANGID(LANG_FINNISH, // Finnish
  63. SUBLANG_DEFAULT),
  64. SORT_DEFAULT ),
  65. L"EL", 'EL', MAKELCID( MAKELANGID(LANG_GREEK, // Greek
  66. SUBLANG_DEFAULT),
  67. SORT_DEFAULT ),
  68. L"EN-GB", 'ENGB', MAKELCID( MAKELANGID(LANG_ENGLISH, // English-United kingdom
  69. SUBLANG_ENGLISH_UK),
  70. SORT_DEFAULT ),
  71. L"FR", 'FR', MAKELCID( MAKELANGID(LANG_FRENCH, // French
  72. SUBLANG_FRENCH),
  73. SORT_DEFAULT ),
  74. L"FR-CA", 'FRCA', MAKELCID( MAKELANGID(LANG_FRENCH, // French-Canadian
  75. SUBLANG_FRENCH_CANADIAN),
  76. SORT_DEFAULT ),
  77. L"FR-FR", 'FRFR', MAKELCID( MAKELANGID(LANG_FRENCH, // French-France
  78. SUBLANG_FRENCH),
  79. SORT_DEFAULT ),
  80. L"DE", 'DE', MAKELCID( MAKELANGID(LANG_GERMAN, // German
  81. SUBLANG_GERMAN),
  82. SORT_DEFAULT ),
  83. L"HU", 'HU', MAKELCID( MAKELANGID(LANG_HUNGARIAN, // Hungarian
  84. SUBLANG_DEFAULT),
  85. SORT_DEFAULT ),
  86. L"IS", 'IS', MAKELCID( MAKELANGID(LANG_ICELANDIC, // Icelandic
  87. SUBLANG_DEFAULT),
  88. SORT_DEFAULT ),
  89. L"IT", 'IT', MAKELCID( MAKELANGID(LANG_ITALIAN, // Italian
  90. SUBLANG_ITALIAN),
  91. SORT_DEFAULT ),
  92. L"JA", 'JA', MAKELCID( MAKELANGID(LANG_JAPANESE, // Japanese
  93. SUBLANG_DEFAULT),
  94. SORT_JAPANESE_UNICODE ),
  95. L"KO", 'KO', MAKELCID( MAKELANGID(LANG_KOREAN, // Korean
  96. SUBLANG_DEFAULT),
  97. SORT_KOREAN_UNICODE ),
  98. L"NO", 'NO', MAKELCID( MAKELANGID(LANG_NORWEGIAN, // Norwegian
  99. SUBLANG_DEFAULT),
  100. SORT_DEFAULT ),
  101. L"PL", 'PL', MAKELCID( MAKELANGID(LANG_POLISH, // Polish
  102. SUBLANG_DEFAULT),
  103. SORT_DEFAULT ),
  104. L"PT", 'PT', MAKELCID( MAKELANGID(LANG_PORTUGUESE, // Portuguese
  105. SUBLANG_DEFAULT),
  106. SORT_DEFAULT ),
  107. L"PT-BR", 'PTBR', MAKELCID( MAKELANGID(LANG_PORTUGUESE, // Portuguese-Brazil
  108. SUBLANG_PORTUGUESE_BRAZILIAN),
  109. SORT_DEFAULT ),
  110. L"RO", 'RO', MAKELCID( MAKELANGID(LANG_ROMANIAN, // Romanian
  111. SUBLANG_DEFAULT),
  112. SORT_DEFAULT ),
  113. L"RU", 'RU', MAKELCID( MAKELANGID(LANG_RUSSIAN, // Russian
  114. SUBLANG_DEFAULT),
  115. SORT_DEFAULT ),
  116. L"SK", 'SK', MAKELCID( MAKELANGID(LANG_SLOVAK, // Slovak
  117. SUBLANG_DEFAULT),
  118. SORT_DEFAULT ),
  119. L"SL", 'SL', MAKELCID( MAKELANGID(LANG_SLOVENIAN, // Slovenian
  120. SUBLANG_DEFAULT),
  121. SORT_DEFAULT ),
  122. L"ES", 'ES', MAKELCID( MAKELANGID(LANG_SPANISH, // Spanish
  123. SUBLANG_SPANISH_MODERN),
  124. SORT_DEFAULT ),
  125. L"ES-ES", 'ESES', MAKELCID( MAKELANGID(LANG_SPANISH, // Spanish-Spain
  126. SUBLANG_SPANISH),
  127. SORT_DEFAULT ),
  128. L"ES-MX", 'ESES', MAKELCID( MAKELANGID(LANG_SPANISH, // Spanish-Mexican
  129. SUBLANG_SPANISH_MEXICAN),
  130. SORT_DEFAULT ),
  131. L"SV", 'SV', MAKELCID( MAKELANGID(LANG_SWEDISH, // Swedish
  132. SUBLANG_DEFAULT),
  133. SORT_DEFAULT ),
  134. L"TR", 'TR', MAKELCID( MAKELANGID(LANG_TURKISH, // Turkish
  135. SUBLANG_DEFAULT),
  136. SORT_DEFAULT ),
  137. // Less common languages
  138. L"AF", 'AF', MAKELCID( MAKELANGID(LANG_AFRIKAANS, // Afrikaans
  139. SUBLANG_DEFAULT),
  140. SORT_DEFAULT ),
  141. L"AR", 'AR', MAKELCID( MAKELANGID(LANG_ARABIC, // Arabic
  142. SUBLANG_DEFAULT),
  143. SORT_DEFAULT ),
  144. L"EU", 'EU', MAKELCID( MAKELANGID(LANG_BASQUE, // Basque
  145. SUBLANG_DEFAULT),
  146. SORT_DEFAULT ),
  147. L"BE", 'BE', MAKELCID( MAKELANGID(LANG_BELARUSIAN, // Byelorussian
  148. SUBLANG_DEFAULT),
  149. SORT_DEFAULT ),
  150. L"CA", 'CA', MAKELCID( MAKELANGID(LANG_CATALAN, // Catalan
  151. SUBLANG_DEFAULT),
  152. SORT_DEFAULT ),
  153. L"HR", 'HR', MAKELCID( MAKELANGID(LANG_CROATIAN, // Croatian
  154. SUBLANG_DEFAULT),
  155. SORT_DEFAULT ),
  156. L"ET", 'ET', MAKELCID( MAKELANGID(LANG_ESTONIAN, // Estonian
  157. SUBLANG_DEFAULT),
  158. SORT_DEFAULT ),
  159. L"FO", 'FO', MAKELCID( MAKELANGID(LANG_FAEROESE, // Faeroese
  160. SUBLANG_DEFAULT),
  161. SORT_DEFAULT ),
  162. // L"??", '??', MAKELCID( MAKELANGID(LANG_FARSI, // Farsi
  163. // SUBLANG_DEFAULT),
  164. // SORT_DEFAULT ),
  165. L"HE", 'HE', MAKELCID( MAKELANGID(LANG_HEBREW, // Hebrew
  166. SUBLANG_DEFAULT),
  167. SORT_DEFAULT ),
  168. L"IW", 'IW', MAKELCID( MAKELANGID(LANG_HEBREW, // Hebrew (ISO 639:1988)
  169. SUBLANG_DEFAULT),
  170. SORT_DEFAULT ),
  171. L"ID", 'ID', MAKELCID( MAKELANGID(LANG_INDONESIAN, // Indonesian
  172. SUBLANG_DEFAULT),
  173. SORT_DEFAULT ),
  174. L"IN", 'IN', MAKELCID( MAKELANGID(LANG_INDONESIAN, // Indonesian (ISO 639:1988)
  175. SUBLANG_DEFAULT),
  176. SORT_DEFAULT ),
  177. L"LV", 'LV', MAKELCID( MAKELANGID(LANG_LATVIAN, // Latvian
  178. SUBLANG_DEFAULT),
  179. SORT_DEFAULT ),
  180. L"LT", 'LT', MAKELCID( MAKELANGID(LANG_LITHUANIAN, // Lithuanian
  181. SUBLANG_DEFAULT),
  182. SORT_DEFAULT ),
  183. L"SR", 'SR', MAKELCID( MAKELANGID(LANG_SERBIAN, // Serbian
  184. SUBLANG_DEFAULT),
  185. SORT_DEFAULT ),
  186. L"TH", 'TH', MAKELCID( MAKELANGID(LANG_THAI, // Thai
  187. SUBLANG_DEFAULT),
  188. SORT_DEFAULT ),
  189. L"UK", 'UK', MAKELCID( MAKELANGID(LANG_UKRAINIAN, // Ukrainian
  190. SUBLANG_DEFAULT),
  191. SORT_DEFAULT ),
  192. L"VI", 'VI', MAKELCID( MAKELANGID(LANG_VIETNAMESE, // Vietnamese
  193. SUBLANG_DEFAULT),
  194. SORT_DEFAULT ),
  195. // NOTE: Neutral must be last!
  196. L"NEUTRAL", 'N', MAKELCID( MAKELANGID(LANG_NEUTRAL, // Neutral
  197. SUBLANG_NEUTRAL),
  198. SORT_DEFAULT ),
  199. };
  200. const unsigned cHTTPLocale = sizeof(aHTTPLocale) / sizeof(aHTTPLocale[0]);
  201. //+-------------------------------------------------------------------------
  202. //
  203. // Function: GetLocaleString
  204. //
  205. // Synopsis: Looks up a locale string given an LCID
  206. //
  207. // Arguments: [lcid] -- The LCID to lookup
  208. // [pwcLocale -- The resulting string
  209. //
  210. //--------------------------------------------------------------------------
  211. void GetLocaleString( LCID lcid, WCHAR * pwcLocale )
  212. {
  213. wcscpy( pwcLocale, L"Neutral" );
  214. XInterface<IMultiLanguage> xMultiLang;
  215. SCODE sc = CoCreateInstance( CLSID_CMultiLanguage,
  216. 0,
  217. CLSCTX_INPROC_SERVER,
  218. IID_IMultiLanguage,
  219. xMultiLang.GetQIPointer() );
  220. if ( SUCCEEDED( sc ) )
  221. {
  222. BSTR bstrLocale;
  223. sc = xMultiLang->GetRfc1766FromLcid( lcid, &bstrLocale );
  224. if ( SUCCEEDED( sc ) )
  225. {
  226. wcscpy( pwcLocale, bstrLocale );
  227. SysFreeString( bstrLocale );
  228. }
  229. }
  230. } //GetLocaleString
  231. //+---------------------------------------------------------------------------
  232. //
  233. // Function: GetStringFromLCID - public
  234. //
  235. // Synposis: Determines the string representation of an LCID
  236. //
  237. // Arguments: [lcid] -- The LCID to lookup
  238. // [pwcLocale -- The resulting string
  239. //
  240. // History: 96-Apr-24 DwightKr Created
  241. //
  242. //----------------------------------------------------------------------------
  243. void GetStringFromLCID( LCID lcid, WCHAR * pwcLocale )
  244. {
  245. //
  246. // Be careful to compare only the language ID, and not the sort ID.
  247. //
  248. lcid = LANGIDFROMLCID(lcid);
  249. for (ULONG i=0; i<cHTTPLocale; i++)
  250. {
  251. if ( lcid == LANGIDFROMLCID( aHTTPLocale[i].lcid ) )
  252. {
  253. qutilDebugOut(( DEB_ITRACE, "GetStringFromLCID: browser locale is %ws; lcid=0x%x\n",
  254. aHTTPLocale[i].wcsHttpAcceptLanguage,
  255. lcid ));
  256. wcscpy( pwcLocale, aHTTPLocale[i].wcsHttpAcceptLanguage );
  257. return;
  258. }
  259. }
  260. // Give up and go for Neutral if the below call fails
  261. qutilDebugOut(( DEB_ITRACE, "GetStringFromLCID: browser locale not found, lcid=0x%x\n",
  262. lcid ));
  263. wcscpy( pwcLocale, L"NEUTRAL" );
  264. //
  265. // This LCID was not found in the table, look one up.
  266. //
  267. GetLocaleString( lcid, pwcLocale );
  268. } //GetStringFromLCID
  269. //+---------------------------------------------------------------------------
  270. //
  271. // Function: EncodeLocale - public
  272. //
  273. // Synopsis: Compact a locale string for easier lookup.
  274. //
  275. // Arguments: [pwszLocale] - locale string
  276. // [dwPrimaryLang] - set to the primary language encoding if
  277. // there is a sublangage ID.
  278. //
  279. // Returns: DWORD - the significant characters in the locale or zero if
  280. // ill-formed
  281. //
  282. //+---------------------------------------------------------------------------
  283. inline DWORD EncodeLocale( WCHAR * pwszLocale, DWORD & dwPrimaryLang )
  284. {
  285. DWORD dwResult = 0;
  286. dwPrimaryLang = 0;
  287. if ( isalpha( pwszLocale[0] ) && isalpha( pwszLocale[1] ) )
  288. {
  289. dwResult = towupper(pwszLocale[0]) << 8;
  290. dwResult |= towupper(pwszLocale[1]) << 0;
  291. pwszLocale += 2;
  292. if (*pwszLocale == L'-')
  293. {
  294. dwPrimaryLang = dwResult;
  295. dwResult <<= 16;
  296. pwszLocale++;
  297. if ( isalpha( pwszLocale[0] ) && isalpha( pwszLocale[1] ) )
  298. {
  299. dwResult |= towupper(pwszLocale[0]) << 8;
  300. dwResult |= towupper(pwszLocale[1]) << 0;
  301. pwszLocale += 2;
  302. }
  303. }
  304. else if (isalpha( *pwszLocale ))
  305. {
  306. // Treat the NEUTRAL locale as a special case
  307. if (_wcsnicmp( pwszLocale-2,
  308. aHTTPLocale[cHTTPLocale-1].wcsHttpAcceptLanguage,
  309. wcslen(aHTTPLocale[cHTTPLocale-1].wcsHttpAcceptLanguage) ) == 0)
  310. {
  311. pwszLocale += wcslen(aHTTPLocale[cHTTPLocale-1].wcsHttpAcceptLanguage) - 2;
  312. dwResult = aHTTPLocale[cHTTPLocale-1].dwLocaleCode;
  313. }
  314. }
  315. }
  316. if ( *pwszLocale != L'\0' &&
  317. ! iswspace( *pwszLocale ) &&
  318. *pwszLocale != L',' && *pwszLocale != L';' )
  319. dwResult = 0;
  320. return dwResult;
  321. } //EncodeLocale
  322. //+---------------------------------------------------------------------------
  323. //
  324. // Function: LcidFromHttpAcceptLanguage
  325. //
  326. // Synposis: Determines the locale from the string passed in.
  327. //
  328. // Arguments: [pwc] the string representation of the locale
  329. //
  330. // History: 00-Oct-04 dlee Created
  331. //
  332. //----------------------------------------------------------------------------
  333. LCID LcidFromHttpAcceptLanguage( WCHAR const * pwc )
  334. {
  335. // Default to an invalid lcid
  336. LCID lcid = InvalidLCID;
  337. if ( 0 != pwc )
  338. {
  339. XInterface<IMultiLanguage> xMultiLang;
  340. SCODE sc = CoCreateInstance( CLSID_CMultiLanguage,
  341. 0,
  342. CLSCTX_INPROC_SERVER,
  343. IID_IMultiLanguage,
  344. xMultiLang.GetQIPointer() );
  345. if ( SUCCEEDED( sc ) )
  346. {
  347. BSTR bstr = SysAllocString( pwc );
  348. if ( 0 != bstr )
  349. {
  350. sc = xMultiLang->GetLcidFromRfc1766( &lcid, bstr );
  351. SysFreeString( bstr );
  352. }
  353. }
  354. }
  355. return lcid;
  356. } //LcidFromHttpAcceptLanguage
  357. //+---------------------------------------------------------------------------
  358. //
  359. // Function: GetLCIDFromString - public
  360. //
  361. // Synposis: Determines the locale from the string passed in.
  362. //
  363. // Arguments: [wcsLocale] the string representation of the locale
  364. //
  365. // History: 96-Apr-20 DwightKr Created
  366. // 97-Jan-07 AlanW Made non-destructive
  367. //
  368. // Notes: The input string is assumed to be a language list as
  369. // formatted for the Accept-Language header. This is a
  370. // command separated list of language codes.
  371. // The code here doesn't evaluate the quality parameter,
  372. // it returns the first available language found.
  373. //
  374. //----------------------------------------------------------------------------
  375. LCID GetLCIDFromString( WCHAR * wcsLocale )
  376. {
  377. unsigned iPrimaryLangEntry = 0xFFFFFFFF;
  378. const WCHAR * wcsDelim = L" \t,;=";
  379. WCHAR * wcsToken = wcsLocale;
  380. while ( 0 != wcsToken )
  381. {
  382. wcsToken += wcsspn( wcsToken, wcsDelim );
  383. DWORD dwPrimaryCode = 0;
  384. DWORD dwLocaleCode = EncodeLocale(wcsToken, dwPrimaryCode);
  385. if (dwLocaleCode != 0 || dwPrimaryCode != 0)
  386. {
  387. for (ULONG i=0; i<cHTTPLocale; i++)
  388. {
  389. if ( dwLocaleCode == aHTTPLocale[i].dwLocaleCode )
  390. {
  391. qutilDebugOut(( DEB_ITRACE,
  392. "GetLCIDFromString is %ws; lcid=0x%x\n",
  393. wcsToken,
  394. aHTTPLocale[i].lcid ));
  395. return LANGIDFROMLCID( aHTTPLocale[i].lcid );
  396. }
  397. if ( dwPrimaryCode == aHTTPLocale[i].dwLocaleCode &&
  398. iPrimaryLangEntry == 0xFFFFFFFF )
  399. iPrimaryLangEntry = i;
  400. }
  401. }
  402. wcsToken = wcschr( wcsToken, L',' );
  403. }
  404. if (iPrimaryLangEntry != 0xFFFFFFFF)
  405. return aHTTPLocale[iPrimaryLangEntry].lcid;
  406. // Fall back to the slow approach.
  407. return LcidFromHttpAcceptLanguage( wcsLocale );
  408. } //GetLCIDFromString
  409. WCHAR const * __stdcall GetStringFromLCID( LCID lcid );
  410. //+---------------------------------------------------------------------------
  411. //
  412. // Function: GetStringFromLCID - public
  413. //
  414. // Synposis: Determines the string representation of an LCID
  415. //
  416. // Arguments: [lcid] - the LCID to lookup
  417. //
  418. // History: 96-Apr-24 DwightKr Created
  419. //
  420. // Note: This must be exported since SQL 7 calls this undocumented API
  421. // It's otherwise unused by Indexing Service.
  422. //
  423. //----------------------------------------------------------------------------
  424. WCHAR const * GetStringFromLCID( LCID lcid )
  425. {
  426. //
  427. // Be careful to compare only the language ID, and not the sort ID.
  428. //
  429. lcid = LANGIDFROMLCID(lcid);
  430. for (ULONG i=0; i<cHTTPLocale; i++)
  431. {
  432. if ( lcid == LANGIDFROMLCID( aHTTPLocale[i].lcid ) )
  433. {
  434. qutilDebugOut(( DEB_ITRACE, "GetStringFromLCID: browser locale is %ws; lcid=0x%x\n",
  435. aHTTPLocale[i].wcsHttpAcceptLanguage,
  436. lcid ));
  437. return aHTTPLocale[i].wcsHttpAcceptLanguage;
  438. }
  439. }
  440. //
  441. // This LCID was not found in the table, report an error.
  442. //
  443. qutilDebugOut(( DEB_ITRACE, "GetStringFromLCID: browser locale not found, lcid=0x%x\n",
  444. lcid ));
  445. return L"NEUTRAL";
  446. } //GetStringFromLCID