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.

496 lines
12 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. #include "dpmtbls.h"
  23. BOOL (*VrInitialized)(VOID); // POINTER TO FUNCTION
  24. extern BOOL IsVdmRedirLoaded(VOID);
  25. /* demClose - Close a file
  26. *
  27. *
  28. * Entry - Client (AX:BP) File Handle
  29. * Client (CX:DX) File position (if -1 no seek needed before closing
  30. * the handle.
  31. * (VadimB)
  32. * Client (es:di) SFT ptr - this is implied in abort.asm code
  33. *
  34. * Exit
  35. * SUCCESS
  36. * Client (CY) = 0
  37. *
  38. * FAILURE
  39. * Client (CY) = 1
  40. * Client (AX) = system status code
  41. *
  42. */
  43. VOID demClose (VOID)
  44. {
  45. HANDLE hFile;
  46. LONG lLoc;
  47. USHORT usDX,usCX;
  48. hFile = GETHANDLE (getAX(),getBP());
  49. if (hFile == 0) {
  50. setCF (0);
  51. return;
  52. }
  53. usCX = getCX();
  54. usDX = getDX();
  55. if (!((usCX == (USHORT)-1) && (usDX == (USHORT)-1))) {
  56. lLoc = (LONG)((((int)usCX) << 16) + (int)usDX);
  57. //
  58. // Note that we don't check for failure in this case as edlin,
  59. // for instance, can have the file position be negative and
  60. // we still need to do the cleanup below. Note that we are not
  61. // even sure why seeking on close matter, but the DOS code does it...
  62. //
  63. DPM_SetFilePointer (hFile,
  64. lLoc,
  65. NULL,
  66. FILE_BEGIN);
  67. }
  68. if (DPM_CloseHandle (hFile) == FALSE){
  69. demClientError(hFile, (CHAR)-1);
  70. }
  71. //
  72. // if the redir TSR is being run in this VDM session, check if the handle
  73. // being closed references a named pipe - we have to delete some info
  74. // that we keep for the open named pipe
  75. //
  76. if (IsVdmRedirLoaded()) {
  77. VrRemoveOpenNamedPipeInfo(hFile);
  78. }
  79. setCF(0);
  80. return;
  81. }
  82. /* demRead - Read a file
  83. *
  84. *
  85. * Entry - Client (AX:BP) File Handle
  86. * Client (CX) Count to read
  87. * Client (DS:DX) Buffer Address
  88. * Client (BX:SI) = current file pointer location.
  89. * ZF = 1 if seek is not needed prior to read.
  90. *
  91. * Exit
  92. * SUCCESS
  93. * Client (CY) = 0
  94. * Client (AX) = Count of bytes read
  95. *
  96. * FAILURE
  97. * Client (CY) = 1
  98. * Client (AX) = system status code
  99. *
  100. */
  101. VOID demRead (VOID)
  102. {
  103. HANDLE hFile;
  104. LPVOID lpBuf;
  105. DWORD dwBytesRead;
  106. USHORT usDS,usDX;
  107. DWORD dwReadError;
  108. BOOL ok;
  109. UCHAR locus, action, class;
  110. LONG lLoc;
  111. hFile = GETHANDLE (getAX(),getBP());
  112. usDS = getDS();
  113. usDX = getDX();
  114. lpBuf = (LPVOID) GetVDMAddr (usDS,usDX);
  115. //
  116. // if this handle is a named pipe then use VrReadNamedPipe since we have
  117. // to perform an overlapped read, and wait on the event handle for completion
  118. // even though we're still doing synchronous read
  119. //
  120. if (IsVdmRedirLoaded()) {
  121. if (VrIsNamedPipeHandle(hFile)) {
  122. //
  123. // named pipe read always sets the extended error information in the
  124. // DOS data segment. This is the only way we can return bytes read
  125. // information and a more data indication
  126. //
  127. ok = VrReadNamedPipe(hFile,
  128. lpBuf,
  129. (DWORD)getCX(),
  130. &dwBytesRead,
  131. &dwReadError
  132. );
  133. switch (dwReadError) {
  134. case NO_ERROR:
  135. locus = action = class = 0;
  136. break;
  137. case ERROR_NO_DATA:
  138. case ERROR_MORE_DATA:
  139. locus = errLOC_Net;
  140. class = errCLASS_TempSit;
  141. action = errACT_Retry;
  142. break;
  143. default:
  144. //
  145. // any error other than the specific ones we handle here should be
  146. // correctly handled by DOS
  147. //
  148. goto readFailureExit;
  149. }
  150. pExtendedError->ExtendedErrorLocus = locus;
  151. STOREWORD(pExtendedError->ExtendedError, (WORD)dwReadError);
  152. pExtendedError->ExtendedErrorAction = action;
  153. pExtendedError->ExtendedErrorClass = class;
  154. if (ok) {
  155. goto readSuccessExit;
  156. } else {
  157. goto readFailureExit;
  158. }
  159. }
  160. }
  161. //
  162. // if the redir TSR is not loaded, or the handle is not a named pipe then
  163. // perform normal file read
  164. //
  165. if (!getZF()) {
  166. ULONG Zero = 0;
  167. lLoc = (LONG)((((int)getBX()) << 16) + (int)getSI());
  168. if ((DPM_SetFilePointer (hFile,
  169. lLoc,
  170. &Zero,
  171. FILE_BEGIN) == -1L) &&
  172. (GetLastError() != NO_ERROR)) {
  173. goto readFailureExit;
  174. }
  175. }
  176. if (DPM_ReadFile (hFile,
  177. lpBuf,
  178. (DWORD)getCX(),
  179. &dwBytesRead,
  180. NULL) == FALSE){
  181. readFailureExit:
  182. Sim32FlushVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(),
  183. (PBYTE )lpBuf, FALSE);
  184. Sim32FreeVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(),
  185. (PBYTE )lpBuf, FALSE);
  186. if (GetLastError() == ERROR_BROKEN_PIPE) {
  187. setAX(0);
  188. setCF(0);
  189. return;
  190. }
  191. demClientError(hFile, (CHAR)-1);
  192. return ;
  193. }
  194. readSuccessExit:
  195. Sim32FlushVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(),
  196. (PBYTE )lpBuf, FALSE);
  197. Sim32FreeVDMPointer (((ULONG)(usDS << 16)) | usDX, getCX(),
  198. (PBYTE )lpBuf, FALSE);
  199. setCF(0);
  200. setAX((USHORT)dwBytesRead);
  201. return;
  202. }
  203. /* demWrite - Write to a file
  204. *
  205. *
  206. * Entry - Client (AX:BP) File Handle
  207. * Client (CX) Count to write
  208. * Client (DS:DX) Buffer Address
  209. * Client (BX:SI) = current file pointer location.
  210. * ZF = 1 if seek is not needed prior to write.
  211. *
  212. * Exit
  213. * SUCCESS
  214. * Client (CY) = 0
  215. * Client (AX) = Count of bytes written
  216. *
  217. * FAILURE
  218. * Client (CY) = 1
  219. * Client (AX) = system status code
  220. *
  221. */
  222. VOID demWrite (VOID)
  223. {
  224. HANDLE hFile;
  225. DWORD dwBytesWritten;
  226. LPVOID lpBuf;
  227. LONG lLoc;
  228. DWORD dwErrCode;
  229. hFile = GETHANDLE (getAX(),getBP());
  230. lpBuf = (LPVOID) GetVDMAddr (getDS(),getDX());
  231. //
  232. // if this handle is a named pipe then use VrWriteNamedPipe since we have
  233. // to perform an overlapped write, and wait on the event handle for completion
  234. // even though we're still doing synchronous write
  235. //
  236. if (IsVdmRedirLoaded()) {
  237. if (VrIsNamedPipeHandle(hFile)) {
  238. if (VrWriteNamedPipe(hFile, lpBuf, (DWORD)getCX(), &dwBytesWritten)) {
  239. goto writeSuccessExit;
  240. } else {
  241. goto writeFailureExit;
  242. }
  243. }
  244. }
  245. //
  246. // if the redir TSR is not loaded, or the handle is not a named pipe then
  247. // perform normal file write
  248. //
  249. if (!getZF()) {
  250. ULONG Zero = 0;
  251. lLoc = (LONG)((((int)getBX()) << 16) + (int)getSI());
  252. if ((DPM_SetFilePointer (hFile,
  253. lLoc,
  254. &Zero,
  255. FILE_BEGIN) == -1L) &&
  256. (GetLastError() != NO_ERROR)) {
  257. demClientError(hFile, (CHAR)-1);
  258. return ;
  259. }
  260. }
  261. // In DOS CX=0 truncates or extends the file to current file pointer.
  262. if (getCX() == 0){
  263. if (DPM_SetEndOfFile(hFile) == FALSE){
  264. demClientError(hFile, (CHAR)-1);
  265. return;
  266. }
  267. setCF (0);
  268. return;
  269. }
  270. if (DPM_WriteFile (hFile,
  271. lpBuf,
  272. (DWORD)getCX(),
  273. &dwBytesWritten,
  274. NULL) == FALSE){
  275. // If disk is full then we should return 0 byte written and CF is clear
  276. dwErrCode = GetLastError();
  277. if(dwErrCode == ERROR_DISK_FULL) {
  278. setCF(0);
  279. setAX(0);
  280. return;
  281. }
  282. SetLastError(dwErrCode);
  283. writeFailureExit:
  284. demClientError(hFile, (CHAR)-1);
  285. return ;
  286. }
  287. writeSuccessExit:
  288. setCF(0);
  289. setAX((USHORT)dwBytesWritten);
  290. return;
  291. }
  292. /* demChgFilePtr - Change File Pointer
  293. *
  294. *
  295. * Entry - Client (AX:BP) File Handle
  296. * Client (CX:DX) New Location
  297. * Client (BL) Positioning Method
  298. * 0 - File Absolute
  299. * 1 - Relative to Current Position
  300. * 2 - Relative to end of file
  301. *
  302. * Exit
  303. * SUCCESS
  304. * Client (CY) = 0
  305. * Client (DX:AX) = New Location
  306. *
  307. * FAILURE
  308. * Client (CY) = 1
  309. * Client (AX) = system status code
  310. *
  311. */
  312. VOID demChgFilePtr (VOID)
  313. {
  314. HANDLE hFile;
  315. LONG lLoc;
  316. DWORD dwLoc;
  317. #if (FILE_BEGIN != 0 || FILE_CURRENT != 1 || FILE_END !=2)
  318. #error "Win32 values not DOS compatible"
  319. #
  320. #endif
  321. hFile = GETHANDLE (getAX(),getBP());
  322. lLoc = (LONG)((((int)getCX()) << 16) + (int)getDX());
  323. if ((dwLoc = DPM_SetFilePointer (hFile,
  324. lLoc,
  325. NULL,
  326. (DWORD)getBL())) == -1L){
  327. demClientError(hFile, (CHAR)-1);
  328. return ;
  329. }
  330. setCF(0);
  331. setAX((USHORT)dwLoc);
  332. setDX((USHORT)(dwLoc >> 16));
  333. return;
  334. }
  335. /* DemCommit -- Commit File(Flush file buffers)
  336. *
  337. * Entry - Client (AX:BP) File Handle
  338. *
  339. * Exit
  340. * SUCCESS
  341. * Client (CY) = 0
  342. * buffer flushed
  343. *
  344. * FAILURE
  345. * Client (CY) = 1
  346. *
  347. */
  348. VOID demCommit(VOID)
  349. {
  350. HANDLE hFile;
  351. BOOL bRet;
  352. hFile = GETHANDLE(getAX(),getBP());
  353. bRet = DPM_FlushFileBuffers(hFile);
  354. #if DBG
  355. if (!bRet) {
  356. //
  357. // FlushFileBuffers fails with access denied if the handle
  358. // is open for read-only access, however it's not an error
  359. // for DOS.
  360. //
  361. DWORD LastError;
  362. LastError = GetLastError();
  363. if (LastError != ERROR_ACCESS_DENIED) {
  364. sprintf(demDebugBuffer,
  365. "ntvdm demCommit warning: FlushFileBuffers error %d\n",
  366. LastError);
  367. OutputDebugStringOem(demDebugBuffer);
  368. }
  369. }
  370. #endif
  371. setCF(0);
  372. }
  373. /* function to check if new data has been written to the file or
  374. if the file has been marked EOF
  375. Input: Client (AX:BP) = 32bits NT file handle
  376. Output: Client ZF = 1 if new data or EOF
  377. CF = 1 if EOF
  378. */
  379. VOID demPipeFileDataEOF(VOID)
  380. {
  381. HANDLE hFile;
  382. BOOL fEOF;
  383. BOOL DataEOF;
  384. DWORD FileSizeLow;
  385. DWORD FileSizeHigh;
  386. hFile = GETHANDLE(getAX(), getBP());
  387. DataEOF = cmdPipeFileDataEOF(hFile, &fEOF);
  388. if (fEOF) {
  389. //EOF, get file size, max size = 32bits
  390. FileSizeLow = GetFileSize(hFile, &FileSizeHigh);
  391. setAX((WORD)(FileSizeLow / 0x10000));
  392. setBP((WORD)FileSizeLow);
  393. setCF(1); // EOF is encountered
  394. }
  395. else
  396. setCF(0);
  397. setZF(DataEOF ? 0 : 1);
  398. }
  399. /* function to check if the file has been marked EOF
  400. Input: Client(AX:BP) = 32bits NT file handle
  401. Output: Client CY = 1 if EOF
  402. */
  403. VOID demPipeFileEOF(VOID)
  404. {
  405. HANDLE hFile;
  406. DWORD FileSizeLow;
  407. DWORD FileSizeHigh;
  408. hFile = GETHANDLE(getAX(), getBP());
  409. if (cmdPipeFileEOF(hFile)) {
  410. FileSizeLow = GetFileSize(hFile, &FileSizeHigh);
  411. setAX((WORD)(FileSizeLow / 0x10000)); // file size in 32bits
  412. setBP((WORD)FileSizeLow);
  413. setCF(1); //EOF is encountered
  414. }
  415. else
  416. setCF(0);
  417. }