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.

619 lines
14 KiB

  1. /* demhndl.c - SVC handlers for calls where file handle is provided.
  2. *
  3. * demClose
  4. * demRead
  5. * demWrite
  6. * demChgFilePtr
  7. * demFileTimes
  8. *
  9. * Modification History:
  10. *
  11. * Sudeepb 02-Apr-1991 Created
  12. * rfirth 25-Sep-1991 Added Vdm Redir stuff for named pipes
  13. */
  14. #include "dem.h"
  15. #include "demmsg.h"
  16. #include <softpc.h>
  17. #include <io.h>
  18. #include <fcntl.h>
  19. #include <vrnmpipe.h>
  20. #include <exterr.h>
  21. #include <mvdm.h>
  22. BOOL (*VrInitialized)(VOID); // POINTER TO FUNCTION
  23. extern BOOL IsVdmRedirLoaded(VOID);
  24. /* demClose - Close a file
  25. *
  26. *
  27. * Entry - Client (AX:BP) File Handle
  28. * Client (CX:DX) File position (if -1 no seek needed before closing
  29. * the handle.
  30. * (VadimB)
  31. * Client (es:di) SFT ptr - this is implied in abort.asm code
  32. *
  33. * Exit
  34. * SUCCESS
  35. * Client (CY) = 0
  36. *
  37. * FAILURE
  38. * Client (CY) = 1
  39. * Client (AX) = system status code
  40. *
  41. */
  42. VOID demClose (VOID)
  43. {
  44. HANDLE hFile;
  45. LONG lLoc;
  46. USHORT usDX,usCX;
  47. hFile = GETHANDLE (getAX(),getBP());
  48. if (hFile == 0) {
  49. setCF (0);
  50. return;
  51. }
  52. usCX = getCX();
  53. usDX = getDX();
  54. if (!((usCX == (USHORT)-1) && (usDX == (USHORT)-1))) {
  55. lLoc = (LONG)((((int)usCX) << 16) + (int)usDX);
  56. if (SetFilePointer (hFile,
  57. lLoc,
  58. NULL,
  59. FILE_BEGIN) == -1L){
  60. demClientError(hFile, (CHAR)-1);
  61. return ;
  62. }
  63. }
  64. if (CloseHandle (hFile) == FALSE){
  65. demClientError(hFile, (CHAR)-1);
  66. return;
  67. }
  68. //
  69. // if the redir TSR is being run in this VDM session, check if the handle
  70. // being closed references a named pipe - we have to delete some info
  71. // that we keep for the open named pipe
  72. //
  73. if (IsVdmRedirLoaded()) {
  74. VrRemoveOpenNamedPipeInfo(hFile);
  75. }
  76. setCF(0);
  77. return;
  78. }
  79. /* demRead - Read a file
  80. *
  81. *
  82. * Entry - Client (AX:BP) File Handle
  83. * Client (CX) Count to read
  84. * Client (DS:DX) Buffer Address
  85. * Client (BX:SI) = current file pointer location.
  86. * ZF = 1 if seek is not needed prior to read.
  87. *
  88. * Exit
  89. * SUCCESS
  90. * Client (CY) = 0
  91. * Client (AX) = Count of bytes read
  92. *
  93. * FAILURE
  94. * Client (CY) = 1
  95. * Client (AX) = system status code
  96. *
  97. */
  98. VOID demRead (VOID)
  99. {
  100. HANDLE hFile;
  101. LPVOID lpBuf;
  102. DWORD dwBytesRead;
  103. USHORT usDS,usDX;
  104. DWORD dwReadError;
  105. BOOL ok;
  106. UCHAR locus, action, class;
  107. LONG lLoc;
  108. hFile = GETHANDLE (getAX(),getBP());
  109. usDS = getDS();
  110. usDX = getDX();
  111. lpBuf = (LPVOID) GetVDMAddr (usDS,usDX);
  112. //
  113. // if this handle is a named pipe then use VrReadNamedPipe since we have
  114. // to perform an overlapped read, and wait on the event handle for completion
  115. // even though we're still doing synchronous read
  116. //
  117. if (IsVdmRedirLoaded()) {
  118. if (VrIsNamedPipeHandle(hFile)) {
  119. //
  120. // named pipe read always sets the extended error information in the
  121. // DOS data segment. This is the only way we can return bytes read
  122. // information and a more data indication
  123. //
  124. ok = VrReadNamedPipe(hFile,
  125. lpBuf,
  126. (DWORD)getCX(),
  127. &dwBytesRead,
  128. &dwReadError
  129. );
  130. switch (dwReadError) {
  131. case NO_ERROR:
  132. locus = action = class = 0;
  133. break;
  134. case ERROR_NO_DATA:
  135. case ERROR_MORE_DATA:
  136. locus = errLOC_Net;
  137. class = errCLASS_TempSit;
  138. action = errACT_Retry;
  139. break;
  140. default:
  141. //
  142. // any error other than the specific ones we handle here should be
  143. // correctly handled by DOS
  144. //
  145. goto readFailureExit;
  146. }
  147. pExtendedError->ExtendedErrorLocus = locus;
  148. STOREWORD(pExtendedError->ExtendedError, (WORD)dwReadError);
  149. pExtendedError->ExtendedErrorAction = action;
  150. pExtendedError->ExtendedErrorClass = class;
  151. if (ok) {
  152. goto readSuccessExit;
  153. } else {
  154. goto readFailureExit;
  155. }
  156. }
  157. }
  158. //
  159. // if the redir TSR is not loaded, or the handle is not a named pipe then
  160. // perform normal file read
  161. //
  162. if (!getZF()) {
  163. ULONG Zero = 0;
  164. lLoc = (LONG)((((int)getBX()) << 16) + (int)getSI());
  165. if ((SetFilePointer (hFile,
  166. lLoc,
  167. &Zero,
  168. FILE_BEGIN) == -1L) &&
  169. (GetLastError() != NO_ERROR)) {
  170. goto readFailureExit;
  171. }
  172. }
  173. if (ReadFile (hFile,
  174. lpBuf,
  175. (DWORD)getCX(),
  176. &dwBytesRead,
  177. NULL) == FALSE){
  178. readFailureExit:
  179. Sim32FlushVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(),
  180. (PBYTE )lpBuf, FALSE);
  181. Sim32FreeVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(),
  182. (PBYTE )lpBuf, FALSE);
  183. if (GetLastError() == ERROR_BROKEN_PIPE) {
  184. setAX(0);
  185. setCF(0);
  186. return;
  187. }
  188. demClientError(hFile, (CHAR)-1);
  189. return ;
  190. }
  191. readSuccessExit:
  192. Sim32FlushVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(),
  193. (PBYTE )lpBuf, FALSE);
  194. Sim32FreeVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(),
  195. (PBYTE )lpBuf, FALSE);
  196. setCF(0);
  197. setAX((USHORT)dwBytesRead);
  198. return;
  199. }
  200. /* demWrite - Write to a file
  201. *
  202. *
  203. * Entry - Client (AX:BP) File Handle
  204. * Client (CX) Count to write
  205. * Client (DS:DX) Buffer Address
  206. * Client (BX:SI) = current file pointer location.
  207. * ZF = 1 if seek is not needed prior to write.
  208. *
  209. * Exit
  210. * SUCCESS
  211. * Client (CY) = 0
  212. * Client (AX) = Count of bytes written
  213. *
  214. * FAILURE
  215. * Client (CY) = 1
  216. * Client (AX) = system status code
  217. *
  218. */
  219. VOID demWrite (VOID)
  220. {
  221. HANDLE hFile;
  222. DWORD dwBytesWritten;
  223. LPVOID lpBuf;
  224. LONG lLoc;
  225. DWORD dwErrCode;
  226. hFile = GETHANDLE (getAX(),getBP());
  227. lpBuf = (LPVOID) GetVDMAddr (getDS(),getDX());
  228. //
  229. // if this handle is a named pipe then use VrWriteNamedPipe since we have
  230. // to perform an overlapped write, and wait on the event handle for completion
  231. // even though we're still doing synchronous write
  232. //
  233. if (IsVdmRedirLoaded()) {
  234. if (VrIsNamedPipeHandle(hFile)) {
  235. if (VrWriteNamedPipe(hFile, lpBuf, (DWORD)getCX(), &dwBytesWritten)) {
  236. goto writeSuccessExit;
  237. } else {
  238. goto writeFailureExit;
  239. }
  240. }
  241. }
  242. //
  243. // if the redir TSR is not loaded, or the handle is not a named pipe then
  244. // perform normal file write
  245. //
  246. if (!getZF()) {
  247. ULONG Zero = 0;
  248. lLoc = (LONG)((((int)getBX()) << 16) + (int)getSI());
  249. if ((SetFilePointer (hFile,
  250. lLoc,
  251. &Zero,
  252. FILE_BEGIN) == -1L) &&
  253. (GetLastError() != NO_ERROR)) {
  254. demClientError(hFile, (CHAR)-1);
  255. return ;
  256. }
  257. }
  258. // In DOS CX=0 truncates or extends the file to current file pointer.
  259. if (getCX() == 0){
  260. if (SetEndOfFile(hFile) == FALSE){
  261. demClientError(hFile, (CHAR)-1);
  262. return;
  263. }
  264. setCF (0);
  265. return;
  266. }
  267. if (WriteFile (hFile,
  268. lpBuf,
  269. (DWORD)getCX(),
  270. &dwBytesWritten,
  271. NULL) == FALSE){
  272. // If disk is full then we should return 0 byte written and CF is clear
  273. dwErrCode = GetLastError();
  274. if(dwErrCode == ERROR_DISK_FULL) {
  275. setCF(0);
  276. setAX(0);
  277. return;
  278. }
  279. SetLastError(dwErrCode);
  280. writeFailureExit:
  281. demClientError(hFile, (CHAR)-1);
  282. return ;
  283. }
  284. writeSuccessExit:
  285. setCF(0);
  286. setAX((USHORT)dwBytesWritten);
  287. return;
  288. }
  289. /* demChgFilePtr - Change File Pointer
  290. *
  291. *
  292. * Entry - Client (AX:BP) File Handle
  293. * Client (CX:DX) New Location
  294. * Client (BL) Positioning Method
  295. * 0 - File Absolute
  296. * 1 - Relative to Current Position
  297. * 2 - Relative to end of file
  298. *
  299. * Exit
  300. * SUCCESS
  301. * Client (CY) = 0
  302. * Client (DX:AX) = New Location
  303. *
  304. * FAILURE
  305. * Client (CY) = 1
  306. * Client (AX) = system status code
  307. *
  308. */
  309. VOID demChgFilePtr (VOID)
  310. {
  311. HANDLE hFile;
  312. LONG lLoc;
  313. DWORD dwLoc;
  314. #if (FILE_BEGIN != 0 || FILE_CURRENT != 1 || FILE_END !=2)
  315. #error "Win32 values not DOS compatible"
  316. #
  317. #endif
  318. hFile = GETHANDLE (getAX(),getBP());
  319. lLoc = (LONG)((((int)getCX()) << 16) + (int)getDX());
  320. if ((dwLoc = SetFilePointer (hFile,
  321. lLoc,
  322. NULL,
  323. (DWORD)getBL())) == -1L){
  324. demClientError(hFile, (CHAR)-1);
  325. return ;
  326. }
  327. setCF(0);
  328. setAX((USHORT)dwLoc);
  329. setDX((USHORT)(dwLoc >> 16));
  330. return;
  331. }
  332. #if 0
  333. /*
  334. * Completely moved to demlfn.c
  335. *
  336. *
  337. *
  338. */
  339. /* demFileTimes - Change or Get File date and times
  340. *
  341. * GET TIME (Client(BL) = 0)
  342. *
  343. * Entry
  344. * Client(AX:BP)
  345. * NT Handle
  346. *
  347. * Exit
  348. * SUCCESS
  349. * Client(CF) = 0
  350. * Client(CX) = File time
  351. * Client(DX) = File date
  352. * FAILURE
  353. * Client(CF) = 1
  354. * Client(AX) = error code
  355. *
  356. * SET TIME (Client(BL) = 1)
  357. *
  358. * Entry
  359. * Client(AX:BP)
  360. * Nt Handle
  361. * Client(CX)
  362. * New file time
  363. * Client(DX)
  364. * New file date
  365. *
  366. * Exit
  367. * SUCCESS
  368. * Client(CF) = 0
  369. * FAILURE
  370. * Client(CF) = 1
  371. * Client(AX) = error code
  372. *
  373. * Hard Error Exit
  374. * Client(CF) = 1
  375. * Client(AX) = 0FFFFh
  376. *
  377. * GET TIME For device (Client(BL) = 2)
  378. *
  379. * Entry
  380. * Client(AX:BP)
  381. * NT Handle - not in use
  382. *
  383. * Exit
  384. * SUCCESS
  385. * Client(CF) = 0
  386. * Client(CX) = Current time
  387. * Client(DX) = Curren date
  388. * FAILURE
  389. * None
  390. *
  391. */
  392. VOID demFileTimes (VOID)
  393. {
  394. HANDLE hFile;
  395. WORD wDate,wTime;
  396. FILETIME LastWriteTime,ftTemp;
  397. SYSTEMTIME stCurrentTime;
  398. UCHAR uchOpt = 0;
  399. uchOpt = getBL();
  400. if(uchOpt != 2)
  401. hFile = GETHANDLE(getAX(),getBP());
  402. if(uchOpt != 1){
  403. if(!uchOpt) {
  404. if(GetFileTime (hFile,NULL,NULL,&LastWriteTime) == -1){
  405. demClientError(hFile, (CHAR)-1);
  406. return;
  407. }
  408. }
  409. else { // Device case. We should return current time
  410. GetSystemTime(&stCurrentTime);
  411. SystemTimeToFileTime(&stCurrentTime, &LastWriteTime);
  412. }
  413. FileTimeToLocalFileTime (&LastWriteTime,&ftTemp);
  414. if(FileTimeToDosDateTime(&ftTemp,
  415. (LPWORD)&wDate,
  416. (LPWORD)&wTime) == FALSE){
  417. demPrintMsg(MSG_TIMEDATE);
  418. setCF(0);
  419. return;
  420. }
  421. setCX(wTime);
  422. setDX(wDate);
  423. setCF(0);
  424. return;
  425. }
  426. wDate = getDX();
  427. wTime = getCX();
  428. if (DosDateTimeToFileTime(wDate,
  429. wTime,
  430. &LastWriteTime) == FALSE){
  431. demPrintMsg(MSG_TIMEDATE);
  432. setCF(0);
  433. return;
  434. }
  435. LocalFileTimeToFileTime (&LastWriteTime,&ftTemp);
  436. if(!SetFileTime(hFile,NULL,NULL,&ftTemp)){
  437. demClientError(hFile, (CHAR)-1);
  438. return;
  439. }
  440. setCF(0);
  441. return;
  442. }
  443. #endif
  444. /* DemCommit -- Commit File(Flush file buffers)
  445. *
  446. * Entry - Client (AX:BP) File Handle
  447. *
  448. * Exit
  449. * SUCCESS
  450. * Client (CY) = 0
  451. * buffer flushed
  452. *
  453. * FAILURE
  454. * Client (CY) = 1
  455. *
  456. */
  457. VOID demCommit(VOID)
  458. {
  459. HANDLE hFile;
  460. BOOL bRet;
  461. hFile = GETHANDLE(getAX(),getBP());
  462. bRet = FlushFileBuffers(hFile);
  463. #if DBG
  464. if (!bRet) {
  465. //
  466. // FlushFileBuffers fails with access denied if the handle
  467. // is open for read-only access, however it's not an error
  468. // for DOS.
  469. //
  470. DWORD LastError;
  471. LastError = GetLastError();
  472. if (LastError != ERROR_ACCESS_DENIED) {
  473. sprintf(demDebugBuffer,
  474. "ntvdm demCommit warning: FlushFileBuffers error %d\n",
  475. LastError);
  476. OutputDebugStringOem(demDebugBuffer);
  477. }
  478. }
  479. #endif
  480. setCF(0);
  481. }
  482. /* function to check if new data has been written to the file or
  483. if the file has been marked EOF
  484. Input: Client (AX:BP) = 32bits NT file handle
  485. Output: Client ZF = 1 if new data or EOF
  486. CF = 1 if EOF
  487. */
  488. VOID demPipeFileDataEOF(VOID)
  489. {
  490. HANDLE hFile;
  491. BOOL fEOF;
  492. BOOL DataEOF;
  493. DWORD FileSizeLow;
  494. DWORD FileSizeHigh;
  495. hFile = GETHANDLE(getAX(), getBP());
  496. DataEOF = cmdPipeFileDataEOF(hFile, &fEOF);
  497. if (fEOF) {
  498. //EOF, get file size, max size = 32bits
  499. FileSizeLow = GetFileSize(hFile, &FileSizeHigh);
  500. setAX((WORD)(FileSizeLow / 0x10000));
  501. setBP((WORD)FileSizeLow);
  502. setCF(1); // EOF is encountered
  503. }
  504. else
  505. setCF(0);
  506. setZF(DataEOF ? 0 : 1);
  507. }
  508. /* function to check if the file has been marked EOF
  509. Input: Client(AX:BP) = 32bits NT file handle
  510. Output: Client CY = 1 if EOF
  511. */
  512. VOID demPipeFileEOF(VOID)
  513. {
  514. HANDLE hFile;
  515. DWORD FileSizeLow;
  516. DWORD FileSizeHigh;
  517. hFile = GETHANDLE(getAX(), getBP());
  518. if (cmdPipeFileEOF(hFile)) {
  519. FileSizeLow = GetFileSize(hFile, &FileSizeHigh);
  520. setAX((WORD)(FileSizeLow / 0x10000)); // file size in 32bits
  521. setBP((WORD)FileSizeLow);
  522. setCF(1); //EOF is encountered
  523. }
  524. else
  525. setCF(0);
  526. }
  527.