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.

404 lines
11 KiB

  1. /* demerror.c - Error handling routines of DEM
  2. *
  3. * demSetHardErrorInfo
  4. * demClientError
  5. * demRetry
  6. *
  7. * Modification History:
  8. *
  9. * Sudeepb 27-Nov-1991 Created
  10. */
  11. #include "dem.h"
  12. #include "demmsg.h"
  13. #include <softpc.h>
  14. PVHE pHardErrPacket;
  15. PSYSDEV pDeviceChain;
  16. SAVEDEMWORLD RetryInfo;
  17. CHAR GetDriveLetterByHandle(HANDLE hFile);
  18. VOID SubstituteDeviceName( PUNICODE_STRING InputDeviceName,
  19. LPSTR OutputDriveLetter);
  20. /* demSetHardErrorInfo - Store away harderr related address of DOSKRNL
  21. *
  22. * Entry
  23. * Client (DS:DX) - VHE structure
  24. * Client (DS:BX) - nuldev, first device in BIOS chain
  25. *
  26. * Exit
  27. * None
  28. */
  29. VOID demSetHardErrorInfo (VOID)
  30. {
  31. pHardErrPacket = (PVHE) GetVDMAddr (getDS(),getDX());
  32. pDeviceChain = (PSYSDEV) GetVDMAddr(getDS(),getBX());
  33. return;
  34. }
  35. /* demRetry - Retry the operation which last resulted in hard error
  36. *
  37. * Entry
  38. * None
  39. *
  40. * Exit
  41. * None
  42. */
  43. VOID demRetry (VOID)
  44. {
  45. ULONG iSvc;
  46. demRestoreHardErrInfo ();
  47. iSvc = CurrentISVC;
  48. #if DBG
  49. if(iSvc < SVC_DEMLASTSVC && (fShowSVCMsg & DEMSVCTRACE) &&
  50. apfnSVC[iSvc] != demNotYetImplemented){
  51. sprintf(demDebugBuffer,"demRetry:Retrying %s\n\tAX=%.4x BX=%.4x CX=%.4x DX=%.4x DI=%.4x SI=%.4x\n",
  52. aSVCNames[iSvc],getAX(),getBX(),getCX(),getDX(),getDI(),getSI());
  53. OutputDebugStringOem(demDebugBuffer);
  54. sprintf(demDebugBuffer,"\tCS=%.4x IP=%.4x DS=%.4x ES=%.4x SS=%.4x SP=%.4x BP=%.4x\n",
  55. getCS(),getIP(), getDS(),getES(),getSS(),getSP(),getBP());
  56. OutputDebugStringOem(demDebugBuffer);
  57. }
  58. if (iSvc >= SVC_DEMLASTSVC || apfnSVC[iSvc] == demNotYetImplemented ){
  59. ASSERT(FALSE);
  60. setCF(1);
  61. setAX(0xff);
  62. return;
  63. }
  64. #endif // DBG
  65. (apfnSVC [iSvc])();
  66. #if DBG
  67. if((fShowSVCMsg & DEMSVCTRACE)){
  68. sprintf(demDebugBuffer,"demRetry:After %s\n\tAX=%.4x BX=%.4x CX=%.4x DX=%.4x DI=%.4x SI=%.4x\n",
  69. aSVCNames[iSvc],getAX(),getBX(),getCX(),getDX(),getDI(),getSI());
  70. OutputDebugStringOem(demDebugBuffer);
  71. sprintf(demDebugBuffer,"\tCS=%.4x IP=%.4x DS=%.4x ES=%.4x SS=%.4x SP=%.4x BP=%.4x CF=%x\n",
  72. getCS(),getIP(), getDS(),getES(),getSS(),getSP(),getBP(),getCF());
  73. OutputDebugStringOem(demDebugBuffer);
  74. }
  75. #endif
  76. return;
  77. }
  78. /* demClientError - Update client registers to signal error
  79. *
  80. * Entry
  81. * HANDLE hFile; file handle , if none == -1
  82. * char chDrive; drive letter , if none == -1
  83. *
  84. * Exit
  85. * Client (CF) = 1
  86. * Client (AX) = Error Code
  87. *
  88. * Notes
  89. * the following errors cause hard errors
  90. * errors above ERROR_GEN_FAILURE are mapped to general fail by the DOS
  91. *
  92. *
  93. * ERROR_WRITE_PROTECT 19L
  94. * ERROR_BAD_UNIT 20L
  95. * ERROR_NOT_READY 21L
  96. * ERROR_BAD_COMMAND 22L
  97. * ERROR_CRC 23L
  98. * ERROR_BAD_LENGTH 24L
  99. * ERROR_SEEK 25L
  100. * ERROR_NOT_DOS_DISK 26L
  101. * ERROR_SECTOR_NOT_FOUND 27L
  102. * ERROR_OUT_OF_PAPER 28L
  103. * ERROR_WRITE_FAULT 29L
  104. * ERROR_READ_FAULT 30L
  105. * ERROR_GEN_FAILURE 31L
  106. * ERROR_WRONG_DISK 34l
  107. * ERROR_NO_MEDIA_IN_DRIVE 1112l
  108. * #ifdef JAPAN
  109. * ERROR_UNRECOGNIZED_MEDIA 1785L
  110. * #ifdef JAPAN
  111. *
  112. */
  113. VOID demClientError (HANDLE hFile, CHAR chDrive)
  114. {
  115. demClientErrorEx (hFile, chDrive, TRUE);
  116. }
  117. ULONG demClientErrorEx (HANDLE hFile, CHAR chDrive, BOOL bSetRegs)
  118. {
  119. ULONG ulErrCode;
  120. if(!(ulErrCode = GetLastError()))
  121. ulErrCode = ERROR_ACCESS_DENIED;
  122. #ifdef JAPAN
  123. if ((ulErrCode < ERROR_WRITE_PROTECT || ulErrCode > ERROR_GEN_FAILURE)
  124. && ulErrCode != ERROR_WRONG_DISK && ulErrCode != ERROR_UNRECOGNIZED_MEDIA)
  125. #else // !JAPAN
  126. if ((ulErrCode < ERROR_WRITE_PROTECT || ulErrCode > ERROR_GEN_FAILURE)
  127. && ulErrCode != ERROR_WRONG_DISK )
  128. #endif // !JAPAN
  129. {
  130. #if DBG
  131. if (fShowSVCMsg & DEMERROR) {
  132. sprintf(demDebugBuffer,"demClientErr: ErrCode=%ld\n", ulErrCode);
  133. OutputDebugStringOem(demDebugBuffer);
  134. }
  135. #endif
  136. if (bSetRegs) {
  137. setAX((USHORT)ulErrCode);
  138. }
  139. }
  140. else { // handle hard error case
  141. if (ulErrCode > ERROR_GEN_FAILURE)
  142. ulErrCode = ERROR_GEN_FAILURE;
  143. // Set the hard error flag
  144. pHardErrPacket->vhe_fbInt24 = 1;
  145. // Get the drive letter
  146. if (hFile != INVALID_HANDLE_VALUE)
  147. chDrive = GetDriveLetterByHandle(hFile);
  148. pHardErrPacket->vhe_bDriveNum = chDrive == -1
  149. ? -1 : toupper(chDrive) - 'A';
  150. // convert error code to i24 based error.
  151. ulErrCode -= ERROR_WRITE_PROTECT;
  152. pHardErrPacket->vhe_HrdErrCode = (UCHAR)ulErrCode;
  153. #if DBG
  154. if (fShowSVCMsg & DEMERROR) {
  155. sprintf(demDebugBuffer,
  156. "demClientErr HRDERR: DriveNum=%ld ErrCode=%ld\n",
  157. (DWORD)pHardErrPacket->vhe_bDriveNum,
  158. (DWORD)pHardErrPacket->vhe_HrdErrCode);
  159. OutputDebugStringOem(demDebugBuffer);
  160. }
  161. #endif
  162. // Save Away Information for possible retry operation
  163. demSaveHardErrInfo ();
  164. }
  165. if (bSetRegs)
  166. setCF(1);
  167. return (ulErrCode);
  168. }
  169. /*
  170. * GetDriveLetterByHandle
  171. *
  172. * retrieves the drive letter for the file handle
  173. * if its a remote drive or fails returns -1
  174. */
  175. CHAR GetDriveLetterByHandle(HANDLE hFile)
  176. {
  177. NTSTATUS Status;
  178. ULONG ul;
  179. ANSI_STRING AnsiString;
  180. FILE_FS_DEVICE_INFORMATION DeviceInfo;
  181. IO_STATUS_BLOCK IoStatusBlock;
  182. POBJECT_NAME_INFORMATION pObNameInfo;
  183. CHAR Buffer[MAX_PATH+sizeof(OBJECT_NAME_INFORMATION)];
  184. CHAR ch;
  185. // if a remote drive return -1 for drive letter
  186. Status = NtQueryVolumeInformationFile(
  187. hFile,
  188. &IoStatusBlock,
  189. &DeviceInfo,
  190. sizeof(DeviceInfo),
  191. FileFsDeviceInformation );
  192. if (NT_SUCCESS(Status) &&
  193. DeviceInfo.Characteristics & FILE_REMOTE_DEVICE )
  194. return (CHAR) -1;
  195. // get the name
  196. pObNameInfo = (POBJECT_NAME_INFORMATION)Buffer;
  197. Status = NtQueryObject( // get len of name
  198. hFile,
  199. ObjectNameInformation,
  200. pObNameInfo,
  201. sizeof(Buffer),
  202. &ul);
  203. if (!NT_SUCCESS(Status))
  204. return -1;
  205. RtlUnicodeStringToAnsiString(&AnsiString, &(pObNameInfo->Name), TRUE);
  206. if (strstr(AnsiString.Buffer,"\\Device") == AnsiString.Buffer)
  207. SubstituteDeviceName(&(pObNameInfo->Name), AnsiString.Buffer);
  208. ch = AnsiString.Buffer[0];
  209. RtlFreeAnsiString(&AnsiString);
  210. return ch;
  211. }
  212. static WCHAR wszDosDevices[] = L"\\DosDevices\\?:";
  213. /*
  214. * SubstituteDeviceName
  215. *
  216. * lifted this code from the user\harderror hard error thread
  217. */
  218. VOID SubstituteDeviceName( PUNICODE_STRING InputDeviceName,
  219. LPSTR OutputDriveLetter )
  220. {
  221. UNICODE_STRING LinkName;
  222. UNICODE_STRING DeviceName;
  223. OBJECT_ATTRIBUTES Obja;
  224. HANDLE LinkHandle;
  225. NTSTATUS Status;
  226. ULONG i;
  227. PWCHAR p;
  228. PWCHAR pSlash = L"\\";
  229. WCHAR DeviceNameBuffer[MAXIMUM_FILENAME_LENGTH];
  230. /*
  231. * Ensure have trailing backslash
  232. */
  233. if (InputDeviceName->Buffer[(InputDeviceName->Length >>1) - 1] != *pSlash)
  234. RtlAppendUnicodeToString(InputDeviceName, pSlash);
  235. RtlInitUnicodeString(&LinkName,wszDosDevices);
  236. p = (PWCHAR)LinkName.Buffer;
  237. p = p+12;
  238. for(i=0;i<26;i++){
  239. *p = (WCHAR)'A' + (WCHAR)i;
  240. InitializeObjectAttributes(
  241. &Obja,
  242. &LinkName,
  243. OBJ_CASE_INSENSITIVE,
  244. NULL,
  245. NULL
  246. );
  247. Status = NtOpenSymbolicLinkObject(
  248. &LinkHandle,
  249. SYMBOLIC_LINK_QUERY,
  250. &Obja
  251. );
  252. if (NT_SUCCESS( Status )) {
  253. //
  254. // Open succeeded, Now get the link value
  255. //
  256. DeviceName.Length = 0;
  257. DeviceName.MaximumLength = sizeof(DeviceNameBuffer);
  258. DeviceName.Buffer = DeviceNameBuffer;
  259. Status = NtQuerySymbolicLinkObject(
  260. LinkHandle,
  261. &DeviceName,
  262. NULL
  263. );
  264. NtClose(LinkHandle);
  265. if ( NT_SUCCESS(Status) ) {
  266. if (DeviceName.Buffer[(DeviceName.Length >>1) - 1] != *pSlash)
  267. RtlAppendUnicodeToString(&DeviceName, pSlash);
  268. #ifdef JAPAN
  269. // #6197 compare only device name
  270. if (InputDeviceName->Length > DeviceName.Length)
  271. InputDeviceName->Length = DeviceName.Length;
  272. #endif // JAPAN
  273. if ( RtlEqualUnicodeString(InputDeviceName,&DeviceName,TRUE) )
  274. {
  275. OutputDriveLetter[0]='A'+(WCHAR)i;
  276. OutputDriveLetter[1]='\0';
  277. return;
  278. }
  279. }
  280. }
  281. }
  282. // just in case we don't find it
  283. OutputDriveLetter[0]=(char)-1;
  284. OutputDriveLetter[1]='\0';
  285. return;
  286. }
  287. /* demSaveHardErrInfo
  288. * demRestoreHardErrInfo
  289. *
  290. * These two routines are used to preserve all the DOSKRNL registers
  291. * which will be needed to retry an SVC handler, in case user opts for
  292. * retry in harderr popup. This is a preferred way to handle retry
  293. * as it gives the DOSKRNL code the freedom to trash any register
  294. * even though it might have to retry the operation. It saves lots
  295. * of code bytes in heavily used DOS macro "HrdSVC".
  296. *
  297. * Entry
  298. * None
  299. *
  300. * Exit
  301. * None
  302. *
  303. * Notes
  304. *
  305. * 1. Doing things this way means, DOSKRNL cannot change the
  306. * registers for retry. Under any circumstances, i can't think
  307. * why it would need to do that anyway.
  308. *
  309. * 2. This mechanism also assumes that DOSKRNL never uses CS,IP,SS,SP
  310. * for passing SVC parameters.
  311. *
  312. * 3. DOS does'nt allow int24 hookers to make any call which comes
  313. * to DEM, so using CurrentISVC is safe.
  314. *
  315. * 4. If an SVC handler can pssibly return a hard error it should never
  316. * modify the client registers.
  317. */
  318. VOID demSaveHardErrInfo (VOID)
  319. {
  320. RetryInfo.ax = getAX();
  321. RetryInfo.bx = getBX();
  322. RetryInfo.cx = getCX();
  323. RetryInfo.dx = getDX();
  324. RetryInfo.ds = getDS();
  325. RetryInfo.es = getES();
  326. RetryInfo.si = getSI();
  327. RetryInfo.di = getDI();
  328. RetryInfo.bp = getBP();
  329. RetryInfo.iSVC = CurrentISVC;
  330. return;
  331. }
  332. VOID demRestoreHardErrInfo (VOID)
  333. {
  334. setAX(RetryInfo.ax);
  335. setBX(RetryInfo.bx);
  336. setCX(RetryInfo.cx);
  337. setDX(RetryInfo.dx);
  338. setDS(RetryInfo.ds);
  339. setES(RetryInfo.es);
  340. setSI(RetryInfo.si);
  341. setDI(RetryInfo.di);
  342. setBP(RetryInfo.bp);
  343. CurrentISVC = RetryInfo.iSVC;
  344. return;
  345. }
  346.