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.

1412 lines
34 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. proc.cpp
  5. Abstract:
  6. This module contains shared code and protocol parsing functionality
  7. for the port redirector dll in win32/wince environments.
  8. Don't like the way server message clean up is handled.
  9. There should be an object that wraps its way around a request packet
  10. to automatically clean up. The current mechanism is prone to memory
  11. leaks and dangling pointers. I would REALLY like to clean this up
  12. because it WILL cause problems when we try to implement future
  13. devices, but need to get approval from Madan, first.
  14. See the old client's ProcObj::UpdateDriverName function for
  15. how to handle making sure that if the driver name changes for cached
  16. information, we whack the cached information.
  17. Author:
  18. madan appiah (madana) 16-Sep-1998
  19. Revision History:
  20. --*/
  21. #include <precom.h>
  22. #define TRC_FILE "proc"
  23. #include <winsock.h>
  24. //
  25. // Include the platform-specific classes.
  26. //
  27. #include "w32draut.h"
  28. #include "w32drman.h"
  29. #include "w32drlpt.h"
  30. #include "w32drcom.h"
  31. #include "w32proc.h"
  32. #include "w32drdev.h"
  33. #include "w32drive.h"
  34. #if ((!defined(OS_WINCE)) || (!defined(WINCE_SDKBUILD)))
  35. #include "w32scard.h"
  36. #endif
  37. #include "drconfig.h"
  38. #include "drdbg.h"
  39. #ifdef OS_WINCE
  40. #include "filemgr.h"
  41. #endif
  42. ///////////////////////////////////////////////////////////////
  43. //
  44. // ProcObj Data Members
  45. //
  46. //
  47. // Device Enumeration Function Pointer List
  48. //
  49. // A function should be added for each class of device being
  50. // redirected. There should be a separate instance of this
  51. // array for each client platform.
  52. //
  53. RDPDeviceEnum ProcObj::_DeviceEnumFunctions[] =
  54. {
  55. #ifndef OS_WINCE
  56. W32DrAutoPrn::Enumerate,
  57. #endif
  58. W32DrManualPrn::Enumerate,
  59. W32DrCOM::Enumerate,
  60. W32DrLPT::Enumerate,
  61. W32Drive::Enumerate,
  62. #if ((!defined(OS_WINCE)) || (!defined(WINCE_SDKBUILD)))
  63. W32SCard::Enumerate
  64. #endif
  65. };
  66. ///////////////////////////////////////////////////////////////
  67. //
  68. // ProcObj Methods
  69. //
  70. ProcObj *ProcObj::Instantiate(VCManager *virtualChannelMgr)
  71. /*++
  72. Routine Description:
  73. Create the correct instance of this class.
  74. Arguments:
  75. virtualChannelMgr - Associated Virtual Channel IO Manager
  76. Return Value:
  77. NULL if the object could not be created.
  78. --*/
  79. {
  80. DC_BEGIN_FN("ProcObj::Instantiate");
  81. TRC_NRM((TB, _T("Win9x, CE, or NT detected.")));
  82. DC_END_FN();
  83. return new W32ProcObj(virtualChannelMgr);
  84. }
  85. ProcObj::ProcObj(
  86. IN VCManager *pVCM
  87. )
  88. /*++
  89. Routine Description:
  90. Constructor
  91. Arguments:
  92. NA
  93. Return Value:
  94. NA
  95. --*/
  96. {
  97. DC_BEGIN_FN("ProcObj::ProcObj");
  98. //
  99. // Initialize Data Members
  100. //
  101. _pVCMgr = pVCM;
  102. _sServerVersion.Major = 0;
  103. _sServerVersion.Minor = 0;
  104. _bDisableDeviceRedirection = FALSE;
  105. _deviceMgr = NULL;
  106. //
  107. // Initialize the client capability set
  108. // This is the capability set that we'll send to server
  109. //
  110. memcpy(&_cCapabilitySet, &CLIENT_CAPABILITY_SET_DEFAULT,
  111. sizeof(CLIENT_CAPABILITY_SET_DEFAULT));
  112. //
  113. // Initialize the server capability set
  114. // Once we receive the server side capability, we'll combine with our local
  115. // capability and stores it.
  116. //
  117. memcpy(&_sCapabilitySet, &SERVER_CAPABILITY_SET_DEFAULT,
  118. sizeof(SERVER_CAPABILITY_SET_DEFAULT));
  119. //
  120. //
  121. // This instance has not yet been initialized.
  122. //
  123. _initialized = FALSE;
  124. DC_END_FN();
  125. }
  126. ProcObj::~ProcObj()
  127. /*++
  128. Routine Description:
  129. Destructor
  130. Arguments:
  131. NA
  132. Return Value:
  133. NA
  134. --*/
  135. {
  136. DrDevice *dev;
  137. DC_BEGIN_FN("ProcObj::~ProcObj");
  138. //
  139. // Clean up the device management list.
  140. //
  141. if (_deviceMgr != NULL) {
  142. _deviceMgr->Lock();
  143. while ((dev = _deviceMgr->GetFirstObject()) != NULL) {
  144. _deviceMgr->RemoveObject(dev->GetID());
  145. delete dev;
  146. }
  147. _deviceMgr->Unlock();
  148. delete _deviceMgr;
  149. }
  150. #if (defined(OS_WINCE)) && (!defined(WINCE_SDKBUILD)) //delete this after all the devices in the device manager have been removed
  151. if (gpCEFileMgr) {
  152. gpCEFileMgr->Uninitialize();
  153. delete gpCEFileMgr;
  154. gpCEFileMgr = NULL;
  155. }
  156. #endif
  157. DC_END_FN();
  158. }
  159. ULONG
  160. ProcObj::Initialize()
  161. /*++
  162. Routine Description:
  163. Initialize an instance of this class.
  164. Arguments:
  165. NA
  166. Return Value:
  167. ERROR_SUCCESS on success. Windows error status, otherwise.
  168. --*/
  169. {
  170. DC_BEGIN_FN("ProcObj::Initialize");
  171. DWORD result = ERROR_SUCCESS;
  172. //
  173. // Fetch Configurable Variables.
  174. //
  175. GetDWordParameter(RDPDR_DISABLE_DR_PARAM, &_bDisableDeviceRedirection);
  176. _deviceMgr = new DrDeviceMgr();
  177. if (_deviceMgr == NULL) {
  178. TRC_ERR((TB, L"Error allocating device manager."));
  179. result = ERROR_NOT_ENOUGH_MEMORY;
  180. goto CLEANUPANDEXIT;
  181. }
  182. result = _deviceMgr->Initialize();
  183. if (result != ERROR_SUCCESS) {
  184. delete _deviceMgr;
  185. _deviceMgr = NULL;
  186. goto CLEANUPANDEXIT;
  187. }
  188. #if (defined(OS_WINCE)) && (!defined(WINCE_SDKBUILD))
  189. TRC_ASSERT((gpCEFileMgr == NULL), (TB, _T("gpCEFileMgr is not NULL")));
  190. gpCEFileMgr = new CEFileMgr();
  191. if (gpCEFileMgr) {
  192. if (!gpCEFileMgr->Initialize()) {
  193. delete gpCEFileMgr;
  194. gpCEFileMgr = NULL;
  195. }
  196. }
  197. if (!gpCEFileMgr) {
  198. TRC_ERR((TB, _T("Memory allocation failed.")));
  199. delete _deviceMgr;
  200. _deviceMgr = NULL;
  201. result = ERROR_NOT_ENOUGH_MEMORY;
  202. goto CLEANUPANDEXIT;
  203. }
  204. #endif
  205. _initialized = TRUE;
  206. CLEANUPANDEXIT:
  207. DC_END_FN();
  208. return result;
  209. }
  210. DWORD
  211. ProcObj::DeviceEnumFunctionsCount()
  212. /*++
  213. Routine Description:
  214. Return the number of entries in the device enum function array.
  215. Arguments:
  216. Return Value:
  217. --*/
  218. {
  219. return(sizeof(_DeviceEnumFunctions) / sizeof(RDPDeviceEnum));
  220. }
  221. VOID
  222. ProcObj::ProcessIORequestPacket(
  223. PRDPDR_IOREQUEST_PACKET pIoRequestPacket,
  224. UINT32 packetLen
  225. )
  226. /*++
  227. Routine Description:
  228. Process an IO request packet.
  229. Arguments:
  230. pData - RDPDR packet as received by VC.
  231. packetLen - length of the packet
  232. Return Value:
  233. TRUE - if the IO completed.
  234. FALSE - if the IO pending and asynchronously completes.
  235. --*/
  236. {
  237. PRDPDR_DEVICE_IOREQUEST pIoRequest = &pIoRequestPacket->IoRequest;
  238. ULONG ulSize = 0;
  239. DC_BEGIN_FN("ProcObj::ProcessIORequestPacket");
  240. ASSERT(_initialized);
  241. //
  242. // Hand it to the proper device object.
  243. //
  244. DrDevice *device = _deviceMgr->GetObject(pIoRequest->DeviceId);
  245. //
  246. // If we have a device then hand off the object to handle the request.
  247. //
  248. if (device != NULL) {
  249. device->ProcessIORequest(pIoRequestPacket, packetLen);
  250. }
  251. //
  252. // Otherwise, clean up the server message because the transaction is
  253. // complete.
  254. //
  255. // No response is sent to server.
  256. //
  257. else {
  258. delete pIoRequestPacket;
  259. }
  260. DC_END_FN();
  261. }
  262. VOID
  263. ProcObj::ProcessServerPacket(
  264. PVC_TX_DATA pData
  265. )
  266. /*++
  267. Routine Description:
  268. Parses the protocol and delegates functionality to a whole horde of
  269. overloaded functions.
  270. This is the main entry point for all device-redirection related
  271. operations.
  272. Arguments:
  273. pData - Data as received from the RDP Virtual Channel interface.
  274. Return Value:
  275. NA
  276. --*/
  277. {
  278. DC_BEGIN_FN("ProcObj::Process");
  279. PRDPDR_HEADER pRdpdrHeader;
  280. ASSERT(_initialized);
  281. //
  282. // Get the header.
  283. //
  284. pRdpdrHeader = (PRDPDR_HEADER)(pData->pbData);
  285. //
  286. // Assert that it is valid.
  287. //
  288. ASSERT(IsValidHeader(pRdpdrHeader));
  289. TRC_NRM((TB, _T("Processing component[%x], packetId[%x], ")
  290. _T("component[%c%c], packetid[%c%c]."),
  291. pRdpdrHeader->Component, pRdpdrHeader->PacketId,
  292. HIBYTE(pRdpdrHeader->Component), LOBYTE(pRdpdrHeader->Component),
  293. HIBYTE(pRdpdrHeader->PacketId),LOBYTE(pRdpdrHeader->PacketId))
  294. );
  295. //
  296. // See if it's a CORE packet.
  297. //
  298. if (pRdpdrHeader->Component == RDPDR_CTYP_CORE) {
  299. ProcessCoreServerPacket(pRdpdrHeader, pData->uiLength);
  300. }
  301. //
  302. // If it's print-specific, hand it off to a static print-specific
  303. // function. Ideally, this would have been handled transparently by
  304. // having the server-side component send the message directly to the
  305. // appropriate client-side object. The current protocol prohibits this,
  306. // however.
  307. //
  308. else if( pRdpdrHeader->Component == RDPDR_CTYP_PRN ) {
  309. switch (pRdpdrHeader->PacketId) {
  310. case DR_PRN_CACHE_DATA : {
  311. TRC_NRM((TB, _T("DR_CORE_DEVICE_CACHE_DATA")));
  312. PRDPDR_PRINTER_CACHEDATA_PACKET pCachePacket;
  313. pCachePacket = (PRDPDR_PRINTER_CACHEDATA_PACKET)pRdpdrHeader;
  314. W32DrPRN::ProcessPrinterCacheInfo(pCachePacket, pData->uiLength);
  315. break;
  316. }
  317. default: {
  318. TRC_ALT((TB, _T("Invalid PacketID Issued, %ld."),
  319. pRdpdrHeader->PacketId)
  320. );
  321. break;
  322. }
  323. }
  324. }
  325. else {
  326. // We don't recognize the packet. Close the channel.
  327. GetVCMgr().ChannelClose();
  328. delete pRdpdrHeader;
  329. TRC_ALT((TB, _T("Unknown Component ID, %ld."), pRdpdrHeader->Component ));
  330. }
  331. DC_END_FN();
  332. return;
  333. }
  334. VOID
  335. ProcObj::ProcessCoreServerPacket(
  336. PRDPDR_HEADER pRdpdrHeader,
  337. UINT32 packetLen
  338. )
  339. /*++
  340. Routine Description:
  341. Handle a "core" server packet.
  342. Arguments:
  343. rRdpdrHeader - Header for packet.
  344. packetLen - Length of packet.
  345. Return Value:
  346. NA
  347. --*/
  348. {
  349. DC_BEGIN_FN("ProcObj::ProcessCoreServerPacket");
  350. ASSERT(_initialized);
  351. //
  352. // Switch on the packetID.
  353. //
  354. switch (pRdpdrHeader->PacketId) {
  355. case DR_CORE_SERVER_ANNOUNCE : {
  356. TRC_NRM((TB, _T("DR_CORE_SERVER_ANNOUNCE")));
  357. //
  358. // check to see we have a matching server.
  359. //
  360. if (packetLen != sizeof(RDPDR_SERVER_ANNOUNCE_PACKET) ) {
  361. ASSERT(packetLen < sizeof(RDPDR_SERVER_ANNOUNCE_PACKET));
  362. //
  363. // we got a server announcement from an old version
  364. // server that didn't have have any version info.
  365. // simply return.
  366. //
  367. TRC_ERR((TB, _T("Mismatch server.")));
  368. break;
  369. }
  370. MsgCoreAnnounce( (PRDPDR_SERVER_ANNOUNCE_PACKET)pRdpdrHeader );
  371. break;
  372. }
  373. case DR_CORE_CLIENTID_CONFIRM : {
  374. TRC_NRM((TB, _T("DR_CORE_CLIENTID_CONFIRM")));
  375. //
  376. // Send the client capability to the server if the server
  377. // supports capability exchange
  378. //
  379. if (COMPARE_VERSION(_sServerVersion.Minor, _sServerVersion.Major,
  380. 5, 1) >= 0) {
  381. AnnounceClientCapability();
  382. }
  383. //
  384. // Send client computer display name if server supports it
  385. //
  386. AnnounceClientDisplayName();
  387. // Don't announce devices if device redirection is disabled.
  388. //
  389. if (!_bDisableDeviceRedirection) {
  390. //
  391. // Announce redirected devices to the server via the subclass.
  392. //
  393. AnnounceDevicesToServer();
  394. }
  395. //
  396. // Clean up the server message because the transaction is
  397. // complete.
  398. //
  399. delete pRdpdrHeader;
  400. break;
  401. }
  402. case DR_CORE_SERVER_CAPABILITY : {
  403. TRC_NRM((TB, _T("DR_CORE_SERVER_CAPABILITY")));
  404. //
  405. // Received server capability set
  406. //
  407. OnServerCapability(pRdpdrHeader, packetLen);
  408. //
  409. // Cleanup the message because the transaction is complete
  410. //
  411. delete pRdpdrHeader;
  412. break;
  413. }
  414. case DR_CORE_DEVICE_REPLY : {
  415. TRC_NRM((TB, _T("DR_CORE_DEVICE_REPLY")));
  416. PRDPDR_DEVICE_REPLY_PACKET pReply =
  417. (PRDPDR_DEVICE_REPLY_PACKET)pRdpdrHeader;
  418. TRC_NRM((TB, _T("Reply Device[0x%x], Code[0x%x]"),
  419. pReply->DeviceReply.DeviceId,
  420. pReply->DeviceReply.ResultCode)
  421. );
  422. //
  423. // Clean up the server message because the transaction is
  424. // complete.
  425. //
  426. delete pRdpdrHeader;
  427. break;
  428. }
  429. case DR_CORE_DEVICELIST_REPLY : {
  430. TRC_NRM((TB, _T("DR_CORE_DEVICELIST_REPLY")));
  431. PRDPDR_DEVICE_REPLY_PACKET pReply =
  432. (PRDPDR_DEVICE_REPLY_PACKET)pRdpdrHeader;
  433. TRC_NRM((TB, _T("Reply Device[0x%x], Code[0x%x]"),
  434. pReply->DeviceReply.DeviceId,
  435. pReply->DeviceReply.ResultCode)
  436. );
  437. //
  438. // Clean up the server message because the transaction is
  439. // complete.
  440. //
  441. delete pRdpdrHeader;
  442. break;
  443. }
  444. case DR_CORE_DEVICE_IOREQUEST : {
  445. TRC_NRM((TB, _T("DR_CORE_DEVICE_IOREQUEST")));
  446. // Make sure packetLen is at least sizeof(RDPDR_IOREQUEST_PACKET)
  447. if (packetLen >= sizeof(RDPDR_IOREQUEST_PACKET)) {
  448. ProcessIORequestPacket((PRDPDR_IOREQUEST_PACKET)pRdpdrHeader, packetLen);
  449. TRC_NRM((TB, _T("MajorFunction processing completed.")));
  450. }
  451. else {
  452. // VirtualChannelClose
  453. GetVCMgr().ChannelClose();
  454. TRC_ASSERT(FALSE, (TB, _T("Packet Length Error")));
  455. delete pRdpdrHeader;
  456. }
  457. break; // DR_CORE_DEVICE_IOREQUEST
  458. }
  459. default: {
  460. TRC_ALT((TB, _T("Invalid PacketID Issued, %ld."),
  461. pRdpdrHeader->PacketId)
  462. );
  463. // We don't recognize the packet. Close the channel.
  464. GetVCMgr().ChannelClose();
  465. //
  466. // Clean up the server message because the transaction is
  467. // complete.
  468. //
  469. delete pRdpdrHeader;
  470. break;
  471. }
  472. }
  473. DC_END_FN();
  474. }
  475. VOID
  476. ProcObj::MsgCoreAnnounce(
  477. PRDPDR_SERVER_ANNOUNCE_PACKET pAnnounce
  478. )
  479. /*++
  480. Routine Description:
  481. Processing for the Server Announce message. Generates and exports
  482. the client confirmation as well as valid the device list.
  483. Arguments:
  484. pAnnounce - The data from the server minus the unnecessary headers.
  485. Return Value:
  486. Pointer to static function data containing the filename.
  487. --*/
  488. {
  489. DrDevice *device;
  490. DC_BEGIN_FN("ProcObj::MsgCoreAnnounce");
  491. PRDPDR_CLIENT_CONFIRM_PACKET pClientConfirmPacket;
  492. PRDPDR_CLIENT_NAME_PACKET pClientNamePacket;
  493. ASSERT(_initialized);
  494. //
  495. // check server version info.
  496. //
  497. if( (pAnnounce->VersionInfo.Major != RDPDR_MAJOR_VERSION) ||
  498. (pAnnounce->VersionInfo.Minor < 1) ) {
  499. TRC_ERR((TB, _T("Server version mismatch.")));
  500. goto Cleanup;
  501. }
  502. //
  503. // Flush devices to make sure they don't have any outstanding IRPs
  504. // from a previous connection
  505. //
  506. _deviceMgr->Lock();
  507. device = _deviceMgr->GetFirstObject();
  508. while (device != NULL) {
  509. device->FlushIRPs();
  510. device = _deviceMgr->GetNextObject();
  511. }
  512. _deviceMgr->Unlock();
  513. //
  514. // save server version number.
  515. //
  516. _sServerVersion = pAnnounce->VersionInfo;
  517. pClientConfirmPacket = new RDPDR_CLIENT_CONFIRM_PACKET;
  518. if (pClientConfirmPacket == NULL) {
  519. TRC_ERR((TB, _T("Failed alloc memory.")));
  520. goto Cleanup;
  521. }
  522. pClientConfirmPacket->Header.Component = RDPDR_CTYP_CORE;
  523. pClientConfirmPacket->Header.PacketId = DR_CORE_CLIENTID_CONFIRM;
  524. ULONG ulClientID;
  525. ulClientID = GetClientID();
  526. //
  527. // fill in the client version info.
  528. //
  529. pClientConfirmPacket->VersionInfo.Major = RDPDR_MAJOR_VERSION;
  530. pClientConfirmPacket->VersionInfo.Minor = RDPDR_MINOR_VERSION;
  531. pClientConfirmPacket->ClientConfirm.ClientId =
  532. ( ulClientID != 0 ) ?
  533. ulClientID :
  534. pAnnounce->ServerAnnounce.ClientId;
  535. //
  536. // ulLen has the computer name length in bytes, add
  537. // RDPDR_CLIENT_CONFIRM_PACKET structure size, to
  538. // send just sufficient data.
  539. //
  540. _pVCMgr->ChannelWrite(pClientConfirmPacket, sizeof(RDPDR_CLIENT_CONFIRM_PACKET));
  541. //
  542. // now send the client computer name packet.
  543. //
  544. ULONG ulLen;
  545. ulLen =
  546. sizeof(RDPDR_CLIENT_NAME_PACKET) +
  547. ((MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR));
  548. pClientNamePacket = (PRDPDR_CLIENT_NAME_PACKET) new BYTE[ulLen];
  549. if (pClientNamePacket == NULL) {
  550. TRC_ERR((TB, _T("Failed alloc memory.")));
  551. goto Cleanup;
  552. }
  553. pClientNamePacket->Header.Component = RDPDR_CTYP_CORE;
  554. pClientNamePacket->Header.PacketId = DR_CORE_CLIENT_NAME;
  555. ulLen = ((MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR));
  556. BOOL bUnicodeFlag;
  557. GetClientComputerName(
  558. (PBYTE)(pClientNamePacket + 1),
  559. &ulLen,
  560. &bUnicodeFlag,
  561. &pClientNamePacket->Name.CodePage);
  562. pClientNamePacket->Name.Unicode = (bUnicodeFlag) ? TRUE : FALSE;
  563. pClientNamePacket->Name.ComputerNameLen = ulLen;
  564. ulLen += sizeof(RDPDR_CLIENT_NAME_PACKET);
  565. _pVCMgr->ChannelWrite(pClientNamePacket, (UINT)ulLen);
  566. //
  567. // don't free up the following buffers here, later a callback event from
  568. // the VC will do so.
  569. //
  570. // - pClientConfirmPacket
  571. // - pClientNamePacket
  572. //
  573. Cleanup:
  574. //
  575. // Release the announce packet since the transaction is now complete.
  576. //
  577. delete pAnnounce;
  578. DC_END_FN();
  579. }
  580. ULONG
  581. ProcObj::GetClientID(
  582. VOID
  583. )
  584. /*++
  585. Routine Description:
  586. Retrive the client ID. Currently we send the IP address of the client machine
  587. as its ID.
  588. Assume : Winsock is startup.
  589. Arguments:
  590. NONE
  591. Return Value:
  592. 0 - if we can't find a unique client ID.
  593. IP Address of the machine - otherwise.
  594. --*/
  595. {
  596. DC_BEGIN_FN("ProcObj::GetClientID");
  597. CHAR achHostName[MAX_PATH];
  598. INT iRetVal;
  599. ULONG ulClientID = 0;
  600. HOSTENT *pHostent;
  601. ASSERT(_initialized);
  602. iRetVal = gethostname( (PCHAR)achHostName, sizeof(achHostName) );
  603. if( iRetVal != 0 ) {
  604. iRetVal = WSAGetLastError();
  605. TRC_ERR((TB, _T("gethostname failed, %ld."), iRetVal));
  606. goto Cleanup;
  607. }
  608. pHostent = gethostbyname( (PCHAR)achHostName );
  609. if( pHostent == NULL ) {
  610. iRetVal = WSAGetLastError();
  611. TRC_ERR((TB, _T("gethostbyname() failed, %ld."), iRetVal));
  612. goto Cleanup;
  613. }
  614. //
  615. // get the first address from the host ent.
  616. //
  617. ULONG *pAddr;
  618. pAddr = (ULONG *)pHostent->h_addr_list[0];
  619. if( pAddr != NULL ) {
  620. ulClientID = *pAddr;
  621. }
  622. Cleanup:
  623. DC_END_FN();
  624. return ulClientID;
  625. }
  626. PRDPDR_HEADER
  627. ProcObj::GenerateAnnouncePacket(
  628. INT *piSize,
  629. BOOL bCheckDeviceChange
  630. )
  631. /*++
  632. Routine Description:
  633. Generate a device announcement packet.
  634. Arguments:
  635. piSize - pointer to an integer variables where the size of the list is
  636. returned.
  637. Return Value:
  638. pointer to a device announcement package.
  639. NULL - if the list generation fails.
  640. --*/
  641. {
  642. PRDPDR_HEADER pPacketHeader = NULL;
  643. PRDPDR_DEVICELIST_ANNOUNCE pDeviceListAnnounce;
  644. PRDPDR_DEVICE_ANNOUNCE pDeviceAnnounce;
  645. ULONG ulDeviceCount;
  646. ULONG announcePacketSize;
  647. DrDevice *device;
  648. DC_BEGIN_FN("ProcObj::GenerateAnnouncePacket");
  649. ASSERT(_initialized);
  650. //
  651. // Lock the list of devices.
  652. //
  653. _deviceMgr->Lock();
  654. //
  655. // Calculate the number of bytes required for the announce packet.
  656. //
  657. announcePacketSize = sizeof(RDPDR_HEADER) + sizeof(RDPDR_DEVICELIST_ANNOUNCE);
  658. device = _deviceMgr->GetFirstObject();
  659. if (device == NULL) {
  660. TRC_NRM((TB, _T("Zero devices found.")));
  661. goto Cleanup;
  662. }
  663. while (device != NULL) {
  664. if (!bCheckDeviceChange || device->_deviceChange == DEVICENEW) {
  665. announcePacketSize += device->GetDevAnnounceDataSize();
  666. }
  667. device = _deviceMgr->GetNextObject();
  668. }
  669. //
  670. // Allocate the announcement packet header.
  671. //
  672. pPacketHeader = (PRDPDR_HEADER)new BYTE[announcePacketSize];
  673. if( pPacketHeader == NULL ) {
  674. TRC_ERR((TB, _T("Memory Allocation failed.")));
  675. goto Cleanup;
  676. }
  677. memset(pPacketHeader, 0, (size_t)announcePacketSize);
  678. //
  679. // Get pointers to the relevant packet header fields.
  680. //
  681. pDeviceListAnnounce = (PRDPDR_DEVICELIST_ANNOUNCE)(pPacketHeader + 1);
  682. pDeviceAnnounce = (PRDPDR_DEVICE_ANNOUNCE)(pDeviceListAnnounce + 1);
  683. //
  684. // Have each device object add its own device announcement information.
  685. //
  686. PBYTE pbPacketEnd;
  687. pbPacketEnd = ((PBYTE)pPacketHeader) + announcePacketSize;
  688. ulDeviceCount = 0;
  689. device = _deviceMgr->GetFirstObject();
  690. while (device != NULL) {
  691. if (!bCheckDeviceChange || device->_deviceChange == DEVICENEW) {
  692. //
  693. // Increment the device count.
  694. //
  695. ulDeviceCount++;
  696. //
  697. // Get the current devices data.
  698. //
  699. device->GetDevAnnounceData(pDeviceAnnounce);
  700. device->_deviceChange = DEVICEANNOUCED;
  701. //
  702. // Move to the next location in the announce packet.
  703. //
  704. pDeviceAnnounce = (PRDPDR_DEVICE_ANNOUNCE)(
  705. ((PBYTE)pDeviceAnnounce) +
  706. device->GetDevAnnounceDataSize()
  707. );
  708. }
  709. //
  710. // Get the next device.
  711. //
  712. device = _deviceMgr->GetNextObject();
  713. }
  714. //
  715. // Record the device count to the device list announce header.
  716. //
  717. pDeviceListAnnounce->DeviceCount = ulDeviceCount;
  718. //
  719. // Return the size of the buffer.
  720. //
  721. *piSize = (INT)announcePacketSize;
  722. Cleanup:
  723. //
  724. // Unlock the device list.
  725. //
  726. _deviceMgr->Unlock();
  727. TRC_NRM((TB, _T("Announcing %ld Devices."), ulDeviceCount));
  728. //
  729. // Return the buffer.
  730. //
  731. DC_END_FN();
  732. return pPacketHeader;
  733. }
  734. PRDPDR_HEADER
  735. ProcObj::GenerateDeviceRemovePacket(
  736. INT *piSize
  737. )
  738. /*++
  739. Routine Description:
  740. Generate a device remove packet.
  741. Arguments:
  742. piSize - pointer to an integer variables where the size of the list is
  743. returned.
  744. Return Value:
  745. pointer to a device remove package.
  746. NULL - if the list generation fails.
  747. --*/
  748. {
  749. PRDPDR_HEADER pPacketHeader = NULL;
  750. PRDPDR_DEVICELIST_REMOVE pDeviceListRemove;
  751. PRDPDR_DEVICE_REMOVE pDeviceRemove;
  752. ULONG ulDeviceCount;
  753. ULONG removePacketSize;
  754. DrDevice *device;
  755. DC_BEGIN_FN("ProcObj::GenerateDeviceRemovePacket");
  756. ASSERT(_initialized);
  757. //
  758. // Lock the list of devices.
  759. //
  760. _deviceMgr->Lock();
  761. //
  762. // Calculate the number of bytes required for the announce packet.
  763. //
  764. removePacketSize = sizeof(RDPDR_HEADER) + sizeof(RDPDR_DEVICELIST_REMOVE);
  765. device = _deviceMgr->GetFirstObject();
  766. if (device == NULL) {
  767. TRC_NRM((TB, _T("Zero devices found.")));
  768. goto Cleanup;
  769. }
  770. ulDeviceCount = 0;
  771. while (device != NULL) {
  772. if (device->_deviceChange == DEVICEREMOVE) {
  773. ulDeviceCount++;
  774. }
  775. device = _deviceMgr->GetNextObject();
  776. }
  777. //
  778. // Didn't find any device to be removed
  779. //
  780. if (ulDeviceCount == 0) {
  781. TRC_NRM((TB, _T("Zero device for removal")));
  782. goto Cleanup;
  783. }
  784. removePacketSize += ulDeviceCount * sizeof(RDPDR_DEVICE_REMOVE);
  785. //
  786. // Allocate the announcement packet header.
  787. //
  788. pPacketHeader = (PRDPDR_HEADER)new BYTE[removePacketSize];
  789. if( pPacketHeader == NULL ) {
  790. TRC_ERR((TB, _T("Memory Allocation failed.")));
  791. goto Cleanup;
  792. }
  793. memset(pPacketHeader, 0, (size_t)removePacketSize);
  794. //
  795. // Get pointers to the relevant packet header fields.
  796. //
  797. pDeviceListRemove = (PRDPDR_DEVICELIST_REMOVE)(pPacketHeader + 1);
  798. pDeviceRemove = (PRDPDR_DEVICE_REMOVE)(pDeviceListRemove + 1);
  799. //
  800. // Have each device object add its own device remove information.
  801. //
  802. ulDeviceCount = 0;
  803. device = _deviceMgr->GetFirstObject();
  804. while (device != NULL) {
  805. if (device->_deviceChange == DEVICEREMOVE) {
  806. //
  807. // Increment the device count.
  808. //
  809. ulDeviceCount++;
  810. //
  811. // Get the current devices data.
  812. //
  813. pDeviceRemove->DeviceId = device->GetID();
  814. //
  815. // Move to the next location in the announce packet.
  816. //
  817. pDeviceRemove++;
  818. }
  819. //
  820. // Get the next device.
  821. //
  822. device = _deviceMgr->GetNextObject();
  823. }
  824. //
  825. // Record the device count to the device list announce header.
  826. //
  827. pDeviceListRemove->DeviceCount = ulDeviceCount;
  828. //
  829. // Return the size of the buffer.
  830. //
  831. *piSize = (INT)removePacketSize;
  832. Cleanup:
  833. //
  834. // Unlock the device list.
  835. //
  836. _deviceMgr->Unlock();
  837. TRC_NRM((TB, _T("Removing %ld Devices."), ulDeviceCount));
  838. //
  839. // Return the buffer.
  840. //
  841. DC_END_FN();
  842. return pPacketHeader;
  843. }
  844. VOID ProcObj::AnnounceClientCapability()
  845. /*++
  846. Routine Description:
  847. Generate a client capability set announcement packet.
  848. Arguments:
  849. N/A
  850. Return Value:
  851. N/A
  852. --*/
  853. {
  854. OSVERSIONINFO OsVersionInfo;
  855. PRDPDR_CLIENT_COMBINED_CAPABILITYSET pClientCapSet;
  856. DC_BEGIN_FN("ProcObj::AnnounceClientCapability");
  857. //
  858. // Setup the client OS version
  859. //
  860. OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  861. if (GetVersionEx(&OsVersionInfo)) {
  862. _cCapabilitySet.GeneralCap.osType = OsVersionInfo.dwPlatformId;
  863. //
  864. // Setup the client OS type
  865. //
  866. switch (_cCapabilitySet.GeneralCap.osType) {
  867. case VER_PLATFORM_WIN32_WINDOWS:
  868. _cCapabilitySet.GeneralCap.osType = RDPDR_OS_TYPE_WIN9X;
  869. break;
  870. case VER_PLATFORM_WIN32_NT:
  871. _cCapabilitySet.GeneralCap.osType = RDPDR_OS_TYPE_WINNT;
  872. break;
  873. case VER_PLATFORM_WIN32s:
  874. ASSERT(FALSE);
  875. break;
  876. default:
  877. _cCapabilitySet.GeneralCap.osType = RDPDR_OS_TYPE_UNKNOWN;
  878. }
  879. //
  880. // Setup the client OS version
  881. //
  882. _cCapabilitySet.GeneralCap.osVersion =
  883. MAKELONG(OsVersionInfo.dwMinorVersion, OsVersionInfo.dwMajorVersion);
  884. //
  885. // Since win9x doesn't support security, we don't adversise these IRPs
  886. //
  887. if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
  888. _cCapabilitySet.GeneralCap.ioCode1 &= ~RDPDR_IRP_MJ_QUERY_SECURITY;
  889. _cCapabilitySet.GeneralCap.ioCode1 &= ~RDPDR_IRP_MJ_SET_SECURITY;
  890. }
  891. }
  892. pClientCapSet = (PRDPDR_CLIENT_COMBINED_CAPABILITYSET) new
  893. BYTE[sizeof(RDPDR_CLIENT_COMBINED_CAPABILITYSET)];
  894. if (pClientCapSet != NULL) {
  895. memcpy(pClientCapSet, &_cCapabilitySet, sizeof(_cCapabilitySet));
  896. //
  897. // Send the client capability to the server
  898. //
  899. _pVCMgr->ChannelWrite(pClientCapSet, sizeof(_cCapabilitySet));
  900. }
  901. DC_END_FN();
  902. }
  903. void ProcObj::AnnounceClientDisplayName()
  904. {
  905. PRDPDR_CLIENT_DISPLAY_NAME_PACKET pClientDisplayNamePDU;
  906. unsigned ClientDisplayNameLen;
  907. WCHAR ClientDisplayName[RDPDR_MAX_CLIENT_DISPLAY_NAME];
  908. DC_BEGIN_FN("ProcObj::AnnounceClientDisplayName");
  909. ClientDisplayNameLen = 0;
  910. ClientDisplayName[0] = L'\0';
  911. if (_sCapabilitySet.GeneralCap.extendedPDU & RDPDR_CLIENT_DISPLAY_NAME_PDU) {
  912. //
  913. // TODO: Need to use shell API to get client display name
  914. //
  915. // ClientDisplayNameLen = (wcslen(ClientDisplayName) + 1) * sizeof(WCHAR);
  916. if (ClientDisplayNameLen) {
  917. pClientDisplayNamePDU = (PRDPDR_CLIENT_DISPLAY_NAME_PACKET) new
  918. BYTE[sizeof(RDPDR_CLIENT_DISPLAY_NAME_PACKET) + ClientDisplayNameLen];
  919. if (pClientDisplayNamePDU != NULL) {
  920. pClientDisplayNamePDU->Header.Component = RDPDR_CTYP_CORE;
  921. pClientDisplayNamePDU->Header.PacketId = DR_CORE_CLIENT_DISPLAY_NAME;
  922. pClientDisplayNamePDU->Name.ComputerDisplayNameLen = (BYTE)ClientDisplayNameLen;
  923. memcpy(pClientDisplayNamePDU + 1, ClientDisplayName, ClientDisplayNameLen);
  924. //
  925. // Send the client capability to the server
  926. //
  927. _pVCMgr->ChannelWrite(pClientDisplayNamePDU, sizeof(RDPDR_CLIENT_DISPLAY_NAME_PACKET) +
  928. ClientDisplayNameLen);
  929. }
  930. }
  931. }
  932. DC_END_FN();
  933. }
  934. BOOL ProcObj::InitServerCapability(PRDPDR_CAPABILITY_HEADER pCapHdr, PBYTE packetLimit)
  935. /*++
  936. Routine Description:
  937. On receiving server capability set, initialize it with the
  938. local default server capability set.
  939. Arguments:
  940. pCapHdr - Capability from the server
  941. Return Value:
  942. TRUE - if the server capability exists locally
  943. FALSE - if the local client doesn't support this capability
  944. --*/
  945. {
  946. BOOL rc = FALSE;
  947. //
  948. // Check the packet for minimum sizes
  949. //
  950. if ((PBYTE)(pCapHdr + 1) > packetLimit) {
  951. return rc;
  952. }
  953. switch(pCapHdr->capabilityType) {
  954. case RDPDR_GENERAL_CAPABILITY_TYPE:
  955. {
  956. PRDPDR_GENERAL_CAPABILITY pGeneralCap = (PRDPDR_GENERAL_CAPABILITY)pCapHdr;
  957. //
  958. // Check the packet data size for this type.
  959. // For the remaining, the above check will suffice.
  960. //
  961. if ((PBYTE)(pGeneralCap+1) <= packetLimit) {
  962. _sCapabilitySet.GeneralCap.version = pGeneralCap->version;
  963. _sCapabilitySet.GeneralCap.osType = pGeneralCap->osType;
  964. _sCapabilitySet.GeneralCap.osVersion = pGeneralCap->osVersion;
  965. _sCapabilitySet.GeneralCap.ioCode1 = pGeneralCap->ioCode1;
  966. _sCapabilitySet.GeneralCap.extendedPDU = pGeneralCap->extendedPDU;
  967. _sCapabilitySet.GeneralCap.protocolMajorVersion = pGeneralCap->protocolMajorVersion;
  968. _sCapabilitySet.GeneralCap.protocolMinorVersion = pGeneralCap->protocolMinorVersion;
  969. rc = TRUE;
  970. }
  971. }
  972. break;
  973. case RDPDR_PRINT_CAPABILITY_TYPE:
  974. {
  975. PRDPDR_PRINT_CAPABILITY pPrintCap = (PRDPDR_PRINT_CAPABILITY)pCapHdr;
  976. _sCapabilitySet.PrintCap.version = pPrintCap->version;
  977. rc = TRUE;
  978. }
  979. break;
  980. case RDPDR_PORT_CAPABILITY_TYPE:
  981. {
  982. PRDPDR_PORT_CAPABILITY pPortCap = (PRDPDR_PORT_CAPABILITY)pCapHdr;
  983. _sCapabilitySet.PortCap.version = pPortCap->version;
  984. rc = TRUE;
  985. }
  986. break;
  987. case RDPDR_FS_CAPABILITY_TYPE:
  988. {
  989. PRDPDR_FS_CAPABILITY pFsCap = (PRDPDR_FS_CAPABILITY)pCapHdr;
  990. _sCapabilitySet.FileSysCap.version = pFsCap->version;
  991. rc = TRUE;
  992. }
  993. break;
  994. case RDPDR_SMARTCARD_CAPABILITY_TYPE:
  995. {
  996. PRDPDR_SMARTCARD_CAPABILITY pSmartCardCap = (PRDPDR_SMARTCARD_CAPABILITY)pCapHdr;
  997. _sCapabilitySet.SmartCardCap.version = pSmartCardCap->version;
  998. rc = TRUE;
  999. }
  1000. break;
  1001. default:
  1002. rc = FALSE;
  1003. break;
  1004. }
  1005. return rc;
  1006. }
  1007. VOID ProcObj::OnServerCapability(PRDPDR_HEADER pRdpdrHeader, ULONG maxDataLength)
  1008. /*++
  1009. Routine Description:
  1010. On receiving server capability set.
  1011. Arguments:
  1012. pRdpdrHeader - Capability Set from the server
  1013. Return Value:
  1014. N/A
  1015. --*/
  1016. {
  1017. DC_BEGIN_FN("ProcObj::OnServerCapability");
  1018. //
  1019. // Validate data lengths
  1020. //
  1021. PBYTE packetLimit = ((PBYTE)pRdpdrHeader) + maxDataLength;
  1022. if (maxDataLength < sizeof(RDPDR_CAPABILITY_SET_HEADER)) {
  1023. TRC_ASSERT(FALSE,
  1024. (TB, _T("Server Capability Header Packet Length Error")));
  1025. TRC_ERR((TB, _T("Invalid Data Length for Server Capability Header")));
  1026. return;
  1027. }
  1028. PRDPDR_CAPABILITY_SET_HEADER pCapSetHeader = (PRDPDR_CAPABILITY_SET_HEADER)pRdpdrHeader;
  1029. PRDPDR_CAPABILITY_HEADER pCapHdr = (PRDPDR_CAPABILITY_HEADER)(pCapSetHeader + 1);
  1030. //
  1031. // Grab the supported capability info from server's capability PDU
  1032. //
  1033. for (unsigned i = 0; i < pCapSetHeader->numberCapabilities; i++) {
  1034. if (InitServerCapability(pCapHdr, packetLimit)) {
  1035. pCapHdr = (PRDPDR_CAPABILITY_HEADER)(((PBYTE)pCapHdr) + pCapHdr->capabilityLength);
  1036. }
  1037. else {
  1038. TRC_ASSERT(FALSE,
  1039. (TB, _T("Server Capability Packet Length Error")));
  1040. TRC_ERR((TB, _T("Invalid Data Length for Server Capability.")));
  1041. _pVCMgr->ChannelClose();
  1042. break;
  1043. }
  1044. }
  1045. DC_END_FN();
  1046. }