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.

433 lines
14 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. fekbd.c
  5. Abstract:
  6. Japanese-specific keyboard stuff. For the Japanese market we need
  7. to detect a keyboard type (AX, 101, 106, IBM, etc) and allow the user
  8. to confirm. We do this because the keys on the keyboards are different
  9. and the user has to enter paths during setup. We also install keyboard
  10. support based on the user's selections here.
  11. Author:
  12. Ted Miller (tedm) 04-July-1995
  13. Revision History:
  14. Adapted from hideyukn and others' code in various places in setupldr
  15. and setupdd.sys.
  16. --*/
  17. #include <precomp.h>
  18. #pragma hdrstop
  19. //
  20. // A note about screen usage:
  21. //
  22. // Screen that asks the user to select a keyboard type
  23. // by pressing henkaku/zenkaku, spacebar, or s is SP_SCRN_LOCALE_SPECIFIC_1.
  24. // Screen that asks the user to select from the master keyboard list
  25. // is SP_SCRN_LOCALE_SPECIFIC_2.
  26. // Screen that asks the user to confirm selection (y/n) is
  27. // SP_SCRN_LOCALE_SPECIFIC_3.
  28. //
  29. PWSTR sz101KeyboardId = L"STANDARD";
  30. PWSTR sz106KeyboardId = L"PCAT_106KEY";
  31. PWSTR szAXKeyboardId = L"AX_105KEY";
  32. PWSTR szIBM002KeyboardId = L"IBM_002_106KEY";
  33. PWSTR SIF_UNATTENDED = L"Unattended";
  34. PWSTR STF_ACCESSIBILITY = L"accessibility";
  35. #define MENU_LEFT_X 15
  36. #define MENU_WIDTH (VideoVariables->ScreenWidth-(2*MENU_LEFT_X))
  37. #define MENU_TOP_Y 16
  38. #define MENU_HEIGHT 4
  39. #define CLEAR_CLIENT_AREA() \
  40. \
  41. SpvidClearScreenRegion( \
  42. 0, \
  43. HEADER_HEIGHT, \
  44. VideoVariables->ScreenWidth, \
  45. VideoVariables->ScreenHeight-(HEADER_HEIGHT+STATUS_HEIGHT), \
  46. DEFAULT_BACKGROUND \
  47. )
  48. #define CLEAR_STATUS_AREA() \
  49. \
  50. SpvidClearScreenRegion( \
  51. 0, \
  52. VideoVariables->ScreenHeight-STATUS_HEIGHT, \
  53. VideoVariables->ScreenWidth, \
  54. STATUS_HEIGHT, \
  55. DEFAULT_STATUS_BACKGROUND \
  56. )
  57. VOID
  58. FESelectKeyboard(
  59. IN PVOID SifHandle,
  60. IN PHARDWARE_COMPONENT *HwComponents,
  61. IN BOOLEAN bNoEasySelection,
  62. IN BOOLEAN CmdConsole
  63. )
  64. {
  65. ULONG ValidKeys1[7] = { ' ','`','~','s','S',KEY_F3,0 };
  66. ULONG ValidKeys2[5] = { 'y','Y','n','N',0 };
  67. ULONG ValidKeys3[3] = { ASCI_CR,KEY_F3,0 };
  68. BOOLEAN Selected;
  69. BOOLEAN Done;
  70. PVOID Menu;
  71. ULONG Line;
  72. PWSTR Text,Key;
  73. ULONG_PTR Selection;
  74. ULONG Keypress;
  75. PWSTR SelectedKeyboardId;
  76. PWSTR Description;
  77. PHARDWARE_COMPONENT p;
  78. //
  79. // The 101 and 106 key keyboards are most popular so we present
  80. // a screen that is biased to them. It aksks the user to press
  81. // hankaku/zenkaku key for 106, space for 101, or S for other,
  82. // at which point they can select either of these or an IBM002 or
  83. // AX type.
  84. //
  85. // Then the user is asked to confirm selection with y or n (which
  86. // are the same scan code on all keyboards).
  87. //
  88. Done = FALSE;
  89. do {
  90. if(!bNoEasySelection) {
  91. //
  92. // Wait for the user to press henkaku/zenkaku, spacebar, or s.
  93. // We also give the option to exit Setup.
  94. //
  95. for(Selected=FALSE; !Selected; ) {
  96. CLEAR_CLIENT_AREA();
  97. CLEAR_STATUS_AREA();
  98. if (CmdConsole) {
  99. SpDisplayScreen(SP_SCRN_LOCALE_SPECIFIC_4,3,HEADER_HEIGHT+3);
  100. } else {
  101. SpDisplayScreen(SP_SCRN_LOCALE_SPECIFIC_1,3,HEADER_HEIGHT+3);
  102. }
  103. switch(SpWaitValidKey(ValidKeys1,NULL,NULL)) {
  104. case ' ':
  105. //
  106. // User selected 101 key.
  107. //
  108. Selected = TRUE;
  109. SelectedKeyboardId = sz101KeyboardId;
  110. break;
  111. case '`':
  112. case '~':
  113. //
  114. // 101 key mapping returns hankaku/zenkaku as ` key.
  115. // User selected 106 key.
  116. //
  117. Selected = TRUE;
  118. SelectedKeyboardId = sz106KeyboardId;
  119. break;
  120. case 's':
  121. case 'S':
  122. //
  123. // User wants to select from the master list.
  124. //
  125. Selected = TRUE;
  126. SelectedKeyboardId = NULL;
  127. break;
  128. case KEY_F3:
  129. //
  130. // User wants to exit.
  131. //
  132. if (!CmdConsole) {
  133. SpConfirmExit();
  134. }
  135. break;
  136. }
  137. }
  138. } else {
  139. SelectedKeyboardId = NULL;
  140. }
  141. //
  142. // If the user wants to select from the master list, do that here.
  143. //
  144. if(!SelectedKeyboardId) {
  145. Menu = SpMnCreate(MENU_LEFT_X,MENU_TOP_Y,MENU_WIDTH,MENU_HEIGHT);
  146. if (!Menu) {
  147. SpOutOfMemory();
  148. return; // make prefix happy
  149. }
  150. Selection = 0;
  151. for(Line=0; Text=SpGetSectionLineIndex(SifHandle,szKeyboard,Line,0); Line++) {
  152. if(Key = SpGetKeyName(SifHandle,szKeyboard,Line)) {
  153. SpMnAddItem(Menu,Text,MENU_LEFT_X+1,MENU_WIDTH-2,TRUE,(ULONG_PTR)Key);
  154. if(!Selection) {
  155. Selection = (ULONG_PTR)Key;
  156. }
  157. }
  158. }
  159. for(Selected=FALSE; !Selected; ) {
  160. CLEAR_CLIENT_AREA();
  161. if (CmdConsole) {
  162. SpDisplayScreen(SP_SCRN_LOCALE_SPECIFIC_5,3,HEADER_HEIGHT+3);
  163. } else {
  164. SpDisplayScreen(SP_SCRN_LOCALE_SPECIFIC_2,3,HEADER_HEIGHT+3);
  165. }
  166. if (CmdConsole) {
  167. SpDisplayStatusOptions(
  168. DEFAULT_STATUS_ATTRIBUTE,
  169. SP_STAT_ENTER_EQUALS_SELECT,
  170. 0);
  171. } else {
  172. SpDisplayStatusOptions(
  173. DEFAULT_STATUS_ATTRIBUTE,
  174. SP_STAT_ENTER_EQUALS_SELECT,
  175. SP_STAT_F3_EQUALS_EXIT,
  176. 0);
  177. }
  178. SpMnDisplay(Menu,Selection,TRUE,ValidKeys3,NULL,NULL,NULL,&Keypress,&Selection);
  179. if(Keypress == ASCI_CR) {
  180. //
  181. // User made selection.
  182. //
  183. SelectedKeyboardId = (PWSTR)Selection;
  184. Selected = TRUE;
  185. } else {
  186. //
  187. // User wants to quit.
  188. //
  189. if (!CmdConsole) {
  190. SpConfirmExit();
  191. }
  192. }
  193. }
  194. SpMnDestroy(Menu);
  195. }
  196. if(!bNoEasySelection) {
  197. Description = SpGetSectionKeyIndex(SifHandle,szKeyboard,SelectedKeyboardId,0);
  198. //
  199. // Confirm the user's choice of keyboard. He needs to press either y or n.
  200. //
  201. CLEAR_CLIENT_AREA();
  202. CLEAR_STATUS_AREA();
  203. SpStartScreen(
  204. SP_SCRN_LOCALE_SPECIFIC_3,
  205. 3,
  206. HEADER_HEIGHT+3,
  207. FALSE,
  208. FALSE,
  209. DEFAULT_ATTRIBUTE,
  210. Description
  211. );
  212. switch(SpWaitValidKey(ValidKeys2,NULL,NULL)) {
  213. case 'y':
  214. case 'Y':
  215. Done = TRUE;
  216. break;
  217. }
  218. } else {
  219. Description = SpGetSectionKeyIndex(SifHandle,szKeyboard,SelectedKeyboardId,0);
  220. Done = TRUE;
  221. }
  222. } while(!Done);
  223. //
  224. // Reinitialize things in the hardware lists.
  225. //
  226. p = HwComponents[HwComponentKeyboard]->Next;
  227. SpFreeHwComponent(&HwComponents[HwComponentKeyboard],FALSE);
  228. HwComponents[HwComponentKeyboard] = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  229. RtlZeroMemory(HwComponents[HwComponentKeyboard],sizeof(HARDWARE_COMPONENT));
  230. HwComponents[HwComponentKeyboard]->IdString = SpDupStringW(SelectedKeyboardId);
  231. HwComponents[HwComponentKeyboard]->Description = SpDupStringW(Description);
  232. HwComponents[HwComponentKeyboard]->Next = p;
  233. }
  234. VOID
  235. FEUnattendSelectKeyboard(
  236. IN PVOID UnattendedSifHandle,
  237. IN PVOID SifHandle,
  238. IN PHARDWARE_COMPONENT *HwComponents
  239. )
  240. {
  241. PWSTR SelectedKeyboardId;
  242. PWSTR Description;
  243. BOOLEAN DefaultIsUsed = FALSE;
  244. //
  245. // Get selected keyboard id from winnt.sif.
  246. //
  247. // *** Example for Japanese version ***
  248. //
  249. // [Unattended]
  250. //
  251. // KeyboardHardware = STANDARD | PCAT_106KEY | AX_105KEY | IBM_002_106KEY
  252. //
  253. // !!! NOTE !!!
  254. //
  255. // But actually, we should use [KeyboardDrivers] section for OEM-PreInstall.
  256. // We should not have this redundant data...
  257. //
  258. SelectedKeyboardId = SpGetSectionKeyIndex(UnattendedSifHandle,SIF_UNATTENDED,L"KeyboardHardware",0);
  259. //
  260. // if we fail to read unattend.txt(actually winnt.sif), use first keyboard as default.
  261. //
  262. if(SelectedKeyboardId == NULL) {
  263. //
  264. // check if any line in [accesibility].
  265. //
  266. // SpCountLinesInSection is better, but it doesn't share out.
  267. //
  268. if (SpGetSectionLineIndex(UnattendedSifHandle,STF_ACCESSIBILITY,0,0)) {
  269. if(IS_JAPANESE_VERSION(SifHandle)) {
  270. FESelectKeyboard(SifHandle, HwComponents, FALSE,FALSE);
  271. } else if(IS_KOREAN_VERSION(SifHandle)) {
  272. FESelectKeyboard(SifHandle, HwComponents, TRUE,FALSE);
  273. }
  274. return;
  275. }
  276. SelectedKeyboardId = SpGetKeyName(SifHandle,szKeyboard,0);
  277. if (SelectedKeyboardId == NULL) {
  278. //
  279. // At least, one line should be existed in [Keyboard] section.
  280. //
  281. SpFatalSifError(SifHandle,szKeyboard,NULL,0,0);
  282. }
  283. DefaultIsUsed = TRUE;
  284. }
  285. //
  286. // Get its Description from txtsetup.sif. This value will be used Hardware confirmation screen,
  287. // if "ConfirmHardware" in winnt.sif is "yes".
  288. //
  289. Description = SpGetSectionKeyIndex(SifHandle,szKeyboard,SelectedKeyboardId,0);
  290. //
  291. // if Description could not be got from txtsetup.sif. we might encounter the problem
  292. // that selected name from unattend.txt is not listed [Keyboard] section in txtsetup.sif.
  293. // Just fall into default case, select "106_TYPE keyboard"
  294. //
  295. if( Description == NULL ) {
  296. if( DefaultIsUsed ) {
  297. //
  298. // if we are here, default was selected. but there is no entry for default
  299. // keyboard in txtsetup.sif. just Popup error.
  300. //
  301. SpFatalSifError(SifHandle,szKeyboard,SelectedKeyboardId,0,0);
  302. } else {
  303. //
  304. // Get first line from txtsetup.sif...
  305. //
  306. SelectedKeyboardId = SpGetSectionLineIndex(SifHandle,szKeyboard,0,0);
  307. if (SelectedKeyboardId == NULL) {
  308. //
  309. // At least, one line should be existed in [Keyboard] section.
  310. //
  311. SpFatalSifError(SifHandle,szKeyboard,NULL,0,0);
  312. }
  313. //
  314. // Retry to get description with default.
  315. //
  316. Description = SpGetSectionKeyIndex(SifHandle,szKeyboard,SelectedKeyboardId,0);
  317. }
  318. }
  319. //
  320. // Reinitialize things in the hardware lists.
  321. //
  322. SpFreeHwComponent(&HwComponents[HwComponentKeyboard],TRUE);
  323. HwComponents[HwComponentKeyboard] = SpMemAlloc(sizeof(HARDWARE_COMPONENT));
  324. RtlZeroMemory(HwComponents[HwComponentKeyboard],sizeof(HARDWARE_COMPONENT));
  325. HwComponents[HwComponentKeyboard]->IdString = SpDupStringW(SelectedKeyboardId);
  326. HwComponents[HwComponentKeyboard]->Description = SpDupStringW(Description);
  327. }
  328. VOID
  329. FEReinitializeKeyboard(
  330. IN PVOID SifHandle,
  331. IN PWSTR Directory,
  332. OUT PVOID *KeyboardVector,
  333. IN PHARDWARE_COMPONENT *HwComponents,
  334. IN PWSTR KeyboardLayoutDefault
  335. )
  336. {
  337. PWSTR LayoutDll;
  338. PVOID Tables;
  339. NTSTATUS Status;
  340. //
  341. // Determine the correct layout dll.
  342. //
  343. LayoutDll = SpGetSectionKeyIndex(
  344. SifHandle,
  345. szKeyboard,
  346. HwComponents[HwComponentKeyboard]->IdString,
  347. 3
  348. );
  349. //
  350. // Don't need to load 101 key layout because it's already loaded.
  351. //
  352. if(LayoutDll && _wcsicmp(LayoutDll,KeyboardLayoutDefault)) {
  353. CLEAR_CLIENT_AREA();
  354. SpDisplayStatusText(
  355. SP_STAT_LOADING_KBD_LAYOUT,
  356. DEFAULT_STATUS_ATTRIBUTE,
  357. LayoutDll
  358. );
  359. Status = SpLoadKbdLayoutDll(Directory,LayoutDll,&Tables);
  360. if(NT_SUCCESS(Status)) {
  361. *KeyboardVector = Tables;
  362. }
  363. }
  364. }