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.

2977 lines
92 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. w32drive
  5. Abstract:
  6. This module defines a child of the client-side RDP
  7. device redirection, the "w32drive" W32Drive to provide
  8. file system redirection on 32bit windows
  9. Author:
  10. Joy Chik 11/1/99
  11. Revision History:
  12. --*/
  13. #include <precom.h>
  14. #define TRC_FILE "w32drive"
  15. #include "drdev.h"
  16. #include "w32drdev.h"
  17. #include "w32drive.h"
  18. #include "proc.h"
  19. #include "drconfig.h"
  20. #include "w32utl.h"
  21. #include "utl.h"
  22. #include "drfsfile.h"
  23. #ifdef OS_WINCE
  24. #include "wceinc.h"
  25. #include "axresrc.h"
  26. #include <lss.h>
  27. #include <ceconfig.h>
  28. #include "filemgr.h"
  29. #endif
  30. ///////////////////////////////////////////////////////////////
  31. //
  32. // W32Drive Methods
  33. //
  34. //
  35. W32Drive::W32Drive(
  36. ProcObj *processObject,
  37. ULONG deviceID,
  38. const TCHAR *deviceName,
  39. const TCHAR *devicePath) : W32DrDeviceAsync(processObject, deviceID, devicePath)
  40. /*++
  41. Routine Description:
  42. Constructor
  43. Arguments:
  44. processObject - Associated process object.
  45. deviceName - Name of the drive.
  46. id - Device ID for the drive.
  47. devicePath - Path that can be opened by CreateFile
  48. for drive.
  49. Return Value:
  50. NA
  51. --*/
  52. {
  53. unsigned len;
  54. DC_BEGIN_FN("W32Drive::W32Drive");
  55. SetDeviceProperty();
  56. _fFailedInConstructor = FALSE;
  57. //
  58. // Record the drive name.
  59. //
  60. TRC_ASSERT((deviceName != NULL), (TB, _T("deviceName is NULL")));
  61. len = (STRLEN(deviceName) + 1);
  62. _driveName = new TCHAR[len];
  63. if (_driveName != NULL) {
  64. StringCchCopy(_driveName, len, deviceName);
  65. }
  66. //
  67. // Check and record our status,
  68. //
  69. if (_driveName == NULL) {
  70. TRC_ERR((TB, _T("Memory allocation failed.")));
  71. SetValid(FALSE);
  72. _fFailedInConstructor = TRUE;
  73. }
  74. }
  75. W32Drive::~W32Drive()
  76. /*++
  77. Routine Description:
  78. Destructor
  79. Arguments:
  80. NA
  81. Return Value:
  82. NA
  83. --*/
  84. {
  85. if (_driveName != NULL) {
  86. delete _driveName;
  87. }
  88. }
  89. DWORD
  90. W32Drive::Enumerate(
  91. IN ProcObj *procObj,
  92. IN DrDeviceMgr *deviceMgr
  93. )
  94. {
  95. //
  96. // We enumerate all 26 drive letters
  97. //
  98. return W32Drive::EnumerateDrives(procObj, deviceMgr, 0x3FFFFFF);
  99. }
  100. DWORD
  101. W32Drive::EnumerateDrives(
  102. IN ProcObj *procObj,
  103. IN DrDeviceMgr *deviceMgr,
  104. IN UINT unitMask
  105. )
  106. /*++
  107. Routine Description:
  108. Enumerate devices of this type by adding appropriate device
  109. instances to the device manager.
  110. Arguments:
  111. procObj - Corresponding process object.
  112. deviceMgr - Device manager to add devices to.
  113. Return Value:
  114. ERROR_SUCCESS on success. Otherwise, an error code is returned.
  115. --*/
  116. {
  117. TCHAR szBuff[LOGICAL_DRIVE_LEN * MAX_LOGICAL_DRIVES + 1];
  118. LPTSTR lpszDrive = &szBuff[0];
  119. TCHAR szDrive[3];
  120. W32Drive *deviceObj;
  121. RDPDR_VERSION serverVer;
  122. DC_BEGIN_FN("W32Drive::Enumerate");
  123. TRC_DBG((TB, _T("Enumerating drives")));
  124. serverVer = procObj->serverVersion();
  125. if(!procObj->GetVCMgr().GetInitData()->fEnableRedirectDrives)
  126. {
  127. TRC_DBG((TB,_T("Drive redirection disabled, bailing out")));
  128. return ERROR_SUCCESS;
  129. }
  130. //
  131. // If the server doesn't support drive redirection,
  132. // then don't bother enumerate the drives, simply
  133. // return success
  134. //
  135. if (COMPARE_VERSION(serverVer.Minor, serverVer.Major,
  136. 4, 1) < 0) {
  137. TRC_NRM((TB, _T("Skipping drive enumeration")));
  138. return ERROR_SUCCESS;
  139. }
  140. szDrive[2] = TEXT('\0');
  141. #ifndef OS_WINCE
  142. DWORD dwEnum;
  143. //
  144. // Enumerate all drive letters and find the valid drives
  145. //
  146. dwEnum = 0;
  147. while (unitMask) {
  148. if (unitMask & 0x1) {
  149. //
  150. // For each drive find whether it is a local sharable drive
  151. //
  152. lpszDrive = &(szBuff[LOGICAL_DRIVE_LEN * dwEnum]);
  153. lpszDrive[0] = TEXT('A') + (TCHAR)dwEnum;
  154. lpszDrive[1] = TEXT(':');
  155. lpszDrive[2] = TEXT('\\');
  156. lpszDrive[3] = TEXT('\0');
  157. switch (GetDriveType(lpszDrive))
  158. {
  159. case DRIVE_REMOVABLE: // The disk can be removed from the drive.
  160. case DRIVE_FIXED: // The disk cannot be removed from the drive.
  161. case DRIVE_CDROM: // The drive is a CD-ROM drive.
  162. case DRIVE_RAMDISK: // The drive is a RAM disk.
  163. case DRIVE_REMOTE: // The drive is a remote (network) drive.
  164. TRC_NRM((TB, _T("Redirecting drive %s"), lpszDrive));
  165. // Copy <driveletter>: into drive device path
  166. szDrive[0] = lpszDrive[0];
  167. szDrive[1] = lpszDrive[1];
  168. deviceObj = new W32Drive(procObj, deviceMgr->GetUniqueObjectID(),
  169. &szDrive[0], &szDrive[0]);
  170. //
  171. // Add to the device manager if we got a valid object.
  172. //
  173. if (deviceObj != NULL) {
  174. if (deviceObj->IfFailedInConstructor() != TRUE) {
  175. deviceObj->Initialize();
  176. if (!(deviceObj->IsValid() &&
  177. (deviceMgr->AddObject(deviceObj) == STATUS_SUCCESS))) {
  178. delete deviceObj;
  179. }
  180. }
  181. else {
  182. TRC_ERR((TB, _T("Failed in new W32Drive")));
  183. delete deviceObj;
  184. }
  185. }
  186. else {
  187. TRC_ERR((TB, _T("Failed to allocate drive device.")));
  188. }
  189. break;
  190. case DRIVE_UNKNOWN: // The drive type cannot be determined.
  191. case DRIVE_NO_ROOT_DIR: // The root path is invalid. For example, no volume is mounted at the path.
  192. default:
  193. TRC_NRM((TB, _T("Skipping drive %s"), lpszDrive));
  194. break;
  195. }
  196. }
  197. unitMask = unitMask >> 0x1;
  198. dwEnum++;
  199. }
  200. #else
  201. //
  202. // JOYC: Need to look into CE way of enumerate drives
  203. // For now, we just use C drive e.g. \\tsclient\c on the server side
  204. //
  205. //CE doesnt have drive letters. So DevicePath='\\', DeviceName="Files". And this string should NOT be localized
  206. deviceObj = new W32Drive(procObj, deviceMgr->GetUniqueObjectID(),
  207. CEROOTDIRNAME, CEROOTDIR);
  208. //
  209. // Add to the device manager if we got a valid object.
  210. //
  211. if (deviceObj != NULL) {
  212. deviceObj->Initialize();
  213. if (!(deviceObj->IsValid() &&
  214. (deviceMgr->AddObject(deviceObj) == STATUS_SUCCESS))) {
  215. delete deviceObj;
  216. }
  217. }
  218. else {
  219. TRC_ERR((TB, _T("Failed to allocate drive device.")));
  220. }
  221. #endif
  222. DC_END_FN();
  223. return ERROR_SUCCESS;
  224. }
  225. DWORD
  226. W32Drive::RemoveDrives(
  227. IN ProcObj *procObj,
  228. IN DrDeviceMgr *deviceMgr,
  229. IN UINT unitMask
  230. )
  231. /*++
  232. Routine Description:
  233. Enumerate devices of this type by removing appropriate device
  234. instances from the device manager.
  235. Arguments:
  236. procObj - Corresponding process object.
  237. deviceMgr - Device manager to add devices to.
  238. Return Value:
  239. ERROR_SUCCESS on success. Otherwise, an error code is returned.
  240. --*/
  241. {
  242. DWORD driveIndex = 0;
  243. RDPDR_VERSION serverVer;
  244. TCHAR szDrive[3];
  245. DC_BEGIN_FN("W32Drive::RemoveDrives");
  246. serverVer = procObj->serverVersion();
  247. if(!procObj->GetVCMgr().GetInitData()->fEnableRedirectDrives)
  248. {
  249. TRC_DBG((TB,_T("Drive redirection disabled, bailing out")));
  250. return ERROR_SUCCESS;
  251. }
  252. //
  253. // If the server doesn't support drive removal,
  254. // then don't bother enumerate the drives, simply
  255. // return
  256. //
  257. if (!(procObj->GetServerCap().GeneralCap.extendedPDU & RDPDR_DEVICE_REMOVE_PDUS)) {
  258. TRC_NRM((TB, _T("Skipping drive enumeration")));
  259. return ERROR_SUCCESS;
  260. }
  261. szDrive[1] = TEXT(':');
  262. szDrive[2] = TEXT('\0');
  263. while (unitMask) {
  264. if (unitMask & 0x1) {
  265. DrDevice *deviceObj;
  266. //
  267. // Find if a device exists
  268. //
  269. szDrive[0] = TEXT('A') + (TCHAR)driveIndex;
  270. deviceObj = (DrDevice*)deviceMgr->GetObject(szDrive, RDPDR_DTYP_FILESYSTEM);
  271. if ( deviceObj != NULL ) {
  272. deviceObj->_deviceChange = DEVICEREMOVE;
  273. // Need to remove this device
  274. TRC_NRM((TB, _T("Deleting drive %s"), szDrive));
  275. }
  276. }
  277. unitMask = unitMask >> 0x1;
  278. driveIndex++;
  279. }
  280. DC_END_FN();
  281. return ERROR_SUCCESS;
  282. }
  283. ULONG
  284. W32Drive::GetDevAnnounceDataSize()
  285. /*++
  286. Routine Description:
  287. Return the size (in bytes) of a device announce packet for
  288. this device.
  289. Arguments:
  290. NA
  291. Return Value:
  292. The size (in bytes) of a device announce packet for this device.
  293. --*/
  294. {
  295. ULONG size = 0;
  296. DC_BEGIN_FN("W32Drive::GetDevAnnounceDataSize");
  297. TRC_ASSERT((IsValid()), (TB, _T("Invalid w32drive object")));
  298. if (!IsValid()) { return 0; }
  299. size = 0;
  300. //
  301. // Add the base announce size.
  302. //
  303. size += sizeof(RDPDR_DEVICE_ANNOUNCE);
  304. DC_END_FN();
  305. return size;
  306. }
  307. VOID W32Drive::GetDevAnnounceData(
  308. IN PRDPDR_DEVICE_ANNOUNCE pDeviceAnnounce
  309. )
  310. /*++
  311. Routine Description:
  312. Add a device announce packet for this device to the input buffer.
  313. Arguments:
  314. pDeviceAnnounce - Device Announce Buf for this Device
  315. Return Value:
  316. NA
  317. --*/
  318. {
  319. DC_BEGIN_FN("W32Drive::GetDevAnnounceData");
  320. TRC_ASSERT((IsValid()), (TB, _T("Invalid w32drive object")));
  321. if (!IsValid()) {
  322. DC_END_FN();
  323. return;
  324. }
  325. pDeviceAnnounce->DeviceId = GetID();
  326. pDeviceAnnounce->DeviceType = GetDeviceType();
  327. pDeviceAnnounce->DeviceDataLength = 0;
  328. //
  329. // Record the device name in ANSI.
  330. //
  331. #ifdef UNICODE
  332. RDPConvertToAnsi(_driveName, (LPSTR)pDeviceAnnounce->PreferredDosName,
  333. sizeof(pDeviceAnnounce->PreferredDosName)
  334. );
  335. #else
  336. STRNCPY((char *)pDeviceAnnounce->PreferredDosName, _driveName, PREFERRED_DOS_NAME_SIZE);
  337. pDeviceAnnounce->PreferredDosName[PREFERRED_DOS_NAME_SIZE - 1] = '\0';
  338. #endif
  339. DC_END_FN();
  340. }
  341. HANDLE
  342. W32Drive::StartFSFunc(
  343. IN W32DRDEV_ASYNCIO_PARAMS *params,
  344. OUT DWORD *status
  345. )
  346. /*++
  347. Routine Description:
  348. Start a generic asynchronous File System IO operation.
  349. Arguments:
  350. params - Context for the IO request.
  351. status - Return status for IO request in the form of a windows
  352. error code.
  353. Return Value:
  354. Returns a handle to an object that will be signalled when the read
  355. completes, if it is not completed in this function. Otherwise, NULL
  356. is returned.
  357. --*/
  358. {
  359. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  360. DrFile* pFile;
  361. ULONG irpMajor;
  362. DC_BEGIN_FN("W32Drive::StartFSFunc");
  363. *status = ERROR_SUCCESS;
  364. // Assert the integrity of the IO context
  365. TRC_ASSERT((params->magicNo == GOODMEMMAGICNUMBER),
  366. (TB, _T("bad params->magicNo: %x"), params->magicNo));
  367. //
  368. // Get the IO request and the IPR major.
  369. //
  370. pIoRequest = &params->pIoRequestPacket->IoRequest;
  371. irpMajor = pIoRequest->MajorFunction;
  372. //
  373. // Hand the request off to the thread pool.
  374. //
  375. params->completionEvent = CreateEvent(
  376. NULL, // no attribute.
  377. TRUE, // manual reset.
  378. FALSE, // initially not signalled.
  379. NULL // no name.
  380. );
  381. if (params->completionEvent == NULL) {
  382. *status = GetLastError();
  383. TRC_ERR((TB, _T("Error in CreateEvent: %08X."), *status));
  384. }
  385. else {
  386. switch (irpMajor)
  387. {
  388. case IRP_MJ_DIRECTORY_CONTROL:
  389. params->thrPoolReq = _threadPool->SubmitRequest(
  390. _AsyncDirCtrlFunc,
  391. params, params->completionEvent
  392. );
  393. break;
  394. }
  395. if (params->thrPoolReq == INVALID_THREADPOOLREQUEST) {
  396. *status = ERROR_SERVICE_NO_THREAD;
  397. }
  398. }
  399. Cleanup:
  400. //
  401. // If IO is pending, return the handle to the pending IO.
  402. //
  403. if (params->thrPoolReq != INVALID_THREADPOOLREQUEST) {
  404. *status = ERROR_IO_PENDING;
  405. DC_END_FN();
  406. return params->completionEvent;
  407. }
  408. //
  409. // Otherwise, clean up the event handle and return NULL so that the
  410. // CompleteIOFunc can be called to send the results to the server.
  411. //
  412. else {
  413. //
  414. // Get File Object
  415. //
  416. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  417. if (pFile) {
  418. pFile->Release();
  419. }
  420. if (params->completionEvent != NULL) {
  421. CloseHandle(params->completionEvent);
  422. params->completionEvent = NULL;
  423. }
  424. DC_END_FN();
  425. return NULL;
  426. }
  427. }
  428. HANDLE
  429. W32Drive::_StartFSFunc(
  430. IN W32DRDEV_ASYNCIO_PARAMS *params,
  431. OUT DWORD *status
  432. )
  433. {
  434. return ((W32Drive*)params->pObject)->StartFSFunc(params, status);
  435. }
  436. VOID
  437. W32Drive::MsgIrpQueryDirectory(
  438. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  439. IN UINT32 packetLen
  440. )
  441. /*++
  442. Routine Description:
  443. Queries the directory information for this drive device.
  444. Arguments:
  445. pIoRequestPacket - Server IO request packet.
  446. packetLen - length of the packet
  447. Return Value:
  448. NA
  449. --*/
  450. {
  451. ULONG ulRetCode = ERROR_SUCCESS;
  452. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  453. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  454. ULONG ulReplyPacketSize = 0;
  455. DWORD result;
  456. ULONG BufferLength = 0;
  457. BYTE Buffer[RDP_FILE_DIRECTORY_INFO_MAXLENGTH + (MAX_PATH + 1) * sizeof(WCHAR)];
  458. TCHAR *pFileName;
  459. DrFile *pFile;
  460. HANDLE FileHandle;
  461. WIN32_FIND_DATA FileData;
  462. unsigned DriveLen, PathLen;
  463. BOOL rc;
  464. HRESULT hr;
  465. DC_BEGIN_FN("W32Drive::MsgIrpQueryDirectory");
  466. ASSERT(_tcslen(_devicePath));
  467. //
  468. // Get IO request pointer.
  469. //
  470. pIoRequest = &pIoRequestPacket->IoRequest;
  471. PathLen = DriveLen = 0;
  472. pFileName = NULL;
  473. memset(Buffer, 0, sizeof(Buffer));
  474. //
  475. // Map file Id to get the file object
  476. //
  477. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  478. //
  479. // Query file or directory information
  480. //
  481. if (pFile) {
  482. if (!pIoRequest->Parameters.QueryDir.InitialQuery) {
  483. ASSERT(((DrFSFile *)pFile)->GetSearchHandle() != INVALID_TS_FILEHANDLE);
  484. rc = FindNextFile(((DrFSFile *)pFile)->GetSearchHandle(), &FileData);
  485. }
  486. else {
  487. TCHAR FileName[MAX_PATH];
  488. //
  489. // Setup the File Name
  490. //
  491. //
  492. // Path is assumed string null terminated
  493. //
  494. if (packetLen < sizeof(RDPDR_IOREQUEST_PACKET) + pIoRequest->Parameters.QueryDir.PathLength) {
  495. // call VirtualChannelClose
  496. ProcessObject()->GetVCMgr().ChannelClose();
  497. TRC_ASSERT(FALSE, (TB, _T("Packet Length Error")));
  498. goto Cleanup;
  499. }
  500. PathLen = pIoRequest->Parameters.QueryDir.PathLength / sizeof(WCHAR) - 1;
  501. if (PathLen) {
  502. WCHAR *Path;
  503. //
  504. // Open a File
  505. //
  506. Path = (WCHAR *)(pIoRequestPacket + 1);
  507. Path[PathLen] = L'\0';
  508. #ifndef OS_WINCE
  509. DriveLen = _tcslen(_devicePath);
  510. #else
  511. DriveLen = 0;
  512. #endif
  513. //
  514. // Append device path and file path together
  515. //
  516. #ifndef OS_WINCE
  517. if (DriveLen + PathLen < MAX_PATH) {
  518. pFileName = &FileName[0];
  519. //Length is pre-checked
  520. hr = StringCchCopy(pFileName, MAX_PATH, _devicePath);
  521. TRC_ASSERT(SUCCEEDED(hr),
  522. (TB,_T("Str copy failed for pre-checked len: 0x%x"),hr));
  523. } else {
  524. UINT cchLen = DriveLen + PathLen + 5;
  525. pFileName = new TCHAR[cchLen];
  526. if (pFileName) {
  527. //
  528. // The file name needs to be in the \\?\ format.
  529. //
  530. // Note: we'll not get UNC path name
  531. hr = StringCchPrintf(pFileName,
  532. cchLen,
  533. TEXT("\\\\?\\%s"),
  534. _devicePath);
  535. TRC_ASSERT(SUCCEEDED(hr),
  536. (TB,_T("Str copy failed for pre-checked len: 0x%x"),hr));
  537. DriveLen += 4;
  538. } else {
  539. TRC_ERR((TB, _T("Failed to alloc File Name")));
  540. goto Cleanup;
  541. }
  542. }
  543. #else
  544. pFileName = &FileName[0];
  545. #endif
  546. #ifndef UNICODE
  547. RDPConvertToAnsi(Path, pFileName + DriveLen, PathLen + 1);
  548. #else
  549. memcpy(pFileName + DriveLen, Path, PathLen * sizeof(WCHAR));
  550. pFileName[DriveLen + PathLen] = _T('\0');
  551. #endif
  552. } else {
  553. //
  554. // Open the root drive
  555. //
  556. hr = StringCchPrintf(FileName, SIZE_TCHARS(FileName),
  557. _T("%s\\"),
  558. _devicePath);
  559. TRC_ASSERT(SUCCEEDED(hr),
  560. (TB,_T("Str printf failed for pre-checked len: 0x%x"),hr));
  561. pFileName = &FileName[0];
  562. }
  563. FileHandle = FindFirstFile(pFileName, &FileData);
  564. if (FileHandle != INVALID_HANDLE_VALUE) {
  565. ((DrFSFile *)pFile)->SetSearchHandle(FileHandle);
  566. rc = TRUE;
  567. } else {
  568. rc = FALSE;
  569. }
  570. }
  571. }
  572. else {
  573. ulRetCode = ERROR_FILE_NOT_FOUND;
  574. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  575. TRC_ERR((TB, _T("Query directory information failed, %ld."), ulRetCode));
  576. goto SendPacket;
  577. }
  578. switch (pIoRequest->Parameters.QueryDir.FileInformationClass) {
  579. case RdpFileDirectoryInformation:
  580. if (rc)
  581. {
  582. PRDP_FILE_DIRECTORY_INFORMATION pFileDirInfo =
  583. (PRDP_FILE_DIRECTORY_INFORMATION) Buffer;
  584. pFileDirInfo->NextEntryOffset = 0;
  585. pFileDirInfo->FileIndex = 0;
  586. pFileDirInfo->CreationTime.LowPart = FileData.ftCreationTime.dwLowDateTime;
  587. pFileDirInfo->CreationTime.HighPart = FileData.ftCreationTime.dwHighDateTime;
  588. pFileDirInfo->LastAccessTime.LowPart = FileData.ftLastAccessTime.dwLowDateTime;
  589. pFileDirInfo->LastAccessTime.HighPart = FileData.ftLastAccessTime.dwHighDateTime;
  590. pFileDirInfo->LastWriteTime.LowPart = FileData.ftLastWriteTime.dwLowDateTime;
  591. pFileDirInfo->LastWriteTime.HighPart = FileData.ftLastWriteTime.dwHighDateTime;
  592. pFileDirInfo->ChangeTime.QuadPart = 0;
  593. pFileDirInfo->EndOfFile.HighPart = FileData.nFileSizeHigh;
  594. pFileDirInfo->EndOfFile.LowPart = FileData.nFileSizeLow;
  595. // TODO Do we need to set the allocation size? and what should it be?
  596. pFileDirInfo->AllocationSize.HighPart = FileData.nFileSizeHigh;
  597. pFileDirInfo->AllocationSize.LowPart = FileData.nFileSizeLow;
  598. pFileDirInfo->FileAttributes = FileData.dwFileAttributes;
  599. pFileDirInfo->FileNameLength = _tcslen(FileData.cFileName) * sizeof(WCHAR);
  600. #ifdef UNICODE
  601. memcpy(&pFileDirInfo->FileName[0], FileData.cFileName, pFileDirInfo->FileNameLength);
  602. #else
  603. RDPConvertToUnicode(FileData.cFileName, (LPWSTR)FileNameBuffer, MAX_PATH);
  604. memcpy(&pFileDirInfo->FileName[0], FileNameBuffer, pFileDirInfo->FileNameLength);
  605. #endif
  606. ulRetCode = ERROR_SUCCESS;
  607. BufferLength = FIELD_OFFSET(RDP_FILE_DIRECTORY_INFORMATION, FileName) +
  608. pFileDirInfo->FileNameLength;
  609. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  610. BufferLength - 1;
  611. }
  612. else {
  613. ulRetCode = GetLastError();
  614. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  615. TRC_ERR((TB, _T("Query directory information failed, %ld."), ulRetCode));
  616. }
  617. break;
  618. case RdpFileFullDirectoryInformation:
  619. if (rc)
  620. {
  621. PRDP_FILE_FULL_DIR_INFORMATION pFileDirInfo =
  622. (PRDP_FILE_FULL_DIR_INFORMATION) Buffer;
  623. pFileDirInfo->NextEntryOffset = 0;
  624. pFileDirInfo->FileIndex = 0;
  625. pFileDirInfo->CreationTime.LowPart = FileData.ftCreationTime.dwLowDateTime;
  626. pFileDirInfo->CreationTime.HighPart = FileData.ftCreationTime.dwHighDateTime;
  627. pFileDirInfo->LastAccessTime.LowPart = FileData.ftLastAccessTime.dwLowDateTime;
  628. pFileDirInfo->LastAccessTime.HighPart = FileData.ftLastAccessTime.dwHighDateTime;
  629. pFileDirInfo->LastWriteTime.LowPart = FileData.ftLastWriteTime.dwLowDateTime;
  630. pFileDirInfo->LastWriteTime.HighPart = FileData.ftLastWriteTime.dwHighDateTime;
  631. pFileDirInfo->ChangeTime.QuadPart = 0;
  632. pFileDirInfo->EndOfFile.HighPart = FileData.nFileSizeHigh;
  633. pFileDirInfo->EndOfFile.LowPart = FileData.nFileSizeLow;
  634. pFileDirInfo->AllocationSize.HighPart = FileData.nFileSizeHigh;
  635. pFileDirInfo->AllocationSize.LowPart = FileData.nFileSizeLow;
  636. pFileDirInfo->FileAttributes = FileData.dwFileAttributes;
  637. pFileDirInfo->FileNameLength = _tcslen(FileData.cFileName) * sizeof(WCHAR);
  638. #ifdef UNICODE
  639. memcpy(&pFileDirInfo->FileName[0], FileData.cFileName, pFileDirInfo->FileNameLength);
  640. #else
  641. RDPConvertToUnicode(FileData.cFileName, (LPWSTR)FileNameBuffer, MAX_PATH);
  642. memcpy(&pFileDirInfo->FileName[0], FileNameBuffer, pFileDirInfo->FileNameLength);
  643. #endif
  644. pFileDirInfo->EaSize = 0;
  645. ulRetCode = ERROR_SUCCESS;
  646. BufferLength = FIELD_OFFSET(RDP_FILE_FULL_DIR_INFORMATION, FileName) +
  647. pFileDirInfo->FileNameLength;
  648. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  649. BufferLength - 1;
  650. }
  651. else {
  652. ulRetCode = GetLastError();
  653. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  654. TRC_ERR((TB, _T("Query full directory information failed, %ld."), ulRetCode));
  655. }
  656. break;
  657. case RdpFileBothDirectoryInformation:
  658. if (rc)
  659. {
  660. PRDP_FILE_BOTH_DIR_INFORMATION pFileDirInfo =
  661. (PRDP_FILE_BOTH_DIR_INFORMATION) Buffer;
  662. pFileDirInfo->NextEntryOffset = 0;
  663. pFileDirInfo->FileIndex = 0;
  664. pFileDirInfo->CreationTime.LowPart = FileData.ftCreationTime.dwLowDateTime;
  665. pFileDirInfo->CreationTime.HighPart = FileData.ftCreationTime.dwHighDateTime;
  666. pFileDirInfo->LastAccessTime.LowPart = FileData.ftLastAccessTime.dwLowDateTime;
  667. pFileDirInfo->LastAccessTime.HighPart = FileData.ftLastAccessTime.dwHighDateTime;
  668. pFileDirInfo->LastWriteTime.LowPart = FileData.ftLastWriteTime.dwLowDateTime;
  669. pFileDirInfo->LastWriteTime.HighPart = FileData.ftLastWriteTime.dwHighDateTime;
  670. pFileDirInfo->ChangeTime.QuadPart = 0;
  671. pFileDirInfo->EndOfFile.HighPart = FileData.nFileSizeHigh;
  672. pFileDirInfo->EndOfFile.LowPart = FileData.nFileSizeLow;
  673. pFileDirInfo->AllocationSize.HighPart = FileData.nFileSizeHigh;
  674. pFileDirInfo->AllocationSize.LowPart = FileData.nFileSizeLow;
  675. pFileDirInfo->FileAttributes = FileData.dwFileAttributes;
  676. pFileDirInfo->EaSize = 0;
  677. #ifndef OS_WINCE
  678. pFileDirInfo->ShortNameLength = (CCHAR)(_tcslen(FileData.cAlternateFileName) * sizeof(WCHAR));
  679. #else
  680. pFileDirInfo->ShortNameLength = sizeof(WCHAR);
  681. #endif
  682. #ifndef OS_WINCE
  683. #ifdef UNICODE
  684. memcpy(&pFileDirInfo->ShortName[0], FileData.cAlternateFileName, pFileDirInfo->ShortNameLength);
  685. #else
  686. RDPConvertToUnicode(FileData.cAlternateFileName, (LPWSTR)ShortName,
  687. sizeof(ShortName) / sizeof(WCHAR));
  688. memcpy(&pFileDirInfo->ShortName[0], ShortName, pFileDirInfo->ShortNameLength);
  689. #endif
  690. #else
  691. pFileDirInfo->ShortName[0] = L'\0';
  692. #endif
  693. pFileDirInfo->FileNameLength = _tcslen(FileData.cFileName) * sizeof(WCHAR);
  694. #ifdef UNICODE
  695. memcpy(&pFileDirInfo->FileName[0], FileData.cFileName, pFileDirInfo->FileNameLength);
  696. #else
  697. RDPConvertToUnicode(FileData.cFileName, FileNameBuffer, MAX_PATH);
  698. memcpy(&pFileDirInfo->FileName[0], FileNameBuffer, pFileDirInfo->FileNameLength);
  699. #endif
  700. ulRetCode = ERROR_SUCCESS;
  701. BufferLength = FIELD_OFFSET(RDP_FILE_BOTH_DIR_INFORMATION, FileName) +
  702. pFileDirInfo->FileNameLength;
  703. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  704. BufferLength - 1;
  705. } else {
  706. ulRetCode = GetLastError();
  707. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  708. TRC_ERR((TB, _T("Query both directory info failed, %ld."), ulRetCode));
  709. }
  710. break;
  711. case RdpFileNamesInformation:
  712. if (rc) {
  713. PRDP_FILE_NAMES_INFORMATION pFileDirInfo =
  714. (PRDP_FILE_NAMES_INFORMATION) Buffer;
  715. pFileDirInfo->NextEntryOffset = 0;
  716. pFileDirInfo->FileIndex = 0;
  717. pFileDirInfo->FileNameLength = _tcslen(FileData.cFileName) * sizeof(WCHAR);
  718. #ifdef UNICODE
  719. memcpy(&pFileDirInfo->FileName[0], FileData.cFileName, pFileDirInfo->FileNameLength);
  720. #else
  721. RDPConvertToUnicode(FileData.cFileName, FileNameBuffer, MAX_PATH);
  722. memcpy(&pFileDirInfo->FileName[0], FileNameBuffer, pFileDirInfo->FileNameLength);
  723. #endif
  724. ulRetCode = ERROR_SUCCESS;
  725. BufferLength = sizeof(RDP_FILE_NAMES_INFORMATION) +
  726. pFileDirInfo->FileNameLength - sizeof(WCHAR);
  727. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  728. BufferLength - 1;
  729. } else {
  730. ulRetCode = GetLastError();
  731. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  732. TRC_ERR((TB, _T("Query file names failed, %ld."), ulRetCode));
  733. }
  734. break;
  735. default:
  736. TRC_ERR((TB, _T("Unsupported QueryDirectory class %x"),
  737. pIoRequest->Parameters.QueryDir.FileInformationClass));
  738. ulRetCode = ERROR_INVALID_FUNCTION;
  739. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  740. break;
  741. }
  742. SendPacket:
  743. //
  744. // Allocate reply buffer.
  745. //
  746. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket, ulReplyPacketSize) ;
  747. if (pReplyPacket) {
  748. //
  749. // Send the result to the server.
  750. //
  751. result = TranslateWinError(ulRetCode);
  752. pReplyPacket->IoCompletion.IoStatus = result;
  753. pReplyPacket->IoCompletion.Parameters.QueryDir.Length = BufferLength;
  754. if (BufferLength)
  755. memcpy(pReplyPacket->IoCompletion.Parameters.QueryDir.Buffer,
  756. Buffer, BufferLength);
  757. ProcessObject()->GetVCMgr().ChannelWrite(
  758. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  759. }
  760. else {
  761. TRC_ERR((TB, _T("Failed to alloc %ld bytes."),ulReplyPacketSize));
  762. }
  763. Cleanup:
  764. //
  765. // Clean up the request packet.
  766. //
  767. delete pIoRequestPacket;
  768. if (pFileName && (DriveLen + PathLen >= MAX_PATH)) {
  769. delete pFileName;
  770. }
  771. DC_END_FN();
  772. }
  773. VOID
  774. W32Drive::MsgIrpDirectoryControl(
  775. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  776. IN UINT32 packetLen
  777. )
  778. /*++
  779. Routine Description:
  780. Queries the directory information for this drive device.
  781. Arguments:
  782. pIoRequestPacket - Server IO request packet.
  783. packetLen - length of the packet
  784. Return Value:
  785. NA
  786. --*/
  787. {
  788. W32DRDEV_ASYNCIO_PARAMS *params;
  789. DrFile* pFile;
  790. DWORD status;
  791. DC_BEGIN_FN("W32DrDeviceAsync::MsgIrpDirectoryControl");
  792. TRC_NRM((TB, _T("Request Directory Control")));
  793. //
  794. // Leave the query directory in the forground thread as it is
  795. //
  796. if (pIoRequestPacket->IoRequest.MinorFunction == IRP_MN_QUERY_DIRECTORY ||
  797. pIoRequestPacket->IoRequest.MinorFunction == 0) {
  798. MsgIrpQueryDirectory(pIoRequestPacket, packetLen);
  799. return;
  800. }
  801. //
  802. // Get File Object and reference it
  803. //
  804. pFile = _FileMgr->GetObject(pIoRequestPacket->IoRequest.FileId);
  805. if (pFile) {
  806. pFile->AddRef();
  807. }
  808. else {
  809. DefaultIORequestMsgHandle(pIoRequestPacket, STATUS_UNSUCCESSFUL);
  810. return;
  811. }
  812. //
  813. // Allocate and dispatch an asynchronous IO request.
  814. //
  815. params = new W32DRDEV_ASYNCIO_PARAMS(this, pIoRequestPacket);
  816. if (params != NULL ) {
  817. TRC_NRM((TB, _T("Async IO operation")));
  818. status = ProcessObject()->DispatchAsyncIORequest(
  819. (RDPAsyncFunc_StartIO)W32Drive::_StartFSFunc,
  820. (RDPAsyncFunc_IOComplete)W32DrDeviceAsync::_CompleteIOFunc,
  821. (RDPAsyncFunc_IOCancel)W32DrDeviceAsync::_CancelIOFunc,
  822. params
  823. );
  824. }
  825. else {
  826. TRC_ERR((TB, _T("Memory alloc failed.")));
  827. status = ERROR_NOT_ENOUGH_MEMORY;
  828. }
  829. //
  830. // Clean up on error.
  831. //
  832. if (status != ERROR_SUCCESS) {
  833. pFile->Release();
  834. if (params != NULL) {
  835. delete params;
  836. }
  837. delete pIoRequestPacket;
  838. }
  839. DC_END_FN();
  840. }
  841. DWORD
  842. W32Drive::AsyncDirCtrlFunc(
  843. IN W32DRDEV_ASYNCIO_PARAMS *params,
  844. IN HANDLE cancelEvent
  845. )
  846. /*++
  847. Routine Description:
  848. Asynchrous Directory Control Function
  849. Arguments:
  850. params - Context for the IO request.
  851. Return Value:
  852. Always returns 0.
  853. --*/
  854. {
  855. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  856. DC_BEGIN_FN("W32Drive::AsyncDirCtrlFunc");
  857. //
  858. // Get the IO request pointer
  859. //
  860. pIoRequest = &params->pIoRequestPacket->IoRequest;
  861. if (pIoRequest->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY) {
  862. #if (!defined (OS_WINCE)) || (!defined (WINCE_SDKBUILD))
  863. return AsyncNotifyChangeDir(params, cancelEvent);
  864. #else
  865. DrFile* pFile;
  866. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  867. if (pFile)
  868. pFile->Release();
  869. return STATUS_NOT_SUPPORTED;
  870. #endif
  871. }
  872. else {
  873. TRC_ASSERT((FALSE), (TB, _T("Invalid Minor Function: %x"), pIoRequest->MinorFunction));
  874. return ERROR_INVALID_PARAMETER;
  875. }
  876. }
  877. DWORD
  878. W32Drive::_AsyncDirCtrlFunc(
  879. IN PVOID params,
  880. IN HANDLE cancelEvent
  881. )
  882. {
  883. return ((W32Drive*)(((W32DRDEV_ASYNCIO_PARAMS *)params)->pObject))->AsyncDirCtrlFunc(
  884. (W32DRDEV_ASYNCIO_PARAMS *)params, cancelEvent);
  885. }
  886. #if (!defined (OS_WINCE)) || (!defined (WINCE_SDKBUILD))
  887. DWORD
  888. W32Drive::AsyncNotifyChangeDir(
  889. IN W32DRDEV_ASYNCIO_PARAMS *params,
  890. IN HANDLE cancelEvent
  891. )
  892. /*++
  893. Routine Description:
  894. Directory change notification Function
  895. Arguments:
  896. params - Context for the IO request.
  897. Return Value:
  898. Always returns 0.
  899. --*/
  900. {
  901. DWORD status;
  902. ULONG replyPacketSize = 0;
  903. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  904. PRDPDR_IOCOMPLETION_PACKET pReplyPacket = NULL;
  905. DrFile* pFile;
  906. HANDLE FileHandle;
  907. HANDLE NotifyHandle;
  908. HANDLE waitableEvents[2];
  909. HRESULT hr;
  910. DC_BEGIN_FN("W32Drive::AsyncNotifyChangeDir");
  911. //
  912. // Get the IO request pointer
  913. //
  914. pIoRequest = &params->pIoRequestPacket->IoRequest;
  915. //
  916. // Get File Object
  917. //
  918. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  919. if (pFile) {
  920. FileHandle = pFile->GetFileHandle();
  921. NotifyHandle = ((DrFSFile*)pFile)->GetNotifyHandle();
  922. }
  923. else {
  924. status = ERROR_CANCELLED;
  925. TRC_ERR((TB, _T("File object already cancelled")));
  926. goto Cleanup;
  927. }
  928. //
  929. // Allocate reply buffer.
  930. //
  931. replyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  932. pReplyPacket = DrUTL_AllocIOCompletePacket(params->pIoRequestPacket,
  933. replyPacketSize) ;
  934. if (pReplyPacket == NULL) {
  935. status = ERROR_NOT_ENOUGH_MEMORY;
  936. TRC_ERR((TB, _T("Failed to alloc %ld bytes."), replyPacketSize));
  937. goto Cleanup;
  938. }
  939. //
  940. // Save the reply packet info to the context for this IO operation.
  941. //
  942. params->pIoReplyPacket = pReplyPacket;
  943. params->IoReplyPacketSize = replyPacketSize;
  944. //
  945. // If we don't yet have a notification handle.
  946. //
  947. if (NotifyHandle == INVALID_HANDLE_VALUE) {
  948. TRC_ASSERT((((DrFSFile*)pFile)->GetFileName() != NULL),
  949. (TB, _T("FileName is empty")));
  950. //
  951. // Setup the notification handle
  952. //
  953. NotifyHandle = FindFirstChangeNotification(((DrFSFile*)pFile)->GetFileName(),
  954. pIoRequest->Parameters.NotifyChangeDir.WatchTree,
  955. pIoRequest->Parameters.NotifyChangeDir.CompletionFilter);
  956. if (NotifyHandle == INVALID_HANDLE_VALUE) {
  957. status = GetLastError();
  958. TRC_ERR((TB, _T("FindFirstChangeNotification: %08X"), status));
  959. goto Cleanup;
  960. }
  961. if (((DrFSFile*)pFile)->SetNotifyHandle(NotifyHandle) == FALSE) {
  962. FindCloseChangeNotification(NotifyHandle);
  963. NotifyHandle = INVALID_HANDLE_VALUE;
  964. status = ERROR_CANCELLED;
  965. goto Cleanup;
  966. }
  967. }
  968. else {
  969. //
  970. // Notification handle already setup. Find next change notification.
  971. //
  972. if (!FindNextChangeNotification(NotifyHandle)) {
  973. status = GetLastError();
  974. TRC_ERR((TB, _T("FindNextChangeNotification: %08X"), status));
  975. goto Cleanup;
  976. }
  977. }
  978. //
  979. // Wait for the cancel or notify event to be signaled.
  980. //
  981. waitableEvents[0] = NotifyHandle;
  982. waitableEvents[1] = cancelEvent;
  983. status = WaitForMultipleObjects(2, waitableEvents, FALSE, INFINITE);
  984. if (status == WAIT_FAILED) {
  985. status = GetLastError();
  986. TRC_ERR((TB, _T("Error %ld."), status));
  987. }
  988. else if (status == WAIT_OBJECT_0){
  989. status = ERROR_SUCCESS;
  990. }
  991. else if (status == WAIT_OBJECT_0 + 1) {
  992. TRC_ERR((TB, _T("Client got disconnected/logoff")));
  993. status = ERROR_CANCELLED;
  994. }
  995. Cleanup:
  996. if (pFile)
  997. pFile->Release();
  998. DC_END_FN();
  999. return status;
  1000. }
  1001. #endif
  1002. VOID
  1003. W32Drive::MsgIrpQueryVolumeInfo(
  1004. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  1005. IN UINT32 packetLen
  1006. )
  1007. /*++
  1008. Routine Description:
  1009. This routine handles drive volume level information query
  1010. Arguments:
  1011. pIoRequestPacket - Server IO request packet.
  1012. packetLen - Length of the packet
  1013. Return Value:
  1014. NA
  1015. --*/
  1016. {
  1017. ULONG ulRetCode = ERROR_SUCCESS;
  1018. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1019. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  1020. ULONG ulReplyPacketSize = 0;
  1021. DWORD result;
  1022. TCHAR DeviceName[MAX_PATH + 2];
  1023. #ifndef OS_WINCE
  1024. TCHAR NameBuffer[MAX_PATH];
  1025. WCHAR TempBuffer[MAX_PATH + 1];
  1026. #endif
  1027. ULONG BufferLength = 0;
  1028. #ifndef OS_WINCE
  1029. DECLSPEC_ALIGN(8) BYTE Buffer[RDP_FILE_VOLUME_INFO_MAXLENGTH + MAX_PATH];
  1030. #else
  1031. BYTE Buffer[RDP_FILE_VOLUME_INFO_MAXLENGTH + MAX_PATH];
  1032. #endif
  1033. HRESULT hr;
  1034. DC_BEGIN_FN("W32Drive::MsgIrpQueryVolumeInfo");
  1035. TRC_ASSERT((_tcslen(_devicePath) != 0), (TB, _T("Empty devicePath")));
  1036. //
  1037. // Get IO request pointer.
  1038. //
  1039. pIoRequest = &pIoRequestPacket->IoRequest;
  1040. //
  1041. // DriveName needs to end with \
  1042. //
  1043. #ifndef OS_WINCE
  1044. hr = StringCchPrintf(DeviceName, SIZE_TCHARS(DeviceName),
  1045. TEXT("%s\\"), _devicePath);
  1046. #else
  1047. hr = StringCchPrintf(DeviceName, SIZE_TCHARS(DeviceName),
  1048. TEXT("\\"));
  1049. #endif
  1050. TRC_ASSERT(SUCCEEDED(hr),
  1051. (TB,_T("Str printf failed for pre-checked len: 0x%x"),hr));
  1052. memset(Buffer, 0, sizeof(Buffer));
  1053. switch (pIoRequest->Parameters.QueryVolume.FsInformationClass) {
  1054. case RdpFsVolumeInformation:
  1055. {
  1056. RDP_FILE_FS_VOLUME_INFORMATION *pVolumeInfo =
  1057. (RDP_FILE_FS_VOLUME_INFORMATION *) Buffer;
  1058. #ifndef OS_WINCE
  1059. if (GetVolumeInformation(DeviceName,
  1060. NameBuffer,
  1061. MAX_PATH,
  1062. &pVolumeInfo->VolumeSerialNumber,
  1063. NULL,
  1064. NULL,
  1065. NULL,
  1066. 0
  1067. ))
  1068. {
  1069. pVolumeInfo->VolumeCreationTime.QuadPart = 0;
  1070. pVolumeInfo->SupportsObjects = FALSE;
  1071. pVolumeInfo->VolumeLabelLength = _tcslen(NameBuffer) * sizeof(WCHAR);
  1072. #ifdef UNICODE
  1073. memcpy(&pVolumeInfo->VolumeLabel[0], NameBuffer, pVolumeInfo->VolumeLabelLength);
  1074. #else
  1075. RDPConvertToUnicode(NameBuffer, (LPWSTR)TempBuffer, MAX_PATH);
  1076. memcpy(&pVolumeInfo->VolumeLabel[0], TempBuffer, pVolumeInfo->VolumeLabelLength);
  1077. #endif
  1078. ulRetCode = ERROR_SUCCESS;
  1079. BufferLength = FIELD_OFFSET(RDP_FILE_FS_VOLUME_INFORMATION, VolumeLabel) +
  1080. pVolumeInfo->VolumeLabelLength;
  1081. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1082. BufferLength - 1;
  1083. }
  1084. else {
  1085. ulRetCode = GetLastError();
  1086. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1087. TRC_ERR((TB, _T("Query volume information failed, %ld."), ulRetCode));
  1088. }
  1089. #else
  1090. pVolumeInfo->VolumeCreationTime.QuadPart = 0;
  1091. pVolumeInfo->SupportsObjects = FALSE;
  1092. pVolumeInfo->VolumeLabelLength = sizeof(WCHAR);
  1093. pVolumeInfo->VolumeLabel[0] = L'\0';
  1094. pVolumeInfo->VolumeSerialNumber = 0;
  1095. ulRetCode = ERROR_SUCCESS;
  1096. BufferLength = FIELD_OFFSET(RDP_FILE_FS_VOLUME_INFORMATION, VolumeLabel) +
  1097. pVolumeInfo->VolumeLabelLength;
  1098. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1099. BufferLength - 1;
  1100. #endif
  1101. break;
  1102. }
  1103. case RdpFsSizeInformation:
  1104. {
  1105. RDP_FILE_FS_SIZE_INFORMATION *pFsSizeInfo =
  1106. (RDP_FILE_FS_SIZE_INFORMATION *) Buffer;
  1107. #ifndef OS_WINCE
  1108. if (GetDiskFreeSpace(DeviceName,
  1109. &pFsSizeInfo->SectorsPerAllocationUnit,
  1110. &pFsSizeInfo->BytesPerSector,
  1111. &pFsSizeInfo->AvailableAllocationUnits.LowPart,
  1112. &pFsSizeInfo->TotalAllocationUnits.LowPart))
  1113. {
  1114. ulRetCode = ERROR_SUCCESS;
  1115. BufferLength = sizeof(RDP_FILE_FS_SIZE_INFORMATION);
  1116. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1117. BufferLength - 1;
  1118. }
  1119. else {
  1120. ulRetCode = GetLastError();
  1121. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1122. TRC_ERR((TB, _T("Query volume size failed, %ld."), ulRetCode));
  1123. }
  1124. #else
  1125. ULARGE_INTEGER FreeBytesAvailableToCaller;
  1126. if (GetDiskFreeSpaceEx(DeviceName, &FreeBytesAvailableToCaller,
  1127. (PULARGE_INTEGER)&pFsSizeInfo->AvailableAllocationUnits,
  1128. (PULARGE_INTEGER)&pFsSizeInfo->TotalAllocationUnits)) {
  1129. pFsSizeInfo->SectorsPerAllocationUnit = 1;
  1130. pFsSizeInfo->BytesPerSector = 1;
  1131. ulRetCode = ERROR_SUCCESS;
  1132. BufferLength = sizeof(RDP_FILE_FS_SIZE_INFORMATION);
  1133. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1134. BufferLength - 1;
  1135. }
  1136. else {
  1137. ulRetCode = GetLastError();
  1138. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1139. TRC_ERR((TB, _T("Query volume size failed, %ld."), ulRetCode));
  1140. }
  1141. #endif
  1142. break;
  1143. }
  1144. case RdpFsFullSizeInformation:
  1145. {
  1146. RDP_FILE_FS_FULL_SIZE_INFORMATION *pFsSizeInfo =
  1147. (RDP_FILE_FS_FULL_SIZE_INFORMATION *) Buffer;
  1148. #ifndef OS_WINCE
  1149. if (GetDiskFreeSpace(DeviceName,
  1150. &pFsSizeInfo->SectorsPerAllocationUnit,
  1151. &pFsSizeInfo->BytesPerSector,
  1152. &pFsSizeInfo->CallerAvailableAllocationUnits.LowPart,
  1153. &pFsSizeInfo->TotalAllocationUnits.LowPart))
  1154. {
  1155. //
  1156. // TODO what's the difference between actual and caller
  1157. // available allocation units?
  1158. //
  1159. pFsSizeInfo->ActualAvailableAllocationUnits.QuadPart =
  1160. pFsSizeInfo->CallerAvailableAllocationUnits.QuadPart;
  1161. ulRetCode = ERROR_SUCCESS;
  1162. BufferLength = sizeof(RDP_FILE_FS_FULL_SIZE_INFORMATION);
  1163. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1164. BufferLength - 1;
  1165. }
  1166. else {
  1167. ulRetCode = GetLastError();
  1168. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1169. TRC_ERR((TB, _T("Query volume full size failed, %ld."), ulRetCode));
  1170. }
  1171. #else
  1172. if (GetDiskFreeSpaceEx(DeviceName,
  1173. (PULARGE_INTEGER)&pFsSizeInfo->CallerAvailableAllocationUnits,
  1174. (PULARGE_INTEGER)&pFsSizeInfo->ActualAvailableAllocationUnits,
  1175. (PULARGE_INTEGER)&pFsSizeInfo->TotalAllocationUnits)) {
  1176. pFsSizeInfo->SectorsPerAllocationUnit = 1;
  1177. pFsSizeInfo->BytesPerSector = 1;
  1178. ulRetCode = ERROR_SUCCESS;
  1179. BufferLength = sizeof(RDP_FILE_FS_FULL_SIZE_INFORMATION);
  1180. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1181. BufferLength - 1;
  1182. }
  1183. else {
  1184. ulRetCode = GetLastError();
  1185. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1186. TRC_ERR((TB, _T("Query volume size failed, %ld."), ulRetCode));
  1187. }
  1188. #endif
  1189. break;
  1190. }
  1191. case RdpFsAttributeInformation:
  1192. {
  1193. RDP_FILE_FS_ATTRIBUTE_INFORMATION *pFsAttribInfo =
  1194. (RDP_FILE_FS_ATTRIBUTE_INFORMATION *) Buffer;
  1195. #ifndef OS_WINCE
  1196. if (GetVolumeInformation(DeviceName,
  1197. NULL,
  1198. NULL,
  1199. NULL,
  1200. (ULONG*)&pFsAttribInfo->MaximumComponentNameLength,
  1201. &pFsAttribInfo->FileSystemAttributes,
  1202. NameBuffer,
  1203. MAX_PATH
  1204. ))
  1205. {
  1206. pFsAttribInfo->FileSystemNameLength =
  1207. _tcslen(NameBuffer) * sizeof(WCHAR);
  1208. #ifdef UNICODE
  1209. memcpy(&pFsAttribInfo->FileSystemName[0], NameBuffer,
  1210. pFsAttribInfo->FileSystemNameLength);
  1211. #else
  1212. RDPConvertToUnicode(NameBuffer, (LPWSTR)TempBuffer, MAX_PATH);
  1213. memcpy(&pFsAttribInfo->FileSystemName[0], TempBuffer,
  1214. pFsAttribInfo->FileSystemNameLength);
  1215. #endif
  1216. ulRetCode = ERROR_SUCCESS;
  1217. BufferLength = FIELD_OFFSET(RDP_FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName) +
  1218. pFsAttribInfo->FileSystemNameLength;
  1219. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1220. BufferLength - 1;
  1221. }
  1222. else {
  1223. ulRetCode = GetLastError();
  1224. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1225. TRC_ERR((TB, _T("Query file system attributes failed, %ld."), ulRetCode));
  1226. }
  1227. #else
  1228. pFsAttribInfo->MaximumComponentNameLength = MAX_PATH;
  1229. pFsAttribInfo->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES |
  1230. FILE_UNICODE_ON_DISK;
  1231. wcscpy(&pFsAttribInfo->FileSystemName[0], L"FAT");
  1232. pFsAttribInfo->FileSystemNameLength =
  1233. _tcslen(pFsAttribInfo->FileSystemName) * sizeof(WCHAR);
  1234. ulRetCode = ERROR_SUCCESS;
  1235. BufferLength = FIELD_OFFSET(RDP_FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName) +
  1236. pFsAttribInfo->FileSystemNameLength;
  1237. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1238. BufferLength - 1;
  1239. #endif
  1240. break;
  1241. }
  1242. default:
  1243. TRC_ERR((TB, _T("Unsupported QueryVolume class %x"),
  1244. pIoRequest->Parameters.QueryVolume.FsInformationClass));
  1245. ulRetCode = ERROR_INVALID_FUNCTION;
  1246. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1247. break;
  1248. }
  1249. //
  1250. // Allocate reply buffer.
  1251. //
  1252. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket,
  1253. ulReplyPacketSize) ;
  1254. if (pReplyPacket) {
  1255. //
  1256. // Send the result to the server.
  1257. //
  1258. result = TranslateWinError(ulRetCode);
  1259. pReplyPacket->IoCompletion.IoStatus = result;
  1260. pReplyPacket->IoCompletion.Parameters.QueryVolume.Length = BufferLength;
  1261. if (BufferLength)
  1262. memcpy(pReplyPacket->IoCompletion.Parameters.QueryVolume.Buffer,
  1263. Buffer, BufferLength);
  1264. ProcessObject()->GetVCMgr().ChannelWrite(
  1265. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  1266. }
  1267. else {
  1268. TRC_ERR((TB, _T("Failed to alloc %ld bytes."),ulReplyPacketSize));
  1269. }
  1270. Cleanup:
  1271. //
  1272. // Clean up the request packet.
  1273. //
  1274. delete pIoRequestPacket;
  1275. DC_END_FN();
  1276. }
  1277. VOID
  1278. W32Drive::MsgIrpSetVolumeInfo(
  1279. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  1280. IN UINT32 packetLen
  1281. )
  1282. /*++
  1283. Routine Description:
  1284. This routine sets drive volume information.
  1285. Arguments:
  1286. pIoRequestPacket - Server IO request packet.
  1287. packetLen - Length of the packet
  1288. Return Value:
  1289. NA
  1290. --*/
  1291. {
  1292. ULONG ulRetCode = ERROR_SUCCESS;
  1293. DWORD result;
  1294. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1295. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  1296. ULONG ulReplyPacketSize = 0;
  1297. TCHAR DeviceName[MAX_PATH + 2];
  1298. PBYTE pDataBuffer;
  1299. HRESULT hr;
  1300. DC_BEGIN_FN("W32Drive::MsgIrpSetVolumeInfo");
  1301. TRC_ASSERT((_tcslen(_devicePath) != 0), (TB, _T("Empty devicePath")));
  1302. //
  1303. // Get IO request pointer.
  1304. //
  1305. pIoRequest = &pIoRequestPacket->IoRequest;
  1306. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1307. //
  1308. // DriveName needs to end with \
  1309. //
  1310. hr = StringCchPrintf(DeviceName, SIZE_TCHARS(DeviceName),
  1311. TEXT("%s\\"), _devicePath);
  1312. TRC_ASSERT(SUCCEEDED(hr),
  1313. (TB,_T("Str printf failed for pre-checked len: 0x%x"),hr));
  1314. pDataBuffer = (PBYTE)(pIoRequest + 1);
  1315. switch (pIoRequest->Parameters.SetVolume.FsInformationClass) {
  1316. case RdpFsLabelInformation:
  1317. {
  1318. PRDP_FILE_FS_LABEL_INFORMATION pLabelInfo =
  1319. (PRDP_FILE_FS_LABEL_INFORMATION) pDataBuffer;
  1320. // To conform with the redirector, we will not allow
  1321. // user to change the volume label info
  1322. ulRetCode = ERROR_ACCESS_DENIED;
  1323. break;
  1324. #if 0
  1325. NameBuffer[0] = TEXT('\0');
  1326. RDPConvertToAnsi(pLabelInfo->VolumeLabel, NameBuffer,
  1327. MAX_PATH);
  1328. if (SetVolumeLabel(DeviceName, NameBuffer)) {
  1329. ulRetCode = ERROR_SUCCESS;
  1330. } else {
  1331. ulRetCode = GetLastError();
  1332. TRC_ERR((TB, _T("Set Volume label failed, %ld."), ulRetCode));
  1333. }
  1334. #endif
  1335. }
  1336. break;
  1337. default:
  1338. TRC_ERR((TB, _T("Unsupported SetVolume class %x"),
  1339. pIoRequest->Parameters.SetVolume.FsInformationClass));
  1340. ulRetCode = ERROR_INVALID_FUNCTION;
  1341. break;
  1342. }
  1343. //
  1344. // Allocate reply buffer.
  1345. //
  1346. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket,
  1347. ulReplyPacketSize) ;
  1348. if (pReplyPacket) {
  1349. //
  1350. // Send the result to the server.
  1351. //
  1352. result = TranslateWinError(ulRetCode);
  1353. pReplyPacket->IoCompletion.IoStatus = result;
  1354. pReplyPacket->IoCompletion.Parameters.SetVolume.Length =
  1355. pIoRequest->Parameters.SetVolume.Length;
  1356. ProcessObject()->GetVCMgr().ChannelWrite(
  1357. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  1358. }
  1359. else {
  1360. TRC_ERR((TB, _T("Failed to alloc %ld bytes."),ulReplyPacketSize));
  1361. }
  1362. Cleanup:
  1363. //
  1364. // Clean up the request packet.
  1365. //
  1366. delete pIoRequestPacket;
  1367. DC_END_FN();
  1368. }
  1369. VOID
  1370. W32Drive::MsgIrpQueryFileInfo(
  1371. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  1372. IN UINT32 packetLen
  1373. )
  1374. /*++
  1375. Routine Description:
  1376. This routine handles query file information
  1377. Arguments:
  1378. pIoRequestPacket - Server IO request packet.
  1379. packetLen - Length of the packet
  1380. Return Value:
  1381. NA
  1382. --*/
  1383. {
  1384. ULONG ulRetCode = ERROR_SUCCESS;
  1385. DWORD result;
  1386. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1387. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  1388. ULONG ulReplyPacketSize = 0;
  1389. BOOL rc;
  1390. ULONG BufferLength = 0;
  1391. BYTE Buffer[RDP_FILE_INFORMATION_MAXLENGTH];
  1392. DrFile* pFile;
  1393. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  1394. BY_HANDLE_FILE_INFORMATION FileInformation;
  1395. DC_BEGIN_FN("W32Drive::MsgIrpQueryFileInfo");
  1396. TRC_ASSERT((_tcslen(_devicePath) != 0), (TB, _T("Empty device path")));
  1397. //
  1398. // Get IO request pointer.
  1399. //
  1400. pIoRequest = &pIoRequestPacket->IoRequest;
  1401. memset(Buffer, 0, sizeof(Buffer));
  1402. //
  1403. // Get file handle
  1404. //
  1405. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  1406. if (pFile)
  1407. FileHandle = pFile->GetFileHandle();
  1408. if (pFile) {
  1409. if (!((DrFSFile *)pFile)->IsDirectory()) {
  1410. TRC_ASSERT((FileHandle != INVALID_TS_FILEHANDLE),
  1411. (TB, _T("Invalid FileHandle")));
  1412. #ifndef OS_WINCE
  1413. rc = GetFileInformationByHandle(FileHandle, &FileInformation);
  1414. #else
  1415. rc = CEGetFileInformationByHandle(FileHandle, &FileInformation);
  1416. #endif
  1417. }
  1418. else {
  1419. //
  1420. // This is a directory, we can only get attributes info
  1421. //
  1422. memset(&FileInformation, 0, sizeof(FileInformation));
  1423. FileInformation.dwFileAttributes =
  1424. GetFileAttributes(((DrFSFile*)pFile)->GetFileName());
  1425. if (FileInformation.dwFileAttributes != -1) {
  1426. rc = TRUE;
  1427. }
  1428. else {
  1429. rc = FALSE;
  1430. }
  1431. }
  1432. switch (pIoRequest->Parameters.QueryFile.FileInformationClass) {
  1433. case RdpFileBasicInformation:
  1434. if (rc)
  1435. {
  1436. PRDP_FILE_BASIC_INFORMATION pFileInfo =
  1437. (PRDP_FILE_BASIC_INFORMATION) Buffer;
  1438. pFileInfo->CreationTime.LowPart = FileInformation.ftCreationTime.dwLowDateTime;
  1439. pFileInfo->CreationTime.HighPart = FileInformation.ftCreationTime.dwHighDateTime;
  1440. pFileInfo->LastAccessTime.LowPart = FileInformation.ftLastAccessTime.dwLowDateTime;
  1441. pFileInfo->LastAccessTime.HighPart = FileInformation.ftLastAccessTime.dwHighDateTime;
  1442. pFileInfo->LastWriteTime.LowPart = FileInformation.ftLastWriteTime.dwLowDateTime;
  1443. pFileInfo->LastWriteTime.HighPart = FileInformation.ftLastWriteTime.dwHighDateTime;
  1444. pFileInfo->ChangeTime.QuadPart = 0;
  1445. pFileInfo->FileAttributes = FileInformation.dwFileAttributes;
  1446. ulRetCode = ERROR_SUCCESS;
  1447. BufferLength = sizeof(RDP_FILE_BASIC_INFORMATION);
  1448. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1449. BufferLength - 1;
  1450. } else {
  1451. ulRetCode = GetLastError();
  1452. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1453. TRC_ERR((TB, _T("Query basic file information failed, %ld."), ulRetCode));
  1454. }
  1455. break;
  1456. case RdpFileStandardInformation:
  1457. if (rc)
  1458. {
  1459. PRDP_FILE_STANDARD_INFORMATION pFileInfo =
  1460. (PRDP_FILE_STANDARD_INFORMATION) Buffer;
  1461. // TODO: AllocationSize same as EndOfFile Size?
  1462. pFileInfo->AllocationSize.HighPart = FileInformation.nFileSizeHigh;
  1463. pFileInfo->AllocationSize.LowPart = FileInformation.nFileSizeLow;
  1464. pFileInfo->EndOfFile.HighPart = FileInformation.nFileSizeHigh;
  1465. pFileInfo->EndOfFile.LowPart = FileInformation.nFileSizeLow;
  1466. pFileInfo->NumberOfLinks = FileInformation.nNumberOfLinks;
  1467. pFileInfo->DeletePending = 0;
  1468. pFileInfo->Directory = !!(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
  1469. ulRetCode = ERROR_SUCCESS;
  1470. BufferLength = sizeof(RDP_FILE_STANDARD_INFORMATION);
  1471. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1472. BufferLength - 1;
  1473. } else {
  1474. ulRetCode = GetLastError();
  1475. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1476. TRC_ERR((TB, _T("Query standard file information failed, %ld."), ulRetCode));
  1477. }
  1478. break;
  1479. case RdpFileAttributeTagInformation:
  1480. if (rc)
  1481. {
  1482. PRDP_FILE_ATTRIBUTE_TAG_INFORMATION pFileInfo =
  1483. (PRDP_FILE_ATTRIBUTE_TAG_INFORMATION) Buffer;
  1484. // TODO: What's ReparseTag?
  1485. pFileInfo->FileAttributes = FileInformation.dwFileAttributes;
  1486. pFileInfo->ReparseTag = 0;
  1487. ulRetCode = ERROR_SUCCESS;
  1488. BufferLength = sizeof(RDP_FILE_ATTRIBUTE_TAG_INFORMATION);
  1489. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1490. BufferLength - 1;
  1491. } else {
  1492. ulRetCode = GetLastError();
  1493. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1494. TRC_ERR((TB, _T("Query attribute tag file information failed, %ld."), ulRetCode));
  1495. }
  1496. break;
  1497. case RdpFileInternalInformation:
  1498. if (rc)
  1499. {
  1500. PRDP_FILE_INTERNAL_INFORMATION pFileInfo =
  1501. (PRDP_FILE_INTERNAL_INFORMATION) Buffer;
  1502. // TODO: should we use this index number?
  1503. pFileInfo->IndexNumber.HighPart = FileInformation.nFileIndexHigh;
  1504. pFileInfo->IndexNumber.LowPart = FileInformation.nFileIndexLow;
  1505. ulRetCode = ERROR_SUCCESS;
  1506. BufferLength = sizeof(RDP_FILE_INTERNAL_INFORMATION);
  1507. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  1508. BufferLength - 1;
  1509. } else {
  1510. ulRetCode = GetLastError();
  1511. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1512. TRC_ERR((TB, _T("CreateFile failed, %ld."), ulRetCode));
  1513. }
  1514. break;
  1515. default:
  1516. TRC_ERR((TB, _T("Unsupported QueryFile class %x"),
  1517. pIoRequest->Parameters.QueryFile.FileInformationClass));
  1518. ulRetCode = ERROR_INVALID_FUNCTION;
  1519. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1520. break;
  1521. }
  1522. }
  1523. else {
  1524. ulRetCode = ERROR_FILE_NOT_FOUND;
  1525. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1526. }
  1527. //
  1528. // Allocate reply buffer.
  1529. //
  1530. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket,
  1531. ulReplyPacketSize) ;
  1532. if (pReplyPacket) {
  1533. //
  1534. // Send the result to the server.
  1535. //
  1536. result = TranslateWinError(ulRetCode);
  1537. pReplyPacket->IoCompletion.IoStatus = result;
  1538. pReplyPacket->IoCompletion.Parameters.QueryFile.Length = BufferLength;
  1539. if (BufferLength)
  1540. memcpy(pReplyPacket->IoCompletion.Parameters.QueryFile.Buffer,
  1541. Buffer, BufferLength);
  1542. ProcessObject()->GetVCMgr().ChannelWrite(
  1543. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  1544. }
  1545. else {
  1546. TRC_ERR((TB, _T("Failed to alloc %ld bytes."),ulReplyPacketSize));
  1547. }
  1548. Cleanup:
  1549. //
  1550. // Clean up the request packet.
  1551. //
  1552. delete pIoRequestPacket;
  1553. DC_END_FN();
  1554. }
  1555. VOID
  1556. W32Drive::MsgIrpSetFileInfo(
  1557. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  1558. IN UINT32 packetLen
  1559. )
  1560. /*++
  1561. Routine Description:
  1562. This routine handles set file information
  1563. Arguments:
  1564. pIoRequestPacket - Server IO request packet.
  1565. packetLen - Length of the packet
  1566. Return Value:
  1567. NA
  1568. --*/
  1569. {
  1570. ULONG ulRetCode = ERROR_SUCCESS;
  1571. DWORD result;
  1572. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1573. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  1574. ULONG ulReplyPacketSize = 0;
  1575. PBYTE pDataBuffer;
  1576. DrFSFile* pFile;
  1577. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  1578. HRESULT hr;
  1579. DC_BEGIN_FN("W32Drive::MsgIrpSetFileInfo");
  1580. TRC_ASSERT((_tcslen(_devicePath) != 0), (TB, _T("Empty devicePath")));
  1581. //
  1582. // Get IO request pointer.
  1583. //
  1584. pIoRequest = &pIoRequestPacket->IoRequest;
  1585. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1586. //
  1587. // Make sure packetLen is right
  1588. //
  1589. if (packetLen < sizeof(RDPDR_IOREQUEST_PACKET) + pIoRequest->Parameters.SetFile.Length) {
  1590. // VirtualChannelClose
  1591. ProcessObject()->GetVCMgr().ChannelClose();
  1592. TRC_ASSERT(FALSE, (TB, _T("Packet Length Error")));
  1593. goto Cleanup;
  1594. }
  1595. //
  1596. // Get file handle
  1597. //
  1598. pFile = (DrFSFile *)_FileMgr->GetObject(pIoRequest->FileId);
  1599. if (pFile)
  1600. FileHandle = pFile->GetFileHandle();
  1601. pDataBuffer = (PBYTE)(pIoRequest + 1);
  1602. if (pFile) {
  1603. switch (pIoRequest->Parameters.SetFile.FileInformationClass) {
  1604. case RdpFileBasicInformation:
  1605. {
  1606. PRDP_FILE_BASIC_INFORMATION pFileInfo =
  1607. (PRDP_FILE_BASIC_INFORMATION) pDataBuffer;
  1608. FILETIME CreationTime, LastAccessTime, LastWriteTime;
  1609. FILETIME *pCreationTime, *pLastAccessTime, *pLastWriteTime;
  1610. //
  1611. // Set the file attributes if the attributes field is nonzero
  1612. //
  1613. if (pFileInfo->FileAttributes != 0) {
  1614. TRC_ASSERT((pFile->GetFileName() != NULL), (TB, _T("Empty FileName")));
  1615. if (SetFileAttributes(pFile->GetFileName(),
  1616. pFileInfo->FileAttributes)) {
  1617. ulRetCode = ERROR_SUCCESS;
  1618. } else {
  1619. ulRetCode = GetLastError();
  1620. TRC_ERR((TB, _T("SetFileAttributes failed, %ld."), ulRetCode));
  1621. }
  1622. break;
  1623. }
  1624. //
  1625. // Set the file time
  1626. //
  1627. if (pFileInfo->CreationTime.QuadPart != 0) {
  1628. CreationTime.dwLowDateTime = pFileInfo->CreationTime.LowPart;
  1629. CreationTime.dwHighDateTime = pFileInfo->CreationTime.HighPart;
  1630. pCreationTime = &CreationTime;
  1631. }
  1632. else{
  1633. pCreationTime = NULL;
  1634. }
  1635. if (pFileInfo->LastAccessTime.QuadPart != 0) {
  1636. LastAccessTime.dwLowDateTime = pFileInfo->LastAccessTime.LowPart;
  1637. LastAccessTime.dwHighDateTime = pFileInfo->LastAccessTime.HighPart;
  1638. pLastAccessTime = &LastAccessTime;
  1639. }
  1640. else {
  1641. pLastAccessTime = NULL;
  1642. }
  1643. if (pFileInfo->LastWriteTime.QuadPart != 0) {
  1644. LastWriteTime.dwLowDateTime = pFileInfo->LastWriteTime.LowPart;
  1645. LastWriteTime.dwHighDateTime = pFileInfo->LastWriteTime.HighPart;
  1646. pLastWriteTime = &LastWriteTime;
  1647. }
  1648. else {
  1649. pLastWriteTime = NULL;
  1650. }
  1651. if (FileHandle != INVALID_HANDLE_VALUE) {
  1652. #ifndef OS_WINCE
  1653. if (SetFileTime(FileHandle, pCreationTime, pLastAccessTime, pLastWriteTime)) {
  1654. #else
  1655. if (CESetFileTime(FileHandle, pCreationTime, pLastAccessTime, pLastWriteTime)) {
  1656. #endif
  1657. ulRetCode = ERROR_SUCCESS;
  1658. } else {
  1659. ulRetCode = GetLastError();
  1660. TRC_ERR((TB, _T("SetFileTime failed, %ld."), ulRetCode));
  1661. }
  1662. }
  1663. else {
  1664. ulRetCode = ERROR_SUCCESS;
  1665. TRC_NRM((TB, _T("Can't set filetime for directory")));
  1666. }
  1667. }
  1668. break;
  1669. case RdpFileEndOfFileInformation:
  1670. {
  1671. PRDP_FILE_END_OF_FILE_INFORMATION pFileInfo =
  1672. (PRDP_FILE_END_OF_FILE_INFORMATION) pDataBuffer;
  1673. LONG OffsetLow;
  1674. LONG OffsetHigh;
  1675. if (FileHandle != INVALID_HANDLE_VALUE) {
  1676. OffsetLow = pFileInfo->EndOfFile.LowPart;
  1677. OffsetHigh = pFileInfo->EndOfFile.HighPart;
  1678. #ifndef OS_WINCE
  1679. if (SetFilePointer(FileHandle,
  1680. #else
  1681. if (CESetFilePointer(FileHandle,
  1682. #endif
  1683. OffsetLow,
  1684. &OffsetHigh,
  1685. FILE_BEGIN) != INVALID_SET_FILE_POINTER) {
  1686. ulRetCode = NO_ERROR;
  1687. }
  1688. else {
  1689. ulRetCode = GetLastError();
  1690. if (ulRetCode != NO_ERROR) {
  1691. ulRetCode = GetLastError();
  1692. TRC_ERR((TB, _T("SetFilePointer failed, %ld."), ulRetCode));
  1693. }
  1694. }
  1695. if (ulRetCode == NO_ERROR) {
  1696. #ifndef OS_WINCE
  1697. if (SetEndOfFile(FileHandle)) {
  1698. #else
  1699. if (CESetEndOfFile(FileHandle)) {
  1700. #endif
  1701. ulRetCode = ERROR_SUCCESS;
  1702. } else {
  1703. ulRetCode = GetLastError();
  1704. TRC_ERR((TB, _T("SetEndOfFile failed, %ld."), ulRetCode));
  1705. }
  1706. }
  1707. }
  1708. else {
  1709. ulRetCode = ERROR_FILE_NOT_FOUND;
  1710. TRC_ERR((TB, _T("SetEndOfFile failed, %ld."), ulRetCode));
  1711. }
  1712. }
  1713. break;
  1714. case RdpFileDispositionInformation:
  1715. {
  1716. if (pFile->GetFileName()) {
  1717. if (!pFile->IsDirectory()) {
  1718. pFile->Close();
  1719. if (DeleteFile(pFile->GetFileName())) {
  1720. ulRetCode = ERROR_SUCCESS;
  1721. }
  1722. else {
  1723. ulRetCode = GetLastError();
  1724. TRC_ERR((TB, _T("DeleteFile failed, %ld."), ulRetCode));
  1725. }
  1726. }
  1727. else {
  1728. if (RemoveDirectory(pFile->GetFileName())) {
  1729. ulRetCode = ERROR_SUCCESS;
  1730. } else {
  1731. ulRetCode = GetLastError();
  1732. TRC_ERR((TB, _T("RemoveDirectory failed, %ld."), ulRetCode));
  1733. }
  1734. }
  1735. }
  1736. else {
  1737. ulRetCode = ERROR_FILE_NOT_FOUND;
  1738. TRC_ERR((TB, _T("DeleteFile/RemoveDirectory failed, %ld."), ulRetCode));
  1739. }
  1740. }
  1741. break;
  1742. case RdpFileRenameInformation:
  1743. {
  1744. PRDP_FILE_RENAME_INFORMATION pFileInfo =
  1745. (PRDP_FILE_RENAME_INFORMATION) pDataBuffer;
  1746. TCHAR NewFileName[MAX_PATH];
  1747. if (pFile->GetFileName()) {
  1748. pFile->Close();
  1749. if (pFileInfo->RootDirectory == 0) {
  1750. //
  1751. // Copy the devicePath, the filename path
  1752. // below is relative to our device path
  1753. //
  1754. #ifndef OS_WINCE
  1755. hr = StringCchCopy(NewFileName, SIZE_TCHARS(NewFileName),
  1756. _devicePath);
  1757. TRC_ASSERT(SUCCEEDED(hr),
  1758. (TB,_T("Str copy failed for pre-checked len: 0x%x"),hr));
  1759. #else
  1760. NewFileName[0] = TEXT('\0');
  1761. #endif
  1762. }
  1763. else {
  1764. // The File name passed to us has already contained
  1765. // the root directory path
  1766. NewFileName[0] = TEXT('\0');
  1767. }
  1768. #ifdef UNICODE
  1769. UINT cchLenRemain = SIZE_TCHARS(NewFileName) - (_tcslen(NewFileName) + 1);
  1770. hr = StringCchCopy(NewFileName + _tcslen(NewFileName),
  1771. cchLenRemain,
  1772. pFileInfo->FileName);
  1773. if (FAILED(hr)) {
  1774. TRC_ERR((TB,_T("Fail to copy filename info: 0x%x"),hr));
  1775. ulRetCode = ERROR_INSUFFICIENT_BUFFER;
  1776. goto SendPacket;
  1777. }
  1778. #else
  1779. RDPConvertToAnsi(pFileInfo->FileName, NewFileName + _tcslen(NewFileName),
  1780. MAX_PATH - _tcslen(NewFileName));
  1781. #endif
  1782. if (pFileInfo->ReplaceIfExists) {
  1783. DeleteFile(NewFileName);
  1784. }
  1785. if (MoveFile(pFile->GetFileName(), NewFileName)) {
  1786. ulRetCode = ERROR_SUCCESS;
  1787. }
  1788. else {
  1789. ulRetCode = GetLastError();
  1790. TRC_ERR((TB, _T("MoveFile failed, %ld."), ulRetCode));
  1791. }
  1792. }
  1793. else {
  1794. ulRetCode = ERROR_FILE_NOT_FOUND;
  1795. TRC_ERR((TB, _T("MoveFile failed, %ld."), ulRetCode));
  1796. }
  1797. }
  1798. break;
  1799. case RdpFileAllocationInformation:
  1800. {
  1801. PRDP_FILE_ALLOCATION_INFORMATION pFileAllocationInfo =
  1802. (PRDP_FILE_ALLOCATION_INFORMATION) pDataBuffer;
  1803. ulRetCode = ERROR_SUCCESS;
  1804. TRC_NRM((TB, _T("Get RdpFileAllocationInformation")));
  1805. // If server side call CreateFile with TRUNCATE_EXISTING flag
  1806. // server will send FileAllocationInformation with
  1807. // AllocationSize.QuadPart is 0, we need to truncate the file
  1808. // Currently we don't support other QuadPart value
  1809. if (0 == pFileAllocationInfo->AllocationSize.QuadPart) {
  1810. if (FileHandle != INVALID_HANDLE_VALUE) {
  1811. if (INVALID_SET_FILE_POINTER != SetFilePointer(FileHandle, 0, 0, FILE_BEGIN))
  1812. {
  1813. if (!SetEndOfFile(FileHandle)) {
  1814. TRC_ERR((TB, _T("SetEndOfFile failed with %x"), GetLastError()));
  1815. ulRetCode = GetLastError();
  1816. }
  1817. }
  1818. else
  1819. {
  1820. TRC_ERR((TB, _T("SetFilePointer failed with %x"), GetLastError()));
  1821. ulRetCode = GetLastError();
  1822. }
  1823. }
  1824. else {
  1825. TRC_ERR((TB, _T("File handle invalid in setting FileAllocationInfo")));
  1826. ulRetCode = ERROR_FILE_NOT_FOUND;
  1827. }
  1828. }
  1829. else {
  1830. TRC_ASSERT(FALSE, (TB, _T("Get FileAllocationInformation with unsupported %d"),
  1831. pFileAllocationInfo->AllocationSize.QuadPart));
  1832. // Still return success here to avoid regression
  1833. }
  1834. }
  1835. break;
  1836. default:
  1837. TRC_ERR((TB, _T("Unsupported SetFile class %x"),
  1838. pIoRequest->Parameters.SetFile.FileInformationClass));
  1839. ulRetCode = ERROR_INVALID_FUNCTION;
  1840. break;
  1841. }
  1842. }
  1843. else {
  1844. ulRetCode = ERROR_FILE_NOT_FOUND;
  1845. }
  1846. SendPacket:
  1847. //
  1848. // Allocate reply buffer.
  1849. //
  1850. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket,
  1851. ulReplyPacketSize) ;
  1852. if (pReplyPacket) {
  1853. //
  1854. // Send the result to the server.
  1855. //
  1856. result = TranslateWinError(ulRetCode);
  1857. pReplyPacket->IoCompletion.IoStatus = result;
  1858. pReplyPacket->IoCompletion.Parameters.SetFile.Length =
  1859. pIoRequest->Parameters.SetFile.Length;
  1860. ProcessObject()->GetVCMgr().ChannelWrite(
  1861. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  1862. }
  1863. else {
  1864. TRC_ERR((TB, _T("Failed to alloc %ld bytes."),ulReplyPacketSize));
  1865. }
  1866. Cleanup:
  1867. //
  1868. // Clean up the request packet.
  1869. //
  1870. delete pIoRequestPacket;
  1871. DC_END_FN();
  1872. }
  1873. VOID
  1874. W32Drive::MsgIrpDeviceControl(
  1875. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  1876. IN UINT32 packetLen
  1877. )
  1878. /*++
  1879. Routine Description:
  1880. Handle a file system control request from the server.
  1881. Arguments:
  1882. pIoRequestPacket - Server IO request packet.
  1883. packetLen - Length of the packet
  1884. Return Value:
  1885. NA
  1886. --*/
  1887. {
  1888. DC_BEGIN_FN("W32Drive::MsgIrpDeviceControl");
  1889. DispatchIOCTLDirectlyToDriver(pIoRequestPacket);
  1890. DC_END_FN();
  1891. }
  1892. VOID
  1893. W32Drive::MsgIrpLockControl(
  1894. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  1895. IN UINT32 packetLen
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. Handle a file system lock control request from the server.
  1900. Arguments:
  1901. pIoRequestPacket - Server IO request packet.
  1902. packetLen - Length of the packet
  1903. Return Value:
  1904. NA
  1905. --*/
  1906. {
  1907. ULONG ulRetCode = ERROR_SUCCESS;
  1908. DWORD result;
  1909. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  1910. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  1911. ULONG ulReplyPacketSize = 0;
  1912. DrFSFile* pFile;
  1913. HANDLE FileHandle;
  1914. PRDP_LOCK_INFO LockInfo;
  1915. DC_BEGIN_FN("W32Drive::MsgIrpLockControl");
  1916. //
  1917. // Get IO request pointer.
  1918. //
  1919. pIoRequest = &pIoRequestPacket->IoRequest;
  1920. //
  1921. // Make sure the packetlength is right
  1922. //
  1923. if (packetLen < sizeof(RDPDR_IOREQUEST_PACKET) + sizeof(RDP_LOCK_INFO) * pIoRequest->Parameters.Locks.NumLocks) {
  1924. // Call VirtualChannelClose
  1925. ProcessObject()->GetVCMgr().ChannelClose();
  1926. TRC_ASSERT(FALSE, (TB, _T("Packet Length Error")));
  1927. goto Cleanup;
  1928. }
  1929. //
  1930. // Get file lock info
  1931. //
  1932. LockInfo = (PRDP_LOCK_INFO) (pIoRequest + 1);
  1933. //
  1934. // Get file handle
  1935. //
  1936. pFile = (DrFSFile *)_FileMgr->GetObject(pIoRequest->FileId);
  1937. if (pFile)
  1938. FileHandle = pFile->GetFileHandle();
  1939. else
  1940. FileHandle = INVALID_HANDLE_VALUE;
  1941. TRC_ASSERT((FileHandle != INVALID_HANDLE_VALUE), (TB, _T("Invalid FileHandle")));
  1942. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  1943. if (FileHandle != INVALID_HANDLE_VALUE) {
  1944. switch (pIoRequest->Parameters.Locks.Operation) {
  1945. //
  1946. // Share lock request
  1947. //
  1948. case RDP_LOWIO_OP_SHAREDLOCK:
  1949. {
  1950. OVERLAPPED Overlapped;
  1951. Overlapped.hEvent = 0;
  1952. Overlapped.Internal = 0;
  1953. Overlapped.InternalHigh = 0;
  1954. Overlapped.Offset = LockInfo->OffsetLow;
  1955. Overlapped.OffsetHigh = LockInfo->OffsetHigh;
  1956. #ifndef OS_WINCE
  1957. if (!LockFileEx(FileHandle,
  1958. #else
  1959. if (!CELockFileEx(FileHandle,
  1960. #endif
  1961. (pIoRequest->Parameters.Locks.Flags & SL_FAIL_IMMEDIATELY) ?
  1962. LOCKFILE_FAIL_IMMEDIATELY : 0,
  1963. 0,
  1964. LockInfo->LengthLow,
  1965. LockInfo->LengthHigh,
  1966. &Overlapped)) {
  1967. ulRetCode = GetLastError();
  1968. TRC_ERR((TB, _T("Lock File failed, %ld."), ulRetCode));
  1969. }
  1970. break;
  1971. }
  1972. //
  1973. // Exclusive lock request
  1974. //
  1975. case RDP_LOWIO_OP_EXCLUSIVELOCK:
  1976. #ifndef OS_WINCE
  1977. if (!LockFile(FileHandle,
  1978. #else
  1979. if (!CELockFile(FileHandle,
  1980. #endif
  1981. LockInfo->OffsetLow,
  1982. LockInfo->OffsetHigh,
  1983. LockInfo->LengthLow,
  1984. LockInfo->LengthHigh)) {
  1985. ulRetCode = GetLastError();
  1986. TRC_ERR((TB, _T("Lock File failed, %ld."), ulRetCode));
  1987. }
  1988. break;
  1989. //
  1990. // Unlock request
  1991. //
  1992. case RDP_LOWIO_OP_UNLOCK:
  1993. {
  1994. for (unsigned i = 0; i < pIoRequest->Parameters.Locks.NumLocks; i++) {
  1995. #ifndef OS_WINCE
  1996. if (!UnlockFile(FileHandle,
  1997. #else
  1998. if (!CEUnlockFile(FileHandle,
  1999. #endif
  2000. LockInfo->OffsetLow,
  2001. LockInfo->OffsetHigh,
  2002. LockInfo->LengthLow,
  2003. LockInfo->LengthHigh)) {
  2004. ulRetCode = GetLastError();
  2005. TRC_ERR((TB, _T("Unlock File failed, %ld."), ulRetCode));
  2006. break;
  2007. }
  2008. LockInfo++;
  2009. }
  2010. break;
  2011. }
  2012. default:
  2013. ulRetCode = ERROR_INVALID_FUNCTION;
  2014. TRC_ERR((TB, _T("Invalid lock operation %x"), pIoRequest->Parameters.Locks.Operation));
  2015. }
  2016. }
  2017. else {
  2018. ulRetCode = ERROR_FILE_NOT_FOUND;
  2019. TRC_ERR((TB, _T("Lock File failed, %ld."), ulRetCode));
  2020. }
  2021. //
  2022. // Allocate reply buffer.
  2023. //
  2024. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket,
  2025. ulReplyPacketSize) ;
  2026. if (pReplyPacket) {
  2027. //
  2028. // Send the result to the server.
  2029. //
  2030. result = TranslateWinError(ulRetCode);
  2031. pReplyPacket->IoCompletion.IoStatus = result;
  2032. ProcessObject()->GetVCMgr().ChannelWrite(
  2033. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  2034. }
  2035. else {
  2036. TRC_ERR((TB, _T("Failed to alloc %ld bytes."),ulReplyPacketSize));
  2037. }
  2038. Cleanup:
  2039. //
  2040. // Clean up the request packet.
  2041. //
  2042. delete pIoRequestPacket;
  2043. DC_END_FN();
  2044. }
  2045. #ifndef OS_WINCE
  2046. BOOL SetPrivilege(
  2047. HANDLE hToken, // token handle
  2048. LPCTSTR Privilege, // Privilege to enable/disable
  2049. BOOL fEnablePrivilege // TRUE to enable. FALSE to disable
  2050. )
  2051. {
  2052. BOOL rc = TRUE;
  2053. TOKEN_PRIVILEGES tp;
  2054. LUID luid;
  2055. TOKEN_PRIVILEGES tpPrevious;
  2056. DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
  2057. HMODULE hModule = NULL;
  2058. typedef BOOL (FNLOOKUP_PRIVILEGE_VALUE)(LPCTSTR, LPCTSTR, PLUID);
  2059. FNLOOKUP_PRIVILEGE_VALUE *pfnLookupPrivilegeValue;
  2060. typedef BOOL (FNADJUST_TOKEN_PRIVILEGES)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
  2061. DWORD, PTOKEN_PRIVILEGES, PDWORD);
  2062. FNADJUST_TOKEN_PRIVILEGES *pfnAdjustTokenPrivileges;
  2063. // get the handle to advapi32.dll library
  2064. hModule = LoadLibrary(TEXT("ADVAPI32.DLL"));
  2065. if (hModule != NULL) {
  2066. // get the proc address for LookupPrivilegeValue
  2067. #ifdef UNICODE
  2068. pfnLookupPrivilegeValue = (FNLOOKUP_PRIVILEGE_VALUE *)GetProcAddress(hModule, "LookupPrivilegeValueW");
  2069. #else
  2070. pfnLookupPrivilegeValue = (FNLOOKUP_PRIVILEGE_VALUE *)GetProcAddress(hModule, "LookupPrivilegeValueA");
  2071. #endif
  2072. if (pfnLookupPrivilegeValue) {
  2073. if (!pfnLookupPrivilegeValue(NULL, Privilege, &luid)) {
  2074. rc = FALSE;
  2075. goto EXIT;
  2076. }
  2077. }
  2078. else {
  2079. // Let it return true.
  2080. goto EXIT;
  2081. }
  2082. pfnAdjustTokenPrivileges = (FNADJUST_TOKEN_PRIVILEGES *)GetProcAddress(hModule, "AdjustTokenPrivileges");
  2083. if (pfnAdjustTokenPrivileges) {
  2084. //
  2085. // first pass. get current privilege setting
  2086. //
  2087. tp.PrivilegeCount = 1;
  2088. tp.Privileges[0].Luid = luid;
  2089. tp.Privileges[0].Attributes = 0;
  2090. pfnAdjustTokenPrivileges(
  2091. hToken,
  2092. FALSE,
  2093. &tp,
  2094. sizeof(TOKEN_PRIVILEGES),
  2095. &tpPrevious,
  2096. &cbPrevious);
  2097. if (GetLastError() != ERROR_SUCCESS) {
  2098. rc = FALSE;
  2099. goto EXIT;
  2100. }
  2101. //
  2102. // second pass. set privilege based on previous setting
  2103. //
  2104. tpPrevious.PrivilegeCount = 1;
  2105. tpPrevious.Privileges[0].Luid = luid;
  2106. if (fEnablePrivilege)
  2107. {
  2108. tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
  2109. }
  2110. else
  2111. {
  2112. tpPrevious.Privileges[0].Attributes ^=
  2113. (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes);
  2114. }
  2115. pfnAdjustTokenPrivileges(
  2116. hToken,
  2117. FALSE,
  2118. &tpPrevious,
  2119. cbPrevious,
  2120. NULL,
  2121. NULL);
  2122. if (GetLastError() != ERROR_SUCCESS) {
  2123. rc = FALSE;
  2124. goto EXIT;
  2125. }
  2126. }
  2127. }
  2128. EXIT:
  2129. if (hModule) {
  2130. FreeLibrary(hModule);
  2131. }
  2132. return rc;
  2133. }
  2134. #endif
  2135. VOID
  2136. W32Drive::MsgIrpQuerySdInfo(
  2137. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  2138. IN UINT32 packetLen
  2139. )
  2140. /*++
  2141. Routine Description:
  2142. Handle a file system control request from the server.
  2143. Arguments:
  2144. pIoRequestPacket - Server IO request packet.
  2145. packetLen - Length of the packet
  2146. Return Value:
  2147. NA
  2148. --*/
  2149. {
  2150. ULONG ulRetCode = ERROR_SUCCESS;
  2151. DWORD result;
  2152. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  2153. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  2154. ULONG ulReplyPacketSize = 0;
  2155. DrFSFile* pFile;
  2156. HANDLE FileHandle;
  2157. BYTE* pSecurityDescriptor = NULL;
  2158. ULONG LengthNeeded = 0;
  2159. ULONG BufferLength = 0;
  2160. HANDLE hProcessToken = NULL;
  2161. HMODULE hModule = NULL;
  2162. DC_BEGIN_FN("W32Drive::MsgIrpQuerySd");
  2163. //
  2164. // Get IO request pointer.
  2165. //
  2166. pIoRequest = &pIoRequestPacket->IoRequest;
  2167. //
  2168. // Get file handle
  2169. //
  2170. pFile = (DrFSFile *)_FileMgr->GetObject(pIoRequest->FileId);
  2171. if (pFile)
  2172. FileHandle = pFile->GetFileHandle();
  2173. else
  2174. FileHandle = INVALID_HANDLE_VALUE;
  2175. if (pFile) {
  2176. #ifndef OS_WINCE
  2177. if (pIoRequest->Parameters.QuerySd.SecurityInformation & SACL_SECURITY_INFORMATION) {
  2178. typedef BOOL (FNOPEN_PROCESS_TOKEN)(HANDLE, DWORD, PHANDLE);
  2179. FNOPEN_PROCESS_TOKEN *pfnOpenProcessToken;
  2180. // get the handle to advapi32.dll library
  2181. hModule = LoadLibrary(TEXT("ADVAPI32.DLL"));
  2182. if (hModule != NULL) {
  2183. // get the proc address for OpenProcessToken
  2184. pfnOpenProcessToken = (FNOPEN_PROCESS_TOKEN *)GetProcAddress(hModule, "OpenProcessToken");
  2185. if (pfnOpenProcessToken) {
  2186. //
  2187. // Get the process token for this process. We'll
  2188. // need it in just a second ....
  2189. //
  2190. if (!pfnOpenProcessToken(GetCurrentProcess(),
  2191. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  2192. &hProcessToken))
  2193. {
  2194. ulRetCode = GetLastError();
  2195. TRC_ERR((TB, _T("OpenProcessToken failed, error %d."), ulRetCode));
  2196. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2197. goto SendPacket;
  2198. }
  2199. //
  2200. // Turn on SeSecurityPrivilege (by name that's SE_SECURITY_NAME). This allows
  2201. // us to read SACLs
  2202. //
  2203. if (!SetPrivilege(hProcessToken,
  2204. SE_SECURITY_NAME,
  2205. TRUE))
  2206. {
  2207. ulRetCode = GetLastError();
  2208. TRC_ERR((TB, _T("SetPrivilege failed. %d."), ulRetCode));
  2209. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2210. goto SendPacket;
  2211. }
  2212. }
  2213. }
  2214. }
  2215. GetFileSecurity(pFile->GetFileName(),
  2216. pIoRequest->Parameters.QuerySd.SecurityInformation,
  2217. NULL,
  2218. 0,
  2219. &LengthNeeded);
  2220. if (LengthNeeded > 0) {
  2221. pSecurityDescriptor = new BYTE[LengthNeeded];
  2222. if (pSecurityDescriptor != NULL) {
  2223. if (GetFileSecurity(pFile->GetFileName(),
  2224. pIoRequest->Parameters.QuerySd.SecurityInformation,
  2225. pSecurityDescriptor,
  2226. LengthNeeded,
  2227. &LengthNeeded)) {
  2228. BufferLength = GetSecurityDescriptorLength(
  2229. (PSECURITY_DESCRIPTOR)pSecurityDescriptor);
  2230. ulRetCode = ERROR_SUCCESS;
  2231. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) +
  2232. BufferLength - 1;
  2233. }
  2234. else {
  2235. ulRetCode = GetLastError();
  2236. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2237. TRC_ERR((TB, _T("GetFileSecurity failed, %ld."), ulRetCode));
  2238. }
  2239. }
  2240. else {
  2241. ulRetCode = GetLastError();
  2242. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2243. TRC_ERR((TB, _T("Failed to allocate memory for security descriptor")));
  2244. }
  2245. }
  2246. else {
  2247. ulRetCode = GetLastError();
  2248. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2249. TRC_ERR((TB, _T("GetFileSecurity failed, %ld."), ulRetCode));
  2250. }
  2251. #else
  2252. BYTE bSecDescr[sizeof(SECURITY_DESCRIPTOR) + (2*sizeof(SID))];
  2253. BufferLength = sizeof(bSecDescr);
  2254. pSecurityDescriptor = bSecDescr;
  2255. SECURITY_DESCRIPTOR sd;
  2256. if (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) &&
  2257. SetSecurityDescriptorGroup(&sd, NULL, FALSE) &&
  2258. SetSecurityDescriptorOwner(&sd, NULL, FALSE) &&
  2259. SetSecurityDescriptorDacl(&sd, (pIoRequest->Parameters.QuerySd.SecurityInformation & DACL_SECURITY_INFORMATION), NULL, FALSE) &&
  2260. SetSecurityDescriptorSacl(&sd, (pIoRequest->Parameters.QuerySd.SecurityInformation & SACL_SECURITY_INFORMATION), NULL, FALSE) &&
  2261. MakeSelfRelativeSD(&sd, pSecurityDescriptor, &BufferLength)) {
  2262. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) + BufferLength - 1;
  2263. ulRetCode = ERROR_SUCCESS;
  2264. }
  2265. else {
  2266. ulRetCode = ERROR_INVALID_PARAMETER;
  2267. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2268. TRC_ERR((TB, _T("Failed to construct a security descriptor, %ld."), ulRetCode));
  2269. }
  2270. #endif
  2271. }
  2272. else {
  2273. ulRetCode = ERROR_FILE_NOT_FOUND;
  2274. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2275. }
  2276. SendPacket:
  2277. //
  2278. // Allocate reply buffer.
  2279. //
  2280. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket,
  2281. ulReplyPacketSize) ;
  2282. if (pReplyPacket) {
  2283. //
  2284. // Send the result to the server.
  2285. //
  2286. result = TranslateWinError(ulRetCode);
  2287. pReplyPacket->IoCompletion.IoStatus = result;
  2288. pReplyPacket->IoCompletion.Parameters.QuerySd.Length = BufferLength;
  2289. if (BufferLength)
  2290. memcpy(pReplyPacket->IoCompletion.Parameters.QuerySd.Buffer,
  2291. pSecurityDescriptor, BufferLength);
  2292. ProcessObject()->GetVCMgr().ChannelWrite(
  2293. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  2294. }
  2295. else {
  2296. TRC_ERR((TB, _T("Failed to alloc %ld bytes."),ulReplyPacketSize));
  2297. }
  2298. Cleanup:
  2299. //
  2300. // Clean up the request packet.
  2301. //
  2302. delete pIoRequestPacket;
  2303. #ifndef OS_WINCE
  2304. //
  2305. // Clean up the security descriptor buffer
  2306. //
  2307. if (pSecurityDescriptor != NULL) {
  2308. delete pSecurityDescriptor;
  2309. }
  2310. #endif
  2311. if (hModule) {
  2312. FreeLibrary(hModule);
  2313. }
  2314. if (hProcessToken) {
  2315. CloseHandle(hProcessToken);
  2316. }
  2317. DC_END_FN();
  2318. }
  2319. VOID
  2320. W32Drive::MsgIrpSetSdInfo(
  2321. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  2322. IN UINT32 packetLen
  2323. )
  2324. /*++
  2325. Routine Description:
  2326. Handle a file system set security request from the server.
  2327. Arguments:
  2328. pIoRequestPacket - Server IO request packet.
  2329. packetLen - Length of the packet
  2330. Return Value:
  2331. NA
  2332. --*/
  2333. {
  2334. ULONG ulRetCode = ERROR_SUCCESS;
  2335. DWORD result;
  2336. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  2337. PRDPDR_IOCOMPLETION_PACKET pReplyPacket;
  2338. ULONG ulReplyPacketSize = 0;
  2339. DrFSFile* pFile;
  2340. HANDLE FileHandle;
  2341. #ifndef OS_WINCE
  2342. PSECURITY_DESCRIPTOR SecurityDescriptor;
  2343. #endif
  2344. DC_BEGIN_FN("W32Drive::MsgIrpQuerySd");
  2345. //
  2346. // Get IO request pointer.
  2347. //
  2348. pIoRequest = &pIoRequestPacket->IoRequest;
  2349. //
  2350. // Make sure the packetLen is right
  2351. //
  2352. if (packetLen < sizeof(RDPDR_IOREQUEST_PACKET) + pIoRequest->Parameters.SetSd.Length) {
  2353. // VirtualChannelClose
  2354. ProcessObject()->GetVCMgr().ChannelClose();
  2355. TRC_ASSERT(FALSE, (TB, _T("Packet Length Error")));
  2356. goto Cleanup;
  2357. }
  2358. //
  2359. // Get file handle
  2360. //
  2361. pFile = (DrFSFile *)_FileMgr->GetObject(pIoRequest->FileId);
  2362. if (pFile)
  2363. FileHandle = pFile->GetFileHandle();
  2364. else
  2365. FileHandle = INVALID_HANDLE_VALUE;
  2366. #ifndef OS_WINCE
  2367. //
  2368. // Set the file security
  2369. //
  2370. SecurityDescriptor = (PSECURITY_DESCRIPTOR)(pIoRequest + 1);
  2371. #endif
  2372. if (pFile) {
  2373. #ifndef OS_WINCE
  2374. if (SetFileSecurity(pFile->GetFileName(),
  2375. pIoRequest->Parameters.SetSd.SecurityInformation,
  2376. SecurityDescriptor)) {
  2377. ulRetCode = ERROR_SUCCESS;
  2378. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET) ;
  2379. }
  2380. else {
  2381. ulRetCode = GetLastError();
  2382. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2383. TRC_ERR((TB, _T("Lock File failed, %ld."), ulRetCode));
  2384. }
  2385. #else
  2386. ulRetCode = ERROR_SUCCESS;
  2387. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2388. #endif
  2389. }
  2390. else {
  2391. ulRetCode = ERROR_FILE_NOT_FOUND;
  2392. ulReplyPacketSize = sizeof(RDPDR_IOCOMPLETION_PACKET);
  2393. }
  2394. //
  2395. // Allocate reply buffer.
  2396. //
  2397. pReplyPacket = DrUTL_AllocIOCompletePacket(pIoRequestPacket,
  2398. ulReplyPacketSize) ;
  2399. if (pReplyPacket) {
  2400. //
  2401. // Send the result to the server.
  2402. //
  2403. result = TranslateWinError(ulRetCode);
  2404. pReplyPacket->IoCompletion.IoStatus = result;
  2405. ProcessObject()->GetVCMgr().ChannelWrite(
  2406. (PVOID)pReplyPacket, (UINT)ulReplyPacketSize);
  2407. }
  2408. else {
  2409. TRC_ERR((TB, _T("Failed to alloc %ld bytes."),ulReplyPacketSize));
  2410. }
  2411. Cleanup:
  2412. //
  2413. // Clean up the request packet.
  2414. //
  2415. delete pIoRequestPacket;
  2416. DC_END_FN();
  2417. }