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.

972 lines
30 KiB

  1. /* cmdconf.c - handles pre-processing of config.sys\autoexec.bat
  2. *
  3. * Modification History:
  4. *
  5. * 21-Nov-1992 Jonle , Created
  6. */
  7. #include "cmd.h"
  8. #include <cmdsvc.h>
  9. #include <demexp.h>
  10. #include <softpc.h>
  11. #include <mvdm.h>
  12. #include <ctype.h>
  13. #include <oemuni.h>
  14. //
  15. // local stuff
  16. //
  17. CHAR *pchTmpConfigFile;
  18. CHAR *pchTmpAutoexecFile;
  19. CHAR achSYSROOT[] = "%SystemRoot%";
  20. CHAR achCOMMAND[] = "\\System32\\command.com";
  21. CHAR achSHELL[] = "shell";
  22. CHAR achCOUNTRY[] = "country";
  23. CHAR achREM[] = "rem";
  24. CHAR achENV[] = "/e:";
  25. CHAR achEOL[] = "\r\n";
  26. CHAR achSET[] = "SET";
  27. CHAR achPROMPT[] = "PROMPT";
  28. CHAR achPATH[] = "PATH";
  29. #ifdef JAPAN
  30. // device=...\$disp.sys /hs=%HardwareScroll%
  31. CHAR achHARDWARESCROLL[] = "%HardwareScroll%";
  32. DWORD dwLenHardwareScroll;
  33. CHAR achHardwareScroll[64];
  34. #endif // JAPAN
  35. #if defined(KOREA)
  36. // device=...\hbios.sys /k:#
  37. CHAR achHBIOS[] = "hbios.sys";
  38. CHAR achFontSys[] = "font_win.sys";
  39. CHAR achDispSys[] = "disp_win.sys";
  40. DWORD dwLenHotkeyOption;
  41. CHAR achHotkeyOption[80];
  42. BOOLEAN fKoreanCP;
  43. #define KOREAN_WANSUNG_CP 949
  44. #endif // KOREA
  45. DWORD dwLenSysRoot;
  46. CHAR achSysRoot[64];
  47. void ExpandConfigFiles(BOOLEAN bConfig);
  48. DWORD WriteExpanded(HANDLE hFile, CHAR *pch, DWORD dwBytes);
  49. void WriteFileAssert(HANDLE hFile, CHAR *pBuff, DWORD dwBytes);
  50. #define ISEOL(ch) ( !(ch) || ((ch) == '\n') || ((ch) == '\r'))
  51. #ifdef JAPAN
  52. DWORD GetHardwareScroll( PCHAR achHardwareScroll, int size );
  53. #endif // JAPAN
  54. #if defined(KOREA)
  55. DWORD GetHotkeyOption( PCHAR achHotkeyOption, UINT size );
  56. #endif // KOREA
  57. /** There are still many items we don't supprot for long path name
  58. (1). device, install in config.sys
  59. (2). Third-party shell
  60. (3). lh, loadhigh and any other commands in autoexec.bat
  61. **/
  62. /* cmdGetConfigSys - Creates a temp file to replace c:\config.sys
  63. *
  64. * Entry - Client (DS:DX) pointer to receive file name
  65. *
  66. * EXIT - This routine will Terminate the vdm if it fails
  67. * And will not return
  68. *
  69. * The buffer to receive the file name must be at least 64 bytes
  70. */
  71. VOID cmdGetConfigSys (VOID)
  72. {
  73. UNICODE_STRING Unicode;
  74. OEM_STRING OemString;
  75. ANSI_STRING AnsiString;
  76. ExpandConfigFiles(TRUE);
  77. RtlInitAnsiString(&AnsiString, pchTmpConfigFile);
  78. if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&Unicode, &AnsiString, TRUE)) )
  79. goto ErrExit;
  80. OemString.Buffer = (char *)GetVDMAddr(getDS(),getDX());
  81. OemString.MaximumLength = 64;
  82. if ( !NT_SUCCESS(RtlUnicodeStringToOemString(&OemString,&Unicode,FALSE)) )
  83. goto ErrExit;
  84. RtlFreeUnicodeString(&Unicode);
  85. return;
  86. ErrExit:
  87. RcErrorDialogBox(ED_INITMEMERR, pchTmpConfigFile, NULL);
  88. TerminateVDM();
  89. }
  90. /* cmdGetAutoexecBat - Creates a temp file to replace c:\autoexec.bat
  91. *
  92. * Entry - Client (DS:DX) pointer to receive file name
  93. *
  94. * EXIT - This routine will Terminate the vdm if it fails
  95. * And will not return
  96. *
  97. *
  98. * The buffer to receive the file name must be at least 64 bytes
  99. */
  100. VOID cmdGetAutoexecBat (VOID)
  101. {
  102. UNICODE_STRING Unicode;
  103. OEM_STRING OemString;
  104. ANSI_STRING AnsiString;
  105. ExpandConfigFiles(FALSE);
  106. #if defined(JAPAN) || defined(KOREA)
  107. // fixed: change code page problem
  108. {
  109. extern int BOPFromDispFlag;
  110. if ( !VDMForWOW && !BOPFromDispFlag ) { // mskkbug#2756 10/15/93 yasuho
  111. SetConsoleCP( 437 );
  112. SetConsoleOutputCP( 437 );
  113. }
  114. }
  115. #endif // JAPAN || KOREA
  116. RtlInitAnsiString(&AnsiString, pchTmpAutoexecFile);
  117. if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&Unicode,&AnsiString,TRUE)) )
  118. goto ErrExit;
  119. OemString.Buffer = (char *)GetVDMAddr(getDS(),getDX());
  120. OemString.MaximumLength = 64;
  121. if (!NT_SUCCESS(RtlUnicodeStringToOemString(&OemString,&Unicode,FALSE)) )
  122. goto ErrExit;
  123. RtlFreeUnicodeString(&Unicode);
  124. return;
  125. ErrExit:
  126. RcErrorDialogBox(ED_INITMEMERR, pchTmpConfigFile, NULL);
  127. TerminateVDM(); // skip cleanup since I insist that we exit!
  128. }
  129. /*
  130. * DeleteConfigFiles - Deletes the temporray config files created
  131. * by cmdGetAutoexecBat and cmdGetConfigSys
  132. */
  133. VOID DeleteConfigFiles(VOID)
  134. {
  135. if (pchTmpConfigFile) {
  136. #if DBG
  137. if (!(fShowSVCMsg & KEEPBOOTFILES))
  138. #endif
  139. DeleteFile(pchTmpConfigFile);
  140. free(pchTmpConfigFile);
  141. pchTmpConfigFile = NULL;
  142. }
  143. if (pchTmpAutoexecFile) {
  144. #if DBG
  145. if (!(fShowSVCMsg & KEEPBOOTFILES))
  146. #endif
  147. DeleteFile(pchTmpAutoexecFile);
  148. free(pchTmpAutoexecFile);
  149. pchTmpAutoexecFile = NULL;
  150. }
  151. return;
  152. }
  153. // if it is a config command
  154. // returns pointer to character immediatly following the equal sign
  155. // else
  156. // returns NULL
  157. PCHAR IsConfigCommand(PCHAR pConfigCommand, int CmdLen, PCHAR pLine)
  158. {
  159. PCHAR pch;
  160. if (!_strnicmp(pLine, pConfigCommand, CmdLen)) {
  161. pch = pLine + CmdLen;
  162. while (!isgraph(*pch) && !ISEOL(*pch)) // skip to "="
  163. pch++;
  164. if (*pch++ == '=') {
  165. return pch;
  166. }
  167. }
  168. return NULL;
  169. }
  170. #if defined(KOREA)
  171. // if it is a HBIOS related config command
  172. // returns TRUE
  173. // else
  174. // returns FALSE
  175. BOOLEAN IsHBIOSConfig(PCHAR pCommand, int CmdLen, PCHAR pLine)
  176. {
  177. CHAR *pch = pLine;
  178. CHAR achDevice[] = "Device";
  179. CHAR achRem[] = "REM";
  180. while (*pch && !ISEOL(*pch)) {
  181. if (!_strnicmp(pch, achRem, sizeof(achRem)-sizeof(CHAR)))
  182. return (FALSE);
  183. if (!_strnicmp(pch, achDevice, sizeof(achDevice)-sizeof(CHAR))) {
  184. while (*pch && !ISEOL(*pch)) {
  185. if (!_strnicmp(pch, pCommand, CmdLen))
  186. return (TRUE);
  187. pch++;
  188. }
  189. return FALSE;
  190. }
  191. pch++;
  192. }
  193. return (FALSE);
  194. }
  195. #endif
  196. /*
  197. * Preprocesses the specfied config file (config.sys\autoexec.bat)
  198. * into a temporary file.
  199. *
  200. * - expands %SystemRoot%
  201. #ifdef JAPAN
  202. * - expands %HardwareScroll%
  203. #endif // JAPAN
  204. #if defined(KOREA)
  205. * - expands HotkeyOption
  206. #endif // KOREA
  207. * - adds SHELL line for config.sys
  208. *
  209. * entry: BOOLEAN bConfig : TRUE - config.sys
  210. * FALSE - autoexec.bat
  211. */
  212. void ExpandConfigFiles(BOOLEAN bConfig)
  213. {
  214. DWORD dw, dwRawFileSize;
  215. HANDLE hRawFile;
  216. HANDLE hTmpFile;
  217. CHAR **ppTmpFile;
  218. CHAR *pRawBuffer;
  219. CHAR *pLine;
  220. CHAR *pTmp;
  221. CHAR *pEnvParam= NULL;
  222. CHAR *pPartyShell=NULL;
  223. CHAR achRawFile[MAX_PATH+12];
  224. CHAR *lpszzEnv, *lpszName;
  225. int cchEnv;
  226. #ifdef JAPAN
  227. dwLenHardwareScroll = GetHardwareScroll( achHardwareScroll, sizeof(achHardwareScroll) );
  228. #endif // JAPAN
  229. #if defined(KOREA)
  230. // HBIOS.SYS is only support WanSung Codepage.
  231. fKoreanCP = (GetConsoleCP() == KOREAN_WANSUNG_CP) ? TRUE : FALSE;
  232. dwLenHotkeyOption = GetHotkeyOption( achHotkeyOption, sizeof(achHotkeyOption) );
  233. #endif // KOREA
  234. dw = GetSystemWindowsDirectory(achRawFile, sizeof(achRawFile));
  235. dwLenSysRoot = GetShortPathNameA(achRawFile, achSysRoot, sizeof(achSysRoot));
  236. if (dwLenSysRoot >= sizeof(achSysRoot)) {
  237. dwLenSysRoot = 0;
  238. achSysRoot[0] = '\0';
  239. }
  240. GetPIFConfigFiles(bConfig, achRawFile, FALSE);
  241. ppTmpFile = bConfig ? &pchTmpConfigFile : &pchTmpAutoexecFile;
  242. hRawFile = CreateFile(achRawFile,
  243. GENERIC_READ,
  244. FILE_SHARE_READ,
  245. NULL,
  246. OPEN_EXISTING,
  247. FILE_ATTRIBUTE_NORMAL,
  248. NULL );
  249. if (hRawFile == (HANDLE)0xFFFFFFFF
  250. || !dwLenSysRoot
  251. || dwLenSysRoot >= sizeof(achSysRoot)
  252. || !(dwRawFileSize = GetFileSize(hRawFile, NULL))
  253. || dwRawFileSize == 0xFFFFFFFF )
  254. {
  255. RcErrorDialogBox(ED_BADSYSFILE, achRawFile, NULL);
  256. TerminateVDM(); // skip cleanup since I insist that we exit!
  257. }
  258. pRawBuffer = malloc(dwRawFileSize+1);
  259. // allocate buffer to save environment settings in autoexec.nt
  260. // I know this is bad to allocate this amount of memory at this
  261. // moment as we dont know if there are anything we want to keep
  262. // at all. This allocation simply provides the following error
  263. // handling easily.
  264. if(!bConfig) {
  265. lpszzEnv = lpszzcmdEnv16 = (PCHAR)malloc(dwRawFileSize);
  266. cchEnv = 0;
  267. }
  268. if (!pRawBuffer || (!bConfig && lpszzcmdEnv16 == NULL)) {
  269. RcErrorDialogBox(ED_INITMEMERR, achRawFile, NULL);
  270. TerminateVDM(); // skip cleanup since I insist that we exit!
  271. }
  272. if (!cmdCreateTempFile(&hTmpFile,ppTmpFile)
  273. || !ReadFile(hRawFile, pRawBuffer, dwRawFileSize, &dw, NULL)
  274. || dw != dwRawFileSize )
  275. {
  276. GetTempPath(MAX_PATH, achRawFile);
  277. achRawFile[63] = '\0';
  278. RcErrorDialogBox(ED_INITTMPFILE, achRawFile, NULL);
  279. TerminateVDM(); // skip cleanup since I insist that we exit!
  280. }
  281. // CHANGE HERE WHEN YOU CHANGE cmdCreateTempFile !!!!!!!!!!
  282. // we depend on the buffer size allocated for the file name
  283. dw = GetShortPathNameA(*ppTmpFile, *ppTmpFile, MAX_PATH +13);
  284. if (dw == 0 || dw > 63)
  285. {
  286. GetTempPath(MAX_PATH, achRawFile);
  287. achRawFile[63] = '\0';
  288. RcErrorDialogBox(ED_INITTMPFILE, achRawFile, NULL);
  289. TerminateVDM(); // skip cleanup since I insist that we exit!
  290. }
  291. // null terminate the buffer so we can use CRT string functions
  292. *(pRawBuffer+dwRawFileSize) = '\0';
  293. // ensure no trailing backslash in System Directory
  294. if (*(achSysRoot+dwLenSysRoot-1) == '\\') {
  295. *(achSysRoot + --dwLenSysRoot) = '\0';
  296. }
  297. pLine = pRawBuffer;
  298. while (dwRawFileSize) {
  299. // skip leading white space
  300. while (dwRawFileSize && !isgraph(*pLine)) {
  301. pLine++;
  302. dwRawFileSize -= sizeof(CHAR);
  303. }
  304. if (!dwRawFileSize) // anything left to do ?
  305. break;
  306. //
  307. // filter out REM comment lines
  308. //
  309. if (!_strnicmp(pLine, achREM, sizeof(achREM) - sizeof(CHAR)) &&
  310. !isgraph(pLine[sizeof(achREM) - sizeof(CHAR)]))
  311. {
  312. while (dwRawFileSize && !ISEOL(*pLine)) {
  313. pLine++;
  314. dwRawFileSize -= sizeof(CHAR);
  315. }
  316. continue;
  317. }
  318. if (bConfig) {
  319. //
  320. // filter out country= setting we will create our own based
  321. // on current country ID and codepage.
  322. //
  323. pTmp = IsConfigCommand(achCOUNTRY, sizeof(achCOUNTRY) - sizeof(CHAR), pLine);
  324. if (pTmp) {
  325. while (dwRawFileSize && !ISEOL(*pLine)) {
  326. pLine++;
  327. dwRawFileSize -= sizeof(CHAR);
  328. }
  329. continue;
  330. }
  331. // filter out shell= command, saving /E:nn parameter
  332. pTmp = IsConfigCommand(achSHELL, sizeof(achSHELL) - sizeof(CHAR),pLine);
  333. if (pTmp) {
  334. // skip leading white space
  335. while (!isgraph(*pTmp) && !ISEOL(*pTmp)) {
  336. dwRawFileSize -= sizeof(CHAR);
  337. pTmp++;
  338. }
  339. /* if for a third party shell (not SCS command.com)
  340. * append the whole thing thru /c parameter
  341. * else
  342. * append user specifed /e: parameter
  343. */
  344. if (!_strnicmp(achSYSROOT,pTmp,sizeof(achSYSROOT)-sizeof(CHAR)))
  345. {
  346. dw = sizeof(achSYSROOT) - sizeof(CHAR);
  347. }
  348. else if (!_strnicmp(achSysRoot,pTmp, strlen(achSysRoot)))
  349. {
  350. dw = strlen(achSysRoot);
  351. }
  352. else {
  353. dw = 0;
  354. }
  355. if (!dw ||
  356. _strnicmp(achCOMMAND,pTmp+dw,sizeof(achCOMMAND)-sizeof(CHAR)) )
  357. {
  358. pPartyShell = pTmp;
  359. }
  360. else {
  361. do {
  362. while (*pTmp != '/' && !ISEOL(*pTmp)) // save "/e:"
  363. pTmp++;
  364. if(ISEOL(*pTmp))
  365. break;
  366. if (!_strnicmp(pTmp,achENV,sizeof(achENV)-sizeof(CHAR)))
  367. pEnvParam = pTmp;
  368. pTmp++;
  369. } while(1); // was: while (!ISEOL(*pTmp));
  370. // we have break form this loop now,
  371. // and don't need in additional macro..
  372. }
  373. // skip the "shell=" line
  374. while (dwRawFileSize && !ISEOL(*pLine)) {
  375. pLine++;
  376. dwRawFileSize -= sizeof(CHAR);
  377. }
  378. continue;
  379. } // END, really is "shell=" line!
  380. }
  381. #if defined(KOREA)
  382. // If current Code page is 437(US), system won't load HBIOS related modules.
  383. if (!fKoreanCP) {
  384. if (IsHBIOSConfig(achFontSys, sizeof(achFontSys)-sizeof(CHAR), pLine)) {
  385. while (dwRawFileSize && !ISEOL(*pLine)) {
  386. pLine++;
  387. dwRawFileSize -= sizeof(CHAR);
  388. }
  389. continue;
  390. }
  391. if (IsHBIOSConfig(achHBIOS, sizeof(achHBIOS)-sizeof(CHAR), pLine)) {
  392. while (dwRawFileSize && !ISEOL(*pLine)) {
  393. pLine++;
  394. dwRawFileSize -= sizeof(CHAR);
  395. }
  396. continue;
  397. }
  398. if (IsHBIOSConfig(achDispSys, sizeof(achDispSys)-sizeof(CHAR), pLine)) {
  399. while (dwRawFileSize && !ISEOL(*pLine)) {
  400. pLine++;
  401. dwRawFileSize -= sizeof(CHAR);
  402. }
  403. continue;
  404. }
  405. }
  406. #endif // KOREA
  407. /** Filter out PROMPT, SET and PATH from autoexec.nt
  408. for environment merging. The output we prepare here is
  409. a multiple strings buffer which has the format as :
  410. "EnvName_1 NULL EnvValue_1 NULL[EnvName_n NULL EnvValue_n NULL] NULL
  411. We don't take them out from the file because command.com needs
  412. them.
  413. **/
  414. if (!bConfig)
  415. if (!_strnicmp(pLine, achPROMPT, sizeof(achPROMPT) - 1)){
  416. // prompt command found.
  417. // the syntax of prompt can be eithe
  418. // prompt xxyyzz or
  419. // prompt=xxyyzz
  420. //
  421. strcpy(lpszzEnv, achPROMPT); // get the name
  422. lpszzEnv += sizeof(achPROMPT);
  423. cchEnv += sizeof(achPROMPT);
  424. pTmp = pLine + sizeof(achPROMPT) - 1;
  425. // skip possible white chars
  426. while (!isgraph(*pTmp) && !ISEOL(*pTmp))
  427. pTmp++;
  428. if (*pTmp == '=') {
  429. pTmp++;
  430. while(!isgraph(*pTmp) && !ISEOL(*pTmp))
  431. pTmp++;
  432. }
  433. while(!ISEOL(*pTmp)){
  434. *lpszzEnv++ = *pTmp++;
  435. cchEnv++;
  436. }
  437. // null terminate this
  438. // it may be "prompt NULL NULL" for delete
  439. // or "prompt NULL something NULL"
  440. *lpszzEnv++ = '\0';
  441. cchEnv++;
  442. }
  443. else if (!_strnicmp(pLine, achPATH, sizeof(achPATH) - 1)) {
  444. // PATH was found, it has the same syntax as
  445. // PROMPT
  446. strcpy(lpszzEnv, achPATH);
  447. lpszzEnv += sizeof(achPATH);
  448. cchEnv += sizeof(achPATH);
  449. pTmp = pLine + sizeof(achPATH) - 1;
  450. while (!isgraph(*pTmp) && !ISEOL(*pTmp))
  451. pTmp++;
  452. if (*pTmp == '=') {
  453. pTmp++;
  454. while(!isgraph(*pTmp) && !ISEOL(*pTmp))
  455. pTmp++;
  456. }
  457. while(!ISEOL(*pTmp)) {
  458. *lpszzEnv++ = *pTmp++;
  459. cchEnv++;
  460. }
  461. *lpszzEnv++ = '\0';
  462. cchEnv++;
  463. }
  464. else if(!_strnicmp(pLine, achSET, sizeof(achSET) -1 )) {
  465. // SET was found, first search for name
  466. pTmp = pLine + sizeof(achSET) - 1;
  467. while(!isgraph(*pTmp) && !ISEOL(*pTmp))
  468. pTmp ++;
  469. // get the name
  470. lpszName = pTmp;
  471. // looking for the '='
  472. // note that the name can have white characters
  473. while (!ISEOL(*lpszName) && *lpszName != '=')
  474. lpszName++;
  475. if (!ISEOL(*lpszName)) {
  476. // copy the name
  477. while (pTmp < lpszName) {
  478. *lpszzEnv++ = *pTmp++;
  479. cchEnv++;
  480. }
  481. *lpszzEnv++ = '\0';
  482. cchEnv++;
  483. // discard the '='
  484. pTmp++;
  485. // grab the value(may be nothing
  486. while (!ISEOL(*pTmp)) {
  487. *lpszzEnv++ = *pTmp++;
  488. cchEnv++;
  489. }
  490. *lpszzEnv++ = '\0';
  491. cchEnv++;
  492. }
  493. }
  494. dw = WriteExpanded(hTmpFile, pLine, dwRawFileSize);
  495. pLine += dw;
  496. dwRawFileSize -=dw;
  497. WriteFileAssert(hTmpFile,achEOL,sizeof(achEOL) - sizeof(CHAR));
  498. } // END, while (dwRawFileSize)
  499. if (bConfig) {
  500. UINT OemCP;
  501. #if defined(JAPAN) || defined(KOREA)
  502. UINT ConsoleCP;
  503. #endif // JAPAN || KOREA
  504. UINT CtryId;
  505. CHAR szCtryId[64]; // expect "nnn" only
  506. /* Ensure that the country settings are in sync with NT This is
  507. * especially important for DosKrnl file UPCASE tables. The
  508. * doskrnl default is "CTRY_UNITED_STATES, 437". But we add the
  509. * country= line to config.sys, even if is US,437, so that the DOS
  510. * will know where the default country.sys is.
  511. */
  512. if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_IDEFAULTCOUNTRY,
  513. szCtryId, sizeof(szCtryId) - 1) )
  514. {
  515. CtryId = strtoul(szCtryId,NULL,10);
  516. }
  517. else {
  518. CtryId = CTRY_UNITED_STATES;
  519. }
  520. OemCP = GetOEMCP();
  521. #if defined(JAPAN) || defined(KOREA)
  522. ConsoleCP = GetConsoleOutputCP();
  523. if (OemCP != ConsoleCP)
  524. OemCP = ConsoleCP;
  525. #endif // JAPAN || KOREA
  526. sprintf(achRawFile,
  527. "%s=%3.3u,%3.3u,%s\\system32\\%s.sys%s",
  528. achCOUNTRY, CtryId, OemCP, achSysRoot, achCOUNTRY, achEOL);
  529. WriteFileAssert(hTmpFile,achRawFile,strlen(achRawFile));
  530. /* We cannot allow the user to set an incorrect shell= command
  531. * so we will contruct the correct shell= command appending
  532. * either (in order of precedence):
  533. * 1. /c ThirdPartyShell
  534. * 2. /e:NNNN
  535. * 3. nothing
  536. *
  537. * If there is a third party shell then we must turn the console
  538. * on now since we no longer have control once system32\command.com
  539. * spawns the third party shell.
  540. */
  541. // write shell=....
  542. sprintf(achRawFile,
  543. "%s=%s%s /p %s\\system32",
  544. achSHELL,achSysRoot, achCOMMAND, achSysRoot);
  545. WriteFileAssert(hTmpFile,achRawFile,strlen(achRawFile));
  546. // write extra string (/c ... or /e:nnn)
  547. if (pPartyShell && isgraph(*pPartyShell)) {
  548. pTmp = pPartyShell;
  549. while (!ISEOL(*pTmp))
  550. pTmp++;
  551. }
  552. else if (pEnvParam && isgraph(*pEnvParam)) {
  553. pTmp = pEnvParam;
  554. while (isgraph(*pTmp))
  555. pTmp++;
  556. }
  557. else {
  558. pTmp = NULL;
  559. }
  560. if (pTmp) {
  561. *pTmp = '\0';
  562. if (pPartyShell) {
  563. cmdInitConsole();
  564. strcpy(achRawFile, " /c ");
  565. strncat(achRawFile, pPartyShell,sizeof(achRawFile)-3);
  566. }
  567. else if (pEnvParam) {
  568. strcpy(achRawFile, " ");
  569. strncat(achRawFile, pEnvParam,sizeof(achRawFile)-1);
  570. }
  571. achRawFile[sizeof(achRawFile)-1] = 0;
  572. WriteExpanded(hTmpFile, achRawFile, strlen(achRawFile));
  573. }
  574. WriteFileAssert(hTmpFile,achEOL,sizeof(achEOL) - sizeof(CHAR));
  575. }
  576. SetEndOfFile(hTmpFile);
  577. CloseHandle(hTmpFile);
  578. CloseHandle(hRawFile);
  579. free(pRawBuffer);
  580. if (!bConfig) {
  581. // shrink(or free) the memory
  582. if (cchEnv && lpszzcmdEnv16) {
  583. // doubld null terminate it
  584. lpszzcmdEnv16[cchEnv++] = '\0';
  585. // shrink the memory. If it fails, simple keep
  586. // it as is
  587. lpszzEnv = realloc(lpszzcmdEnv16, cchEnv);
  588. if (lpszzEnv != NULL)
  589. lpszzcmdEnv16 = lpszzEnv;
  590. }
  591. else {
  592. free(lpszzcmdEnv16);
  593. lpszzcmdEnv16 = NULL;
  594. }
  595. }
  596. }
  597. /*
  598. * WriteExpanded - writes up to dwChars or EOL, expanding %SystemRoot%
  599. * returns number of CHARs processed in buffer
  600. * (not number of bytes actually written)
  601. */
  602. DWORD WriteExpanded(HANDLE hFile, CHAR *pch, DWORD dwChars)
  603. {
  604. DWORD dw;
  605. DWORD dwSave = dwChars;
  606. CHAR *pSave = pch;
  607. while (dwChars && !ISEOL(*pch)) {
  608. if (*pch == '%' &&
  609. !_strnicmp(pch, achSYSROOT, sizeof(achSYSROOT)-sizeof(CHAR)) )
  610. {
  611. dw = pch - pSave;
  612. if (dw) {
  613. WriteFileAssert(hFile, pSave, dw);
  614. }
  615. WriteFileAssert(hFile, achSysRoot, dwLenSysRoot);
  616. pch += sizeof(achSYSROOT)-sizeof(CHAR);
  617. pSave = pch;
  618. dwChars -= sizeof(achSYSROOT)-sizeof(CHAR);
  619. }
  620. #ifdef JAPAN
  621. // device=...\$disp.sys /hs=%HardwareScroll%
  622. else if (*pch == '%' &&
  623. !_strnicmp(pch, achHARDWARESCROLL, sizeof(achHARDWARESCROLL)-sizeof(CHAR)) )
  624. {
  625. dw = pch - pSave;
  626. if (dw) {
  627. WriteFileAssert(hFile, pSave, dw);
  628. }
  629. WriteFileAssert(hFile, achHardwareScroll, dwLenHardwareScroll);
  630. pch += sizeof(achHARDWARESCROLL)-sizeof(CHAR);
  631. pSave = pch;
  632. dwChars -= sizeof(achHARDWARESCROLL)-sizeof(CHAR);
  633. }
  634. #endif // JAPAN
  635. #if defined(KOREA) // looking for hbios.sys
  636. else if (fKoreanCP && *pch == 'h' &&
  637. !_strnicmp(pch, achHBIOS, sizeof(achHBIOS)-sizeof(CHAR)) )
  638. {
  639. dw = pch - pSave;
  640. if (dw) {
  641. WriteFileAssert(hFile, pSave, dw);
  642. }
  643. WriteFileAssert(hFile, achHotkeyOption, dwLenHotkeyOption);
  644. pch += sizeof(achHBIOS)-sizeof(CHAR);
  645. pSave = pch;
  646. dwChars -= sizeof(achHBIOS)-sizeof(CHAR);
  647. }
  648. #endif // KOREA
  649. else {
  650. pch++;
  651. dwChars -= sizeof(CHAR);
  652. }
  653. }
  654. dw = pch - pSave;
  655. if (dw) {
  656. WriteFileAssert(hFile, pSave, dw);
  657. }
  658. return (dwSave - dwChars);
  659. }
  660. /*
  661. * WriteFileAssert
  662. *
  663. * Cecks for error in wrtiting the temp boot file,
  664. * If one occurs displays warning popup and terminates the vdm.
  665. *
  666. */
  667. void WriteFileAssert(HANDLE hFile, CHAR *pBuff, DWORD dwBytes)
  668. {
  669. DWORD dw;
  670. CHAR ach[MAX_PATH];
  671. if (!WriteFile(hFile, pBuff, dwBytes, &dw, NULL) ||
  672. dw != dwBytes)
  673. {
  674. GetTempPath(MAX_PATH, ach);
  675. ach[63] = '\0';
  676. RcErrorDialogBox(ED_INITTMPFILE, ach, NULL);
  677. TerminateVDM(); // skip cleanup since I insist that we exit!
  678. }
  679. }
  680. #ifdef JAPAN
  681. //
  682. // MSKK 8/26/1993 V-KazuyS
  683. // Get HardwareScroll type from registry
  684. // this parameter also use console.
  685. //
  686. DWORD GetHardwareScroll( PCHAR achHardwareScroll, int size )
  687. {
  688. HKEY hKey;
  689. DWORD dwType;
  690. DWORD retCode;
  691. CHAR szBuf[256];
  692. DWORD cbData=256L;
  693. DWORD num;
  694. PCHAR psz;
  695. // Get HardwareScroll type ( ON, LC or OFF ) from REGISTRY file.
  696. // OPEN THE KEY.
  697. retCode = RegOpenKeyEx (
  698. HKEY_LOCAL_MACHINE, // Key handle at root level.
  699. "HARDWARE\\DEVICEMAP\\VIDEO", // Path name of child key.
  700. 0, // Reserved.
  701. KEY_EXECUTE, // Requesting read access.
  702. &hKey ); // Address of key to be returned.
  703. // If retCode != 0 then we cannot find section in Register file
  704. if ( retCode ) {
  705. #ifdef JAPAN_DBG
  706. DbgPrint( "NTVDM: RegOpenKeyEx failed %xh\n", retCode );
  707. #endif
  708. strcpy( achHardwareScroll, "off");
  709. return ( strlen("off") );
  710. }
  711. dwType = REG_SZ;
  712. // Query for line from REGISTER file
  713. retCode = RegQueryValueEx( hKey,
  714. "\\Device\\Video0",
  715. NULL,
  716. &dwType,
  717. szBuf,
  718. &cbData);
  719. szBuf[sizeof(szBuf)-1] = '\0';
  720. if ( retCode ) {
  721. #ifdef JAPAN_DBG
  722. DbgPrint( "NTVDM: RegQueryValueEx failed %xh\n", retCode );
  723. #endif
  724. strcpy( achHardwareScroll, "off");
  725. return ( strlen("off") );
  726. }
  727. RegCloseKey(hKey);
  728. #ifdef JAPAN_DBG
  729. DbgPrint( "NTVDM: Get \\Device\\Video0=[%s]\n", szBuf );
  730. #endif
  731. psz = strchr( (szBuf+1), '\\' ); // skip \\REGISTRY\\ *
  732. #ifdef JAPAN_DBG
  733. DbgPrint( "NTVDM: skip \\registry\\ [%s]\n", psz );
  734. #endif
  735. if ( psz != NULL )
  736. psz = strchr( (psz+1), '\\' ); // skip Machine\\ *
  737. if ( psz == NULL ) {
  738. #ifdef JAPAN_DBG
  739. DbgPrint( "NTVDM: Illegal value[%s]h\n", szBuf );
  740. #endif
  741. strcpy( achHardwareScroll, "off" );
  742. return ( strlen("off") );
  743. }
  744. psz++;
  745. #ifdef JAPAN_DBG
  746. DbgPrint( "NTVDM: Open 2nd Key=[%s]\n", psz );
  747. #endif
  748. retCode = RegOpenKeyEx (
  749. HKEY_LOCAL_MACHINE, // Key handle at root level.
  750. psz, // Path name of child key.
  751. 0, // Reserved.
  752. KEY_EXECUTE, // Requesting read access.
  753. &hKey ); // Address of key to be returned.
  754. // If retCode != 0 then we cannot find section in Register file
  755. if ( retCode ) {
  756. #ifdef JAPAN_DBG
  757. DbgPrint( "NTVDM: RegOpenKeyEx failed %xh\n", retCode );
  758. #endif
  759. strcpy( achHardwareScroll, "off" );
  760. return ( strlen("off") );
  761. }
  762. dwType = REG_SZ;
  763. // Query for line from REGISTER file
  764. retCode = RegQueryValueEx( hKey,
  765. "ConsoleFullScreen.HardwareScroll",
  766. NULL,
  767. &dwType,
  768. szBuf,
  769. &cbData);
  770. if ( retCode ) {
  771. #ifdef JAPAN_DBG
  772. DbgPrint( "NTVDM: RegQueryValueEx failed %xh\n", retCode );
  773. #endif
  774. strcpy( achHardwareScroll, "off" );
  775. return ( strlen("off") );
  776. }
  777. RegCloseKey(hKey);
  778. #ifdef JAPAN_DBG
  779. DbgPrint( "NTVDM: Get FullScreenHardwareScroll=[%s]\n", szBuf );
  780. #endif
  781. num = ( lstrlen(szBuf)+1 > size ) ? size : lstrlen(szBuf)+1;
  782. RtlCopyMemory( achHardwareScroll, szBuf, num );
  783. achHardwareScroll[num] = '\0';
  784. #ifdef JAPAN_DBG
  785. DbgPrint( "NTVDM: Set %HardwareScroll%=[%s]\n", achHardwareScroll );
  786. #endif
  787. return num;
  788. }
  789. #endif // JAPAN
  790. #if defined(KOREA)
  791. /*
  792. * 8/05/1996 bklee
  793. * Get keyboard layout from system and set hotkey option for hbios.sys
  794. * Here are hotkey options for HBIOS.SYS.
  795. *
  796. * Keyboard Type Hangul Hanja
  797. * 1 101a r + alt r + ctrl : default
  798. * 2 101b r + ctrl r + alt
  799. * 3 103 Hangul Hanja
  800. * 4 84 alt + shift ctrl + shift
  801. * 5 86 Hangul Hanja
  802. * 6 101c l shift + space l ctrl + space
  803. * 7 64 : N/A. map to default
  804. */
  805. DWORD GetHotkeyOption( PCHAR achHotkeyOption, UINT size )
  806. {
  807. // GetKeyboardType(1) return 1 to 6 as sub-keyboard type.
  808. // No 7 sub-keyboard type will be returned.
  809. UINT HotkeyIndex[6] = { 4, 5, 1, 2, 6, 3 };
  810. UINT SubKeyType, HotkeyOption;
  811. if ( GetKeyboardType(0) == 8 ) { // KOREAN Keyboard layout
  812. SubKeyType = GetKeyboardType(1);
  813. if ( SubKeyType > 0 && SubKeyType < 7 )
  814. HotkeyOption = HotkeyIndex[SubKeyType - 1];
  815. else
  816. HotkeyOption = 1; // Set to default.
  817. wsprintf(achHotkeyOption, "hbios.sys /K:%d", HotkeyOption);
  818. }
  819. else
  820. strcpy(achHotkeyOption, "hbios.sys");
  821. return(strlen(achHotkeyOption));
  822. }
  823. #endif // KOREA