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.

1081 lines
30 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name :
  4. devmgr.cpp
  5. Abstract:
  6. DeviceManager object creates/manages the devices
  7. Revision History:
  8. --*/
  9. #include "precomp.hxx"
  10. #define TRC_FILE "devmgr"
  11. #include "trc.h"
  12. DrDeviceManager::DrDeviceManager()
  13. {
  14. BEGIN_FN("DrDeviceManager::DrDeviceManager");
  15. TRC_NRM((TB, "DeviceManagr Class: %p", this));
  16. SetClassName("DrDeviceManager");
  17. _Session = NULL;
  18. }
  19. DrDeviceManager::~DrDeviceManager()
  20. {
  21. BEGIN_FN("DrDeviceManager::~DrDeviceManager");
  22. TRC_NRM((TB, "DeviceManager deletion: %p", this));
  23. }
  24. BOOL DrDeviceManager::Initialize(DrSession *Session)
  25. {
  26. BEGIN_FN("DrDeviceManager::Initialize");
  27. ASSERT(_Session == NULL);
  28. ASSERT(Session != NULL);
  29. ASSERT(Session->IsValid());
  30. _Session = Session;
  31. if (!NT_ERROR(_Session->RegisterPacketReceiver(this))) {
  32. return TRUE;
  33. } else {
  34. _Session = NULL;
  35. return FALSE;
  36. }
  37. }
  38. VOID DrDeviceManager::Uninitialize()
  39. /*++
  40. Routine Description:
  41. Called if the something went wrong during startup
  42. --*/
  43. {
  44. BEGIN_FN("DrDeviceManager::Uninitialize");
  45. ASSERT(_Session != NULL);
  46. ASSERT(_Session->IsValid());
  47. _Session->RemovePacketReceiver(this);
  48. _Session = NULL;
  49. }
  50. BOOL DrDeviceManager::RecognizePacket(PRDPDR_HEADER RdpdrHeader)
  51. /*++
  52. Routine Description:
  53. Determines if the packet will be handled by this object
  54. Arguments:
  55. RdpdrHeader - Header of the packet.
  56. Return Value:
  57. TRUE if this object should handle this packet
  58. FALSE if this object should not handle this packet
  59. --*/
  60. {
  61. BEGIN_FN("DrDeviceManager::RecognizePacket");
  62. ASSERT(RdpdrHeader != NULL);
  63. //
  64. // If you add a packet here, update the ASSERTS in HandlePacket
  65. //
  66. switch (RdpdrHeader->Component) {
  67. case RDPDR_CTYP_CORE:
  68. switch (RdpdrHeader->PacketId) {
  69. case DR_CORE_DEVICE_ANNOUNCE:
  70. case DR_CORE_DEVICELIST_ANNOUNCE:
  71. case DR_CORE_DEVICE_REMOVE:
  72. case DR_CORE_DEVICELIST_REMOVE:
  73. return TRUE;
  74. }
  75. }
  76. return FALSE;
  77. }
  78. NTSTATUS DrDeviceManager::HandlePacket(PRDPDR_HEADER RdpdrHeader, ULONG Length,
  79. BOOL *DoDefaultRead)
  80. /*++
  81. Routine Description:
  82. Handles this packet
  83. Arguments:
  84. RdpdrHeader - Header of the packet.
  85. Length - Total length of the packet
  86. Return Value:
  87. NTSTATUS - An error code indicates the client is Bad and should be
  88. disconnected, otherwise SUCCESS.
  89. --*/
  90. {
  91. NTSTATUS Status = STATUS_DEVICE_PROTOCOL_ERROR;
  92. BEGIN_FN("DrDeviceManager::HandlePacket");
  93. //
  94. // RdpdrHeader read, dispatch based on the header
  95. //
  96. ASSERT(RdpdrHeader != NULL);
  97. ASSERT(RdpdrHeader->Component == RDPDR_CTYP_CORE);
  98. switch (RdpdrHeader->Component) {
  99. case RDPDR_CTYP_CORE:
  100. ASSERT(RdpdrHeader->PacketId == DR_CORE_DEVICE_ANNOUNCE ||
  101. RdpdrHeader->PacketId == DR_CORE_DEVICELIST_ANNOUNCE ||
  102. RdpdrHeader->PacketId == DR_CORE_DEVICE_REMOVE ||
  103. RdpdrHeader->PacketId == DR_CORE_DEVICELIST_REMOVE);
  104. switch (RdpdrHeader->PacketId) {
  105. case DR_CORE_DEVICE_ANNOUNCE:
  106. Status = OnDeviceAnnounce(RdpdrHeader, Length, DoDefaultRead);
  107. break;
  108. case DR_CORE_DEVICELIST_ANNOUNCE:
  109. Status = OnDeviceListAnnounce(RdpdrHeader, Length, DoDefaultRead);
  110. break;
  111. case DR_CORE_DEVICE_REMOVE:
  112. Status = OnDeviceRemove(RdpdrHeader, Length, DoDefaultRead);
  113. break;
  114. case DR_CORE_DEVICELIST_REMOVE:
  115. Status = OnDeviceListRemove(RdpdrHeader, Length, DoDefaultRead);
  116. break;
  117. }
  118. }
  119. return Status;
  120. }
  121. NTSTATUS DrDeviceManager::OnDeviceAnnounce(PRDPDR_HEADER RdpdrHeader, ULONG cbPacket,
  122. BOOL *DoDefaultRead)
  123. /*++
  124. Routine Description:
  125. Called in response to recognizing a DeviceAnnounce packet has been
  126. received.
  127. Arguments:
  128. RdpdrHeader - The packet
  129. cbPacket - Bytes in the packet
  130. --*/
  131. {
  132. PRDPDR_DEVICE_ANNOUNCE_PACKET DeviceAnnouncePacket =
  133. (PRDPDR_DEVICE_ANNOUNCE_PACKET)RdpdrHeader;
  134. BEGIN_FN("DrDeviceManager::OnDeviceAnnounce");
  135. ASSERT(RdpdrHeader != NULL);
  136. PUCHAR pPacketLimit = ((PUCHAR)RdpdrHeader) + cbPacket;
  137. //
  138. // We just call DrProcessDeviceAnnounce, which deals with one of these
  139. // for this packet type and for DeviceListAnnounce
  140. *DoDefaultRead = FALSE;
  141. if (cbPacket >= sizeof(RDPDR_DEVICE_ANNOUNCE_PACKET)) {
  142. PRDPDR_DEVICE_ANNOUNCE DeviceAnnounce = &DeviceAnnouncePacket->DeviceAnnounce;
  143. //
  144. // Make sure we don't go past the end of our buffer
  145. // Checks:
  146. // The end of this device is not beyond the valid area
  147. //
  148. if ((cbPacket - sizeof(RDPDR_DEVICE_ANNOUNCE_PACKET)) >= DeviceAnnounce->DeviceDataLength) {
  149. ProcessDeviceAnnounce(&DeviceAnnouncePacket->DeviceAnnounce);
  150. *DoDefaultRead = TRUE;
  151. return STATUS_SUCCESS;
  152. }
  153. else {
  154. ASSERT(FALSE);
  155. TRC_ERR((TB, "Invalid Device DataLength %d", DeviceAnnounce->DeviceDataLength));
  156. }
  157. }
  158. else {
  159. ASSERT(FALSE);
  160. TRC_ERR((TB, "Invalid Packet Length %d", cbPacket));
  161. }
  162. //
  163. // Invalid data. Fail
  164. //
  165. return STATUS_UNSUCCESSFUL;
  166. }
  167. NTSTATUS DrDeviceManager::OnDeviceListAnnounce(PRDPDR_HEADER RdpdrHeader, ULONG cbPacket,
  168. BOOL *DoDefaultRead)
  169. /*++
  170. Routine Description:
  171. Called in response to recognizing a DeviceListAnnounce packet has been
  172. received. Reads in the DeviceCount field of the packet, and the first
  173. device.
  174. Arguments:
  175. RdpdrHeader - The packet
  176. cbPacket - Bytes in the packet
  177. Return Value:
  178. Boolean indication of whether to do a default read (TRUE) or not (FALSE),
  179. where FALSE might be specified if another read has been requested
  180. explicitly to get a full packet
  181. --*/
  182. {
  183. NTSTATUS Status;
  184. PRDPDR_DEVICELIST_ANNOUNCE_PACKET DeviceListAnnouncePacket =
  185. (PRDPDR_DEVICELIST_ANNOUNCE_PACKET)RdpdrHeader;
  186. PRDPDR_DEVICE_ANNOUNCE DeviceAnnounce =
  187. DR_FIRSTDEVICEANNOUNCE(DeviceListAnnouncePacket);
  188. ULONG DeviceCount = 0;
  189. PUCHAR pPacketLimit = ((PUCHAR)RdpdrHeader) + cbPacket;
  190. PUCHAR pCopyTo;
  191. ULONG cbRemaining;
  192. ULONG cbDesiredBuffer;
  193. PRDPDR_DEVICE_ANNOUNCE NextDeviceAnnounce;
  194. BEGIN_FN("DrDeviceManager::OnDeviceListAnnounce");
  195. ASSERT(_Session != NULL);
  196. ASSERT(_Session->IsValid());
  197. ASSERT(RdpdrHeader != NULL);
  198. ASSERT(RdpdrHeader->Component == RDPDR_CTYP_CORE);
  199. ASSERT(RdpdrHeader->PacketId == DR_CORE_DEVICELIST_ANNOUNCE);
  200. TRC_NRM((TB, "OnDeviceListAnnounce called (%ld)", cbPacket));
  201. *DoDefaultRead = FALSE;
  202. if (cbPacket >= sizeof(RDPDR_DEVICELIST_ANNOUNCE_PACKET)) {
  203. DeviceCount = DeviceListAnnouncePacket->DeviceListAnnounce.DeviceCount;
  204. } else {
  205. //
  206. // Not enough data to even know the size of the rest
  207. // We have seen valid case assert here.
  208. //
  209. //TRC_ASSERT(cbPacket >= sizeof(RDPDR_DEVICELIST_ANNOUNCE_PACKET),
  210. // (TB, "Didn't receive full DeviceListAnnounce basic packet"));
  211. if (_Session->ReadMore(cbPacket, sizeof(RDPDR_DEVICELIST_ANNOUNCE_PACKET))) {
  212. return STATUS_SUCCESS;
  213. } else {
  214. return STATUS_UNSUCCESSFUL;
  215. }
  216. }
  217. TRC_NRM((TB, "Annoucing %lx devices", DeviceCount));
  218. //
  219. // Make sure we don't go past the end of our buffer
  220. // Three checks:
  221. // 1) More devices to process
  222. // 2) Pointer is valid enough to check the variable size
  223. // 3) The next device (the end of this device) is not beyond the valid area
  224. //
  225. while (DeviceCount > 0 && ((PUCHAR)&DeviceAnnounce->DeviceDataLength <=
  226. pPacketLimit - sizeof(DeviceAnnounce->DeviceDataLength)) &&
  227. ((PUCHAR)(NextDeviceAnnounce = DR_NEXTDEVICEANNOUNCE(DeviceAnnounce)) <= pPacketLimit) &&
  228. (NextDeviceAnnounce >= DeviceAnnounce + 1)) {
  229. //
  230. // Only process the device announcement PDU when the session is connected
  231. //
  232. if (_Session->IsConnected()) {
  233. ProcessDeviceAnnounce(DeviceAnnounce);
  234. }
  235. // Move to the next device
  236. DeviceAnnounce = NextDeviceAnnounce;
  237. DeviceCount--;
  238. }
  239. if (DeviceCount == 0) {
  240. TRC_NRM((TB, "Finished handling all devices in DeviceList"));
  241. //
  242. // All done processing, return TRUE to use default continuation
  243. //
  244. *DoDefaultRead = TRUE;
  245. return STATUS_SUCCESS;
  246. } else {
  247. TRC_NRM((TB, "More devices to handle in DeviceList"));
  248. //
  249. // We didn't get all the data for the device(s)
  250. //
  251. if (DeviceCount < DeviceListAnnouncePacket->DeviceListAnnounce.DeviceCount) {
  252. //
  253. // We processed at least one device. Move the final partial device
  254. // up next to the header, update the header to indicate the number
  255. // of devices left to process,
  256. //
  257. TRC_NRM((TB, "Some devices processed, shuffling "
  258. "DeviceList"));
  259. // Move partial device
  260. cbRemaining = (ULONG)(pPacketLimit - ((PUCHAR)DeviceAnnounce));
  261. pCopyTo = (PUCHAR)DR_FIRSTDEVICEANNOUNCE(DeviceListAnnouncePacket);
  262. RtlMoveMemory(pCopyTo, DeviceAnnounce, cbRemaining);
  263. // update the device count
  264. DeviceListAnnouncePacket->DeviceListAnnounce.DeviceCount = DeviceCount;
  265. // update the Packet limit for the amount we've consumed
  266. pPacketLimit = pCopyTo + cbRemaining;
  267. cbPacket = (ULONG)(pPacketLimit - (PUCHAR)RdpdrHeader);
  268. }
  269. //
  270. // If we have enough information to know the size of buffer we need,
  271. // allocate that now
  272. //
  273. DeviceAnnounce = DR_FIRSTDEVICEANNOUNCE(DeviceListAnnouncePacket);
  274. if ((PUCHAR)&DeviceAnnounce->DeviceDataLength <=
  275. pPacketLimit - sizeof(DeviceAnnounce->DeviceDataLength)) {
  276. TRC_NRM((TB, "Resizing buffer for expected device"
  277. "size"));
  278. //
  279. // Since the DeviceAnnoucePacket include one Device, we need a
  280. // buffer the size of the packet plus the variable data length
  281. // DrReallocateChannelBuffer is smart enough not to realloc
  282. // if we ask for a size <= current buffer size
  283. //
  284. cbDesiredBuffer = sizeof(RDPDR_DEVICELIST_ANNOUNCE_PACKET) +
  285. DeviceAnnounce->DeviceDataLength;
  286. TRC_NRM((TB, "DrOnDeviceListAnnounce cbDesiredBuffer is %ld.",
  287. cbDesiredBuffer));
  288. if (cbDesiredBuffer <= DeviceAnnounce->DeviceDataLength) {
  289. ASSERT(FALSE);
  290. TRC_ERR((TB, "Invalid Device DataLength %d", DeviceAnnounce->DeviceDataLength));
  291. return STATUS_UNSUCCESSFUL;
  292. }
  293. //
  294. // Start a read right after the partially received packet with a
  295. // handler that can update the received size and send it back to this
  296. // routine to complete.
  297. //
  298. if (_Session->ReadMore(cbPacket, cbDesiredBuffer)) {
  299. return STATUS_SUCCESS;
  300. } else {
  301. return STATUS_UNSUCCESSFUL;
  302. }
  303. } else {
  304. //
  305. // Just ask for some more data, again after the partially received
  306. // packet
  307. //
  308. if (_Session->ReadMore(cbPacket, sizeof(RDPDR_DEVICELIST_ANNOUNCE_PACKET))) {
  309. return STATUS_SUCCESS;
  310. } else {
  311. return STATUS_UNSUCCESSFUL;
  312. }
  313. }
  314. }
  315. }
  316. NTSTATUS DrDeviceManager::OnDeviceRemove(PRDPDR_HEADER RdpdrHeader, ULONG cbPacket,
  317. BOOL *DoDefaultRead)
  318. /*++
  319. Routine Description:
  320. Called in response to recognizing a DeviceRemove packet has been
  321. received.
  322. Arguments:
  323. RdpdrHeader - The packet
  324. cbPacket - Bytes in the packet
  325. --*/
  326. {
  327. PRDPDR_DEVICE_REMOVE_PACKET DeviceRemovePacket =
  328. (PRDPDR_DEVICE_REMOVE_PACKET)RdpdrHeader;
  329. BEGIN_FN("DrDeviceManager::OnDeviceRemove");
  330. ASSERT(RdpdrHeader != NULL);
  331. if (cbPacket < sizeof(RDPDR_DEVICE_REMOVE_PACKET)) {
  332. return STATUS_UNSUCCESSFUL;
  333. }
  334. //
  335. // We just call DrProcessDeviceRemove, which deals with one of these
  336. // for this packet type and for DeviceListRemove
  337. //
  338. ProcessDeviceRemove(&DeviceRemovePacket->DeviceRemove);
  339. *DoDefaultRead = TRUE;
  340. return STATUS_SUCCESS;
  341. }
  342. NTSTATUS DrDeviceManager::OnDeviceListRemove(PRDPDR_HEADER RdpdrHeader, ULONG cbPacket,
  343. BOOL *DoDefaultRead)
  344. /*++
  345. Routine Description:
  346. Called in response to recognizing a DeviceListRemove packet has been
  347. received. Reads in the DeviceCount field of the packet, and the first
  348. device.
  349. Arguments:
  350. RdpdrHeader - The packet
  351. cbPacket - Bytes in the packet
  352. Return Value:
  353. Boolean indication of whether to do a default read (TRUE) or not (FALSE),
  354. where FALSE might be specified if another read has been requested
  355. explicitly to get a full packet
  356. --*/
  357. {
  358. NTSTATUS Status;
  359. PRDPDR_DEVICELIST_REMOVE_PACKET DeviceListRemovePacket =
  360. (PRDPDR_DEVICELIST_REMOVE_PACKET)RdpdrHeader;
  361. PRDPDR_DEVICE_REMOVE DeviceRemove =
  362. DR_FIRSTDEVICEREMOVE(DeviceListRemovePacket);
  363. ULONG DeviceCount = 0;
  364. PUCHAR pPacketLimit = ((PUCHAR)RdpdrHeader) + cbPacket;
  365. PUCHAR pCopyTo;
  366. ULONG cbRemaining;
  367. ULONG cbDesiredBuffer;
  368. PRDPDR_DEVICE_REMOVE NextDeviceRemove;
  369. BEGIN_FN("DrDeviceManager::OnDeviceListRemove");
  370. ASSERT(_Session != NULL);
  371. ASSERT(_Session->IsValid());
  372. ASSERT(RdpdrHeader != NULL);
  373. ASSERT(RdpdrHeader->Component == RDPDR_CTYP_CORE);
  374. ASSERT(RdpdrHeader->PacketId == DR_CORE_DEVICELIST_REMOVE);
  375. TRC_NRM((TB, "OnDeviceListRemove called (%ld)", cbPacket));
  376. *DoDefaultRead = FALSE;
  377. if (cbPacket >= sizeof(RDPDR_DEVICELIST_REMOVE_PACKET)) {
  378. DeviceCount = DeviceListRemovePacket->DeviceListRemove.DeviceCount;
  379. } else {
  380. //
  381. // Not enough data to even know the size of the rest
  382. // I don't think this should ever happen
  383. //
  384. TRC_ASSERT(cbPacket >= sizeof(RDPDR_DEVICELIST_REMOVE_PACKET),
  385. (TB, "Didn't receive full DeviceListRemove basic packet"));
  386. if (_Session->ReadMore(cbPacket, sizeof(RDPDR_DEVICELIST_REMOVE_PACKET))) {
  387. return STATUS_SUCCESS;
  388. } else {
  389. return STATUS_UNSUCCESSFUL;
  390. }
  391. }
  392. TRC_NRM((TB, "Removing %lx devices", DeviceCount));
  393. //
  394. // Make sure we don't go past the end of our buffer
  395. // Three checks:
  396. // 1) More devices to process
  397. // 2) Pointer is valid enough to check the variable size
  398. // 3) The next device (the end of this device) is not beyond the valid area
  399. //
  400. while (DeviceCount > 0 &&
  401. ((PUCHAR)(NextDeviceRemove = DR_NEXTDEVICEREMOVE(DeviceRemove)) <= pPacketLimit) &&
  402. (NextDeviceRemove >= DeviceRemove + 1)) {
  403. ProcessDeviceRemove(DeviceRemove);
  404. // Move to the next device
  405. DeviceRemove = NextDeviceRemove;
  406. DeviceCount--;
  407. }
  408. if (DeviceCount == 0) {
  409. TRC_NRM((TB, "Finished handling all devices in DeviceList"));
  410. //
  411. // All done processing, return TRUE to use default continuation
  412. //
  413. *DoDefaultRead = TRUE;
  414. return STATUS_SUCCESS;
  415. } else {
  416. TRC_NRM((TB, "More devices to handle in DeviceList"));
  417. //
  418. // We didn't get all the data for the device(s)
  419. //
  420. if (DeviceCount < DeviceListRemovePacket->DeviceListRemove.DeviceCount) {
  421. //
  422. // We processed at least one device. Move the final partial device
  423. // up next to the header, update the header to indicate the number
  424. // of devices left to process,
  425. //
  426. TRC_NRM((TB, "Some devices processed, shuffling "
  427. "DeviceList"));
  428. // Move partial device
  429. cbRemaining = (ULONG)(pPacketLimit - ((PUCHAR)DeviceRemove));
  430. pCopyTo = (PUCHAR)DR_FIRSTDEVICEREMOVE(DeviceListRemovePacket);
  431. RtlMoveMemory(pCopyTo, DeviceRemove, cbRemaining);
  432. // update the device count
  433. DeviceListRemovePacket->DeviceListRemove.DeviceCount = DeviceCount;
  434. // update the Packet limit for the amount we've consumed
  435. pPacketLimit = pCopyTo + cbRemaining;
  436. cbPacket = (ULONG)(pPacketLimit - (PUCHAR)RdpdrHeader);
  437. }
  438. //
  439. // Try to read the remaing device remove entries
  440. //
  441. cbDesiredBuffer = sizeof(RDPDR_DEVICE_REMOVE) * DeviceCount;
  442. TRC_NRM((TB, "DrOnDeviceListRemove cbDesiredBuffer is %ld.",
  443. cbDesiredBuffer));
  444. //
  445. // Start a read right after the partially received packet with a
  446. // handler that can update the received size and send it back to this
  447. // routine to complete.
  448. //
  449. if (_Session->ReadMore(cbPacket, cbDesiredBuffer)) {
  450. return STATUS_SUCCESS;
  451. } else {
  452. return STATUS_UNSUCCESSFUL;
  453. }
  454. }
  455. }
  456. VOID DrDeviceManager::ProcessDeviceAnnounce(PRDPDR_DEVICE_ANNOUNCE DeviceAnnounce)
  457. /*++
  458. Routine Description:
  459. Processes a device announce, sends a reply and adds it if appropriate
  460. Arguments:
  461. DeviceAnnounce - The actual device that was reported
  462. Return Value:
  463. None
  464. --*/
  465. {
  466. NTSTATUS Status;
  467. SmartPtr<DrDevice> Device;
  468. SmartPtr<DrSession> Session = _Session;
  469. BOOL bDeviceAdded = FALSE;
  470. BEGIN_FN("DrDeviceManager::ProcessDeviceAnnounce");
  471. TRC_NRM((TB, "Device contains %ld bytes user data",
  472. DeviceAnnounce->DeviceDataLength));
  473. //
  474. // Check to make sure the device doesn't already exist,
  475. // if it is a smartcard subsystem device, then it is OK
  476. // it it already exists
  477. //
  478. if (FindDeviceById(DeviceAnnounce->DeviceId, Device) &&
  479. (DeviceAnnounce->DeviceType != RDPDR_DTYP_SMARTCARD)) {
  480. //
  481. // The client announced a device we already knew about. If it was
  482. // disabled, we can re-enable it and reply with success. If it was
  483. // not disabled, then the poor client is confused and needs to be
  484. // swatted down
  485. //
  486. TRC_ALT((TB, "Client announced a duplicate device, discarding"));
  487. //
  488. // Set DeviceEntry = NULL so error code will be used below
  489. //
  490. Device = NULL;
  491. Status = STATUS_DUPLICATE_OBJECTID;
  492. } else {
  493. TRC_NRM((TB, "No duplicate device found"));
  494. Status = STATUS_INSUFFICIENT_RESOURCES;
  495. switch (DeviceAnnounce->DeviceType)
  496. {
  497. case RDPDR_DTYP_SERIAL:
  498. Device = new(NonPagedPool) DrSerialPort(Session, DeviceAnnounce->DeviceType,
  499. DeviceAnnounce->DeviceId,
  500. DeviceAnnounce->PreferredDosName);
  501. break;
  502. case RDPDR_DTYP_PARALLEL:
  503. Device = new(NonPagedPool) DrParallelPort(Session, DeviceAnnounce->DeviceType,
  504. DeviceAnnounce->DeviceId,
  505. DeviceAnnounce->PreferredDosName);
  506. break;
  507. case RDPDR_DTYP_PRINT:
  508. Device = new(NonPagedPool) DrPrinter(Session, DeviceAnnounce->DeviceType,
  509. DeviceAnnounce->DeviceId,
  510. DeviceAnnounce->PreferredDosName);
  511. break;
  512. case RDPDR_DTYP_FILESYSTEM:
  513. Device = new(NonPagedPool) DrDrive(Session, DeviceAnnounce->DeviceType,
  514. DeviceAnnounce->DeviceId,
  515. DeviceAnnounce->PreferredDosName);
  516. break;
  517. case RDPDR_DTYP_SMARTCARD:
  518. Device = NULL;
  519. if (FindDeviceByDosName(DeviceAnnounce->PreferredDosName, Device, TRUE) &&
  520. (Device->GetDeviceType() == RDPDR_DTYP_SMARTCARD)) {
  521. bDeviceAdded = TRUE;
  522. Status = STATUS_SUCCESS;
  523. }
  524. else {
  525. Device = new(NonPagedPool) DrSmartCard(Session, DeviceAnnounce->DeviceType,
  526. DeviceAnnounce->DeviceId,
  527. DeviceAnnounce->PreferredDosName);
  528. }
  529. break;
  530. default:
  531. //
  532. // "I don't know and I don't care"
  533. // We've never heard of this kind of device so we'll reject it
  534. //
  535. TRC_ALT((TB, "Client announced unsupported device %d", DeviceAnnounce->DeviceType));
  536. Status = STATUS_NOT_SUPPORTED;
  537. Device = NULL;
  538. }
  539. }
  540. //
  541. // DeviceEntry != NULL means SUCCESS
  542. //
  543. if (Device != NULL) {
  544. //
  545. // Give the specific device a chance to initialize based on the data
  546. //
  547. Status = Device->Initialize(DeviceAnnounce,
  548. DeviceAnnounce->DeviceDataLength);
  549. } else {
  550. TRC_ERR((TB, "Error creating new device: 0x%08lx", Status));
  551. //
  552. // Don't set the Status here, it was set up above
  553. //
  554. }
  555. if (NT_SUCCESS(Status)) {
  556. if (bDeviceAdded || AddDevice(Device)) {
  557. if (DeviceAnnounce->DeviceType == RDPDR_DTYP_SMARTCARD) {
  558. SmartPtr<DrSmartCard> SmartCard((DrSmartCard*)(DrDevice *)Device);
  559. SmartCard->ClientConnect(DeviceAnnounce, DeviceAnnounce->DeviceDataLength);
  560. }
  561. Status = STATUS_SUCCESS;
  562. }
  563. else {
  564. Device = NULL;
  565. //
  566. // This means another thread has just added the scard device
  567. //
  568. if (DeviceAnnounce->DeviceType == RDPDR_DTYP_SMARTCARD &&
  569. FindDeviceByDosName(DeviceAnnounce->PreferredDosName, Device, TRUE)) {
  570. SmartPtr<DrSmartCard> SmartCard((DrSmartCard*)(DrDevice *)Device);
  571. SmartCard->ClientConnect(DeviceAnnounce, DeviceAnnounce->DeviceDataLength);
  572. Status = STATUS_SUCCESS;
  573. }
  574. else {
  575. Status = STATUS_INSUFFICIENT_RESOURCES;
  576. }
  577. }
  578. }
  579. //
  580. // Notify the client of the results
  581. //
  582. DeviceReplyWrite(DeviceAnnounce->DeviceId, Status);
  583. }
  584. VOID DrDeviceManager::ProcessDeviceRemove(PRDPDR_DEVICE_REMOVE DeviceRemove)
  585. /*++
  586. Routine Description:
  587. Processes a device remove, sends a reply and adds it if appropriate
  588. Arguments:
  589. DeviceRemove - The actual device that was reported
  590. Return Value:
  591. None
  592. --*/
  593. {
  594. SmartPtr<DrDevice> Device;
  595. SmartPtr<DrSession> Session = _Session;
  596. BEGIN_FN("DrDeviceManager::ProcessDeviceRemove");
  597. TRC_NRM((TB, "Device id %ld for removal",
  598. DeviceRemove->DeviceId));
  599. //
  600. // Check to make sure the device exists
  601. //
  602. if (FindDeviceById(DeviceRemove->DeviceId, Device)) {
  603. //
  604. // Found the device, now remove it
  605. //
  606. Device->Remove();
  607. RemoveDevice(Device);
  608. Device = NULL;
  609. } else {
  610. TRC_ALT((TB, "Client announced an invalid device, discarding"));
  611. }
  612. }
  613. BOOL DrDeviceManager::AddDevice(SmartPtr<DrDevice> &Device)
  614. /*++
  615. Routine Description:
  616. Adds a completely initialized Device to the list
  617. Arguments:
  618. Device - The device to be added
  619. Return Value:
  620. Boolean indicating success
  621. --*/
  622. {
  623. BOOL rc = FALSE;
  624. SmartPtr<DrDevice> DeviceFound;
  625. BEGIN_FN("DrDeviceManager::AddDevice");
  626. //
  627. // Explicit AddRef
  628. //
  629. ASSERT(Device != NULL);
  630. ASSERT(Device->IsValid());
  631. _DeviceList.LockExclusive();
  632. if (Device->GetDeviceType() == RDPDR_DTYP_SMARTCARD) {
  633. if (FindDeviceByDosName((UCHAR *)DR_SMARTCARD_SUBSYSTEM, DeviceFound, TRUE)) {
  634. goto EXIT;
  635. }
  636. }
  637. Device->AddRef();
  638. //
  639. // Add it to the list
  640. //
  641. if (_DeviceList.CreateEntry((DrDevice *)Device)) {
  642. //
  643. // successfully added this entry
  644. //
  645. rc = TRUE;
  646. } else {
  647. //
  648. // Unable to add it to the list, clean up
  649. //
  650. Device->Release();
  651. rc = FALSE;
  652. }
  653. EXIT:
  654. _DeviceList.Unlock();
  655. return rc;
  656. }
  657. BOOL DrDeviceManager::FindDeviceById(ULONG DeviceId,
  658. SmartPtr<DrDevice> &DeviceFound, BOOL fMustBeValid)
  659. /*++
  660. Routine Description:
  661. Finds a device in the list
  662. Arguments:
  663. DeviceId - The id of the device to find
  664. DeviceFound - The location to store the result
  665. fMustBeValid - Whether it must be valid for use or can be in any state
  666. Return Value:
  667. Boolean indicating success
  668. --*/
  669. {
  670. DrDevice *DeviceEnum;
  671. ListEntry *ListEnum;
  672. BOOL Found = FALSE;
  673. BEGIN_FN("DrDeviceManager::FindDeviceById");
  674. TRC_NRM((TB, "Id(%lu), %d", DeviceId, fMustBeValid));
  675. _DeviceList.LockShared();
  676. ListEnum = _DeviceList.First();
  677. while (ListEnum != NULL) {
  678. DeviceEnum = (DrDevice *)ListEnum->Node();
  679. ASSERT(DeviceEnum->IsValid());
  680. if (DeviceEnum->GetDeviceId() == DeviceId) {
  681. TRC_DBG((TB, "Found matching device Id"));
  682. if (!fMustBeValid || (DeviceEnum->IsAvailable())) {
  683. DeviceFound = DeviceEnum;
  684. }
  685. //
  686. // These aren't guaranteed valid once the resource is released
  687. //
  688. DeviceEnum = NULL;
  689. ListEnum = NULL;
  690. break;
  691. }
  692. ListEnum = _DeviceList.Next(ListEnum);
  693. }
  694. _DeviceList.Unlock();
  695. return DeviceFound != NULL;
  696. }
  697. BOOL DrDeviceManager::FindDeviceByDosName(UCHAR *DeviceDosName,
  698. SmartPtr<DrDevice> &DeviceFound, BOOL fMustBeValid)
  699. /*++
  700. Routine Description:
  701. Finds a device in the list
  702. Arguments:
  703. DeviceDosName - The DOS name of the device to find
  704. DeviceFound - The location to store the result
  705. fMustBeValid - Whether it must be valid for use or can be in any state
  706. Return Value:
  707. Boolean indicating success
  708. --*/
  709. {
  710. DrDevice *DeviceEnum;
  711. ListEntry *ListEnum;
  712. BOOL Found = FALSE;
  713. BEGIN_FN("DrDeviceManager::FindDeviceByDosName");
  714. TRC_NRM((TB, "DosName(%s), %d", DeviceDosName, fMustBeValid));
  715. _DeviceList.LockShared();
  716. ListEnum = _DeviceList.First();
  717. while (ListEnum != NULL) {
  718. DeviceEnum = (DrDevice *)ListEnum->Node();
  719. ASSERT(DeviceEnum->IsValid());
  720. if (_stricmp((CHAR *)(DeviceEnum->GetDeviceDosName()), (CHAR *)(DeviceDosName)) == 0) {
  721. TRC_DBG((TB, "Found matching device Dos Name"));
  722. if (!fMustBeValid || (DeviceEnum->IsAvailable())) {
  723. DeviceFound = DeviceEnum;
  724. }
  725. //
  726. // These aren't guaranteed valid once the resource is released
  727. //
  728. DeviceEnum = NULL;
  729. ListEnum = NULL;
  730. break;
  731. }
  732. ListEnum = _DeviceList.Next(ListEnum);
  733. }
  734. _DeviceList.Unlock();
  735. return DeviceFound != NULL;
  736. }
  737. VOID DrDeviceManager::Disconnect()
  738. {
  739. BEGIN_FN("DrDeviceManager::Disconnect");
  740. RemoveAll();
  741. }
  742. VOID DrDeviceManager::RemoveAll()
  743. {
  744. DrDevice *DeviceEnum;
  745. ListEntry *ListEnum;
  746. BOOL Found = FALSE;
  747. BEGIN_FN("DrDeviceManager::RemoveAll");
  748. _DeviceList.LockExclusive();
  749. ListEnum = _DeviceList.First();
  750. while (ListEnum != NULL) {
  751. DeviceEnum = (DrDevice *)ListEnum->Node();
  752. if (!DeviceEnum->SupportDiscon()) {
  753. _DeviceList.RemoveEntry(ListEnum);
  754. DeviceEnum->Remove();
  755. DeviceEnum->Release();
  756. ListEnum = _DeviceList.First();
  757. }
  758. else {
  759. DeviceEnum->Disconnect();
  760. ListEnum = _DeviceList.Next(ListEnum);
  761. }
  762. }
  763. _DeviceList.Unlock();
  764. }
  765. VOID DrDeviceManager::RemoveDevice(SmartPtr<DrDevice> &Device)
  766. {
  767. DrDevice *DeviceEnum;
  768. ListEntry *ListEnum;
  769. BOOL Found = FALSE;
  770. BEGIN_FN("DrDeviceManager::RemoveDevice");
  771. _DeviceList.LockExclusive();
  772. ListEnum = _DeviceList.First();
  773. while (ListEnum != NULL) {
  774. DeviceEnum = (DrDevice *)ListEnum->Node();
  775. if (DeviceEnum == Device) {
  776. TRC_DBG((TB, "Found matching device"));
  777. Found = TRUE;
  778. break;
  779. }
  780. ListEnum = _DeviceList.Next(ListEnum);
  781. }
  782. if (Found) {
  783. _DeviceList.RemoveEntry(ListEnum);
  784. Device->Release();
  785. }
  786. else {
  787. TRC_DBG((TB, "Not found device for remove"));
  788. }
  789. _DeviceList.Unlock();
  790. }
  791. VOID DrDeviceManager::DeviceReplyWrite(ULONG DeviceId, NTSTATUS Result)
  792. /*++
  793. Routine Description:
  794. Sends a DeviceReply packet to the client
  795. Arguments:
  796. ClientEntry - Pointer to data about the particular client
  797. Return Value:
  798. NTSTATUS - Success/failure indication of the operation
  799. --*/
  800. {
  801. PRDPDR_DEVICE_REPLY_PACKET pDeviceReplyPacket;
  802. BEGIN_FN("DrDeviceManager::DeviceReplyWrite");
  803. //
  804. // Construct the packet
  805. //
  806. pDeviceReplyPacket = new RDPDR_DEVICE_REPLY_PACKET;
  807. if (pDeviceReplyPacket != NULL) {
  808. pDeviceReplyPacket->Header.Component = RDPDR_CTYP_CORE;
  809. pDeviceReplyPacket->Header.PacketId = DR_CORE_DEVICE_REPLY;
  810. pDeviceReplyPacket->DeviceReply.DeviceId = DeviceId;
  811. pDeviceReplyPacket->DeviceReply.ResultCode = Result;
  812. //
  813. // We use the async send, so don't free the buffer
  814. //
  815. _Session->SendToClient(pDeviceReplyPacket, sizeof(RDPDR_DEVICE_REPLY_PACKET),
  816. this, TRUE);
  817. }
  818. }
  819. NTSTATUS DrDeviceManager::SendCompleted(PVOID Context,
  820. PIO_STATUS_BLOCK IoStatusBlock)
  821. {
  822. BEGIN_FN("DrDeviceManager::SendCompleted");
  823. return IoStatusBlock->Status;
  824. }