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.

727 lines
17 KiB

  1. /* demmisc.c - Misc. SVC routines
  2. *
  3. * demLoadDos
  4. *
  5. * Modification History:
  6. *
  7. * Sudeepb 31-Mar-1991 Created
  8. */
  9. #include "dem.h"
  10. #include "demmsg.h"
  11. // #include "demdasd.h"
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <softpc.h>
  15. #include <mvdm.h>
  16. #include <dbgsvc.h>
  17. #include <nt_vdd.h>
  18. #if DEVL
  19. // int 21h func names
  20. // index off of function number in ah
  21. char *scname[] = {
  22. "Terminate Program",
  23. "Read Kbd with Echo",
  24. "Display Character",
  25. "Auxillary Input",
  26. "Auxillary Output",
  27. "Print Character",
  28. "Direct Con Output",
  29. "Direct Con Input",
  30. "Read Kbd without Echo",
  31. "Display String",
  32. "Read String",
  33. "Check Keyboard Status",
  34. "Flush Buffer,Read Kbd",
  35. "Reset Drive",
  36. "Set Default Drive",
  37. "FCB Open",
  38. "FCB Close",
  39. "FCB Find First",
  40. "FCB Find Next",
  41. "FCB Delete",
  42. "FCB Seq Read",
  43. "FCB Seq Write",
  44. "FCB Create",
  45. "FCB Rename",
  46. "18h??",
  47. "Get Default Drive",
  48. "Set Disk Transfer Addr",
  49. "Get Default Drive Data",
  50. "Get Drive Data",
  51. "1Dh??",
  52. "1Eh??",
  53. "Get Default DPB",
  54. "20h??",
  55. "FCB Random Read",
  56. "FCB Random Write",
  57. "FCB Get File Size",
  58. "FCB Set Random Record",
  59. "Set Interrupt Vector",
  60. "Create Process Data Block",
  61. "FCB Random Read Block",
  62. "FCB Random Write Block",
  63. "FCB Parse File Name",
  64. "Get Date",
  65. "Set Date",
  66. "Get Time",
  67. "Set Time",
  68. "SetReset Write Verify",
  69. "Get Disk Transefr Addr",
  70. "Get Version Number",
  71. "Keep Process",
  72. "Get Drive Parameters",
  73. "GetSet CTRL C",
  74. "Get InDOS Flag",
  75. "Get Interrupt Vector",
  76. "Get Disk Free Space",
  77. "Char Oper",
  78. "GetSet Country Info",
  79. "Make Dir",
  80. "Remove Dir",
  81. "Change DirDir",
  82. "Create File",
  83. "Open File",
  84. "Close File",
  85. "Read File",
  86. "Write File",
  87. "Delete File",
  88. "Move File Ptr",
  89. "GetSet File Attr",
  90. "IOCTL",
  91. "Dup File Handle",
  92. "Force Dup Handle",
  93. "Get Current Dir",
  94. "Alloc Mem",
  95. "Free Mem",
  96. "Realloc Mem",
  97. "Exec Process",
  98. "Exit Process",
  99. "Get Child Process Exit Code",
  100. "Find First",
  101. "Find Next",
  102. "Set Current PSP",
  103. "Get Current PSP",
  104. "Get In Vars",
  105. "Set DPB",
  106. "Get Verify On Write",
  107. "Dup PDB",
  108. "Rename File",
  109. "GetSet File Date and Time",
  110. "Allocation Strategy",
  111. "Get Extended Error",
  112. "Create Temp File",
  113. "Create New File",
  114. "LockUnlock File",
  115. "SetExtendedErrorNetwork-ServerCall",
  116. "Network-UserOper",
  117. "Network-AssignOper",
  118. "xNameTrans",
  119. "PathParse",
  120. "GetCurrentPSP",
  121. "ECS CALL",
  122. "Set Printer Flag",
  123. "Extended Country Info",
  124. "GetSet CodePage",
  125. "Set Max Handle",
  126. "Commit File",
  127. "GetSetMediaID",
  128. "6ah??",
  129. "IFS IOCTL",
  130. "Extended OpenCreate",
  131. "6d??",
  132. "6e??",
  133. "6f??",
  134. "70??",
  135. "LFN API"
  136. };
  137. #endif
  138. extern BOOL IsFirstCall;
  139. extern void nt_floppy_release_lock(void);
  140. LPSTR pszBIOSDirectory;
  141. // internal func prototype
  142. BOOL IsDebuggee(void);
  143. void SignalSegmentNotice(WORD wType,
  144. WORD wModuleSeg,
  145. WORD wLoadSeg,
  146. WORD wNewSeg,
  147. LPSTR lpName,
  148. DWORD dwImageLen );
  149. #if defined(NEC_98)
  150. BYTE DemBreakFunc = 0xff;
  151. #endif // NEC_98
  152. /* demLoadDos - Load NTDOS.SYS.
  153. *
  154. * This SVC is made by NTIO.SYS to load NTDOS.SYS.
  155. *
  156. * Entry - Client (DI) - Load Segment
  157. *
  158. * Exit - SUCCESS returns
  159. * FAILURE Kills the VDM
  160. */
  161. VOID demLoadDos (VOID)
  162. {
  163. PBYTE pbLoadAddr;
  164. HANDLE hfile;
  165. DWORD BytesRead;
  166. #ifdef FE_SB
  167. LANGID LcId = GetSystemDefaultLangID();
  168. #endif //FE_SB
  169. // get linear address where ntdos.sys will be loaded
  170. pbLoadAddr = (PBYTE) GetVDMAddr(getDI(),0);
  171. // set up BIOS path string
  172. if(DbgIsDebuggee() &&
  173. ((pszBIOSDirectory = (PCHAR)malloc (strlen (pszDefaultDOSDirectory) +
  174. 1 + sizeof(NTIO_409) + sizeof(NTIO_411) + 1 )) != NULL)) {
  175. strcpy (pszBIOSDirectory, pszDefaultDOSDirectory);
  176. #ifdef FE_SB
  177. switch (LcId) {
  178. case MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT):
  179. strcat (pszBIOSDirectory,NTIO_411);
  180. break;
  181. case MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT):
  182. strcat (pszBIOSDirectory,NTIO_412);
  183. break;
  184. case MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL):
  185. strcat (pszBIOSDirectory,NTIO_404);
  186. break;
  187. case MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED):
  188. case MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_HONGKONG):
  189. strcat (pszBIOSDirectory,NTIO_804);
  190. break;
  191. default:
  192. strcat (pszBIOSDirectory,NTIO_409);
  193. break;
  194. }
  195. #else
  196. strcat (pszBIOSDirectory,"\\ntio.sys");
  197. #endif
  198. }
  199. // prepare the dos file name
  200. #ifdef FE_SB
  201. switch (LcId)
  202. {
  203. case MAKELANGID(LANG_JAPANESE,SUBLANG_DEFAULT):
  204. strcat (pszDefaultDOSDirectory,NTDOS_411);
  205. break;
  206. case MAKELANGID(LANG_KOREAN,SUBLANG_DEFAULT):
  207. strcat (pszDefaultDOSDirectory,NTDOS_412);
  208. break;
  209. case MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_TRADITIONAL):
  210. strcat (pszDefaultDOSDirectory,NTDOS_404);
  211. break;
  212. case MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_SIMPLIFIED):
  213. case MAKELANGID(LANG_CHINESE,SUBLANG_CHINESE_HONGKONG):
  214. strcat (pszDefaultDOSDirectory,NTDOS_804);
  215. break;
  216. default:
  217. strcat (pszDefaultDOSDirectory,NTDOS_409);
  218. break;
  219. }
  220. #else
  221. strcat (pszDefaultDOSDirectory,"\\ntdos.sys");
  222. #endif
  223. hfile = CreateFileOem(pszDefaultDOSDirectory,
  224. GENERIC_READ,
  225. FILE_SHARE_READ,
  226. NULL,
  227. OPEN_EXISTING,
  228. FILE_ATTRIBUTE_NORMAL,
  229. NULL );
  230. if (hfile == (HANDLE)0xffffffff) {
  231. TerminateVDM();
  232. }
  233. BytesRead = 1;
  234. while (BytesRead) {
  235. if (!ReadFile(hfile, pbLoadAddr, 16384, &BytesRead, NULL)) {
  236. TerminateVDM();
  237. }
  238. pbLoadAddr = (PBYTE)((ULONG)pbLoadAddr + BytesRead);
  239. }
  240. CloseHandle (hfile);
  241. if (!DbgIsDebuggee()) {
  242. free(pszDefaultDOSDirectory);
  243. }
  244. return;
  245. }
  246. /* demDOSDispCall
  247. *
  248. * This SVC is made by System_Call upon entering the dos
  249. *
  250. *
  251. * Entry: Client registers as per user app upon entry to dos
  252. *
  253. * Exit - SUCCESS returns, if being debugged and DEMDOSDISP&fShowSvcMsg
  254. * dumps user app's registers and service name
  255. */
  256. VOID demDOSDispCall(VOID)
  257. {
  258. #if DEVL
  259. WORD ax;
  260. if (!DbgIsDebuggee()) {
  261. return;
  262. }
  263. if (fShowSVCMsg & DEMDOSDISP) {
  264. ax = getAX();
  265. sprintf(demDebugBuffer,"demDosDispCall %s\n\tAX=%.4x BX=%.4x CX=%.4x DX=%.4x DI=%.4x SI=%.4x\n",
  266. scname[HIBYTE(ax)],
  267. ax,getBX(),getCX(),getDX(),getDI(), getSI());
  268. OutputDebugStringOem(demDebugBuffer);
  269. sprintf(demDebugBuffer,"\tCS=%.4x IP=%.4x DS=%.4x ES=%.4x SS=%.4x SP=%.4x BP=%.4x\n",
  270. getCS(),getIP(), getDS(),getES(),getSS(),getSP()+2,getBP());
  271. OutputDebugStringOem(demDebugBuffer);
  272. }
  273. #if defined(NEC_98)
  274. if ((fShowSVCMsg & DEMDOSAPPBREAK) && (DemBreakFunc != 0xff))
  275. if (getAH() == DemBreakFunc)
  276. DebugBreak();
  277. if (fShowSVCMsg & 0x01) {
  278. sprintf(demDebugBuffer,"Int 21 AX=%04x BX=%04x CX=%04x DX=%04x SP=%04x BP=%04x SI=%04x DI=%04x\n",getAX(),getBX(),getCX(),getDX(),getSP(),getBP(),getSI(),getDI()); // NEC
  279. OutputDebugStringOem(demDebugBuffer);
  280. }
  281. #endif // NEC_98
  282. #endif
  283. }
  284. /* demDOSDispRet
  285. *
  286. * This SVC is made by System_Call upon exiting from the dos
  287. *
  288. * Entry: Client registers as per user app upon exit to dos
  289. *
  290. * Exit - SUCCESS returns, if being debugged and DEMDOSDISP&fShowSvcMsg
  291. * dumps user app's registers
  292. */
  293. VOID demDOSDispRet(VOID)
  294. {
  295. #if DEVL
  296. PWORD16 pStk;
  297. if (!DbgIsDebuggee()) {
  298. return;
  299. }
  300. if (fShowSVCMsg & DEMDOSDISP) {
  301. // get ptr to flag word on stack
  302. pStk = (WORD *)GetVDMAddr(getSS(), getSP());
  303. pStk += 2;
  304. sprintf (demDebugBuffer,"demDosDispRet\n\tAX=%.4x BX=%.4x CX=%.4x DX=%.4x DI=%.4x SI=%.4x\n",
  305. getAX(),getBX(),getCX(),getDX(),getDI(),getSI());
  306. OutputDebugStringOem(demDebugBuffer);
  307. sprintf(demDebugBuffer,"\tCS=%.4x IP=%.4x DS=%.4x ES=%.4x SS=%.4x SP=%.4x BP=%.4x CF=%.1x\n",
  308. getCS(),getIP(), getDS(),getES(),getSS(),getSP(),getBP(), (*pStk) & 1);
  309. OutputDebugStringOem(demDebugBuffer);
  310. }
  311. #endif
  312. }
  313. /* demEntryDosApp - Dump Entry Point Dos Apps
  314. *
  315. * This SVC is made by NTDOS.SYS,$exec just prior to entering dos app
  316. *
  317. * Entry - Client DS:SI points to entry point
  318. * Client AX:DI points to initial stack
  319. * Client DX has PDB pointer
  320. *
  321. * Exit - SUCCESS returns, if being debugged and DEMDOSAPPBREAK&fShowSvcMsg
  322. * breaks to debugger
  323. */
  324. VOID demEntryDosApp(VOID)
  325. {
  326. USHORT PDB;
  327. PDB = getDX();
  328. if(!IsFirstCall)
  329. VDDCreateUserHook(PDB);
  330. if (!DbgIsDebuggee()) {
  331. return;
  332. }
  333. DbgDosAppStart(getDS(), getSI());
  334. #if DEVL
  335. if (fShowSVCMsg & DEMDOSAPPBREAK) {
  336. sprintf(demDebugBuffer,"demEntryDosApp: Entry=%.4x:%.4x, Stk=%.4x:%.4x PDB=%.4x\n",
  337. getCS(),getIP(),getAX(),getDI(),PDB);
  338. OutputDebugStringOem(demDebugBuffer);
  339. DebugBreak();
  340. }
  341. #endif
  342. }
  343. /* demLoadDosAppSym - Load Dos Apps Symbols
  344. *
  345. * This SVC is made by NTDOS.SYS,$exec to load Dos App symbols
  346. *
  347. * Entry - Client ES:DI -Fully Qualified Path Name of executable
  348. * Client BX -Load Segment\Reloc Factor
  349. * Client DX:AX -HIWORD:LOWORD exe size
  350. *
  351. * Exit - SUCCESS returns, raises debug exception, if being debugged
  352. *
  353. */
  354. VOID demLoadDosAppSym(VOID)
  355. {
  356. SignalSegmentNotice(DBG_MODLOAD,
  357. 0, getBX(), 0,
  358. (LPSTR)GetVDMAddr(getES(),getDI()),
  359. MAKELONG(getAX(), getDX()) );
  360. }
  361. /* demFreeDosAppSym - Free Dos Apps Symbols
  362. *
  363. * This SVC is made by NTDOS.SYS,$exec to Free Dos App symbols
  364. *
  365. * Entry - Client ES:DI -Fully Qualified Path Name of executable
  366. *
  367. * Exit - SUCCESS returns, raises debug exception, if being debugged
  368. *
  369. */
  370. VOID demFreeDosAppSym(VOID)
  371. {
  372. SignalSegmentNotice(DBG_MODFREE,
  373. 0, 0, 0,
  374. (LPSTR)GetVDMAddr(getES(), getDI()),
  375. 0);
  376. }
  377. /* demSystemSymbolOp - Manipulate Symbols for special modules
  378. *
  379. * This SVC is made by NTDOS.SYS,NTIO.SYS
  380. *
  381. * Client AH -Operation
  382. * Client AL -module identifier
  383. * Client BX -Load Segment\Reloc Factor
  384. * Client CX:DX -HIWORD:LOWORD exe size
  385. *
  386. * Exit - SUCCESS returns, raises debug exception, if being debugged
  387. *
  388. */
  389. VOID demSystemSymbolOp(VOID)
  390. {
  391. LPSTR pszPathName;
  392. if (!DbgIsDebuggee()) {
  393. return;
  394. }
  395. switch(getAL()) {
  396. case ID_NTIO:
  397. pszPathName = pszBIOSDirectory;
  398. break;
  399. case ID_NTDOS:
  400. pszPathName = pszDefaultDOSDirectory;
  401. break;
  402. default:
  403. pszPathName = NULL;
  404. }
  405. // check this again for the case where the static strings have been freed
  406. if (pszPathName != NULL) {
  407. switch(getAH() & (255-SYMOP_CLEANUP)) {
  408. case SYMOP_LOAD:
  409. SignalSegmentNotice(DBG_MODLOAD,
  410. 0, getBX(), 0,
  411. pszPathName,
  412. MAKELONG(getDX(), getCX()) );
  413. break;
  414. case SYMOP_FREE:
  415. //bugbug not implemented yet
  416. break;
  417. case SYMOP_MOVE:
  418. SignalSegmentNotice(DBG_SEGMOVE,
  419. getDI(), getBX(), getES(),
  420. pszPathName,
  421. MAKELONG(getDX(), getCX()) );
  422. break;
  423. }
  424. }
  425. if (getAH() & SYMOP_CLEANUP) {
  426. if (pszBIOSDirectory != NULL) {
  427. free (pszBIOSDirectory);
  428. }
  429. if (pszDefaultDOSDirectory != NULL) {
  430. free(pszDefaultDOSDirectory);
  431. }
  432. }
  433. }
  434. VOID demOutputString(VOID)
  435. {
  436. LPSTR lpText;
  437. UCHAR fPE;
  438. if ( !DbgIsDebuggee() ) {
  439. return;
  440. }
  441. fPE = ISPESET;
  442. lpText = (LPSTR)Sim32GetVDMPointer(
  443. ((ULONG)getDS() << 16) + (ULONG)getSI(),
  444. (ULONG)getBX(), fPE );
  445. OutputDebugStringOem( lpText );
  446. }
  447. VOID demInputString(VOID)
  448. {
  449. LPSTR lpText;
  450. UCHAR fPE;
  451. if ( !DbgIsDebuggee() ) {
  452. return;
  453. }
  454. fPE = ISPESET;
  455. lpText = (LPSTR)Sim32GetVDMPointer(
  456. ((ULONG)getDS() << 16) + (ULONG)getDI(),
  457. (ULONG)getBX(), fPE );
  458. DbgPrompt( "", lpText, 0x80 );
  459. }
  460. /* SignalSegmentNotice
  461. *
  462. * packs up the data and raises STATUS_SEGMENT_NOTIFICATION
  463. *
  464. * Entry - WORD wType - DBG_MODLOAD, DBG_MODFREE
  465. * WORD wModuleSeg- segment number within module (1 based)
  466. * WORD wLoadSeg - Starting Segment (reloc factor)
  467. * LPSTR lpName - ptr to Name of Image
  468. * DWORD dwModLen - Length of module
  469. *
  470. *
  471. * if wType ==DBG_MODLOAD wOldLoadSeg is unused
  472. * if wType ==DBG_MODFREE wLoadSeg,dwImageLen,wOldLoadSeg are unused
  473. *
  474. * Use 0 or NULL for unused parameters
  475. *
  476. * Exit - void
  477. *
  478. */
  479. void SignalSegmentNotice(WORD wType,
  480. WORD wModuleSeg,
  481. WORD wLoadSeg,
  482. WORD wNewSeg,
  483. LPSTR lpName,
  484. DWORD dwImageLen )
  485. {
  486. int i;
  487. DWORD dw;
  488. LPSTR lpstr;
  489. LPSTR lpModuleName;
  490. char ach[MAX_PATH+9]; // 9 for module name
  491. if (!DbgIsDebuggee()) {
  492. return;
  493. }
  494. // create file name
  495. dw = GetFullPathNameOem(lpName,
  496. sizeof(ach)-9, // 9 for module name
  497. ach,
  498. &lpstr);
  499. if (!dw || dw >= sizeof(ach)) {
  500. lpName = " ";
  501. strcpy(ach, lpName);
  502. }
  503. else {
  504. lpName = lpstr;
  505. }
  506. // copy in module name
  507. i = 8; // limit len of module name
  508. dw = strlen(ach);
  509. lpModuleName = lpstr = ach+dw+1;
  510. while (*lpName && *lpName != '.' && i--)
  511. {
  512. *lpstr++ = *lpName++;
  513. dw++;
  514. }
  515. *lpstr = '\0';
  516. dw += 2;
  517. #if DBG
  518. if (fShowSVCMsg) {
  519. sprintf(demDebugBuffer,"dem Segment Notify: <%s> Seg=%lxh, ImageLen=%ld\n",
  520. ach, (DWORD)wLoadSeg, dwImageLen);
  521. OutputDebugStringOem(demDebugBuffer);
  522. }
  523. #endif
  524. // Send it to the debugger
  525. DbgSegmentNotice(wType, wModuleSeg, wLoadSeg, wNewSeg, lpModuleName, ach, dwImageLen);
  526. }
  527. /* demIsDebug - Determine if 16bit DOS should make entry/exit calls at int21
  528. *
  529. * Entry: void
  530. *
  531. * Exit: Client AL = 0 if not
  532. * Client AL = 1 if yes
  533. *
  534. */
  535. VOID demIsDebug(void)
  536. {
  537. BYTE dbgflags = 0;
  538. if (DbgIsDebuggee()) {
  539. dbgflags |= ISDBG_DEBUGGEE;
  540. if (fShowSVCMsg)
  541. dbgflags |= ISDBG_SHOWSVC;
  542. }
  543. setAL (dbgflags);
  544. return;
  545. }
  546. /* demDiskReset - Reset floppy disks.
  547. *
  548. * Entry - None
  549. *
  550. * Exit - FDAccess in DOSDATA (NTDOS.SYS) is 0.
  551. */
  552. VOID demDiskReset (VOID)
  553. {
  554. extern WORD * pFDAccess; // defined in SoftPC.
  555. HostFloppyReset();
  556. HostFdiskReset();
  557. *pFDAccess = 0;
  558. return;
  559. }
  560. /* demExitVDM - Kill the VDM From 16Bit side with a proper message
  561. * in case something goes wrong.
  562. *
  563. * Entry - DS:SI - Message String
  564. *
  565. * Exit - None (VDM Is killed)
  566. */
  567. VOID demExitVDM ( VOID )
  568. {
  569. RcErrorDialogBox(ED_BADSYSFILE,"config.nt",NULL);
  570. TerminateVDM ();
  571. }
  572. /* demWOWFiles - Return what should be the value of files= for WOW VDM.
  573. *
  574. * Entry - AL - files= specified in config.sys
  575. *
  576. * Exit - client AL is set to max if WOW VDM else unmodified
  577. */
  578. VOID demWOWFiles ( VOID )
  579. {
  580. if(VDMForWOW)
  581. setAL (255);
  582. return;
  583. }
  584. /** GetDOSAppName - Return the name of the current DOS executable
  585. *
  586. * ENTRY -
  587. * OUT ppszApp Name: address of the app
  588. *
  589. * EXIT
  590. * SUCCESS - Returns SUCCESS
  591. * FAILURE - Returns FAILURE
  592. *
  593. * Comments:
  594. * This routine uses the current PDB to figure out the name of the currently
  595. * executing DOS application.
  596. */
  597. VOID GetDOSAppName(LPSTR pszAppName)
  598. {
  599. PCHAR pch = NULL;
  600. PUSHORT pusEnvSeg;
  601. #define PDB_ENV_OFFSET 0x2c
  602. if (pusCurrentPDB) {
  603. pusEnvSeg = (PUSHORT)Sim32GetVDMPointer((*pusCurrentPDB) << 16, 0, 0);
  604. pusEnvSeg = (PUSHORT)((PCHAR)pusEnvSeg + PDB_ENV_OFFSET);
  605. // Get a pointer to the environment
  606. if (VDMForWOW || (getMSW() & MSW_PE)) {
  607. pch = (PCHAR)Sim32GetVDMPointer(*pusEnvSeg << 16, 1, TRUE);
  608. } else {
  609. pch = (PCHAR)Sim32GetVDMPointer(*pusEnvSeg << 16, 0, 0);
  610. }
  611. }
  612. if (NULL == pch) {
  613. *pszAppName = '\0';
  614. }
  615. else {
  616. // Walk through the environment strings until we get to the command line
  617. while (*pch) {
  618. pch += strlen(pch) + 1;
  619. }
  620. pch += 3; // skip past the double null and string count
  621. strcpy(pszAppName, pch);
  622. }
  623. }