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.

1204 lines
34 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. drdevol
  5. Abstract:
  6. This module contains a subclass of W32DrDev that uses overlapped IO
  7. implementations of read, write, and IOCTL handlers.
  8. Author:
  9. Tad Brockway 3/23/99
  10. Revision History:
  11. --*/
  12. #include <precom.h>
  13. #define TRC_FILE "DrDeviceOverlapped"
  14. #include "drdevol.h"
  15. #include "proc.h"
  16. #include "drdbg.h"
  17. #include "w32utl.h"
  18. #include "utl.h"
  19. #include "w32proc.h"
  20. #include "drfsfile.h"
  21. VOID
  22. W32DrDeviceOverlapped::CancelIOFunc(
  23. IN W32DRDEV_OVERLAPPEDIO_PARAMS *params
  24. )
  25. /*++
  26. Routine Description:
  27. Start a Read IO operation.
  28. Arguments:
  29. params - Context for the IO request.
  30. Return Value:
  31. NA
  32. --*/
  33. {
  34. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  35. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  36. ULONG replyPacketSize = 0;
  37. DC_BEGIN_FN("W32DrDeviceOverlapped::CancelIOFunc");
  38. // Assert the integrity of the IO context
  39. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  40. //
  41. // Get the IO request.
  42. //
  43. pIoRequest = &params->pIoRequestPacket->IoRequest;
  44. //
  45. // Allocate and send the reply buffer. VCMgr cleans up the
  46. // reply buffer for us.
  47. //
  48. replyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  49. replyPacketSize += (pIoRequest->Parameters.Read.Length - 1);
  50. pReplyPacket = DrUTL_AllocIOCompletePacket(params->pIoRequestPacket,
  51. replyPacketSize) ;
  52. if (pReplyPacket != NULL) {
  53. pReplyPacket->IoCompletion.IoStatus = STATUS_CANCELLED;
  54. ProcessObject()->GetVCMgr().ChannelWriteEx(pReplyPacket, replyPacketSize);
  55. }
  56. else {
  57. TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
  58. }
  59. //
  60. // Clean up the IO request parameters.
  61. //
  62. if (params->overlapped.hEvent != NULL) {
  63. CloseHandle(params->overlapped.hEvent);
  64. params->overlapped.hEvent = NULL;
  65. }
  66. delete params->pIoRequestPacket;
  67. params->pIoRequestPacket = NULL;
  68. delete params;
  69. DC_END_FN();
  70. }
  71. VOID
  72. W32DrDeviceOverlapped::_CancelIOFunc(
  73. IN W32DRDEV_OVERLAPPEDIO_PARAMS *params
  74. )
  75. {
  76. DC_BEGIN_FN("W32DrDeviceOverlapped::_CancelIOFunc");
  77. // Assert the integrity of the IO context
  78. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  79. // Dispatch it.
  80. params->pObject->CancelIOFunc(params);
  81. DC_END_FN();
  82. }
  83. VOID W32DrDeviceOverlapped::_CompleteIOFunc(PVOID clientData,
  84. DWORD status)
  85. /*++
  86. Routine Description:
  87. Calls the instance-specific async IO completion function.
  88. Arguments:
  89. params - Context for the IO request.
  90. error - Status.
  91. Return Value:
  92. NA
  93. --*/
  94. {
  95. W32DRDEV_OVERLAPPEDIO_PARAMS *params = (W32DRDEV_OVERLAPPEDIO_PARAMS *)clientData;
  96. DC_BEGIN_FN("W32DrDeviceOverlapped::_CompleteIOFunc");
  97. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  98. params->pObject->CompleteIOFunc(params, status);
  99. DC_END_FN();
  100. }
  101. VOID
  102. W32DrDeviceOverlapped::MsgIrpCreate(
  103. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  104. IN UINT32 packetLen
  105. )
  106. /*++
  107. Routine Description:
  108. Handle a "Create" IO request from the server.
  109. Arguments:
  110. pIoRequestPacket - Server IO request packet.
  111. packetLen - Length of the packet
  112. Return Value:
  113. NA
  114. --*/
  115. {
  116. ULONG ulRetCode = ERROR_SUCCESS;
  117. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  118. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  119. ULONG ulReplyPacketSize = 0;
  120. DWORD result;
  121. DWORD flags;
  122. TCHAR FileName[MAX_PATH];
  123. TCHAR *pFileName;
  124. HANDLE FileHandle;
  125. ULONG FileId = 0;
  126. DrFile *FileObj;
  127. DWORD CreateDisposition;
  128. DWORD DesiredAccess;
  129. DWORD FileAttributes = -1;
  130. DWORD Information;
  131. BOOL IsDirectory = FALSE;
  132. DC_BEGIN_FN("W32DrDeviceOverlapped::MsgIrpCreate");
  133. //
  134. // This version does not work without a file name.
  135. //
  136. ASSERT(_tcslen(_devicePath));
  137. //
  138. // Get IO request pointer.
  139. //
  140. pIoRequest = &pIoRequestPacket->IoRequest;
  141. //
  142. // Get the file attributes, but make sure the overlapped bit is set.
  143. //
  144. flags = pIoRequest->Parameters.Create.FileAttributes | FILE_FLAG_OVERLAPPED;
  145. //
  146. // Disable the error box popup, e.g. There is no disk in Drive A
  147. //
  148. SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  149. //
  150. // Setup parameters to pass into the createfile
  151. //
  152. pFileName = ConstructFileName((PWCHAR)(pIoRequestPacket + 1),
  153. pIoRequest->Parameters.Create.PathLength);
  154. if (pFileName == NULL) {
  155. goto Cleanup;
  156. }
  157. DesiredAccess = ConstructDesiredAccess(pIoRequest->Parameters.Create.DesiredAccess);
  158. CreateDisposition = ConstructCreateDisposition(pIoRequest->Parameters.Create.Disposition);
  159. flags |= ConstructFileFlags(pIoRequest->Parameters.Create.CreateOptions);
  160. if (GetDeviceType() == RDPDR_DTYP_FILESYSTEM) {
  161. FileAttributes = GetFileAttributes(pFileName);
  162. IsDirectory = IsDirectoryFile(DesiredAccess,
  163. pIoRequest->Parameters.Create.CreateOptions,
  164. FileAttributes, &flags);
  165. }
  166. //
  167. // If we are requesting a directory and the file is not a directory
  168. // We return ERROR_DIRECTORY code back to the server
  169. //
  170. if (FileAttributes != -1 && !(FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && IsDirectory) {
  171. ulRetCode = ERROR_DIRECTORY;
  172. goto SendPkt;
  173. }
  174. //
  175. // Check if we are trying to create a directory
  176. //
  177. if (!((pIoRequest->Parameters.Create.CreateOptions & FILE_DIRECTORY_FILE) &&
  178. CreateDisposition == CREATE_NEW)) {
  179. FileHandle = CreateFile(pFileName, DesiredAccess,
  180. pIoRequest->Parameters.Create.ShareAccess & ~(FILE_SHARE_DELETE),
  181. NULL,
  182. CreateDisposition,
  183. flags,
  184. NULL
  185. );
  186. if (FileHandle != INVALID_HANDLE_VALUE || IsDirectory) {
  187. //
  188. // We either get a valid file handle or this is a directory
  189. // and we are trying to query directory information, so
  190. // we will just by pass the create file
  191. //
  192. FileId = _FileMgr->GetUniqueObjectID();
  193. //
  194. // Create the file object
  195. //
  196. if (GetDeviceType() == RDPDR_DTYP_FILESYSTEM) {
  197. FileObj = new DrFSFile(this, FileId, FileHandle, IsDirectory, pFileName);
  198. }
  199. else {
  200. FileObj = new DrFile(this, FileId, FileHandle);
  201. }
  202. if (FileObj) {
  203. //
  204. // give subclass object a change to initialize.
  205. //
  206. if( ERROR_SUCCESS != InitializeDevice( FileObj ) ) {
  207. TRC_ERR((TB, _T("Failed to initialize device")));
  208. delete FileObj;
  209. goto Cleanup;
  210. }
  211. if (_FileMgr->AddObject(FileObj) != ERROR_NOT_ENOUGH_MEMORY) {
  212. FileObj->AddRef();
  213. }
  214. else {
  215. TRC_ERR((TB, _T("Failed to add File Object")));
  216. delete FileObj;
  217. goto Cleanup;
  218. }
  219. }
  220. else {
  221. TRC_ERR((TB, _T("Failed to alloc File Object")));
  222. goto Cleanup;
  223. }
  224. }
  225. else {
  226. ulRetCode = GetLastError();
  227. TRC_ERR((TB, _T("CreateFile failed, %ld."), ulRetCode));
  228. }
  229. }
  230. else {
  231. if (CreateDirectory(pFileName, NULL)) {
  232. //
  233. // Set the attributes on the directory
  234. //
  235. if (SetFileAttributes(pFileName, pIoRequest->Parameters.Create.FileAttributes)) {
  236. //
  237. // Create a new directory
  238. //
  239. FileId = _FileMgr->GetUniqueObjectID();
  240. IsDirectory = TRUE;
  241. FileObj = new DrFSFile(this, FileId, INVALID_HANDLE_VALUE, IsDirectory, pFileName);
  242. if (FileObj) {
  243. if (_FileMgr->AddObject(FileObj) != ERROR_NOT_ENOUGH_MEMORY) {
  244. FileObj->AddRef();
  245. }
  246. else {
  247. TRC_ERR((TB, _T("Failed to add File Object")));
  248. delete FileObj;
  249. goto Cleanup;
  250. }
  251. }
  252. else {
  253. TRC_ERR((TB, _T("Failed to alloc File Object")));
  254. goto Cleanup;
  255. }
  256. }
  257. else {
  258. ulRetCode = GetLastError();
  259. TRC_ERR((TB, _T("SetFileAttribute for CreateDirectory failed, %ld."), ulRetCode));
  260. }
  261. }
  262. else {
  263. ulRetCode = GetLastError();
  264. TRC_ERR((TB, _T("CreateDirectory failed, %ld."), ulRetCode));
  265. }
  266. }
  267. SendPkt:
  268. //
  269. // Setup return information.
  270. //
  271. if (CreateDisposition == CREATE_ALWAYS)
  272. Information = FILE_OVERWRITTEN;
  273. else if (CreateDisposition == OPEN_ALWAYS)
  274. Information = FILE_OPENED;
  275. //
  276. // Allocate reply buffer.
  277. //
  278. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  279. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket, ulReplyPacketSize);
  280. if (pReplyPacket) {
  281. //
  282. // Setup File Id for create IRP
  283. //
  284. pReplyPacket->IoCompletion.Parameters.Create.FileId = (UINT32) FileId;
  285. pReplyPacket->IoCompletion.Parameters.Create.Information = (UCHAR)Information;
  286. //
  287. // Send the result to the server.
  288. //
  289. result = TranslateWinError(ulRetCode);
  290. pReplyPacket->IoCompletion.IoStatus = result;
  291. ProcessObject()->GetVCMgr().ChannelWriteEx(
  292. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  293. }
  294. else {
  295. TRC_ERR((TB, _T("Failed to alloc %ld bytes."), ulReplyPacketSize));
  296. }
  297. Cleanup:
  298. //
  299. // Clean up the request packet and file name.
  300. //
  301. if (pFileName != NULL && pIoRequest->Parameters.Create.PathLength != 0) {
  302. delete pFileName;
  303. }
  304. delete pIoRequestPacket;
  305. DC_END_FN();
  306. }
  307. VOID W32DrDeviceOverlapped::MsgIrpReadWrite(
  308. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  309. IN UINT32 packetLen
  310. )
  311. /*++
  312. Routine Description:
  313. Handles Read and Write IO requests.
  314. Arguments:
  315. pIoRequestPacket - Server IO request packet.
  316. packetLen - Length of the packet
  317. Return Value:
  318. NA
  319. --*/
  320. {
  321. W32DRDEV_OVERLAPPEDIO_PARAMS *params;
  322. DWORD result;
  323. DC_BEGIN_FN("W32DrDeviceOverlapped::MsgIrpReadWrite");
  324. TRC_NRM((TB, _T("Request to write %d bytes"),
  325. pIoRequestPacket->IoRequest.Parameters.Write.Length));
  326. //
  327. // Allocate and dispatch an asynchronous IO request.
  328. //
  329. params = new W32DRDEV_OVERLAPPEDIO_PARAMS(this, pIoRequestPacket);
  330. if (params != NULL ) {
  331. TRC_NRM((TB, _T("Async IO operation")));
  332. result = ProcessObject()->DispatchAsyncIORequest(
  333. (RDPAsyncFunc_StartIO)
  334. W32DrDeviceOverlapped::_StartIOFunc,
  335. (RDPAsyncFunc_IOComplete)
  336. W32DrDeviceOverlapped::_CompleteIOFunc,
  337. (RDPAsyncFunc_IOCancel)
  338. W32DrDeviceOverlapped::_CancelIOFunc,
  339. params
  340. );
  341. }
  342. else {
  343. TRC_ERR((TB, _T("Memory alloc failed.")));
  344. result = ERROR_NOT_ENOUGH_MEMORY;
  345. }
  346. //
  347. // Clean up on error.
  348. //
  349. if (result != ERROR_SUCCESS) {
  350. if (params != NULL) {
  351. delete params;
  352. }
  353. delete pIoRequestPacket;
  354. // How can I return an error the server if I cannot allocate
  355. // the return buffer. This needs to be fixed. Otherwise, the server will
  356. // just hang on to an IO request that never completes.
  357. }
  358. DC_END_FN();
  359. }
  360. HANDLE
  361. W32DrDeviceOverlapped::StartReadIO(
  362. IN W32DRDEV_OVERLAPPEDIO_PARAMS *params,
  363. OUT DWORD *status
  364. )
  365. /*++
  366. Routine Description:
  367. Start an overlapped Read IO operation.
  368. Arguments:
  369. params - Context for the IO request.
  370. status - Return status for IO request in the form of a windows
  371. error code.
  372. Return Value:
  373. Returns a handle the pending IO object if the operation did not
  374. complete. Otherwise, NULL is returned.
  375. --*/
  376. {
  377. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  378. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  379. ULONG replyPacketSize = 0;
  380. DrFile *pFile;
  381. HANDLE FileHandle;
  382. DC_BEGIN_FN("W32DrDeviceOverlapped::StartReadIO");
  383. // Assert the integrity of the IO context
  384. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  385. *status = ERROR_SUCCESS;
  386. //
  387. // Get the IO request.
  388. //
  389. pIoRequest = &params->pIoRequestPacket->IoRequest;
  390. //
  391. // Get File object and File handle
  392. //
  393. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  394. if (pFile)
  395. FileHandle = pFile->GetFileHandle();
  396. else
  397. FileHandle = INVALID_HANDLE_VALUE;
  398. //
  399. // Allocate reply buffer.
  400. //
  401. replyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  402. replyPacketSize += (pIoRequest->Parameters.Read.Length - 1);
  403. pReplyPacket = DrUTL_AllocIOCompletePacket(params->pIoRequestPacket,
  404. replyPacketSize) ;
  405. if (pReplyPacket == NULL) {
  406. *status = ERROR_NOT_ENOUGH_MEMORY;
  407. TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
  408. goto Cleanup;
  409. }
  410. //
  411. // Save the reply packet info to the context for this IO operation.
  412. //
  413. params->pIoReplyPacket = pReplyPacket;
  414. params->IoReplyPacketSize = replyPacketSize;
  415. //
  416. // Create an event for the overlapped IO.
  417. //
  418. memset(&params->overlapped, 0, sizeof(params->overlapped));
  419. params->overlapped.hEvent = CreateEvent(
  420. NULL, // no attribute.
  421. TRUE, // manual reset.
  422. FALSE, // initially not signalled.
  423. NULL // no name.
  424. );
  425. if (params->overlapped.hEvent == NULL) {
  426. TRC_ERR((TB, _T("Failed to create event")));
  427. *status = ERROR_NOT_ENOUGH_MEMORY;
  428. goto Cleanup;
  429. }
  430. //
  431. // Use ReadFile to execute the read.
  432. //
  433. //
  434. // Set the file pointer position if this is a seekable device
  435. //
  436. if (IsSeekableDevice()) {
  437. DWORD dwPtr;
  438. //
  439. // The offset is from FILE_BEGIN
  440. //
  441. dwPtr = SetFilePointer(FileHandle,
  442. pIoRequest->Parameters.Read.OffsetLow,
  443. &(pIoRequest->Parameters.Read.OffsetHigh),
  444. FILE_BEGIN);
  445. if (dwPtr == INVALID_SET_FILE_POINTER) {
  446. *status = GetLastError();
  447. if (*status != NO_ERROR) {
  448. pReplyPacket->IoCompletion.Parameters.Read.Length = 0;
  449. TRC_ERR((TB, _T("Error SetFilePointer %x."), *status));
  450. goto Cleanup;
  451. }
  452. }
  453. }
  454. if (!ReadFile(
  455. FileHandle,
  456. pReplyPacket->IoCompletion.Parameters.Read.Buffer,
  457. pIoRequest->Parameters.Read.Length,
  458. &(pReplyPacket->IoCompletion.Parameters.Read.Length),
  459. &params->overlapped)) {
  460. //
  461. // If IO is pending.
  462. //
  463. *status = GetLastError();
  464. if (*status == ERROR_IO_PENDING) {
  465. TRC_NRM((TB, _T("Pending read IO.")));
  466. }
  467. else {
  468. TRC_ERR((TB, _T("Error %x."), *status));
  469. goto Cleanup;
  470. }
  471. }
  472. else {
  473. TRC_NRM((TB, _T("Read completed synchronously.")));
  474. *status = ERROR_SUCCESS;
  475. }
  476. Cleanup:
  477. //
  478. // If IO is pending, return the handle to the pending IO.
  479. //
  480. if (*status == ERROR_IO_PENDING) {
  481. DC_END_FN();
  482. return params->overlapped.hEvent;
  483. }
  484. //
  485. // Otherwise, clean up the event handle and return NULL so that the
  486. // CompleteIOFunc can be called to send the results to the server.
  487. //
  488. else {
  489. CloseHandle(params->overlapped.hEvent);
  490. params->overlapped.hEvent = NULL;
  491. DC_END_FN();
  492. return NULL;
  493. }
  494. }
  495. HANDLE
  496. W32DrDeviceOverlapped::StartWriteIO(
  497. IN W32DRDEV_OVERLAPPEDIO_PARAMS *params,
  498. OUT DWORD *status
  499. )
  500. /*++
  501. Routine Description:
  502. Start an overlapped Write IO operation.
  503. Arguments:
  504. params - Context for the IO request.
  505. status - Return status for IO request in the form of a windows
  506. error code.
  507. Return Value:
  508. Returns a handle the pending IO object if the operation did not
  509. complete. Otherwise, NULL is returned.
  510. --*/
  511. {
  512. PBYTE pDataBuffer;
  513. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  514. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  515. ULONG replyPacketSize = 0;
  516. DrFile *pFile;
  517. HANDLE FileHandle;
  518. DC_BEGIN_FN("W32DrDeviceOverlapped::StartWriteIO");
  519. *status = ERROR_SUCCESS;
  520. // Assert the integrity of the IO context
  521. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  522. //
  523. // Get the IO request.
  524. //
  525. pIoRequest = &params->pIoRequestPacket->IoRequest;
  526. //
  527. // Get File object and File handle
  528. //
  529. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  530. if (pFile)
  531. FileHandle = pFile->GetFileHandle();
  532. else
  533. FileHandle = INVALID_HANDLE_VALUE;
  534. //
  535. // Allocate reply buffer.
  536. //
  537. replyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  538. pReplyPacket = DrUTL_AllocIOCompletePacket(params->pIoRequestPacket,
  539. replyPacketSize) ;
  540. if (pReplyPacket == NULL) {
  541. *status = ERROR_NOT_ENOUGH_MEMORY;
  542. TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
  543. goto Cleanup;
  544. }
  545. //
  546. // Save the reply packet info to the context for this IO operation.
  547. //
  548. params->pIoReplyPacket = pReplyPacket;
  549. params->IoReplyPacketSize = replyPacketSize;
  550. //
  551. // Create an event for the overlapped IO.
  552. //
  553. memset(&params->overlapped, 0, sizeof(params->overlapped));
  554. params->overlapped.hEvent = CreateEvent(
  555. NULL, // no attribute.
  556. TRUE, // manual reset.
  557. FALSE, // initially not signalled.
  558. NULL // no name.
  559. );
  560. if (params->overlapped.hEvent == NULL) {
  561. TRC_ERR((TB, _T("Failed to create event")));
  562. *status = ERROR_NOT_ENOUGH_MEMORY;
  563. goto Cleanup;
  564. }
  565. //
  566. // Get the data buffer pointer.
  567. //
  568. pDataBuffer = (PBYTE)(pIoRequest + 1);
  569. //
  570. // Use WriteFile to execute the write operation.
  571. //
  572. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  573. //
  574. // Set the file pointer position if this is a seekable device
  575. //
  576. if (IsSeekableDevice()) {
  577. DWORD dwPtr;
  578. //
  579. // The offset is from FILE_BEGIN
  580. //
  581. dwPtr = SetFilePointer(FileHandle,
  582. pIoRequest->Parameters.Write.OffsetLow,
  583. &(pIoRequest->Parameters.Write.OffsetHigh),
  584. FILE_BEGIN);
  585. if (dwPtr == INVALID_SET_FILE_POINTER) {
  586. *status = GetLastError();
  587. if (*status != NO_ERROR) {
  588. pReplyPacket->IoCompletion.Parameters.Write.Length = 0;
  589. TRC_ERR((TB, _T("Error SetFilePointer %x."), *status));
  590. goto Cleanup;
  591. }
  592. }
  593. }
  594. if (!WriteFile(
  595. FileHandle,
  596. pDataBuffer,
  597. pIoRequest->Parameters.Write.Length,
  598. &(pReplyPacket->IoCompletion.Parameters.Write.Length),
  599. &params->overlapped)) {
  600. //
  601. // If IO is pending.
  602. //
  603. *status = GetLastError();
  604. if (*status == ERROR_IO_PENDING) {
  605. TRC_NRM((TB, _T("Pending IO.")));
  606. }
  607. else {
  608. TRC_NRM((TB, _T("Error %x."), *status));
  609. goto Cleanup;
  610. }
  611. }
  612. else {
  613. TRC_NRM((TB, _T("Read completed synchronously.")));
  614. *status = ERROR_SUCCESS;
  615. }
  616. Cleanup:
  617. //
  618. // If IO is pending, return the handle to the pending IO.
  619. //
  620. if (*status == ERROR_IO_PENDING) {
  621. DC_END_FN();
  622. return params->overlapped.hEvent;
  623. }
  624. //
  625. // Otherwise, clean up the event handle and return NULL so that the
  626. // CompleteIOFunc can be called to send the results to the server.
  627. //
  628. else {
  629. CloseHandle(params->overlapped.hEvent);
  630. params->overlapped.hEvent = NULL;
  631. DC_END_FN();
  632. return NULL;
  633. }
  634. }
  635. HANDLE
  636. W32DrDeviceOverlapped::StartIOCTL(
  637. IN W32DRDEV_OVERLAPPEDIO_PARAMS *params,
  638. OUT DWORD *status
  639. )
  640. /*++
  641. Routine Description:
  642. Start a generic overlapped IOCTL operation.
  643. Arguments:
  644. params - Context for the IO request.
  645. status - Return status for IO request in the form of a windows
  646. error code.
  647. Return Value:
  648. Returns a handle the pending IO object if the operation did not
  649. complete. Otherwise, NULL is returned.
  650. --*/
  651. {
  652. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  653. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  654. ULONG replyPacketSize = 0;
  655. DrFile *pFile;
  656. HANDLE FileHandle;
  657. PVOID pInputBuffer = NULL;
  658. PVOID pOutputBuffer = NULL;
  659. DC_BEGIN_FN("W32DrDeviceOverlapped::StartIOCTL");
  660. *status = ERROR_SUCCESS;
  661. // Assert the integrity of the IO context
  662. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  663. //
  664. // Get the IO request.
  665. //
  666. pIoRequest = &params->pIoRequestPacket->IoRequest;
  667. //
  668. // Get File object and File handle
  669. //
  670. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  671. if (pFile)
  672. FileHandle = pFile->GetFileHandle();
  673. else
  674. FileHandle = INVALID_HANDLE_VALUE;
  675. //
  676. // Allocate reply buffer.
  677. //
  678. replyPacketSize = DR_IOCTL_REPLYBUFSIZE(pIoRequest);
  679. pReplyPacket = DrUTL_AllocIOCompletePacket(params->pIoRequestPacket,
  680. replyPacketSize) ;
  681. if (pReplyPacket == NULL) {
  682. *status = ERROR_NOT_ENOUGH_MEMORY;
  683. TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
  684. goto Cleanup;
  685. }
  686. if (pIoRequest->Parameters.DeviceIoControl.InputBufferLength) {
  687. pInputBuffer = pIoRequest + 1;
  688. }
  689. if (pIoRequest->Parameters.DeviceIoControl.OutputBufferLength) {
  690. pOutputBuffer = pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBuffer;
  691. }
  692. //
  693. // Save the reply packet info to the context for this IO operation.
  694. //
  695. params->pIoReplyPacket = pReplyPacket;
  696. params->IoReplyPacketSize = replyPacketSize;
  697. //
  698. // Create an event for the overlapped IO.
  699. //
  700. memset(&params->overlapped, 0, sizeof(params->overlapped));
  701. params->overlapped.hEvent = CreateEvent(
  702. NULL, // no attribute.
  703. TRUE, // manual reset.
  704. FALSE, // initially not signalled.
  705. NULL // no name.
  706. );
  707. if (params->overlapped.hEvent == NULL) {
  708. TRC_NRM((TB, _T("Failed to create event")));
  709. *status = ERROR_NOT_ENOUGH_MEMORY;
  710. goto Cleanup;
  711. }
  712. //
  713. // Use DeviceIoControl to execute the IO request.
  714. //
  715. if (FileHandle != INVALID_HANDLE_VALUE) {
  716. if (!DeviceIoControl(FileHandle,
  717. pIoRequest->Parameters.DeviceIoControl.IoControlCode,
  718. pInputBuffer,
  719. pIoRequest->Parameters.DeviceIoControl.InputBufferLength,
  720. pOutputBuffer,
  721. pIoRequest->Parameters.DeviceIoControl.OutputBufferLength,
  722. &(pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength),
  723. &params->overlapped)) {
  724. //
  725. // If IO is pending.
  726. //
  727. *status = GetLastError();
  728. if (*status == ERROR_IO_PENDING) {
  729. TRC_NRM((TB, _T("Pending IO.")));
  730. }
  731. else {
  732. TRC_NRM((TB, _T("Error %ld."), *status));
  733. goto Cleanup;
  734. }
  735. }
  736. else {
  737. *status = ERROR_SUCCESS;
  738. }
  739. }
  740. else {
  741. TRC_NRM((TB, _T("IOCTL completed unsuccessfully.")));
  742. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength = 0;
  743. *status = ERROR_INVALID_FUNCTION;
  744. }
  745. Cleanup:
  746. //
  747. // If IO is pending, return the handle to the pending IO.
  748. //
  749. if (*status == ERROR_IO_PENDING) {
  750. DC_END_FN();
  751. return params->overlapped.hEvent;
  752. }
  753. //
  754. // Otherwise, return NULL so that the CompleteIOFunc can be called
  755. // to send the results to the server.
  756. //
  757. else {
  758. DC_END_FN();
  759. if (params->overlapped.hEvent) {
  760. CloseHandle(params->overlapped.hEvent);
  761. params->overlapped.hEvent = NULL;
  762. }
  763. return NULL;
  764. }
  765. }
  766. VOID
  767. W32DrDeviceOverlapped::CompleteIOFunc(
  768. IN W32DRDEV_OVERLAPPEDIO_PARAMS *params,
  769. IN DWORD status
  770. )
  771. /*++
  772. Routine Description:
  773. Complete an async IO operation.
  774. Arguments:
  775. params - Context for the IO request.
  776. error - Status.
  777. Return Value:
  778. NA
  779. --*/
  780. {
  781. ULONG replyPacketSize;
  782. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  783. PRDPDR_IOREQUEST_PACKET pIoRequestPacket;
  784. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  785. DrFile *pFile;
  786. HANDLE FileHandle;
  787. DWORD Temp;
  788. DC_BEGIN_FN("W32DrDeviceOverlapped::CompleteIOFunc");
  789. //
  790. // Simplify the params.
  791. //
  792. replyPacketSize = params->IoReplyPacketSize;
  793. pReplyPacket = params->pIoReplyPacket;
  794. pIoRequestPacket = params->pIoRequestPacket;
  795. pIoRequest = &pIoRequestPacket->IoRequest;
  796. if (pReplyPacket != NULL) {
  797. //
  798. // Get File object and File handle
  799. //
  800. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  801. if (pFile)
  802. FileHandle = pFile->GetFileHandle();
  803. else
  804. FileHandle = INVALID_HANDLE_VALUE;
  805. //
  806. // If the operation had been pending, then we need to get
  807. // the overlapped results.
  808. //
  809. if (params->overlapped.hEvent != NULL) {
  810. LPDWORD bytesTransferred = NULL;
  811. ULONG irpMajor;
  812. irpMajor = pIoRequestPacket->IoRequest.MajorFunction;
  813. if (irpMajor == IRP_MJ_READ) {
  814. bytesTransferred = &pReplyPacket->IoCompletion.Parameters.Read.Length;
  815. }
  816. else if (irpMajor == IRP_MJ_WRITE) {
  817. bytesTransferred =
  818. &pReplyPacket->IoCompletion.Parameters.Write.Length;
  819. }
  820. else if (irpMajor == IRP_MJ_DEVICE_CONTROL) {
  821. bytesTransferred =
  822. &pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength;
  823. // IOCTL_SERIAL_WAIT_ON_MASK corresponds to WatiCommEvent(), for this call
  824. // *bytesTransferred returned from GetOverlappedResult() is undefined,
  825. // so we manually set OutputBufferLength to sizeof(DWORD) here
  826. if (params->pIoRequestPacket->IoRequest.Parameters.DeviceIoControl.IoControlCode == IOCTL_SERIAL_WAIT_ON_MASK) {
  827. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength = sizeof(DWORD);
  828. bytesTransferred = &Temp;
  829. }
  830. }
  831. else {
  832. ASSERT(FALSE);
  833. }
  834. if (!GetOverlappedResult(
  835. FileHandle,
  836. &params->overlapped,
  837. bytesTransferred,
  838. TRUE // wait
  839. )) {
  840. status = GetLastError();
  841. TRC_ERR((TB, _T("GetOverlappedResult %ld."), status));
  842. }
  843. CloseHandle(params->overlapped.hEvent);
  844. params->overlapped.hEvent = NULL;
  845. }
  846. if (pIoRequestPacket->IoRequest.MajorFunction == IRP_MJ_READ) {
  847. //
  848. // Make sure the reply is the minimum size required
  849. //
  850. replyPacketSize = (ULONG)FIELD_OFFSET(RDPDR_IOCOMPLETION_PACKET,
  851. IoCompletion.Parameters.Read.Buffer) +
  852. pReplyPacket->IoCompletion.Parameters.Read.Length;
  853. TRC_NRM((TB, _T("Read %d bytes"),
  854. pReplyPacket->IoCompletion.Parameters.Read.Length));
  855. }
  856. else if (pIoRequestPacket->IoRequest.MajorFunction == IRP_MJ_DEVICE_CONTROL) {
  857. //
  858. // Make sure the reply is the minimum size required
  859. //
  860. replyPacketSize = (ULONG)FIELD_OFFSET(RDPDR_IOCOMPLETION_PACKET,
  861. IoCompletion.Parameters.DeviceIoControl.OutputBuffer) +
  862. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength;
  863. TRC_NRM((TB, _T("DeviceIoControl %d bytes"),
  864. pReplyPacket->IoCompletion.Parameters.DeviceIoControl.OutputBufferLength));
  865. }
  866. //
  867. // Finish the response and send it.
  868. //
  869. TRC_NRM((TB, _T("replyPacketSize %ld."), replyPacketSize));
  870. pReplyPacket->IoCompletion.IoStatus = TranslateWinError(status);
  871. ProcessObject()->GetVCMgr().ChannelWriteEx(pReplyPacket, replyPacketSize);
  872. }
  873. else {
  874. //
  875. // We previously failed allocating reply packet, try again
  876. //
  877. DefaultIORequestMsgHandle(pIoRequestPacket, ERROR_NOT_ENOUGH_MEMORY);
  878. params->pIoRequestPacket = NULL;
  879. }
  880. //
  881. // ChannelWrite releases the reply packet for us.
  882. //
  883. params->pIoReplyPacket = NULL;
  884. params->IoReplyPacketSize = 0;
  885. //
  886. // Clean up the rest of the request packet and IO parms.
  887. //
  888. if (params->pIoRequestPacket != NULL) {
  889. delete params->pIoRequestPacket;
  890. params->pIoRequestPacket = NULL;
  891. }
  892. DC_END_FN();
  893. delete params;
  894. }
  895. VOID
  896. W32DrDeviceOverlapped::DispatchIOCTLDirectlyToDriver(
  897. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket
  898. )
  899. /*++
  900. Routine Description:
  901. Dispatch an IOCTL directly to the device driver. This will
  902. likely not work for platforms that don't match the server
  903. platform.
  904. Arguments:
  905. pIoRequestPacket - Request packet received from server.
  906. Return Value:
  907. The size (in bytes) of a device announce packet for this device.
  908. --*/
  909. {
  910. W32DRDEV_OVERLAPPEDIO_PARAMS *params;
  911. DWORD result;
  912. DC_BEGIN_FN("W32DrDeviceOverlapped::DispatchIOCTLDirectlyToDriver");
  913. //
  914. // Allocate and dispatch an asynchronous IO request.
  915. //
  916. params = new W32DRDEV_OVERLAPPEDIO_PARAMS(this, pIoRequestPacket);
  917. if (params != NULL ) {
  918. result = ProcessObject()->DispatchAsyncIORequest(
  919. (RDPAsyncFunc_StartIO)
  920. W32DrDeviceOverlapped::_StartIOFunc,
  921. (RDPAsyncFunc_IOComplete)
  922. W32DrDeviceOverlapped::_CompleteIOFunc,
  923. (RDPAsyncFunc_IOCancel)
  924. W32DrDeviceOverlapped::_CancelIOFunc,
  925. params
  926. );
  927. }
  928. else {
  929. TRC_ERR((TB, _T("Memory alloc failed.")));
  930. result = ERROR_NOT_ENOUGH_MEMORY;
  931. }
  932. //
  933. // Clean up on error.
  934. //
  935. if (result != ERROR_SUCCESS) {
  936. if (params != NULL) {
  937. delete params;
  938. }
  939. delete pIoRequestPacket;
  940. // How can I return an error the server if I cannot allocate
  941. // the return buffer. This needs to be fixed. Otherwise, the server will
  942. // just hang on to an IO request that never completes.
  943. }
  944. DC_END_FN();
  945. }
  946. HANDLE
  947. W32DrDeviceOverlapped::_StartIOFunc(
  948. IN PVOID clientData,
  949. OUT DWORD *status
  950. )
  951. /*++
  952. Routine Description:
  953. Dispatch an IO operation start to the right instance of this class.
  954. Arguments:
  955. clientData - Context for the IO request.
  956. status - Return status for IO request in the form of a windows
  957. error code.
  958. Return Value:
  959. NA
  960. --*/
  961. {
  962. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  963. W32DRDEV_OVERLAPPEDIO_PARAMS *params = (W32DRDEV_OVERLAPPEDIO_PARAMS *)clientData;
  964. DC_BEGIN_FN("W32DrDeviceOverlapped::_StartIOFunc");
  965. // Assert the integrity of the IO context
  966. ASSERT(params->magicNo == GOODMEMMAGICNUMBER);
  967. //
  968. // Get the IO request.
  969. //
  970. pIoRequest = &params->pIoRequestPacket->IoRequest;
  971. //
  972. // Dispatch it.
  973. //
  974. DC_END_FN();
  975. switch(pIoRequest->MajorFunction) {
  976. ASSERT(params->pObject != NULL);
  977. case IRP_MJ_READ:
  978. return params->pObject->StartReadIO(params, status);
  979. case IRP_MJ_WRITE:
  980. return params->pObject->StartWriteIO(params, status);
  981. case IRP_MJ_DEVICE_CONTROL:
  982. return params->pObject->StartIOCTL(params, status);
  983. default: ASSERT(FALSE);
  984. return NULL;
  985. }
  986. }