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.

477 lines
12 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. eudc.c
  5. Abstract:
  6. Author:
  7. KazuM Apr.19.1996
  8. Revision History:
  9. --*/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #if defined(FE_SB)
  13. NTSTATUS
  14. CreateEUDC(
  15. PCONSOLE_INFORMATION Console
  16. )
  17. {
  18. PEUDC_INFORMATION EudcInfo;
  19. EudcInfo = ConsoleHeapAlloc(EUDC_TAG, sizeof(EUDC_INFORMATION));
  20. if (EudcInfo == NULL) {
  21. return STATUS_NO_MEMORY;
  22. }
  23. EudcInfo->LocalVDMEudcMode = FALSE;
  24. EudcInfo->LocalKeisenEudcMode = FALSE;
  25. EudcInfo->hDCLocalEudc = NULL;
  26. EudcInfo->hBmpLocalEudc = NULL;
  27. EudcInfo->EudcFontCacheInformation = NULL;
  28. EudcInfo->LocalEudcSize.X = DEFAULT_EUDCSIZE;
  29. EudcInfo->LocalEudcSize.Y = DEFAULT_EUDCSIZE;
  30. RtlZeroMemory(&EudcInfo->EudcRange,sizeof(EudcInfo->EudcRange));
  31. EudcInfo->EudcRangeSize = GetSystemEUDCRangeW(EudcInfo->EudcRange, EUDC_RANGE_SIZE);
  32. if (EudcInfo->EudcRangeSize)
  33. EudcInfo->EudcRangeSize--; // remove terminator
  34. Console->EudcInformation = (PVOID)EudcInfo;
  35. return STATUS_SUCCESS;
  36. }
  37. VOID
  38. DeleteEUDC(
  39. PCONSOLE_INFORMATION Console
  40. )
  41. {
  42. PEUDC_INFORMATION EudcInfo = Console->EudcInformation;
  43. if (EudcInfo->hDCLocalEudc) {
  44. ReleaseDC(NULL, EudcInfo->hDCLocalEudc);
  45. DeleteObject(EudcInfo->hBmpLocalEudc);
  46. }
  47. }
  48. NTSTATUS
  49. RegisterLocalEUDC(
  50. IN PCONSOLE_INFORMATION Console,
  51. IN WCHAR wChar,
  52. IN COORD FontSize,
  53. IN PCHAR FontFace
  54. )
  55. {
  56. NTSTATUS Status;
  57. PCHAR TmpBuff;
  58. DWORD BuffSize;
  59. PEUDC_INFORMATION EudcInfo = Console->EudcInformation;
  60. if (EudcInfo->EudcFontCacheInformation == NULL) {
  61. Status = (NTSTATUS)CreateFontCache(&(PFONT_CACHE_INFORMATION)EudcInfo->EudcFontCacheInformation);
  62. if (!NT_SUCCESS(Status)) {
  63. RIPMSG1(RIP_WARNING, "RegisterLocalEUDC: failed in CreateFontCache, Status is %08x", Status);
  64. return Status;
  65. }
  66. }
  67. BuffSize = CalcBitmapBufferSize(FontSize, BYTE_ALIGN);
  68. TmpBuff = FontFace;
  69. while(BuffSize--)
  70. *TmpBuff++ = ~(*TmpBuff);
  71. return (NTSTATUS)SetFontImage(EudcInfo->EudcFontCacheInformation,
  72. wChar,
  73. FontSize,
  74. BYTE_ALIGN,
  75. FontFace
  76. );
  77. }
  78. VOID
  79. FreeLocalEUDC(
  80. IN PCONSOLE_INFORMATION Console
  81. )
  82. {
  83. PEUDC_INFORMATION EudcInfo = Console->EudcInformation;
  84. if (EudcInfo->EudcFontCacheInformation != NULL) {
  85. DestroyFontCache((PFONT_CACHE_INFORMATION)EudcInfo->EudcFontCacheInformation);
  86. }
  87. ConsoleHeapFree(Console->EudcInformation);
  88. }
  89. VOID
  90. GetFitLocalEUDCFont(
  91. IN PCONSOLE_INFORMATION Console,
  92. IN WCHAR wChar
  93. )
  94. {
  95. NTSTATUS Status;
  96. COORD FontSize;
  97. VOID *FontFace;
  98. DWORD BuffSize;
  99. PEUDC_INFORMATION EudcInfo;
  100. PFONT_CACHE_INFORMATION FontCacheInfo;
  101. EudcInfo = (PEUDC_INFORMATION)Console->EudcInformation;
  102. FontCacheInfo = (PFONT_CACHE_INFORMATION)EudcInfo->EudcFontCacheInformation;
  103. FontSize = CON_FONTSIZE(Console);
  104. if (IsConsoleFullWidth(Console->hDC,Console->OutputCP,wChar)) {
  105. FontSize.X *= 2;
  106. }
  107. if ((EudcInfo->LocalEudcSize.X != FontSize.X) ||
  108. (EudcInfo->LocalEudcSize.Y != FontSize.Y) ) {
  109. ReleaseDC(NULL, EudcInfo->hDCLocalEudc);
  110. DeleteObject(EudcInfo->hBmpLocalEudc);
  111. EudcInfo->hDCLocalEudc = CreateCompatibleDC(Console->hDC);
  112. EudcInfo->hBmpLocalEudc = CreateBitmap(FontSize.X, FontSize.Y, BITMAP_PLANES, BITMAP_BITS_PIXEL, NULL);
  113. SelectObject(EudcInfo->hDCLocalEudc, EudcInfo->hBmpLocalEudc);
  114. EudcInfo->LocalEudcSize.X = FontSize.X;
  115. EudcInfo->LocalEudcSize.Y = FontSize.Y;
  116. }
  117. BuffSize = CalcBitmapBufferSize(FontSize,WORD_ALIGN);
  118. FontFace = ConsoleHeapAlloc(TMP_DBCS_TAG, BuffSize);
  119. if (FontFace == NULL) {
  120. RIPMSG0(RIP_WARNING, "GetFitLocalEUDCFont: failed to allocate FontFace.");
  121. return;
  122. }
  123. Status = (NTSTATUS)GetFontImage(FontCacheInfo,
  124. wChar,
  125. FontSize,
  126. WORD_ALIGN,
  127. FontFace
  128. );
  129. if (! NT_SUCCESS(Status)) {
  130. if ((Console->Flags & CONSOLE_VDM_REGISTERED) &&
  131. FontSize.X == DefaultFontSize.X * 2 &&
  132. FontSize.Y == DefaultFontSize.Y &&
  133. FontSize.X == VDM_EUDC_FONT_SIZE_X &&
  134. FontSize.Y - 2 == VDM_EUDC_FONT_SIZE_Y ) {
  135. COORD TmpFontSize = FontSize;
  136. TmpFontSize.Y -= 2;
  137. RtlFillMemory((PVOID)FontFace,BuffSize,0xff);
  138. Status = (NTSTATUS)GetFontImage(FontCacheInfo,
  139. wChar,
  140. TmpFontSize,
  141. WORD_ALIGN,
  142. FontFace
  143. );
  144. if (! NT_SUCCESS(Status)) {
  145. Status = (NTSTATUS)GetStretchedFontImage(FontCacheInfo,
  146. wChar,
  147. FontSize,
  148. WORD_ALIGN,
  149. FontFace
  150. );
  151. if (! NT_SUCCESS(Status)) {
  152. ASSERT(FALSE);
  153. ConsoleHeapFree(FontFace);
  154. return;
  155. }
  156. }
  157. }
  158. else {
  159. Status = (NTSTATUS)GetStretchedFontImage(FontCacheInfo,
  160. wChar,
  161. FontSize,
  162. WORD_ALIGN,
  163. FontFace
  164. );
  165. if (! NT_SUCCESS(Status)) {
  166. ASSERT(FALSE);
  167. ConsoleHeapFree(FontFace);
  168. return;
  169. }
  170. }
  171. Status = (NTSTATUS)SetFontImage(FontCacheInfo,
  172. wChar,
  173. FontSize,
  174. WORD_ALIGN,
  175. FontFace
  176. );
  177. if (! NT_SUCCESS(Status)) {
  178. ASSERT(FALSE);
  179. ConsoleHeapFree(FontFace);
  180. return;
  181. }
  182. }
  183. SetBitmapBits(EudcInfo->hBmpLocalEudc, BuffSize, (PBYTE)FontFace);
  184. ConsoleHeapFree(FontFace);
  185. }
  186. BOOL
  187. IsEudcRange(
  188. IN PCONSOLE_INFORMATION Console,
  189. IN WCHAR ch
  190. )
  191. {
  192. PEUDC_INFORMATION EudcInfo;
  193. int i;
  194. EudcInfo = (PEUDC_INFORMATION)Console->EudcInformation;
  195. for (i=0; i < EudcInfo->EudcRangeSize; i+=2)
  196. {
  197. if (EudcInfo->EudcRange[i] <= ch && ch <= EudcInfo->EudcRange[i+1])
  198. return TRUE;
  199. }
  200. return FALSE;
  201. }
  202. BOOL
  203. CheckEudcRangeInString(
  204. IN PCONSOLE_INFORMATION Console,
  205. IN PWCHAR string,
  206. IN SHORT len,
  207. OUT SHORT *find_pos
  208. )
  209. {
  210. SHORT i;
  211. for (i = 0; i < len; i++,string++)
  212. {
  213. if (IsEudcRange(Console, *string))
  214. {
  215. *find_pos = i;
  216. return TRUE;
  217. }
  218. }
  219. return FALSE;
  220. }
  221. LPWSTR
  222. SkipWhite(
  223. LPWSTR lpch
  224. )
  225. {
  226. if( lpch == NULL )
  227. return( NULL );
  228. for ( ; ; lpch++ )
  229. {
  230. switch (*lpch)
  231. {
  232. case L' ':
  233. case L'\t':
  234. case L'\r':
  235. case L'\n':
  236. break;
  237. default:
  238. return(lpch);
  239. }
  240. }
  241. }
  242. WORD
  243. ConvertStringToHex(
  244. LPWSTR lpch,
  245. LPWSTR *endptr
  246. )
  247. {
  248. WCHAR ch;
  249. WORD val = 0;
  250. while ( (ch=*lpch) != L'\0')
  251. {
  252. if (L'0' <= ch && ch <= L'9')
  253. val = (val << 4) + (ch - L'0');
  254. else if (L'A' <= ch && ch <= L'F')
  255. val = (val << 4) + (ch - L'A' + 10);
  256. else if (L'a' <= ch && ch <= L'f')
  257. val = (val << 4) + (ch - L'a' + 10);
  258. else
  259. break;
  260. lpch++;
  261. }
  262. if (endptr)
  263. *endptr = lpch;
  264. return val;
  265. }
  266. WORD
  267. ConvertStringToDec(
  268. LPWSTR lpch,
  269. LPWSTR *endptr
  270. )
  271. {
  272. WCHAR ch;
  273. WORD val = 0;
  274. while ( (ch=*lpch) != L'\0')
  275. {
  276. if (L'0' <= ch && ch <= L'9')
  277. val = (val * 10) + (ch - L'0');
  278. else
  279. break;
  280. lpch++;
  281. }
  282. if (endptr)
  283. *endptr = lpch;
  284. return val;
  285. }
  286. INT
  287. GetSystemEUDCRangeW(
  288. WORD *pwEUDCCharTable,
  289. UINT cjSize)
  290. {
  291. NTSTATUS Status;
  292. HKEY hkRegistry;
  293. UNICODE_STRING SystemACPString;
  294. WCHAR awcACP[10];
  295. WCHAR awchBuffer[512];
  296. INT iEntry = 0;
  297. /*
  298. * Check parameter
  299. *
  300. * If pwEUDCWideCharTable == NULL && cjSize == 0
  301. * We have to return the needed buffer size to store data
  302. */
  303. if ((pwEUDCCharTable == NULL && cjSize != 0) ||
  304. (pwEUDCCharTable != NULL && cjSize == 0)) {
  305. return 0;
  306. }
  307. /*
  308. * Open registry key.
  309. */
  310. Status = MyRegOpenKey(NULL,
  311. MACHINE_REGISTRY_EUDC,
  312. &hkRegistry);
  313. if (!NT_SUCCESS(Status)) {
  314. RIPMSG2(RIP_WARNING,
  315. "GetSystemEUDCRangeW: RegOpenKeyExW(%ws) failed, error = 0x%x",
  316. MACHINE_REGISTRY_EUDC,
  317. GetLastError());
  318. return 0;
  319. }
  320. /*
  321. * Convert ACP to Unicode string.
  322. */
  323. SystemACPString.Length = 0;
  324. SystemACPString.MaximumLength = ARRAY_SIZE(awcACP);
  325. SystemACPString.Buffer = awcACP;
  326. RtlIntegerToUnicodeString(WINDOWSCP, 10, &SystemACPString);
  327. /*
  328. * Read registry data.
  329. */
  330. Status = MyRegQueryValue(hkRegistry,
  331. awcACP,
  332. sizeof(awchBuffer), (PBYTE)&awchBuffer);
  333. if (!NT_SUCCESS(Status)) {
  334. RIPMSG2(RIP_VERBOSE,
  335. "GetSystemEUDCRangeW: NtQueryValueKey(%ws) failed, error = 0x%x",
  336. awcACP,
  337. GetLastError());
  338. } else {
  339. LPWSTR pwszBuf = awchBuffer;
  340. /*
  341. * Parse the data.
  342. */
  343. while (pwszBuf != NULL && *pwszBuf != UNICODE_NULL) {
  344. WORD ch1,ch2;
  345. /*
  346. * Get Start Range value.
  347. */
  348. pwszBuf = SkipWhite(pwszBuf);
  349. ch1 = ConvertStringToHex(pwszBuf, &pwszBuf);
  350. pwszBuf = SkipWhite(pwszBuf);
  351. if (*pwszBuf != L'-') {
  352. RIPMSG0(RIP_WARNING, "GetSystemEUDCRangeW: Invalid format");
  353. iEntry = 0;
  354. goto Error;
  355. }
  356. /*
  357. * Get End Range value.
  358. */
  359. pwszBuf = SkipWhite(pwszBuf + 1);
  360. ch2 = ConvertStringToHex(pwszBuf, &pwszBuf);
  361. /*
  362. * Confirm the data sort order is correct.
  363. */
  364. if (ch1 > ch2) {
  365. RIPMSG0(RIP_WARNING, "GetSystemEUDCRangeW: Sort order is incorrect");
  366. iEntry = 0;
  367. goto Error;
  368. }
  369. /*
  370. * Move pointer to next.
  371. */
  372. pwszBuf = SkipWhite(pwszBuf);
  373. if (*pwszBuf == L',') {
  374. pwszBuf = SkipWhite(pwszBuf + 1);
  375. }
  376. /*
  377. * Above, if pwszBuf is NULL, we've reached the EOD.
  378. */
  379. iEntry++;
  380. /*
  381. * If caller buffer is large enough to store the data, store it.
  382. * Even if that's not the case, we have to continue to parse the
  383. * data to compute the number of entry.
  384. */
  385. /*
  386. * 3 - Because we have to store NULL as a mark of EOD.
  387. */
  388. if (cjSize >= 3) {
  389. *pwEUDCCharTable++ = ch1;
  390. *pwEUDCCharTable++ = ch2;
  391. cjSize -= 2;
  392. }
  393. }
  394. *pwEUDCCharTable = UNICODE_NULL;
  395. iEntry = iEntry * 2 + 1;
  396. }
  397. Error:
  398. /*
  399. * Close registry handle.
  400. */
  401. UserAssert(hkRegistry != NULL);
  402. NtClose(hkRegistry);
  403. return iEntry;
  404. }
  405. #endif