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.

1876 lines
47 KiB

  1. /*++
  2. Copyright (c) 1998-2000 Microsoft Corporation
  3. Module Name:
  4. w32drprn
  5. Abstract:
  6. This module defines the parent for the Win32 client-side RDP
  7. printer redirection "device" class hierarchy, W32DrPRN.
  8. Author:
  9. Tad Brockway 3/23/99
  10. Revision History:
  11. --*/
  12. #include <precom.h>
  13. #define TRC_FILE "W32DrPRN"
  14. #include <string.h>
  15. #include "w32drprn.h"
  16. #include "w32utl.h"
  17. #include "drobjmgr.h"
  18. #include "w32drman.h"
  19. #include "w32proc.h"
  20. #include "drdbg.h"
  21. #ifdef OS_WINCE
  22. #include "ceconfig.h"
  23. #endif
  24. DWORD W32DrPRN::_maxCacheDataSize = DEFAULT_MAXCACHELEN;
  25. ///////////////////////////////////////////////////////////////
  26. //
  27. // W32DrPRN Members
  28. //
  29. W32DrPRN::W32DrPRN(ProcObj *processObject, const DRSTRING printerName,
  30. const DRSTRING driverName, const DRSTRING portName,
  31. const DRSTRING pnpName,
  32. BOOL isDefaultPrinter, ULONG deviceID,
  33. const TCHAR *devicePath) :
  34. W32DrDeviceAsync(processObject, deviceID, devicePath),
  35. DrPRN(printerName, driverName, pnpName, isDefaultPrinter)
  36. /*++
  37. Routine Description:
  38. Constructor
  39. Arguments:
  40. printerName - Name of printing device.
  41. driverName - Name of print driver name.
  42. portName - Name of client-side printing port.
  43. pnpName - PnP ID String
  44. default - Is this the default printer?
  45. id - Unique device identifier for printing device.
  46. devicePath - Path to the device.
  47. Return Value:
  48. NA
  49. --*/
  50. {
  51. //
  52. // Record the port name.
  53. //
  54. SetPortName(portName);
  55. }
  56. W32DrPRN *
  57. W32DrPRN::ResolveCachedPrinter(
  58. IN ProcObj *procObj,
  59. IN DrDeviceMgr *deviceMgr,
  60. IN HKEY hParentKey,
  61. IN LPTSTR printerName
  62. )
  63. /*++
  64. Routine Description:
  65. Open the subkey of hParentKey associated with the specified
  66. printer name and instantiate a manual printer or find an existing
  67. automatic printer object in the device manager, depending on the
  68. type of cached data found.
  69. Arguments:
  70. procObj - Associated Processing Object.
  71. hParentKey - Parent key of printer key.
  72. printerName - Name of printer ... and name of printer subkey.
  73. Return Value:
  74. None.
  75. --*/
  76. {
  77. W32DrPRN *prnDevice = NULL;
  78. DWORD cachedDataSize;
  79. LPTSTR regValueName;
  80. LONG result;
  81. HKEY hPrinterKey;
  82. DWORD ulType;
  83. BOOL isManual = FALSE;
  84. DC_BEGIN_FN("W32DrPRN::ResolveCachedPrinter");
  85. //
  86. // Open the key for the cached printer.
  87. //
  88. result = RegCreateKeyEx(
  89. hParentKey, printerName, 0L,
  90. NULL, REG_OPTION_NON_VOLATILE,
  91. KEY_ALL_ACCESS, NULL,
  92. &hPrinterKey, NULL
  93. );
  94. if (result != ERROR_SUCCESS) {
  95. TRC_ERR((TB, _T("RegCreateKeyEx failed: %ld."),result));
  96. hPrinterKey = NULL;
  97. goto CleanUpAndExit;
  98. }
  99. //
  100. // See if the value name for the cached printer data is for
  101. // a manual printer.
  102. //
  103. regValueName = (LPTSTR)REG_RDPDR_PRINTER_CACHE_DATA;
  104. cachedDataSize = 0;
  105. #ifndef OS_WINCE
  106. result = RegQueryValueEx(hPrinterKey, regValueName,
  107. NULL, &ulType, NULL, &cachedDataSize
  108. );
  109. //
  110. // Check for hacks
  111. //
  112. if (cachedDataSize >= GetMaxCacheDataSize() * 1000) {
  113. ASSERT(FALSE);
  114. goto CleanUpAndExit;
  115. }
  116. #else
  117. cachedDataSize = GetCachedDataSize(hPrinterKey);
  118. #endif
  119. //
  120. // If no manual printer then check for an automatic printer.
  121. //
  122. if (result == ERROR_FILE_NOT_FOUND) {
  123. regValueName = (LPTSTR)REG_RDPDR_AUTO_PRN_CACHE_DATA;
  124. cachedDataSize = 0;
  125. result = RegQueryValueEx(hPrinterKey, regValueName,
  126. NULL, &ulType, NULL, &cachedDataSize
  127. );
  128. //
  129. // If the entry exists and has some data associated with it
  130. // then see if we have a corresponding automatic printer to
  131. // add the data to.
  132. //
  133. if ((result == ERROR_SUCCESS) && (cachedDataSize > 0)) {
  134. prnDevice = (W32DrPRN *)deviceMgr->GetObject(
  135. (LPTSTR)printerName,
  136. RDPDR_DTYP_PRINT
  137. );
  138. if (prnDevice != NULL) {
  139. ASSERT(!STRICMP(prnDevice->ClassName(), TEXT("W32DrAutoPrn")));
  140. }
  141. }
  142. else {
  143. prnDevice = NULL;
  144. }
  145. }
  146. //
  147. // Otherwise, if there is some actual cached data then instantiate
  148. // a manual printer object and add it to the device manager.
  149. //
  150. else if ((result == ERROR_SUCCESS) && (cachedDataSize > 0)) {
  151. TCHAR UniquePortName[MAX_PATH];
  152. ULONG DeviceId;
  153. isManual = TRUE;
  154. //
  155. // The unique port name is going to be passed to the server
  156. // as preferred dos name (max 7 characters long). As we want to
  157. // keep a unique dos name for each printer device, we need
  158. // to fake our own port name.
  159. //
  160. DeviceId = deviceMgr->GetUniqueObjectID();
  161. StringCchPrintf(UniquePortName,
  162. SIZE_TCHARS(UniquePortName),
  163. TEXT("PRN%ld"), DeviceId);
  164. UniquePortName[7] = TEXT('\0');
  165. #ifndef OS_WINCE
  166. prnDevice = new W32DrManualPrn(procObj, printerName, TEXT(""),
  167. UniquePortName, FALSE,
  168. DeviceId);
  169. #else
  170. //check of it is the default printer
  171. BOOL fDefault = FALSE;
  172. HKEY hk = NULL;
  173. WCHAR szWDefault[PREFERRED_DOS_NAME_SIZE];
  174. UCHAR szADefault[PREFERRED_DOS_NAME_SIZE];
  175. DWORD dwSize = sizeof(szWDefault);
  176. if ( (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_RDPDR_WINCE_DEFAULT_PRN, 0, 0, &hk)) &&
  177. (ERROR_SUCCESS == RegQueryValueEx(hk, NULL, NULL, &ulType, (LPBYTE )szWDefault, &dwSize)) &&
  178. (ulType == REG_SZ) && (dwSize < sizeof(szWDefault)) &&
  179. (WideCharToMultiByte(GetACP(), 0, szWDefault, -1, (char *)szADefault, sizeof(szADefault), NULL, NULL) > 0) )
  180. {
  181. UCHAR szPort[PREFERRED_DOS_NAME_SIZE] = {0};
  182. dwSize = sizeof(szPort);
  183. RegQueryValueEx(hPrinterKey, regValueName, NULL, &ulType, szPort, &dwSize);
  184. fDefault = (0 == _stricmp((char *)szADefault, (char *)szPort));
  185. }
  186. if (hk)
  187. RegCloseKey(hk);
  188. prnDevice = new W32DrManualPrn(procObj, printerName, TEXT(""),
  189. UniquePortName, fDefault,
  190. DeviceId);
  191. #endif
  192. if (prnDevice != NULL) {
  193. prnDevice->Initialize();
  194. if (!prnDevice->IsValid() ||
  195. (deviceMgr->AddObject(prnDevice) != ERROR_SUCCESS)) {
  196. delete prnDevice;
  197. prnDevice = NULL;
  198. }
  199. }
  200. else {
  201. TRC_ERR((TB, _T("Out of memory when crating manual printer.")));
  202. }
  203. }
  204. else {
  205. TRC_NRM((TB, _T("Can't resolve printer %s."),printerName));
  206. prnDevice = NULL;
  207. }
  208. //
  209. // If ended up with a printer device object then add the cached data.
  210. //
  211. if ((prnDevice != NULL) &&
  212. (prnDevice->SetCachedDataSize(cachedDataSize) == ERROR_SUCCESS)) {
  213. //
  214. // Read the cached data.
  215. //
  216. #ifndef OS_WINCE
  217. result = RegQueryValueEx(hPrinterKey, regValueName,
  218. NULL, &ulType, prnDevice->GetCachedDataPtr(),
  219. &cachedDataSize
  220. );
  221. #else
  222. ulType = REG_BINARY;
  223. result = ReadCachedData(hPrinterKey,
  224. prnDevice->GetCachedDataPtr(),
  225. &cachedDataSize
  226. );
  227. #endif
  228. //
  229. // Let the printer device object know that we are done recovering
  230. // cached data.
  231. //
  232. if (result == ERROR_SUCCESS) {
  233. //
  234. // Make sure the found data is binary data.
  235. //
  236. ASSERT(ulType == REG_BINARY);
  237. if (ulType == REG_BINARY) {
  238. prnDevice->CachedDataRestored();
  239. }
  240. else {
  241. result = ERROR_INVALID_DATA;
  242. }
  243. }
  244. else {
  245. TRC_NRM((TB, _T("RegQueryValueEx failed: %ld."),result));
  246. }
  247. //
  248. // On error processing the cached data.
  249. //
  250. if ((result != ERROR_SUCCESS) || (!prnDevice->IsValid())) {
  251. //
  252. // For a manual printer, we should close and delete its reg key.
  253. //
  254. if (isManual) {
  255. TRC_ALT((TB, _T("Deleting manual printer %s on cache data error."),
  256. printerName));
  257. ASSERT(hPrinterKey != NULL);
  258. RegCloseKey(hPrinterKey);
  259. hPrinterKey = NULL;
  260. RegDeleteKey(hParentKey, printerName);
  261. }
  262. //
  263. // If the printer is an auto printer, zero the cached data for this device
  264. // on error and delete the reg value, but we should still redirect the
  265. // printer.
  266. //
  267. else {
  268. prnDevice->SetCachedDataSize(0);
  269. RegDeleteValue(hPrinterKey, regValueName);
  270. }
  271. }
  272. }
  273. //
  274. // See if our resulting printer is valid after all this processing. If not,
  275. // it should be whacked and removed from the device object list.
  276. //
  277. if ((prnDevice != NULL) && !prnDevice->IsValid()) {
  278. TRC_ERR((TB, _T("Whacking invalid printer device %s."), printerName));
  279. deviceMgr->RemoveObject(prnDevice->GetID());
  280. delete prnDevice;
  281. prnDevice = NULL;
  282. }
  283. CleanUpAndExit:
  284. //
  285. // Close the printer registry key.
  286. //
  287. if (hPrinterKey != NULL) {
  288. RegCloseKey(hPrinterKey);
  289. }
  290. DC_END_FN();
  291. return prnDevice;
  292. }
  293. VOID
  294. W32DrPRN::ProcessPrinterCacheInfo(
  295. IN PRDPDR_PRINTER_CACHEDATA_PACKET pCachePacket,
  296. IN UINT32 maxDataLen
  297. )
  298. /*++
  299. Routine Description:
  300. Process device cache info packet from the server.
  301. Arguments:
  302. pCachePacket - Pointer to the cache info packet from server.
  303. maxDataLen - Maximum data length for this packet
  304. Return Value:
  305. NA
  306. --*/
  307. {
  308. DC_BEGIN_FN("DrPRN::ProcessPrinterCacheInfo");
  309. //
  310. // Compute the valid maximum length that any of the events have
  311. //
  312. maxDataLen -= sizeof(RDPDR_PRINTER_CACHEDATA_PACKET);
  313. switch ( pCachePacket->EventId )
  314. {
  315. case RDPDR_ADD_PRINTER_EVENT :
  316. AddPrinterCacheInfo(
  317. (PRDPDR_PRINTER_ADD_CACHEDATA)(pCachePacket + 1), maxDataLen);
  318. break;
  319. case RDPDR_DELETE_PRINTER_EVENT :
  320. DeletePrinterCacheInfo(
  321. (PRDPDR_PRINTER_DELETE_CACHEDATA)(pCachePacket + 1), maxDataLen);
  322. break;
  323. case RDPDR_UPDATE_PRINTER_EVENT :
  324. UpdatePrinterCacheInfo(
  325. (PRDPDR_PRINTER_UPDATE_CACHEDATA)(pCachePacket + 1), maxDataLen);
  326. break;
  327. case RDPDR_RENAME_PRINTER_EVENT :
  328. RenamePrinterCacheInfo(
  329. (PRDPDR_PRINTER_RENAME_CACHEDATA)(pCachePacket + 1), maxDataLen);
  330. break;
  331. default:
  332. TRC_ALT((TB, _T("Unhandled %ld."), pCachePacket->EventId));
  333. break;
  334. }
  335. //
  336. // Clean up the server message because the transaction is complete.
  337. //
  338. delete pCachePacket;
  339. DC_END_FN();
  340. }
  341. ULONG
  342. W32DrPRN::AddPrinterCacheInfo(
  343. PRDPDR_PRINTER_ADD_CACHEDATA pAddPrinterData,
  344. UINT32 maxDataLen
  345. )
  346. /*++
  347. Routine Description:
  348. Writes device cache info to the registry.
  349. Arguments:
  350. pAddPrinterData - pointer to the RDPDR_PRINTER_ADD_CACHEDATA structure.
  351. maxDataLen - Maximum data length for this data
  352. Return Value:
  353. Windows Error Code.
  354. --*/
  355. {
  356. ULONG ulError;
  357. LPTSTR pszKeyName;
  358. LPWSTR pszUnicodeKeyString;
  359. PBYTE lpStringData;
  360. HKEY hKey = NULL;
  361. HKEY hPrinterKey = NULL;
  362. ULONG ulDisposition;
  363. ULONG ulPrinterData;
  364. DC_BEGIN_FN("W32DrPRN::AddPrinterCacheInfo");
  365. ASSERT(pAddPrinterData->PrinterNameLen != 0);
  366. if( pAddPrinterData->PrinterNameLen == 0 ) {
  367. ulError = ERROR_INVALID_PARAMETER;
  368. goto Cleanup;
  369. }
  370. ulPrinterData =
  371. sizeof(RDPDR_PRINTER_ADD_CACHEDATA) +
  372. pAddPrinterData->PnPNameLen +
  373. pAddPrinterData->DriverLen +
  374. pAddPrinterData->PrinterNameLen +
  375. pAddPrinterData->CachedFieldsLen;
  376. //
  377. // Make sure that the data length is valid.
  378. // Make sure that the cache info doesn't exceed
  379. // the max configured length
  380. //
  381. //
  382. if(ulPrinterData > maxDataLen ||
  383. ulPrinterData > GetMaxCacheDataSize() * 1000) {
  384. ulError = ERROR_INVALID_DATA;
  385. TRC_ERR((TB, _T("Cache Data Length is invalid - %ld"), ulError));
  386. ASSERT(FALSE);
  387. goto Cleanup;
  388. }
  389. //
  390. // Prepare registry key name.
  391. //
  392. lpStringData = (PBYTE)(pAddPrinterData + 1);
  393. pszUnicodeKeyString = (LPWSTR)
  394. (lpStringData +
  395. pAddPrinterData->PnPNameLen +
  396. pAddPrinterData->DriverLen);
  397. #ifdef UNICODE
  398. pszKeyName = pszUnicodeKeyString;
  399. #else
  400. //
  401. // Convert the unicode string to ansi.
  402. //
  403. CHAR achAnsiKeyName[MAX_PATH];
  404. RDPConvertToAnsi(
  405. pszUnicodeKeyString,
  406. (LPSTR)achAnsiKeyName,
  407. sizeof(achAnsiKeyName) );
  408. pszKeyName = (LPSTR)achAnsiKeyName;
  409. #endif
  410. //
  411. // Open rdpdr cached printers key.
  412. //
  413. ulError =
  414. RegCreateKeyEx(
  415. HKEY_CURRENT_USER,
  416. REG_RDPDR_CACHED_PRINTERS,
  417. 0L,
  418. NULL,
  419. REG_OPTION_NON_VOLATILE,
  420. KEY_ALL_ACCESS,
  421. NULL,
  422. &hKey,
  423. &ulDisposition);
  424. if (ulError != ERROR_SUCCESS) {
  425. TRC_ERR((TB, _T("RegCreateKeyEx %ld."), ulError));
  426. goto Cleanup;
  427. }
  428. //
  429. // Create/Open registry key.
  430. //
  431. ulError =
  432. RegCreateKeyEx(
  433. hKey,
  434. pszKeyName,
  435. 0L,
  436. NULL,
  437. REG_OPTION_NON_VOLATILE,
  438. KEY_ALL_ACCESS,
  439. NULL,
  440. &hPrinterKey,
  441. &ulDisposition);
  442. if (ulError != ERROR_SUCCESS) {
  443. TRC_ERR((TB, _T("RegCreateKeyEx %ld."), ulError));
  444. goto Cleanup;
  445. }
  446. //
  447. // Write cache data.
  448. //
  449. ulError =
  450. RegSetValueEx(
  451. hPrinterKey,
  452. REG_RDPDR_PRINTER_CACHE_DATA,
  453. NULL,
  454. REG_BINARY,
  455. (PBYTE)pAddPrinterData,
  456. ulPrinterData
  457. );
  458. if (ulError != ERROR_SUCCESS) {
  459. TRC_ERR((TB, _T("RegSetValueEx() failed, %ld."), ulError));
  460. goto Cleanup;
  461. }
  462. //
  463. // We are done.
  464. //
  465. Cleanup:
  466. if( hPrinterKey != NULL ) {
  467. RegCloseKey( hPrinterKey );
  468. }
  469. if( hKey != NULL ) {
  470. RegCloseKey( hKey );
  471. }
  472. DC_END_FN();
  473. return ulError;
  474. }
  475. ULONG
  476. W32DrPRN::DeletePrinterCacheInfo(
  477. PRDPDR_PRINTER_DELETE_CACHEDATA pDeletePrinterData,
  478. UINT32 maxDataLen
  479. )
  480. /*++
  481. Routine Description:
  482. Delete device cache info from the registry.
  483. Arguments:
  484. pDeletePrinterData - pointer to the RDPDR_PRINTER_DELETE_CACHEDATA structure.
  485. maxDataLen - Maximum data length for this data
  486. Return Value:
  487. Windows Error Code.
  488. --*/
  489. {
  490. ULONG ulError;
  491. LPTSTR pszKeyName;
  492. LPWSTR pszUnicodeKeyString;
  493. HKEY hKey = NULL;
  494. ULONG ulDisposition;
  495. DC_BEGIN_FN("W32DrPRN::DeletePrinterCacheInfo");
  496. ASSERT(pDeletePrinterData->PrinterNameLen != 0);
  497. if( pDeletePrinterData->PrinterNameLen == 0 ) {
  498. ulError = ERROR_INVALID_PARAMETER;
  499. goto Cleanup;
  500. }
  501. ULONG ulPrinterData =
  502. sizeof(RDPDR_PRINTER_DELETE_CACHEDATA) +
  503. pDeletePrinterData->PrinterNameLen;
  504. //
  505. // Make sure that the data length is valid
  506. //
  507. if(ulPrinterData > maxDataLen ||
  508. ulPrinterData > GetMaxCacheDataSize() * 1000) {
  509. ulError = ERROR_INVALID_DATA;
  510. TRC_ERR((TB, _T("Cache Data Length is invalid - %ld"), ulError));
  511. ASSERT(FALSE);
  512. goto Cleanup;
  513. }
  514. //
  515. // prepare registry key name.
  516. //
  517. pszUnicodeKeyString = (LPWSTR)(pDeletePrinterData + 1);
  518. #ifdef UNICODE
  519. pszKeyName = pszUnicodeKeyString;
  520. #else // UNICODE
  521. //
  522. // convert the unicode string to ansi.
  523. //
  524. CHAR achAnsiKeyName[MAX_PATH];
  525. RDPConvertToAnsi(
  526. pszUnicodeKeyString,
  527. (LPSTR)achAnsiKeyName,
  528. sizeof(achAnsiKeyName) );
  529. pszKeyName = (LPSTR)achAnsiKeyName;
  530. #endif // UNICODE
  531. //
  532. // open rdpdr cached printers key.
  533. //
  534. ulError =
  535. RegCreateKeyEx(
  536. HKEY_CURRENT_USER,
  537. REG_RDPDR_CACHED_PRINTERS,
  538. 0L,
  539. NULL,
  540. REG_OPTION_NON_VOLATILE,
  541. KEY_ALL_ACCESS,
  542. NULL,
  543. &hKey,
  544. &ulDisposition);
  545. if (ulError != ERROR_SUCCESS) {
  546. TRC_ERR((TB, _T("RegCreateKeyEx() failed, %ld."), ulError));
  547. goto Cleanup;
  548. }
  549. //
  550. // delete registry key.
  551. //
  552. // Note : assumed, no sub-key presends.
  553. //
  554. ulError = RegDeleteKey( hKey, pszKeyName );
  555. if (ulError != ERROR_SUCCESS) {
  556. TRC_ERR((TB, _T("RegDeleteKey() failed, %ld."), ulError));
  557. goto Cleanup;
  558. }
  559. Cleanup:
  560. if( hKey != NULL ) {
  561. RegCloseKey( hKey );
  562. }
  563. DC_END_FN();
  564. return ulError;
  565. }
  566. ULONG
  567. W32DrPRN::RenamePrinterCacheInfo(
  568. PRDPDR_PRINTER_RENAME_CACHEDATA pRenamePrinterData,
  569. UINT32 maxDataLen
  570. )
  571. /*++
  572. Routine Description:
  573. Rename device cache info in the registry.
  574. Arguments:
  575. pRenamePrinterData - pointer to the RDPDR_PRINTER_RENAME_CACHEDATA
  576. structure.
  577. maxDataLen - Maximum data length for this data
  578. Return Value:
  579. Windows Error Code.
  580. --*/
  581. {
  582. DC_BEGIN_FN("W32DrPRN::RenamePrinterCacheInfo");
  583. ULONG ulError;
  584. LPTSTR pszOldKeyName;
  585. LPTSTR pszNewKeyName;
  586. LPWSTR pszOldUnicodeKeyString;
  587. LPWSTR pszNewUnicodeKeyString;
  588. HKEY hKey = NULL;
  589. HKEY hOldKey = NULL;
  590. HKEY hNewKey = NULL;
  591. ULONG ulDisposition;
  592. ULONG ulType;
  593. ULONG ulPrinterDataLen;
  594. ULONG ulAllocPrinterDataLen = REGISTRY_ALLOC_DATA_SIZE;
  595. PBYTE pbPrinterData = NULL;
  596. BOOL bBufferExpanded = FALSE;
  597. BOOL bAutoPrinter = FALSE;
  598. LPTSTR pszValueStr;
  599. pszValueStr = (LPTSTR)REG_RDPDR_PRINTER_CACHE_DATA;
  600. ASSERT(pRenamePrinterData->OldPrinterNameLen != 0);
  601. ASSERT(pRenamePrinterData->NewPrinterNameLen != 0);
  602. if( pRenamePrinterData->OldPrinterNameLen == 0 ) {
  603. ulError = ERROR_INVALID_PARAMETER;
  604. goto Cleanup;
  605. }
  606. if( pRenamePrinterData->NewPrinterNameLen == 0 ) {
  607. ulError = ERROR_INVALID_PARAMETER;
  608. goto Cleanup;
  609. }
  610. ULONG ulPrinterData =
  611. sizeof(RDPDR_PRINTER_RENAME_CACHEDATA) +
  612. pRenamePrinterData->OldPrinterNameLen +
  613. pRenamePrinterData->NewPrinterNameLen;
  614. //
  615. // Make sure that the data length is valid
  616. //
  617. if(ulPrinterData > maxDataLen ||
  618. ulPrinterData > GetMaxCacheDataSize() * 1000) {
  619. ulError = ERROR_INVALID_DATA;
  620. TRC_ERR((TB, _T("Cache Data Length is invalid - %ld"), ulError));
  621. ASSERT(FALSE);
  622. goto Cleanup;
  623. }
  624. //
  625. // prepare registry key name.
  626. //
  627. pszOldUnicodeKeyString = (LPWSTR)(pRenamePrinterData + 1);
  628. pszNewUnicodeKeyString = (LPWSTR)
  629. ((PBYTE)pszOldUnicodeKeyString +
  630. pRenamePrinterData->OldPrinterNameLen);
  631. TRC_ERR((TB, _T("pszOldUnicodeKeyString is %ws."), pszOldUnicodeKeyString));
  632. TRC_ERR((TB, _T("pszNewUnicodeKeyString is %ws."), pszNewUnicodeKeyString));
  633. //
  634. // No change in queue name.
  635. //
  636. if( _wcsicmp(pszOldUnicodeKeyString, pszNewUnicodeKeyString) == 0 ) {
  637. ulError = ERROR_SUCCESS;
  638. goto Cleanup;
  639. }
  640. #ifdef UNICODE
  641. pszOldKeyName = pszOldUnicodeKeyString;
  642. pszNewKeyName = pszNewUnicodeKeyString;
  643. #else // UNICODE
  644. //
  645. // convert the unicode string to ansi.
  646. //
  647. CHAR achOldAnsiKeyName[MAX_PATH];
  648. CHAR achNewAnsiKeyName[MAX_PATH];
  649. RDPConvertToAnsi(
  650. pszOldUnicodeKeyString,
  651. (LPSTR)achOldAnsiKeyName,
  652. sizeof(achOldAnsiKeyName) );
  653. pszOldKeyName = (LPSTR)achOldAnsiKeyName;
  654. RDPConvertToAnsi(
  655. pszNewUnicodeKeyString,
  656. (LPSTR)achNewAnsiKeyName,
  657. sizeof(achNewAnsiKeyName) );
  658. pszNewKeyName = (LPSTR)achNewAnsiKeyName;
  659. #endif // UNICODE
  660. //
  661. // open rdpdr cached printers key.
  662. //
  663. ulError =
  664. RegCreateKeyEx(
  665. HKEY_CURRENT_USER,
  666. REG_RDPDR_CACHED_PRINTERS,
  667. 0L,
  668. NULL,
  669. REG_OPTION_NON_VOLATILE,
  670. KEY_ALL_ACCESS,
  671. NULL,
  672. &hKey,
  673. &ulDisposition);
  674. if (ulError != ERROR_SUCCESS) {
  675. TRC_ERR((TB, _T("RegCreateKeyEx() failed, %ld."), ulError));
  676. goto Cleanup;
  677. }
  678. //
  679. // Open old Key.
  680. //
  681. ulError =
  682. RegOpenKeyEx(
  683. hKey,
  684. pszOldKeyName,
  685. 0L,
  686. KEY_ALL_ACCESS,
  687. &hOldKey);
  688. if (ulError != ERROR_SUCCESS) {
  689. TRC_ERR((TB, _T("RegOpenKeyEx() failed, %ld."), ulError));
  690. goto Cleanup;
  691. }
  692. //
  693. // read cache data.
  694. //
  695. ReadAgain:
  696. pbPrinterData = new BYTE[ulAllocPrinterDataLen];
  697. if( pbPrinterData == NULL ) {
  698. ulError = ERROR_NOT_ENOUGH_MEMORY;
  699. goto Cleanup;
  700. }
  701. ulPrinterDataLen = ulAllocPrinterDataLen;
  702. ulError =
  703. RegQueryValueEx(
  704. hOldKey,
  705. pszValueStr,
  706. NULL,
  707. &ulType,
  708. pbPrinterData,
  709. &ulPrinterDataLen);
  710. TRC_ERR((TB, _T("RegQueryValueEx returned: %ld."), ulError));
  711. if (ulError != ERROR_SUCCESS) {
  712. if( ulError == ERROR_MORE_DATA ) {
  713. //
  714. // do the buffer expansion only once to aviod infinite look
  715. // in case of registry corruption or so.
  716. //
  717. if( !bBufferExpanded ) {
  718. ASSERT(ulPrinterDataLen > ulAllocPrinterDataLen);
  719. //
  720. // need bigger buffer.
  721. // Compute new buffer size.
  722. //
  723. ulAllocPrinterDataLen =
  724. ((ulPrinterDataLen / REGISTRY_ALLOC_DATA_SIZE) + 1) *
  725. REGISTRY_ALLOC_DATA_SIZE;
  726. //
  727. // free old buffer.
  728. //
  729. delete pbPrinterData;
  730. pbPrinterData = NULL;
  731. ASSERT(ulAllocPrinterDataLen >= ulPrinterDataLen);
  732. bBufferExpanded = TRUE;
  733. goto ReadAgain;
  734. }
  735. }
  736. else {
  737. //
  738. // It could be auto printer. Try again.
  739. //
  740. if (!bAutoPrinter) {
  741. bAutoPrinter = TRUE;
  742. pszValueStr = (LPTSTR)REG_RDPDR_AUTO_PRN_CACHE_DATA;
  743. //
  744. // free old buffer
  745. //
  746. delete pbPrinterData;
  747. pbPrinterData = NULL;
  748. goto ReadAgain;
  749. }
  750. }
  751. }
  752. if (ulError != ERROR_SUCCESS) {
  753. TRC_ERR((TB, _T("RegQueryValueEx() failed, %ld."), ulError));
  754. goto Cleanup;
  755. }
  756. ASSERT(ulType == REG_BINARY);
  757. if( ulType != REG_BINARY ) {
  758. TRC_ERR((TB, _T("RegQueryValueEx returns wrong type, %ld."), ulType));
  759. goto Cleanup;
  760. }
  761. //
  762. // Update the printer name in the cache info
  763. //
  764. ulError = DrPRN::UpdatePrinterNameInCacheData(
  765. &pbPrinterData,
  766. &ulPrinterDataLen,
  767. (PBYTE)pszNewUnicodeKeyString,
  768. pRenamePrinterData->NewPrinterNameLen);
  769. //
  770. // Let's not worry about the success/failure of the above function.
  771. // We will anyway right the cache information to the new key
  772. //
  773. //
  774. // write the data to the new key.
  775. //
  776. //
  777. // open new key.
  778. //
  779. ulError =
  780. RegCreateKeyEx(
  781. hKey,
  782. pszNewKeyName,
  783. 0L,
  784. NULL,
  785. REG_OPTION_NON_VOLATILE,
  786. KEY_ALL_ACCESS,
  787. NULL,
  788. &hNewKey,
  789. &ulDisposition);
  790. if (ulError != ERROR_SUCCESS) {
  791. TRC_ERR((TB, _T("RegCreateKeyEx() failed, %ld."), ulError));
  792. goto Cleanup;
  793. }
  794. ASSERT(ulDisposition != REG_OPENED_EXISTING_KEY);
  795. ulError =
  796. RegSetValueEx(
  797. hNewKey,
  798. pszValueStr,
  799. NULL,
  800. ulType,
  801. pbPrinterData,
  802. ulPrinterDataLen);
  803. if (ulError != ERROR_SUCCESS) {
  804. TRC_ERR((TB, _T("RegSetValueEx() failed, %ld."), ulError));
  805. goto Cleanup;
  806. }
  807. //
  808. // Try to rename the local printer
  809. //
  810. if (bAutoPrinter) {
  811. RenamePrinter(pszOldKeyName, pszNewKeyName);
  812. }
  813. //
  814. // now delete old registry key.
  815. //
  816. // Note : assumed, no sub-key presends.
  817. //
  818. ulError = RegCloseKey( hOldKey );
  819. if (ulError != ERROR_SUCCESS) {
  820. TRC_ERR((TB, _T("RegCloseKey() failed, %ld."), ulError));
  821. goto Cleanup;
  822. }
  823. hOldKey = NULL;
  824. ulError = RegDeleteKey( hKey, pszOldKeyName );
  825. if (ulError != ERROR_SUCCESS) {
  826. TRC_ERR((TB, _T("RegDeleteKey() failed, %ld."), ulError));
  827. goto Cleanup;
  828. }
  829. Cleanup:
  830. if( hKey != NULL ) {
  831. RegCloseKey( hKey );
  832. }
  833. if( hOldKey != NULL ) {
  834. RegCloseKey( hOldKey );
  835. }
  836. if( hNewKey != NULL ) {
  837. RegCloseKey( hNewKey );
  838. }
  839. if (pbPrinterData) {
  840. delete pbPrinterData;
  841. }
  842. DC_END_FN();
  843. return ulError;
  844. }
  845. ULONG
  846. W32DrPRN::UpdatePrinterCacheInfo(
  847. PRDPDR_PRINTER_UPDATE_CACHEDATA pUpdatePrinterData,
  848. UINT32 maxDataLen
  849. )
  850. /*++
  851. Routine Description:
  852. Update device cache info in the registry.
  853. Arguments:
  854. pUpdatePrinterData - pointer to the RDPDR_PRINTER_UPDATE_CACHEDATA
  855. structure.
  856. maxDataLen - Maximum data length for this data
  857. Return Value:
  858. Windows Error Code.
  859. --*/
  860. {
  861. DC_BEGIN_FN("W32DrPRN::UpdatePrinterCacheInfo");
  862. ULONG ulError;
  863. LPTSTR pszKeyName;
  864. LPWSTR pszUnicodeKeyString;
  865. HKEY hKey = NULL;
  866. HKEY hPrinterKey = NULL;
  867. ULONG ulDisposition;
  868. ULONG ulConfigDataLen;
  869. PBYTE pbConfigData;
  870. ULONG ulPrinterDataLen;
  871. ULONG ulAllocPrinterDataLen = REGISTRY_ALLOC_DATA_SIZE;
  872. PBYTE pbPrinterData = NULL;
  873. BOOL bAutoPrinter = FALSE;
  874. ASSERT(pUpdatePrinterData->PrinterNameLen != 0);
  875. if( pUpdatePrinterData->PrinterNameLen == 0 ) {
  876. ulError = ERROR_INVALID_PARAMETER;
  877. goto Cleanup;
  878. }
  879. ulPrinterDataLen =
  880. sizeof(RDPDR_PRINTER_UPDATE_CACHEDATA) +
  881. pUpdatePrinterData->PrinterNameLen +
  882. pUpdatePrinterData->ConfigDataLen;
  883. //
  884. // Make sure that the data length is valid
  885. //
  886. if(ulPrinterDataLen > maxDataLen ||
  887. ulPrinterDataLen > GetMaxCacheDataSize() * 1000) {
  888. ulError = ERROR_INVALID_DATA;
  889. TRC_ERR((TB, _T("Cache Data Length is invalid - %ld"), ulError));
  890. ASSERT(FALSE);
  891. goto Cleanup;
  892. }
  893. //
  894. // prepare registry key name.
  895. //
  896. pszUnicodeKeyString = (LPWSTR)(pUpdatePrinterData + 1);
  897. #ifdef UNICODE
  898. pszKeyName = pszUnicodeKeyString;
  899. #else // UNICODE
  900. //
  901. // convert the unicode string to ansi.
  902. //
  903. CHAR achAnsiKeyName[MAX_PATH];
  904. RDPConvertToAnsi(
  905. pszUnicodeKeyString,
  906. (LPSTR)achAnsiKeyName,
  907. sizeof(achAnsiKeyName) );
  908. pszKeyName = (LPSTR)achAnsiKeyName;
  909. #endif // UNICODE
  910. //
  911. // open rdpdr cached printers key.
  912. //
  913. ulError =
  914. RegCreateKeyEx(
  915. HKEY_CURRENT_USER,
  916. REG_RDPDR_CACHED_PRINTERS,
  917. 0L,
  918. NULL,
  919. REG_OPTION_NON_VOLATILE,
  920. KEY_ALL_ACCESS,
  921. NULL,
  922. &hKey,
  923. &ulDisposition);
  924. if (ulError != ERROR_SUCCESS) {
  925. TRC_ERR((TB, _T("RegCreateKeyEx() failed, %ld."), ulError));
  926. goto Cleanup;
  927. }
  928. //
  929. // update registry data.
  930. //
  931. //
  932. // Open registry key.
  933. //
  934. ulError =
  935. RegCreateKeyEx(
  936. hKey,
  937. pszKeyName,
  938. 0L,
  939. NULL,
  940. REG_OPTION_NON_VOLATILE,
  941. KEY_ALL_ACCESS,
  942. NULL,
  943. &hPrinterKey,
  944. &ulDisposition);
  945. if (ulError != ERROR_SUCCESS) {
  946. TRC_ERR((TB, _T("RegCreateKeyEx() failed, %ld."), ulError));
  947. goto Cleanup;
  948. }
  949. if( ulDisposition != REG_OPENED_EXISTING_KEY ) {
  950. //
  951. // we do not find a cache entry, so it must be automatic printer
  952. // cache data.
  953. //
  954. bAutoPrinter = TRUE;
  955. TRC_NRM((TB, _T("Created new Key, Auto cache printer detected.")));
  956. }
  957. if( !bAutoPrinter ) {
  958. //
  959. // read old cache data.
  960. //
  961. ULONG ulType;
  962. #ifndef OS_WINCE
  963. do {
  964. pbPrinterData = new BYTE[ulAllocPrinterDataLen];
  965. if( pbPrinterData == NULL ) {
  966. ulError = ERROR_NOT_ENOUGH_MEMORY;
  967. goto Cleanup;
  968. }
  969. ulPrinterDataLen = ulAllocPrinterDataLen;
  970. ulError =
  971. RegQueryValueEx(
  972. hPrinterKey,
  973. (PTCHAR)REG_RDPDR_PRINTER_CACHE_DATA,
  974. NULL,
  975. &ulType,
  976. pbPrinterData,
  977. &ulPrinterDataLen);
  978. if( ulError == ERROR_MORE_DATA ) {
  979. ASSERT(ulPrinterDataLen > ulAllocPrinterDataLen);
  980. //
  981. // need bigger buffer.
  982. // Compute new buffer size.
  983. //
  984. ulAllocPrinterDataLen =
  985. ((ulPrinterDataLen / REGISTRY_ALLOC_DATA_SIZE) + 1) *
  986. REGISTRY_ALLOC_DATA_SIZE;
  987. //
  988. // free old buffer.
  989. //
  990. delete pbPrinterData;
  991. pbPrinterData = NULL;
  992. ASSERT(ulAllocPrinterDataLen >= ulPrinterDataLen);
  993. }
  994. else if( ulError == ERROR_FILE_NOT_FOUND ) {
  995. //
  996. // we do not find a cache entry, so it must be automatic
  997. // printer cache data.
  998. //
  999. TRC_NRM((TB, _T("No Old Cache data, Auto cache printer detected.")));
  1000. bAutoPrinter = TRUE;
  1001. ulError = ERROR_SUCCESS;
  1002. ulType = REG_BINARY;
  1003. }
  1004. } while ( ulError == ERROR_MORE_DATA );
  1005. #else
  1006. ulPrinterDataLen = GetCachedDataSize(hPrinterKey);
  1007. pbPrinterData = new BYTE[ulPrinterDataLen];
  1008. if( pbPrinterData == NULL ) {
  1009. ulError = ERROR_NOT_ENOUGH_MEMORY;
  1010. goto Cleanup;
  1011. }
  1012. ulType = REG_BINARY;
  1013. ulError = ReadCachedData(hPrinterKey, pbPrinterData, &ulPrinterDataLen);
  1014. #endif
  1015. if (ulError != ERROR_SUCCESS) {
  1016. TRC_ERR((TB, _T("RegQueryValueEx() failed, %ld."), ulError));
  1017. goto Cleanup;
  1018. }
  1019. ASSERT(ulType == REG_BINARY);
  1020. }
  1021. if( !bAutoPrinter ) {
  1022. //
  1023. // update the printer data.
  1024. //
  1025. ulConfigDataLen = pUpdatePrinterData->ConfigDataLen;
  1026. pbConfigData =
  1027. (PBYTE)(pUpdatePrinterData + 1) +
  1028. pUpdatePrinterData->PrinterNameLen;
  1029. ulError =
  1030. DrPRN::UpdatePrinterCacheData(
  1031. &pbPrinterData,
  1032. &ulPrinterDataLen,
  1033. pbConfigData,
  1034. ulConfigDataLen );
  1035. if (ulError != ERROR_SUCCESS) {
  1036. TRC_ERR((TB, _T("UpdatePrinterCacheData() failed, %ld."), ulError));
  1037. goto Cleanup;
  1038. }
  1039. //
  1040. // write cache data.
  1041. //
  1042. #ifndef OS_WINCE
  1043. ulError =
  1044. RegSetValueEx(
  1045. hPrinterKey,
  1046. REG_RDPDR_PRINTER_CACHE_DATA,
  1047. NULL,
  1048. REG_BINARY,
  1049. pbPrinterData,
  1050. ulPrinterDataLen );
  1051. #else
  1052. ulError = WriteCachedData(hPrinterKey, pbPrinterData, ulPrinterDataLen);
  1053. #endif
  1054. }
  1055. else {
  1056. pbConfigData = (PBYTE)(pUpdatePrinterData+1);
  1057. pbConfigData += pUpdatePrinterData->PrinterNameLen;
  1058. //
  1059. // write cache data.
  1060. //
  1061. ulError =
  1062. RegSetValueEx(
  1063. hPrinterKey,
  1064. REG_RDPDR_AUTO_PRN_CACHE_DATA,
  1065. NULL,
  1066. REG_BINARY,
  1067. pbConfigData,
  1068. pUpdatePrinterData->ConfigDataLen );
  1069. }
  1070. if (ulError != ERROR_SUCCESS) {
  1071. TRC_ERR((TB, _T("RegSetValueEx() failed, %ld."), ulError));
  1072. goto Cleanup;
  1073. }
  1074. //
  1075. // we are done.
  1076. //
  1077. Cleanup:
  1078. if( hPrinterKey != NULL ) {
  1079. RegCloseKey( hPrinterKey );
  1080. }
  1081. if( hKey != NULL ) {
  1082. RegCloseKey( hKey );
  1083. }
  1084. //
  1085. // delete data buffers.
  1086. //
  1087. delete pbPrinterData;
  1088. DC_END_FN();
  1089. return ulError;
  1090. }
  1091. VOID
  1092. W32DrPRN::RenamePrinter(
  1093. LPTSTR pwszOldname,
  1094. LPTSTR pwszNewname
  1095. )
  1096. {
  1097. DC_BEGIN_FN("W32DrPRN::RenamePrinter");
  1098. ASSERT(pwszOldname != NULL);
  1099. ASSERT(pwszNewname != NULL);
  1100. if (!(pwszOldname && pwszNewname)) {
  1101. DC_END_FN();
  1102. return;
  1103. }
  1104. #ifndef OS_WINCE
  1105. HANDLE hPrinter = NULL;
  1106. BOOL bRunningOn9x = TRUE;
  1107. OSVERSIONINFO osVersion;
  1108. PRINTER_INFO_2 * ppi2 = NULL;
  1109. PRINTER_INFO_2A * ppi2a = NULL; //ansi version
  1110. DWORD size = 0;
  1111. if (!OpenPrinter(pwszOldname, &hPrinter, NULL)) {
  1112. TRC_ERR((TB, _T("OpenPrinter() failed, %ld."), GetLastError()));
  1113. goto Cleanup;
  1114. }
  1115. //
  1116. // We don't have GetPrinter/SetPrinter wrappers
  1117. // so just call either the A or W api's depending on the platform
  1118. // this works because we treat the returned data as an opaque
  1119. // blob and pass it from one API to the next.
  1120. //
  1121. // Doing it this way is more efficient than calling wrappers
  1122. // that would do a _lot_ of uncessary conversions. Although
  1123. // it does make the code a little bit bigger.
  1124. //
  1125. //
  1126. osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1127. if (GetVersionEx(&osVersion)) {
  1128. if (osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT) {
  1129. bRunningOn9x = FALSE;
  1130. }
  1131. }
  1132. else
  1133. {
  1134. TRC_ERR((TB, _T("GetVersionEx: %08X"), GetLastError()));
  1135. }
  1136. //
  1137. // Code is duplicated to into two large separate
  1138. // branches to reduce number of overall branches
  1139. //
  1140. if(!bRunningOn9x)
  1141. {
  1142. //Not win9x, use UNICODE API's
  1143. if (!GetPrinter(
  1144. hPrinter,
  1145. 2,
  1146. (LPBYTE)ppi2,
  1147. 0,
  1148. &size)) {
  1149. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  1150. TRC_ERR((TB, _T("GetPrinter() failed, %ld."), GetLastError()));
  1151. goto Cleanup;
  1152. }
  1153. ppi2 = (PRINTER_INFO_2 *) new BYTE [size];
  1154. if (ppi2 != NULL) {
  1155. if (!GetPrinter(
  1156. hPrinter,
  1157. 2,
  1158. (LPBYTE)ppi2,
  1159. size,
  1160. &size)) {
  1161. TRC_ERR((TB, _T("GetPrinter() failed, %ld."), GetLastError()));
  1162. goto Cleanup;
  1163. }
  1164. }
  1165. else {
  1166. TRC_ERR((TB, _T("GetPrinter() failed, %ld."), GetLastError()));
  1167. goto Cleanup;
  1168. }
  1169. //
  1170. // replace the name
  1171. //
  1172. ppi2->pPrinterName = pwszNewname;
  1173. ppi2->pSecurityDescriptor = NULL; //we don't want to modify the security descriptors.
  1174. if (!SetPrinter(hPrinter, 2, (LPBYTE)ppi2, 0)) {
  1175. TRC_ERR((TB, _T("SetPrinter() failed, %ld."), GetLastError()));
  1176. }
  1177. }
  1178. }
  1179. else
  1180. {
  1181. //Do this in ANSI mode
  1182. if (!GetPrinterA(
  1183. hPrinter,
  1184. 2,
  1185. (LPBYTE)ppi2a,
  1186. 0,
  1187. &size)) {
  1188. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  1189. TRC_ERR((TB, _T("GetPrinter() failed, %ld."), GetLastError()));
  1190. goto Cleanup;
  1191. }
  1192. ppi2a = (PRINTER_INFO_2A *) new BYTE [size];
  1193. if (ppi2 != NULL) {
  1194. if (!GetPrinterA(
  1195. hPrinter,
  1196. 2,
  1197. (LPBYTE)ppi2a,
  1198. size,
  1199. &size)) {
  1200. TRC_ERR((TB, _T("GetPrinter() failed, %ld."), GetLastError()));
  1201. goto Cleanup;
  1202. }
  1203. }
  1204. else {
  1205. TRC_ERR((TB, _T("GetPrinter() failed, %ld."), GetLastError()));
  1206. goto Cleanup;
  1207. }
  1208. //
  1209. // replace the name
  1210. //
  1211. CHAR ansiPrinterName[2048];
  1212. RDPConvertToAnsi( pwszNewname, ansiPrinterName,
  1213. sizeof(ansiPrinterName) );
  1214. ppi2a->pPrinterName = ansiPrinterName;
  1215. ppi2a->pSecurityDescriptor = NULL; //we don't want to modify the security descriptors.
  1216. if (!SetPrinterA(hPrinter, 2, (LPBYTE)ppi2a, 0)) {
  1217. TRC_ERR((TB, _T("SetPrinter() failed, %ld."), GetLastError()));
  1218. }
  1219. }
  1220. }
  1221. Cleanup:
  1222. if (hPrinter != NULL) {
  1223. ClosePrinter(hPrinter);
  1224. }
  1225. if (ppi2) {
  1226. delete[] ppi2;
  1227. }
  1228. else if (ppi2a)
  1229. {
  1230. //can't have gone through both UNICODE and ANSI branches
  1231. delete[] ppi2a;
  1232. }
  1233. #endif //!OS_WINCE
  1234. DC_END_FN();
  1235. }
  1236. ULONG
  1237. W32DrPRN::GetDevAnnounceDataSize()
  1238. /*++
  1239. Routine Description:
  1240. Return the size (in bytes) of a device announce packet for
  1241. this device.
  1242. Arguments:
  1243. NA
  1244. Return Value:
  1245. The size (in bytes) of a device announce packet for this device.
  1246. --*/
  1247. {
  1248. ULONG size = 0;
  1249. DC_BEGIN_FN("W32DrPRN::GetDevAnnounceDataSize");
  1250. ASSERT(IsValid());
  1251. if (!IsValid()) { return 0; }
  1252. size = 0;
  1253. //
  1254. // Add the base announce size.
  1255. //
  1256. size += sizeof(RDPDR_DEVICE_ANNOUNCE);
  1257. //
  1258. // Add the printer announce header.
  1259. //
  1260. size += sizeof(RDPDR_PRINTERDEVICE_ANNOUNCE);
  1261. //
  1262. // Include printer name.
  1263. //
  1264. size += ((STRLEN(_printerName) + 1) * sizeof(WCHAR));
  1265. //
  1266. // Include printer driver name.
  1267. //
  1268. size += ((STRLEN(_driverName) + 1) * sizeof(WCHAR));
  1269. //
  1270. // Include cached data.
  1271. //
  1272. size += _cachedDataSize;
  1273. DC_END_FN();
  1274. return size;
  1275. }
  1276. VOID
  1277. W32DrPRN::GetDevAnnounceData(
  1278. IN PRDPDR_DEVICE_ANNOUNCE pDeviceAnnounce
  1279. )
  1280. /*++
  1281. Routine Description:
  1282. Add a device announce packet for this device to the input buffer.
  1283. Arguments:
  1284. pDeviceAnnounce - Device Packet to Append Device Data To
  1285. deviceType - Device Type Identifier
  1286. deviceID - Identifier for Device
  1287. Return Value:
  1288. NA
  1289. --*/
  1290. {
  1291. PRDPDR_PRINTERDEVICE_ANNOUNCE pPrinterAnnounce;
  1292. PBYTE pbStringData;
  1293. DC_BEGIN_FN("W32DrPRN::GetDevAnnounceData");
  1294. ASSERT(IsValid());
  1295. if (!IsValid()) { return; }
  1296. //
  1297. // Record the device ID.
  1298. //
  1299. pDeviceAnnounce->DeviceType = GetDeviceType();
  1300. pDeviceAnnounce->DeviceId = GetID();
  1301. //
  1302. // Record the port name in ANSI.
  1303. //
  1304. #ifdef UNICODE
  1305. RDPConvertToAnsi(GetPortName(), (LPSTR)pDeviceAnnounce->PreferredDosName,
  1306. sizeof(pDeviceAnnounce->PreferredDosName)
  1307. );
  1308. #else
  1309. STRCPY((char *)pDeviceAnnounce->PreferredDosName, GetPortName());
  1310. #endif
  1311. //
  1312. // Get pointers to printer-specific data.
  1313. //
  1314. pPrinterAnnounce =
  1315. (PRDPDR_PRINTERDEVICE_ANNOUNCE)(pDeviceAnnounce + 1);
  1316. //
  1317. // Embedded data pointer.
  1318. //
  1319. pbStringData = (PBYTE)(pPrinterAnnounce + 1);
  1320. //
  1321. // Flags
  1322. //
  1323. pPrinterAnnounce->Flags = 0;
  1324. if (_isDefault) {
  1325. pPrinterAnnounce->Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
  1326. }
  1327. if (_isNetwork) {
  1328. pPrinterAnnounce->Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER;
  1329. }
  1330. if (_isTSqueue) {
  1331. pPrinterAnnounce->Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER;
  1332. }
  1333. //
  1334. // ANSI Code Page
  1335. //
  1336. pPrinterAnnounce->CodePage = 0;
  1337. //
  1338. // Misc. Field Lengths
  1339. //
  1340. pPrinterAnnounce->PnPNameLen = 0;
  1341. pPrinterAnnounce->CachedFieldsLen = 0;
  1342. //
  1343. // Copy the driver name.
  1344. //
  1345. if (GetDriverName() != NULL) {
  1346. #if defined(UNICODE)
  1347. //
  1348. // Unicode to Unicode just requires a memcpy.
  1349. //
  1350. pPrinterAnnounce->DriverLen = ((STRLEN(GetDriverName()) + 1) *
  1351. sizeof(WCHAR));
  1352. memcpy(pbStringData, _driverName, pPrinterAnnounce->DriverLen);
  1353. #else
  1354. //
  1355. // On Win32 ANSI, we will convert to Unicode.
  1356. //
  1357. pPrinterAnnounce->DriverLen = ((STRLEN(GetDriverName()) + 1) *
  1358. sizeof(WCHAR));
  1359. RDPConvertToUnicode(_driverName, (LPWSTR)pbStringData,
  1360. pPrinterAnnounce->DriverLen );
  1361. #endif
  1362. pbStringData += pPrinterAnnounce->DriverLen;
  1363. }
  1364. else {
  1365. pPrinterAnnounce->DriverLen = 0;
  1366. }
  1367. //
  1368. // Copy the printer name.
  1369. //
  1370. if (GetPrinterName() != NULL) {
  1371. #if defined(UNICODE)
  1372. //
  1373. // Unicode to Unicode just requires a memcpy.
  1374. //
  1375. pPrinterAnnounce->PrinterNameLen = (STRLEN(_printerName) + 1) *
  1376. sizeof(WCHAR);
  1377. memcpy(pbStringData, _printerName, pPrinterAnnounce->PrinterNameLen );
  1378. #else
  1379. //
  1380. // On Win32 ANSI, we will convert to Unicode.
  1381. //
  1382. pPrinterAnnounce->PrinterNameLen = (STRLEN(_printerName) + 1) *
  1383. sizeof(WCHAR);
  1384. RDPConvertToUnicode(_printerName, (LPWSTR)pbStringData,
  1385. pPrinterAnnounce->PrinterNameLen );
  1386. #endif
  1387. pbStringData += pPrinterAnnounce->PrinterNameLen;
  1388. }
  1389. else {
  1390. pPrinterAnnounce->PrinterNameLen = 0;
  1391. }
  1392. //
  1393. // Copy the cached data.
  1394. //
  1395. if (_cachedData != NULL) {
  1396. pPrinterAnnounce->CachedFieldsLen = _cachedDataSize;
  1397. memcpy(pbStringData, _cachedData, (size_t)_cachedDataSize);
  1398. pbStringData += _cachedDataSize;
  1399. }
  1400. //
  1401. // Computer the length of the data area that follows the device announce
  1402. // header.
  1403. //
  1404. pDeviceAnnounce->DeviceDataLength =
  1405. (ULONG)(pbStringData - (PBYTE)pPrinterAnnounce);
  1406. DC_END_FN();
  1407. }
  1408. #ifdef OS_WINCE
  1409. ULONG
  1410. W32DrPRN::GetCachedDataSize(
  1411. HKEY hPrinterKey
  1412. )
  1413. {
  1414. DC_BEGIN_FN("W32DrPRN::GetCachedDataSize");
  1415. TRC_ASSERT((hPrinterKey != NULL), (TB,_T("hPrinterKey is NULL")));
  1416. DWORD dwRet = ERROR_SUCCESS;
  1417. DWORD dwTotSize = 0;
  1418. WCHAR szValueName[MAX_PATH];
  1419. for (DWORD dwIndex = 0; dwRet == ERROR_SUCCESS; dwIndex++)
  1420. {
  1421. DWORD dwType;
  1422. DWORD dwSize = 0;
  1423. wsprintf(szValueName, L"%s%d", REG_RDPDR_PRINTER_CACHE_DATA, dwIndex);
  1424. dwRet = RegQueryValueEx(hPrinterKey, szValueName, NULL, &dwType, NULL, &dwSize);
  1425. if ((dwRet == ERROR_SUCCESS) && (dwType == REG_BINARY) )
  1426. {
  1427. dwTotSize += dwSize;
  1428. }
  1429. }
  1430. DC_END_FN();
  1431. return dwTotSize;
  1432. }
  1433. ULONG
  1434. W32DrPRN::ReadCachedData(
  1435. HKEY hPrinterKey,
  1436. UCHAR *pBuf,
  1437. ULONG *pulSize
  1438. )
  1439. {
  1440. DC_BEGIN_FN("W32DrPRN::ReadCachedData");
  1441. TRC_ASSERT((hPrinterKey != NULL), (TB,_T("hPrinterKey is NULL")));
  1442. TRC_ASSERT(((pBuf != NULL) && (pulSize != NULL)), (TB,_T("Invalid parameters pBuf = 0x%08x, pulSize=0x%08x"), pBuf, pulSize));
  1443. DWORD dwRet = ERROR_SUCCESS;
  1444. DWORD dwRemaining = *pulSize;
  1445. WCHAR szValueName[MAX_PATH];
  1446. for (DWORD dwIndex = 0; dwRet == ERROR_SUCCESS; dwIndex++)
  1447. {
  1448. DWORD dwType;
  1449. DWORD dwSize = dwRemaining;
  1450. wsprintf(szValueName, L"%s%d", REG_RDPDR_PRINTER_CACHE_DATA, dwIndex);
  1451. dwRet = RegQueryValueEx(hPrinterKey, szValueName, NULL, &dwType, pBuf, &dwSize);
  1452. if ((dwRet == ERROR_SUCCESS) && (dwType == REG_BINARY) )
  1453. {
  1454. dwRemaining -= dwSize;
  1455. pBuf += dwSize;
  1456. }
  1457. }
  1458. *pulSize -= dwRemaining;
  1459. return (*pulSize > 0) ? ERROR_SUCCESS : dwRet;
  1460. }
  1461. ULONG
  1462. W32DrPRN::WriteCachedData(
  1463. HKEY hPrinterKey,
  1464. UCHAR *pBuf,
  1465. ULONG ulSize
  1466. )
  1467. {
  1468. DC_BEGIN_FN("W32DrPRN::WriteCachedData");
  1469. TRC_ASSERT((hPrinterKey != NULL), (TB,_T("hPrinterKey is NULL")));
  1470. TRC_ASSERT((pBuf != NULL), (TB,_T("pBuf is NULL!")));
  1471. DWORD dwRet = ERROR_SUCCESS;
  1472. DWORD dwRemaining = ulSize;
  1473. WCHAR szValueName[MAX_PATH];
  1474. for (DWORD dwIndex = 0; dwRemaining > 0; dwIndex++)
  1475. {
  1476. DWORD dwSize = (dwRemaining >= 4096) ? 4096 : dwRemaining;
  1477. wsprintf(szValueName, L"%s%d", REG_RDPDR_PRINTER_CACHE_DATA, dwIndex);
  1478. dwRet = RegSetValueEx(hPrinterKey, szValueName, NULL, REG_BINARY, pBuf, dwSize);
  1479. if (dwRet == ERROR_SUCCESS)
  1480. {
  1481. dwRemaining -= dwSize;
  1482. pBuf += dwSize;
  1483. }
  1484. else
  1485. {
  1486. TRC_ERR((TB, _T("Error - RegQueryValueEx on %s failed"), szValueName));
  1487. for (DWORD dw=0; dw<dwIndex; dw++)
  1488. {
  1489. wsprintf(szValueName, L"%s%d", REG_RDPDR_PRINTER_CACHE_DATA, dw);
  1490. RegDeleteValue(hPrinterKey, szValueName);
  1491. }
  1492. return dwRet;
  1493. }
  1494. }
  1495. DC_END_FN();
  1496. return ERROR_SUCCESS;
  1497. }
  1498. #endif