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.

600 lines
13 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. w32drdev
  5. Abstract:
  6. This module defines the parent for the Win32 client-side RDP
  7. device redirection "device" class hierarchy, W32DrDevice.
  8. Author:
  9. Tad Brockway 3/23/99
  10. Revision History:
  11. --*/
  12. #include <precom.h>
  13. #define TRC_FILE "W32DrDevice"
  14. #include "w32drdev.h"
  15. #include "proc.h"
  16. #include "drdbg.h"
  17. #include "w32utl.h"
  18. #include "utl.h"
  19. #include "w32proc.h"
  20. #ifdef OS_WINCE
  21. #include "filemgr.h"
  22. #endif
  23. ///////////////////////////////////////////////////////////////
  24. //
  25. // W32DrDevice Members
  26. //
  27. //
  28. W32DrDevice::W32DrDevice(
  29. IN ProcObj *processObject,
  30. IN ULONG deviceID,
  31. IN const TCHAR *devicePath
  32. ) : DrDevice(processObject, deviceID)
  33. /*++
  34. Routine Description:
  35. Constructor for the W32DrDevice class.
  36. Arguments:
  37. processObject - Associated Process Object
  38. deviceID - Unique device identifier.
  39. devicePath - Path to device that can be used by
  40. CreateFile to open device.
  41. Return Value:
  42. NA
  43. --*/
  44. {
  45. DC_BEGIN_FN("W32DrDevice::W32DrDevice");
  46. //
  47. // Record device path.
  48. //
  49. ASSERT(STRLEN(devicePath) < MAX_PATH);
  50. STRNCPY(_devicePath, devicePath, MAX_PATH);
  51. _devicePath[MAX_PATH-1] = '\0';
  52. //
  53. // Initialize the handle to the string resource module.
  54. //
  55. _hRdpDrModuleHandle = NULL;
  56. DC_END_FN();
  57. }
  58. W32DrDevice::~W32DrDevice()
  59. /*++
  60. Routine Description:
  61. Destructor for the W32DrDevice class.
  62. Arguments:
  63. NA
  64. Return Value:
  65. NA
  66. --*/
  67. {
  68. DC_BEGIN_FN("W32DrDevice::~W32DrDevice");
  69. //
  70. // Close the string resource module.
  71. //
  72. if (_hRdpDrModuleHandle != NULL) {
  73. FreeLibrary( _hRdpDrModuleHandle );
  74. }
  75. DC_END_FN();
  76. }
  77. TCHAR*
  78. W32DrDevice::ConstructFileName(
  79. PWCHAR Path,
  80. ULONG PathBytes
  81. )
  82. /*++
  83. Routine Description:
  84. Setup the file name
  85. --*/
  86. {
  87. TCHAR *pFileName;
  88. HRESULT hr;
  89. UINT cchFileName;
  90. //
  91. // Get the File Name
  92. //
  93. if (PathBytes) {
  94. ULONG PathLen, DeviceLen;
  95. //
  96. // Open a File
  97. //
  98. //
  99. // Path is assumed string null terminated
  100. //
  101. PathLen = PathBytes / sizeof(WCHAR) - 1;
  102. Path[PathLen] = L'\0';
  103. #ifndef OS_WINCE
  104. DeviceLen = _tcslen(_devicePath);
  105. #else
  106. DeviceLen = 0;
  107. #endif
  108. //
  109. // Append device path and file path together
  110. // Assuming we need the \\?\ format, string
  111. // is null terminated
  112. //
  113. #ifndef OS_WINCE
  114. cchFileName = (DeviceLen + PathLen + 5);
  115. pFileName = new TCHAR[cchFileName];
  116. #else
  117. cchFileName = PathLen + 1
  118. pFileName = new TCHAR[cchFileName];
  119. #endif
  120. if (pFileName) {
  121. #ifndef OS_WINCE
  122. if (DeviceLen + PathLen < MAX_PATH) {
  123. //
  124. // Buffer is allocated large enough for the string
  125. //
  126. StringCchCopy(pFileName, cchFileName, _devicePath);
  127. }
  128. else {
  129. //
  130. // Buffer is allocated large enough for the string
  131. //
  132. StringCchPrintf(pFileName, cchFileName,
  133. TEXT("\\\\?\\%s"),
  134. _devicePath);
  135. DeviceLen += 4;
  136. }
  137. #endif
  138. }
  139. else {
  140. goto Cleanup;
  141. }
  142. #ifndef UNICODE
  143. RDPConvertToAnsi(Path, pFileName + DeviceLen, PathLen + 1);
  144. #else
  145. memcpy(pFileName + DeviceLen, Path, PathLen * sizeof(WCHAR));
  146. pFileName[DeviceLen + PathLen] = _T('\0');
  147. #endif
  148. }
  149. else {
  150. //
  151. // Open the device itself
  152. //
  153. pFileName = _devicePath;
  154. }
  155. Cleanup:
  156. return pFileName;
  157. }
  158. DWORD
  159. W32DrDevice::ConstructCreateDisposition(
  160. DWORD Disposition
  161. )
  162. /*++
  163. Routine Description:
  164. Construct client create disposition
  165. --*/
  166. {
  167. DWORD CreateDisposition;
  168. //
  169. // Setup CreateDisposition
  170. //
  171. switch (Disposition) {
  172. case FILE_CREATE :
  173. CreateDisposition = CREATE_NEW;
  174. break;
  175. case FILE_OVERWRITE_IF :
  176. CreateDisposition = CREATE_ALWAYS;
  177. break;
  178. case FILE_OPEN :
  179. CreateDisposition = OPEN_EXISTING;
  180. break;
  181. case FILE_OPEN_IF :
  182. CreateDisposition = OPEN_ALWAYS;
  183. break;
  184. default :
  185. CreateDisposition = 0;
  186. }
  187. return CreateDisposition;
  188. }
  189. DWORD
  190. W32DrDevice::ConstructDesiredAccess(
  191. DWORD AccessMask
  192. )
  193. /*++
  194. Routine Description:
  195. Construct client desired access from server's access mask
  196. --*/
  197. {
  198. DWORD DesiredAccess;
  199. //
  200. // Setup DesiredAccess
  201. //
  202. DesiredAccess = 0;
  203. //
  204. // If the user requested WRITE_DATA, return write.
  205. //
  206. if (AccessMask & FILE_WRITE_DATA) {
  207. DesiredAccess |= GENERIC_WRITE;
  208. }
  209. //
  210. // If the user requested READ_DATA, return read.
  211. //
  212. if (AccessMask & FILE_READ_DATA) {
  213. DesiredAccess |= GENERIC_READ;
  214. }
  215. //
  216. // If the user requested FILE_EXECUTE, return execute.
  217. //
  218. if (AccessMask & FILE_EXECUTE) {
  219. DesiredAccess |= GENERIC_READ;
  220. }
  221. return DesiredAccess;
  222. }
  223. DWORD
  224. W32DrDevice::ConstructFileFlags(
  225. DWORD CreateOptions
  226. )
  227. /*++
  228. Routine Description:
  229. Construct file flags
  230. --*/
  231. {
  232. DWORD CreateFlags;
  233. CreateFlags = 0;
  234. CreateFlags |= (CreateOptions & FILE_WRITE_THROUGH ? FILE_FLAG_WRITE_THROUGH : 0);
  235. CreateFlags |= (CreateOptions & FILE_RANDOM_ACCESS ? FILE_FLAG_RANDOM_ACCESS : 0 );
  236. //CreateFlags |= (CreateOptions & FILE_SYNCHRONOUS_IO_NONALERT ? 0 : FILE_FLAG_OVERLAPPED);
  237. #ifndef OS_WINCE
  238. CreateFlags |= (CreateOptions & FILE_NO_INTERMEDIATE_BUFFERING ? FILE_FLAG_NO_BUFFERING : 0);
  239. CreateFlags |= (CreateOptions & FILE_SEQUENTIAL_ONLY ? FILE_FLAG_SEQUENTIAL_SCAN : 0);
  240. CreateFlags |= (CreateOptions & FILE_OPEN_FOR_BACKUP_INTENT ? FILE_FLAG_BACKUP_SEMANTICS : 0);
  241. CreateFlags |= (CreateOptions & FILE_DELETE_ON_CLOSE ? FILE_FLAG_DELETE_ON_CLOSE : 0);
  242. CreateFlags |= (CreateOptions & FILE_OPEN_REPARSE_POINT ? FILE_FLAG_OPEN_REPARSE_POINT : 0);
  243. CreateFlags |= (CreateOptions & FILE_OPEN_NO_RECALL ? FILE_FLAG_OPEN_NO_RECALL : 0);
  244. #endif
  245. return CreateFlags;
  246. }
  247. BOOL
  248. W32DrDevice::IsDirectoryFile(
  249. DWORD DesiredAccess, DWORD CreateOptions, DWORD FileAttributes,
  250. PDWORD FileFlags
  251. )
  252. /*++
  253. Routine Description:
  254. Check if the pFileName corresponds to a directory
  255. --*/
  256. {
  257. BOOL IsDirectory = FALSE;
  258. //
  259. // Set up the directory check
  260. //
  261. if (!(CreateOptions & FILE_DIRECTORY_FILE)) {
  262. //
  263. // File doesn't have the directory flag on
  264. // or nondirecotry flag on, so it's not sure
  265. // if the file is a directory request or not
  266. //
  267. if (!(CreateOptions & FILE_NON_DIRECTORY_FILE)) {
  268. if (FileAttributes != -1) {
  269. //
  270. // From file attributes, we know this is an directory file
  271. // and we are requesting query access only. So, we add the
  272. // BACKUP_SEMANTICS for the file and set the directory flag
  273. // to be true. We always set the backup_semantics flag
  274. //
  275. #ifndef OS_WINCE
  276. *FileFlags |= FILE_FLAG_BACKUP_SEMANTICS;
  277. #endif
  278. if ((FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && DesiredAccess == 0) {
  279. IsDirectory = TRUE;
  280. }
  281. }
  282. }
  283. else {
  284. //
  285. // Non directory file flag is on, so we are doing file create/open request
  286. //
  287. }
  288. }
  289. else {
  290. //
  291. // File has the directory flag on, but we still want to do create file
  292. // on the directory
  293. //
  294. // Set the BACKUP_SEMANTICS, add it to the file flags
  295. // and remember this is a directory
  296. //
  297. if (FileAttributes != -1) {
  298. #ifndef OS_WINCE
  299. *FileFlags |= FILE_FLAG_BACKUP_SEMANTICS;
  300. #endif
  301. IsDirectory = TRUE;
  302. }
  303. }
  304. return IsDirectory;
  305. }
  306. VOID
  307. W32DrDevice::MsgIrpFlushBuffers(
  308. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  309. IN UINT32 packetLen
  310. )
  311. /*++
  312. Routine Description:
  313. Handle a "Cleanup" IO request from the server.
  314. Arguments:
  315. pIoRequestPacket - Server IO request packet.
  316. Return Value:
  317. NA
  318. --*/
  319. {
  320. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  321. BOOL result;
  322. DWORD returnValue;
  323. DrFile* pFile;
  324. HANDLE FileHandle;
  325. DC_BEGIN_FN("W32DrDevice::MsgIrpFlushBuffers");
  326. //
  327. // Get IO request pointer.
  328. //
  329. pIoRequest = &pIoRequestPacket->IoRequest;
  330. //
  331. // Get File Object
  332. //
  333. pFile = _FileMgr->GetObject(pIoRequest->FileId);
  334. if (pFile)
  335. FileHandle = pFile->GetFileHandle();
  336. else
  337. FileHandle = INVALID_HANDLE_VALUE;
  338. //
  339. // Flush the device handle.
  340. //
  341. ASSERT(FileHandle != INVALID_HANDLE_VALUE);
  342. #ifndef OS_WINCE
  343. result = FlushFileBuffers(FileHandle);
  344. #else
  345. result = CEFlushFileBuffers(FileHandle);
  346. #endif
  347. if (!result) {
  348. TRC_ERR((TB, _T("Flush returned %ld."), GetLastError()));
  349. }
  350. //
  351. // Send the result to the server.
  352. //
  353. returnValue = result ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  354. DefaultIORequestMsgHandle(pIoRequestPacket, returnValue);
  355. DC_END_FN();
  356. }
  357. VOID
  358. W32DrDevice::MsgIrpClose(
  359. IN PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  360. IN UINT32 packetLen
  361. )
  362. /*++
  363. Routine Description:
  364. Handle a "Close" IO request from the server.
  365. Arguments:
  366. pIoRequestPacket - Server IO request packet.
  367. Return Value:
  368. NA
  369. --*/
  370. {
  371. PRDPDR_DEVICE_IOREQUEST pIoRequest;
  372. DWORD returnValue = STATUS_SUCCESS;
  373. DrFile* pFile;
  374. DC_BEGIN_FN("W32DrDevice::MsgIrpClose");
  375. //
  376. // Get IO request pointer.
  377. //
  378. pIoRequest = &pIoRequestPacket->IoRequest;
  379. if (_FileMgr == NULL) {
  380. returnValue = STATUS_UNSUCCESSFUL;
  381. goto Cleanup;
  382. }
  383. //
  384. // Remove the File Object
  385. //
  386. pFile = _FileMgr->RemoveObject(pIoRequest->FileId);
  387. if ( pFile != NULL) {
  388. if (!pFile->Close()) {
  389. TRC_ERR((TB, _T("Close returned %ld."), GetLastError()));
  390. returnValue = STATUS_UNSUCCESSFUL;
  391. }
  392. pFile->Release();
  393. }
  394. else {
  395. returnValue = STATUS_UNSUCCESSFUL;
  396. }
  397. Cleanup:
  398. //
  399. // Send the result to the server.
  400. //
  401. DefaultIORequestMsgHandle(pIoRequestPacket, returnValue);
  402. DC_END_FN();
  403. }
  404. ULONG
  405. W32DrDevice::ReadResources(
  406. ULONG ulMessageID,
  407. LPTSTR *ppStringBuffer,
  408. PVOID pArguments,
  409. BOOL bFromSystemModule
  410. )
  411. /*++
  412. Routine Description:
  413. Read a string from the resources file.
  414. Arguments:
  415. lMessageID - Message ID.
  416. ppStringBuffer - Buffer pointer where the alloted buffer pointer
  417. is returned.
  418. pArguments - Pointer array.
  419. bFromSystemModule - When set TRUE return the message from the system
  420. module otherwise from the rdpdr.dll message module.
  421. Return Value:
  422. Returns ERROR_SUCCESS on success. Otherwise, a Windows error code is
  423. returned.
  424. --*/
  425. {
  426. ULONG ulError;
  427. HINSTANCE hModuleHandle;
  428. ULONG ulModuleFlag;
  429. ULONG ulLen;
  430. DC_BEGIN_FN("W32DrDevice::ReadResources");
  431. if( !bFromSystemModule ) {
  432. if (_hRdpDrModuleHandle == NULL ) {
  433. _hRdpDrModuleHandle = LoadLibrary(RDPDR_MODULE_NAME);
  434. if( _hRdpDrModuleHandle == NULL ) {
  435. ulError = GetLastError();
  436. TRC_ERR((TB, _T("LoadLibrary failed for %s: %ld."),
  437. RDPDR_MODULE_NAME, ulError));
  438. goto Cleanup;
  439. }
  440. }
  441. hModuleHandle = _hRdpDrModuleHandle;
  442. ulModuleFlag = FORMAT_MESSAGE_FROM_HMODULE;
  443. }
  444. else {
  445. hModuleHandle = NULL;
  446. ulModuleFlag = FORMAT_MESSAGE_FROM_SYSTEM;
  447. }
  448. ulLen =
  449. FormatMessage(
  450. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  451. ulModuleFlag |
  452. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  453. hModuleHandle,
  454. ulMessageID,
  455. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  456. (LPTSTR)ppStringBuffer,
  457. 0,
  458. (va_list *)pArguments );
  459. if( ulLen == 0 ) {
  460. ulError = GetLastError();
  461. TRC_ERR((TB, _T("FormatMessage() %ld."), ulError));
  462. goto Cleanup;
  463. }
  464. ASSERT(*ppStringBuffer != NULL);
  465. ulError = ERROR_SUCCESS;
  466. Cleanup:
  467. DC_END_FN();
  468. return ulError;
  469. }