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.

1260 lines
34 KiB

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