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.

822 lines
28 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. drenum.c
  5. Abstract:
  6. This module implements the routines required for interaction with network
  7. provider router interface in NT
  8. Author:
  9. Joy Chik 1/20/2000
  10. --*/
  11. #include <drprov.h>
  12. #include "drdbg.h"
  13. extern UNICODE_STRING DrProviderName;
  14. extern UNICODE_STRING DrDeviceName;
  15. extern DWORD GLOBAL_DEBUG_FLAGS;
  16. DWORD
  17. DrOpenMiniRdr(
  18. OUT HANDLE *DrDeviceHandle
  19. )
  20. /*++
  21. Routine Description:
  22. This routine opens the RDP redirector File System Driver.
  23. Arguments:
  24. DrDeviceHandle - Device handle to the MiniRdr
  25. Return Value:
  26. STATUS - Success or reason for failure.
  27. --*/
  28. {
  29. NTSTATUS ntstatus;
  30. DWORD Status = WN_SUCCESS;
  31. IO_STATUS_BLOCK IoStatusBlock;
  32. OBJECT_ATTRIBUTES ObjectAttributes;
  33. UNICODE_STRING DeviceName;
  34. DBGMSG(DBG_TRACE, ("DRPROV: DrOpenMiniRdr\n"));
  35. //
  36. // Open the redirector device.
  37. //
  38. RtlInitUnicodeString(&DeviceName, RDPDR_DEVICE_NAME_U);
  39. InitializeObjectAttributes(
  40. &ObjectAttributes,
  41. &DeviceName,
  42. OBJ_CASE_INSENSITIVE,
  43. NULL,
  44. NULL
  45. );
  46. ntstatus = NtOpenFile(
  47. DrDeviceHandle,
  48. SYNCHRONIZE,
  49. &ObjectAttributes,
  50. &IoStatusBlock,
  51. FILE_SHARE_VALID_FLAGS,
  52. FILE_SYNCHRONOUS_IO_NONALERT
  53. );
  54. // If we failed to open the rdpdr minirdr, we
  55. // return as access denied
  56. if (ntstatus != STATUS_SUCCESS) {
  57. DBGMSG(DBG_TRACE, ("DRPROV: DrOpenMiniRdr failed with status: %x\n", ntstatus));
  58. Status = WN_ACCESS_DENIED;
  59. }
  60. DBGMSG(DBG_TRACE, ("DRPROV: DrOpenMiniRdr, return status: %x\n", Status));
  61. return Status;
  62. }
  63. DWORD
  64. DrDeviceControlGetInfo(
  65. IN HANDLE FileHandle,
  66. IN ULONG DeviceControlCode,
  67. IN PVOID RequestPacket,
  68. IN ULONG RequestPacketLength,
  69. OUT LPBYTE *OutputBuffer,
  70. IN ULONG PreferedMaximumLength,
  71. IN ULONG BufferHintSize,
  72. OUT PULONG_PTR Information OPTIONAL
  73. )
  74. /*++
  75. Routine Description:
  76. This function allocates the buffer and fill it with the information
  77. that is retrieved from the redirector.
  78. Arguments:
  79. FileHandle - Supplies a handle to the file or device of which to get
  80. information about.
  81. DeviceControlCode - Supplies the NtFsControlFile or NtIoDeviceControlFile
  82. function control code.
  83. RequestPacket - Supplies a pointer to the device request packet.
  84. RrequestPacketLength - Supplies the length of the device request packet.
  85. OutputBuffer - Returns a pointer to the buffer allocated by this routine
  86. which contains the use information requested. This pointer is set to
  87. NULL if return code is not wn_success.
  88. PreferedMaximumLength - Supplies the number of bytes of information to
  89. return in the buffer. If this value is MAXULONG, we will try to
  90. return all available information if there is enough memory resource.
  91. BufferHintSize - Supplies the hint size of the output buffer so that the
  92. memory allocated for the initial buffer will most likely be large
  93. enough to hold all requested data.
  94. Information - Returns the information code from the NtFsControlFile or
  95. NtIoDeviceControlFile call.
  96. Return Value:
  97. STATUS - Success or reason for failure.
  98. --*/
  99. {
  100. DWORD status;
  101. NTSTATUS ntStatus;
  102. DWORD OutputBufferLength;
  103. DWORD TotalBytesNeeded = 1;
  104. ULONG OriginalResumeKey;
  105. PRDPDR_REQUEST_PACKET Rrp = (PRDPDR_REQUEST_PACKET) RequestPacket;
  106. IO_STATUS_BLOCK IoStatusBlock;
  107. DBGMSG(DBG_TRACE, ("DRPROV: DrDeviceControlGetINfo\n"));
  108. //
  109. // If PreferedMaximumLength is MAXULONG, then we are supposed to get all
  110. // the information, regardless of size. Allocate the output buffer of a
  111. // reasonable size and try to use it. If this fails, the Redirector FSD
  112. // will say how much we need to allocate.
  113. //
  114. if (PreferedMaximumLength == MAXULONG) {
  115. OutputBufferLength = (BufferHintSize) ? BufferHintSize :
  116. INITIAL_ALLOCATION_SIZE;
  117. }
  118. else {
  119. OutputBufferLength = PreferedMaximumLength;
  120. }
  121. if ((*OutputBuffer = (BYTE *)MemAlloc(OutputBufferLength)) == NULL) {
  122. DBGMSG(DBG_TRACE, ("DRPROV: DrDeviceControlGetInfo, MemAlloc failed\n"));
  123. status = WN_OUT_OF_MEMORY;
  124. goto EXIT;
  125. }
  126. OriginalResumeKey = Rrp->Parameters.Get.ResumeHandle;
  127. //
  128. // Make the request of the Redirector
  129. //
  130. ntStatus = NtFsControlFile(
  131. FileHandle,
  132. NULL,
  133. NULL,
  134. NULL,
  135. &IoStatusBlock,
  136. DeviceControlCode,
  137. Rrp,
  138. RequestPacketLength,
  139. *OutputBuffer,
  140. OutputBufferLength
  141. );
  142. if (ntStatus == STATUS_SUCCESS) {
  143. TotalBytesNeeded = Rrp->Parameters.Get.TotalBytesNeeded;
  144. status = WN_SUCCESS;
  145. goto EXIT;
  146. }
  147. else {
  148. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  149. DBGMSG(DBG_TRACE, ("DRPROV: DrDeviceControlGetInfo, buffer too small\n"));
  150. TotalBytesNeeded = Rrp->Parameters.Get.TotalBytesNeeded;
  151. status = WN_MORE_DATA;
  152. }
  153. else {
  154. DBGMSG(DBG_TRACE, ("DRPROV: DrDeviceControlGetInfo, failed NtFsControlFile, %x\n", ntStatus));
  155. status = WN_BAD_NETNAME;
  156. goto EXIT;
  157. }
  158. }
  159. if ((TotalBytesNeeded > OutputBufferLength) &&
  160. (PreferedMaximumLength == MAXULONG)) {
  161. //
  162. // Initial output buffer allocated was too small and we need to return
  163. // all data. First free the output buffer before allocating the
  164. // required size plus a fudge factor just in case the amount of data
  165. // grew.
  166. //
  167. MemFree(*OutputBuffer);
  168. OutputBufferLength = TotalBytesNeeded + FUDGE_FACTOR_SIZE;
  169. if ((*OutputBuffer = (BYTE *)MemAlloc(OutputBufferLength)) == NULL) {
  170. DBGMSG(DBG_TRACE, ("DRPROV: DrDeviceControlGetInfo, MemAlloc failed\n"));
  171. status = WN_OUT_OF_MEMORY;
  172. goto EXIT;
  173. }
  174. //
  175. // Try again to get the information from the redirector
  176. //
  177. Rrp->Parameters.Get.ResumeHandle = OriginalResumeKey;
  178. //
  179. // Make the request of the Redirector
  180. //
  181. ntStatus = NtFsControlFile(
  182. FileHandle,
  183. NULL,
  184. NULL,
  185. NULL,
  186. &IoStatusBlock,
  187. DeviceControlCode,
  188. Rrp,
  189. RequestPacketLength,
  190. *OutputBuffer,
  191. OutputBufferLength
  192. );
  193. if (ntStatus == STATUS_SUCCESS)
  194. {
  195. TotalBytesNeeded = Rrp->Parameters.Get.TotalBytesNeeded;
  196. status = WN_SUCCESS;
  197. goto EXIT;
  198. }
  199. else {
  200. if (ntStatus == STATUS_BUFFER_TOO_SMALL) {
  201. DBGMSG(DBG_TRACE, ("DRPROV: DrDeviceControlGetInfo, buffer too small\n"));
  202. status = WN_OUT_OF_MEMORY;
  203. TotalBytesNeeded = Rrp->Parameters.Get.TotalBytesNeeded;
  204. goto EXIT;
  205. }
  206. else {
  207. DBGMSG(DBG_TRACE, ("DRPROV: DrDeviceControlGetInfo, failed NtFsControlFile, %x\n", ntStatus));
  208. status = WN_BAD_NETNAME;
  209. goto EXIT;
  210. }
  211. }
  212. }
  213. EXIT:
  214. //
  215. // If not successful in getting any data, or if TotalBytesNeeded is 0,
  216. // Free the output buffer.
  217. //
  218. if ((status != WN_SUCCESS) || (TotalBytesNeeded == 0)) {
  219. if (*OutputBuffer != NULL) {
  220. MemFree(*OutputBuffer);
  221. *OutputBuffer = NULL;
  222. }
  223. if (TotalBytesNeeded == 0) {
  224. status = WN_NO_MORE_ENTRIES;
  225. }
  226. }
  227. DBGMSG(DBG_TRACE, ("DRPROV: DrDeviceControlGetInfo, return status, %x\n", status));
  228. return status;
  229. }
  230. DWORD
  231. DrEnumServerInfo(PRDPDR_ENUMERATION_HANDLE pEnumHandle,
  232. LPDWORD lpcCount,
  233. LPNETRESOURCEW pBufferResource,
  234. LPDWORD lpBufferSize)
  235. /*++
  236. Routine Description:
  237. This function requests the redirector to enumerate the server info,
  238. it then reckages it into the user supplied buffer and return
  239. Arguments:
  240. pEnumHandle - Supplies the enumeration handle. It's a structure the dll
  241. used to store enumberation state and info.
  242. lpcCount - On return, this contains the number of NETRESOURCE entries
  243. returned back to user.
  244. pBufferResource - On return, this contains all the netresource entries.
  245. lpBufferSize - This contains the size of the buffer. On return, it
  246. is the size of the network resource entries.
  247. Return Value:
  248. STATUS - Success or reason for failure.
  249. --*/
  250. {
  251. DWORD status = WN_SUCCESS;
  252. DWORD localCount = 0;
  253. RDPDR_REQUEST_PACKET Rrp; // Redirector request packet
  254. HANDLE DrDeviceHandle = INVALID_HANDLE_VALUE;
  255. LPBYTE Buffer = NULL;
  256. PRDPDR_SERVER_INFO pServerEntry;
  257. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumServerInfo\n"));
  258. // Initialize enum count to 0
  259. *lpcCount = 0;
  260. if (pEnumHandle->enumIndex == 0) {
  261. if (DrOpenMiniRdr(&DrDeviceHandle) != WN_SUCCESS) {
  262. //
  263. // MPR doesn't like return device error in this case
  264. // We'll just return 0 entries
  265. //
  266. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumServerInfo, DrOpenMiniRdr failed\n"));
  267. status = WN_NO_MORE_ENTRIES;
  268. DrDeviceHandle = INVALID_HANDLE_VALUE;
  269. goto EXIT;
  270. }
  271. //
  272. // Ask the redirector to enumerate the information of server
  273. // established by the caller.
  274. //
  275. Rrp.SessionId = NtCurrentPeb()->SessionId;
  276. Rrp.Parameters.Get.ResumeHandle = 0;
  277. //
  278. // Make the request to the Redirector
  279. //
  280. status = DrDeviceControlGetInfo(DrDeviceHandle,
  281. FSCTL_DR_ENUMERATE_SERVERS,
  282. &Rrp,
  283. sizeof(RDPDR_REQUEST_PACKET),
  284. (LPBYTE *) &Buffer,
  285. MAXULONG,
  286. 0,
  287. NULL);
  288. if (status == WN_SUCCESS) {
  289. pEnumHandle->pEnumBuffer = Buffer;
  290. }
  291. else {
  292. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumServerInfo, DrDeviceControlGetInfo failed, %x\n", status));
  293. goto EXIT;
  294. }
  295. pServerEntry = ((PRDPDR_SERVER_INFO) Buffer);
  296. if (*lpBufferSize >= sizeof(NETRESOURCEW) +
  297. pServerEntry->ServerName.Length + sizeof(WCHAR) +
  298. DrProviderName.Length + sizeof(WCHAR)) {
  299. UNICODE_STRING ServerName;
  300. ServerName.Length = pServerEntry->ServerName.Length;
  301. ServerName.MaximumLength = pServerEntry->ServerName.MaximumLength;
  302. ServerName.Buffer = (PWCHAR)((PCHAR)(pServerEntry) + pServerEntry->ServerName.BufferOffset);
  303. pBufferResource->dwScope = pEnumHandle->dwScope;
  304. pBufferResource->dwType = RESOURCETYPE_DISK;
  305. pBufferResource->dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
  306. pBufferResource->dwUsage = RESOURCEUSAGE_CONTAINER ;
  307. pBufferResource->lpLocalName = NULL;
  308. // Server name
  309. pBufferResource->lpRemoteName = (PWCHAR) &pBufferResource[1];
  310. RtlCopyMemory(pBufferResource->lpRemoteName,
  311. ServerName.Buffer,
  312. ServerName.Length);
  313. pBufferResource->lpRemoteName[ServerName.Length /
  314. sizeof(WCHAR)] = L'\0';
  315. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumServerInfo, ServerName, %ws\n",
  316. pBufferResource->lpRemoteName));
  317. // Provider name
  318. pBufferResource->lpProvider = pBufferResource->lpRemoteName +
  319. (ServerName.Length / sizeof(WCHAR) + 1);
  320. RtlCopyMemory(pBufferResource->lpProvider, DrProviderName.Buffer,
  321. DrProviderName.Length);
  322. pBufferResource->lpProvider[DrProviderName.Length /
  323. sizeof(WCHAR)] = L'\0';
  324. pBufferResource->lpComment = NULL;
  325. localCount = 1;
  326. pEnumHandle->enumIndex++;
  327. status = WN_SUCCESS;
  328. goto EXIT;
  329. }
  330. else {
  331. localCount = 0;
  332. *lpBufferSize = sizeof(NETRESOURCEW) +
  333. pServerEntry->ServerName.Length + sizeof(WCHAR) +
  334. DrProviderName.Length + sizeof(WCHAR);
  335. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumServerInfo, buffer too small\n"));
  336. status = WN_MORE_DATA;
  337. goto EXIT;
  338. }
  339. } else {
  340. localCount = 0;
  341. status = WN_NO_MORE_ENTRIES;
  342. goto EXIT;
  343. }
  344. EXIT:
  345. *lpcCount = localCount;
  346. if (DrDeviceHandle != INVALID_HANDLE_VALUE) {
  347. CloseHandle(DrDeviceHandle);
  348. }
  349. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumServerInfo, return status %x\n", status));
  350. return status;
  351. }
  352. DWORD
  353. DrEnumShareInfo(PRDPDR_ENUMERATION_HANDLE pEnumHandle,
  354. LPDWORD lpcCount,
  355. LPNETRESOURCEW pBufferResource,
  356. LPDWORD lpBufferSize)
  357. /*++
  358. Routine Description:
  359. This function requests the redirector to enumerate the share info,
  360. it then reckages it into the user supplied buffer and return
  361. Arguments:
  362. pEnumHandle - Supplies the enumeration handle. It's a structure the dll
  363. used to store enumberation state and info.
  364. lpcCount - On return, this contains the number of NETRESOURCE entries
  365. returned back to user.
  366. pBufferResource - On return, this contains all the netresource entries.
  367. lpBufferSize - This contains the size of the buffer. On return, it
  368. is the size of the network resource entries.
  369. Return Value:
  370. STATUS - Success or reason for failure.
  371. --*/
  372. {
  373. DWORD status = WN_SUCCESS;
  374. DWORD localCount = 0;
  375. HANDLE DrDeviceHandle = INVALID_HANDLE_VALUE;
  376. RDPDR_REQUEST_PACKET Rrp; // Redirector request packet
  377. LPBYTE Buffer = NULL;
  378. PRDPDR_SHARE_INFO pShareEntry;
  379. DWORD Entry, RemainingBufferSize;
  380. BYTE *BufferResourceStart, *BufferResourceEnd;
  381. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumShareInfo\n"));
  382. *lpcCount = 0;
  383. BufferResourceStart = (PBYTE)pBufferResource;
  384. BufferResourceEnd = ((PBYTE)(pBufferResource)) + *lpBufferSize;
  385. if (pEnumHandle->RemoteName.Length == 0 || pEnumHandle->RemoteName.Buffer == NULL) {
  386. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumShareInfo, no RemoteName\n"));
  387. status = WN_BAD_NETNAME;
  388. goto EXIT;
  389. }
  390. if (pEnumHandle->enumIndex == 0) {
  391. if (DrOpenMiniRdr(&DrDeviceHandle) != WN_SUCCESS) {
  392. //
  393. // MPR doesn't like return device error in this case
  394. // We'll just return 0 entries
  395. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumShareInfo, DrOpenMiniRdr failed\n"));
  396. status = WN_NO_MORE_ENTRIES;
  397. DrDeviceHandle = INVALID_HANDLE_VALUE;
  398. goto EXIT;
  399. }
  400. //
  401. // Ask the redirector to enumerate the information of connections
  402. // established by the caller.
  403. //
  404. Rrp.SessionId = NtCurrentPeb()->SessionId;
  405. Rrp.Parameters.Get.ResumeHandle = 0;
  406. //
  407. // Make the request to the Redirector
  408. //
  409. status = DrDeviceControlGetInfo(DrDeviceHandle,
  410. FSCTL_DR_ENUMERATE_SHARES,
  411. &Rrp,
  412. sizeof(RDPDR_REQUEST_PACKET),
  413. (LPBYTE *) &Buffer,
  414. MAXULONG,
  415. 0,
  416. NULL);
  417. if (status == WN_SUCCESS) {
  418. pEnumHandle->totalEntries = Rrp.Parameters.Get.EntriesRead;
  419. pEnumHandle->pEnumBuffer = Buffer;
  420. }
  421. else {
  422. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumShareInfo, DrDeviceControlGetInfo failed, %x\n", status));
  423. goto EXIT;
  424. }
  425. }
  426. else {
  427. Buffer = pEnumHandle->pEnumBuffer;
  428. if (Buffer == NULL) {
  429. status = WN_NO_MORE_ENTRIES;
  430. goto EXIT;
  431. }
  432. }
  433. if (pEnumHandle->enumIndex == pEnumHandle->totalEntries) {
  434. status = WN_NO_MORE_ENTRIES;
  435. goto EXIT;
  436. }
  437. for (Entry = pEnumHandle->enumIndex; Entry < pEnumHandle->totalEntries; Entry++) {
  438. pShareEntry = ((PRDPDR_SHARE_INFO) Buffer) + Entry;
  439. if ((unsigned) (BufferResourceEnd - BufferResourceStart) >
  440. sizeof(NETRESOURCEW) +
  441. pShareEntry->ShareName.Length + sizeof(WCHAR) +
  442. DrProviderName.Length + sizeof(WCHAR)) {
  443. UNICODE_STRING ShareName;
  444. pBufferResource[localCount].dwScope = pEnumHandle->dwScope;
  445. pBufferResource[localCount].dwType = RESOURCETYPE_DISK;
  446. pBufferResource[localCount].dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
  447. pBufferResource[localCount].dwUsage = RESOURCEUSAGE_CONNECTABLE;
  448. pBufferResource[localCount].lpLocalName = NULL;
  449. ShareName.Length = pShareEntry->ShareName.Length;
  450. ShareName.MaximumLength = pShareEntry->ShareName.MaximumLength;
  451. ShareName.Buffer = (PWCHAR)((PCHAR)(pShareEntry) + pShareEntry->ShareName.BufferOffset);
  452. // share name
  453. BufferResourceEnd -= ShareName.Length + sizeof(WCHAR);
  454. pBufferResource[localCount].lpRemoteName = (PWCHAR) (BufferResourceEnd);
  455. RtlCopyMemory(pBufferResource[localCount].lpRemoteName,
  456. ShareName.Buffer,
  457. ShareName.Length);
  458. pBufferResource[localCount].lpRemoteName[ShareName.Length /
  459. sizeof(WCHAR)] = L'\0';
  460. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumShareInfo, ShareName, %ws\n",
  461. pBufferResource[localCount].lpRemoteName));
  462. // provider name
  463. BufferResourceEnd -= DrProviderName.Length + sizeof(WCHAR);
  464. pBufferResource[localCount].lpProvider = (PWCHAR) (BufferResourceEnd);
  465. RtlCopyMemory(pBufferResource[localCount].lpProvider, DrProviderName.Buffer,
  466. DrProviderName.Length);
  467. pBufferResource[localCount].lpProvider[DrProviderName.Length /
  468. sizeof(WCHAR)] = L'\0';
  469. pBufferResource[localCount].lpComment = NULL;
  470. localCount += 1;
  471. BufferResourceStart = (PBYTE)(&pBufferResource[localCount]);
  472. pEnumHandle->enumIndex++;
  473. }
  474. else {
  475. // enumerated some entries, so return success
  476. if (localCount) {
  477. status = WN_SUCCESS;
  478. break;
  479. }
  480. // can't even hold a single entry, return buffer too small
  481. else {
  482. *lpBufferSize = sizeof(NETRESOURCEW) +
  483. pEnumHandle->RemoteName.Length +
  484. pShareEntry->ShareName.Length + sizeof(WCHAR) +
  485. DrProviderName.Length + sizeof(WCHAR);
  486. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumShareInfo, buffer too small\n"));
  487. status = WN_MORE_DATA;
  488. goto EXIT;
  489. }
  490. }
  491. }
  492. EXIT:
  493. *lpcCount = localCount;
  494. if (DrDeviceHandle != INVALID_HANDLE_VALUE) {
  495. CloseHandle(DrDeviceHandle);
  496. }
  497. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumShareInfo, return status %x\n", status));
  498. return status;
  499. }
  500. DWORD
  501. DrEnumConnectionInfo(PRDPDR_ENUMERATION_HANDLE pEnumHandle,
  502. LPDWORD lpcCount,
  503. LPNETRESOURCEW pBufferResource,
  504. LPDWORD lpBufferSize)
  505. /*++
  506. Routine Description:
  507. This function requests the redirector to enumerate the connection info,
  508. it then reckages it into the user supplied buffer and return
  509. Arguments:
  510. pEnumHandle - Supplies the enumeration handle. It's a structure the dll
  511. used to store enumberation state and info.
  512. lpcCount - On return, this contains the number of NETRESOURCE entries
  513. returned back to user.
  514. pBufferResource - On return, this contains all the netresource entries.
  515. lpBufferSize - This contains the size of the buffer. On return, it
  516. is the size of the network resource entries.
  517. Return Value:
  518. STATUS - Success or reason for failure.
  519. --*/
  520. {
  521. DWORD status = WN_SUCCESS;
  522. DWORD localCount = 0;
  523. HANDLE DrDeviceHandle = INVALID_HANDLE_VALUE;
  524. RDPDR_REQUEST_PACKET Rrp; // Redirector request packet
  525. LPBYTE Buffer = NULL;
  526. PRDPDR_CONNECTION_INFO pConnectionEntry;
  527. DWORD Entry, RemainingBufferSize;
  528. BYTE *BufferResourceStart, *BufferResourceEnd;
  529. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumConnectionInfo\n"));
  530. *lpcCount = 0;
  531. BufferResourceStart = (PBYTE)pBufferResource;
  532. BufferResourceEnd = ((PBYTE)(pBufferResource)) + *lpBufferSize;
  533. if (pEnumHandle->enumIndex == 0) {
  534. if (DrOpenMiniRdr(&DrDeviceHandle) != WN_SUCCESS) {
  535. //
  536. // MPR doesn't like return device error in this case
  537. // We'll just return 0 entries
  538. //
  539. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumConnectionInfo, DrOpenMiniRdr failed\n"));
  540. status = WN_NO_MORE_ENTRIES;
  541. DrDeviceHandle = INVALID_HANDLE_VALUE;
  542. goto EXIT;
  543. }
  544. //
  545. // Ask the redirector to enumerate the information of connections
  546. // established by the caller.
  547. //
  548. Rrp.SessionId = NtCurrentPeb()->SessionId;
  549. Rrp.Parameters.Get.ResumeHandle = 0;
  550. //
  551. // Make the request to the Redirector
  552. //
  553. status = DrDeviceControlGetInfo(DrDeviceHandle,
  554. FSCTL_DR_ENUMERATE_CONNECTIONS,
  555. &Rrp,
  556. sizeof(RDPDR_REQUEST_PACKET),
  557. (LPBYTE *) &Buffer,
  558. MAXULONG,
  559. 0,
  560. NULL);
  561. if (status == WN_SUCCESS) {
  562. pEnumHandle->totalEntries = Rrp.Parameters.Get.EntriesRead;
  563. pEnumHandle->pEnumBuffer = Buffer;
  564. }
  565. else {
  566. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumConnectionInfo, DrDeviceControlGetInfo failed, %x\n", status));
  567. goto EXIT;
  568. }
  569. }
  570. else {
  571. Buffer = pEnumHandle->pEnumBuffer;
  572. if (Buffer == NULL) {
  573. status = WN_NO_MORE_ENTRIES;
  574. goto EXIT;
  575. }
  576. }
  577. if (pEnumHandle->enumIndex == pEnumHandle->totalEntries) {
  578. status = WN_NO_MORE_ENTRIES;
  579. goto EXIT;
  580. }
  581. for (Entry = pEnumHandle->enumIndex; Entry < pEnumHandle->totalEntries; Entry++) {
  582. pConnectionEntry = ((PRDPDR_CONNECTION_INFO) Buffer) + Entry;
  583. if ((unsigned) (BufferResourceEnd - BufferResourceStart) >
  584. sizeof(NETRESOURCEW) +
  585. pConnectionEntry->RemoteName.Length + sizeof(WCHAR) +
  586. pConnectionEntry->LocalName.Length + sizeof(WCHAR) +
  587. DrProviderName.Length + sizeof(WCHAR)) {
  588. UNICODE_STRING RemoteName;
  589. UNICODE_STRING LocalName;
  590. pBufferResource[localCount].dwScope = pEnumHandle->dwScope;
  591. pBufferResource[localCount].dwType = RESOURCETYPE_DISK;
  592. pBufferResource[localCount].dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
  593. pBufferResource[localCount].dwUsage = 0;
  594. RemoteName.Length = pConnectionEntry->RemoteName.Length;
  595. RemoteName.MaximumLength = pConnectionEntry->RemoteName.MaximumLength;
  596. RemoteName.Buffer = (PWCHAR)((PCHAR)pConnectionEntry +
  597. pConnectionEntry->RemoteName.BufferOffset);
  598. LocalName.Length = pConnectionEntry->LocalName.Length;
  599. LocalName.MaximumLength = pConnectionEntry->LocalName.MaximumLength;
  600. LocalName.Buffer = (PWCHAR)((PCHAR)pConnectionEntry +
  601. pConnectionEntry->LocalName.BufferOffset);
  602. // Remote name
  603. BufferResourceEnd -= RemoteName.Length + sizeof(WCHAR);
  604. pBufferResource[localCount].lpRemoteName = (PWCHAR) (BufferResourceEnd);
  605. RtlCopyMemory(pBufferResource[localCount].lpRemoteName,
  606. RemoteName.Buffer,
  607. RemoteName.Length);
  608. pBufferResource[localCount].lpRemoteName[RemoteName.Length /
  609. sizeof(WCHAR)] = L'\0';
  610. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumConnectionInfo, RemoteName, %ws\n",
  611. pBufferResource[localCount].lpRemoteName));
  612. // Local name
  613. if (LocalName.Length != 0) {
  614. BufferResourceEnd -= LocalName.Length + sizeof(WCHAR);
  615. pBufferResource[localCount].lpLocalName = (PWCHAR) (BufferResourceEnd);
  616. RtlCopyMemory(pBufferResource[localCount].lpLocalName,
  617. LocalName.Buffer,
  618. LocalName.Length);
  619. pBufferResource[localCount].lpLocalName[LocalName.Length /
  620. sizeof(WCHAR)] = L'\0';
  621. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumConnectionInfo, LocalName, %ws\n",
  622. pBufferResource[localCount].lpLocalName));
  623. }
  624. else {
  625. pBufferResource[localCount].lpLocalName = NULL;
  626. }
  627. // Provider name
  628. BufferResourceEnd -= DrProviderName.Length + sizeof(WCHAR);
  629. pBufferResource[localCount].lpProvider = (PWCHAR) (BufferResourceEnd);
  630. RtlCopyMemory(pBufferResource[localCount].lpProvider, DrProviderName.Buffer,
  631. DrProviderName.Length);
  632. pBufferResource[localCount].lpProvider[DrProviderName.Length /
  633. sizeof(WCHAR)] = L'\0';
  634. pBufferResource[localCount].lpComment = NULL;
  635. localCount += 1;
  636. BufferResourceStart = (PBYTE)(&pBufferResource[localCount]);
  637. pEnumHandle->enumIndex++;
  638. } else {
  639. // enumerated some entries, so return success
  640. if (localCount) {
  641. status = WN_SUCCESS;
  642. break;
  643. }
  644. // can't even hold a single entry, return buffer too small
  645. else {
  646. *lpBufferSize = sizeof(NETRESOURCEW) +
  647. pConnectionEntry->RemoteName.Length + sizeof(WCHAR) +
  648. DrProviderName.Length + sizeof(WCHAR) +
  649. pConnectionEntry->LocalName.Length + sizeof(WCHAR);
  650. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumConnectionInfo, buffer too small\n"));
  651. status = WN_MORE_DATA;
  652. break;
  653. }
  654. }
  655. }
  656. EXIT:
  657. *lpcCount = localCount;
  658. if (DrDeviceHandle != INVALID_HANDLE_VALUE) {
  659. CloseHandle(DrDeviceHandle);
  660. }
  661. DBGMSG(DBG_TRACE, ("DRENUM: DrEnumConnectionInfo, return status %x\n", status));
  662. return status;
  663. }