Source code of Windows XP (NT5)
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.

4835 lines
108 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1998 - 1999
  3. All rights reserved.
  4. Module Name:
  5. Stream.cxx
  6. Abstract:
  7. implements TPrnStream class methods
  8. Author:
  9. Adina Trufinescu (AdinaTru) 4-Nov-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include "prnprst.hxx"
  15. static
  16. FieldInfo PrinterInfo2Fields[]={
  17. {offsetof(PRINTER_INFO_2, pServerName), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  18. {offsetof(PRINTER_INFO_2, pPrinterName), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  19. {offsetof(PRINTER_INFO_2, pShareName), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  20. {offsetof(PRINTER_INFO_2, pPortName), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  21. {offsetof(PRINTER_INFO_2, pDriverName), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  22. {offsetof(PRINTER_INFO_2, pComment), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  23. {offsetof(PRINTER_INFO_2, pLocation), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  24. {offsetof(PRINTER_INFO_2, pDevMode), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  25. {offsetof(PRINTER_INFO_2, pSepFile), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  26. {offsetof(PRINTER_INFO_2, pPrintProcessor), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  27. {offsetof(PRINTER_INFO_2, pDatatype), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  28. {offsetof(PRINTER_INFO_2, pParameters), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  29. {offsetof(PRINTER_INFO_2, pSecurityDescriptor), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  30. {offsetof(PRINTER_INFO_2, Attributes), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  31. {offsetof(PRINTER_INFO_2, Priority), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  32. {offsetof(PRINTER_INFO_2, DefaultPriority), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  33. {offsetof(PRINTER_INFO_2, StartTime), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  34. {offsetof(PRINTER_INFO_2, UntilTime), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  35. {offsetof(PRINTER_INFO_2, Status), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  36. {offsetof(PRINTER_INFO_2, cJobs), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  37. {offsetof(PRINTER_INFO_2, AveragePPM), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  38. {0xFFFFFFFF, 0, 0, DATA_TYPE}
  39. };
  40. static
  41. FieldInfo PrinterInfo7Fields[]={
  42. {offsetof(PRINTER_INFO_7, pszObjectGUID), sizeof(ULONG_PTR),sizeof(DWORD), PTR_TYPE },
  43. {offsetof(PRINTER_INFO_7, dwAction), sizeof(DWORD), sizeof(DWORD), DATA_TYPE },
  44. {0xFFFFFFFF, 0, 0, DATA_TYPE}
  45. };
  46. /*++
  47. Title:
  48. TPrnStream
  49. Routine Description:
  50. Initialize class members.
  51. Initialise m_pIStream to NULL.
  52. TPrnStream Read/write/Seek functionality is implemented through this object methods call.
  53. m_pIStream is created when BindPrnStream is called. If this function fails,
  54. any subsequent method call will fail too.
  55. Arguments:
  56. None
  57. Return Value:
  58. Nothing
  59. --*/
  60. TPrnStream::
  61. TPrnStream(
  62. IN LPCTSTR pszPrnName,
  63. IN LPCTSTR pszFileName
  64. ) : m_pIStream(NULL),
  65. m_strFileName(pszFileName),
  66. m_strPrnName(pszPrnName),
  67. m_hPrinterHandle(INVALID_HANDLE_VALUE),
  68. m_bHeaderWritten(FALSE),
  69. m_cIndex(0),
  70. m_ResolveCase(0),
  71. m_pPrnBinItem(NULL),
  72. m_EnumColorProfiles(NULL),
  73. m_AssociateColorProfileWithDevice(NULL),
  74. m_DisassociateColorProfileFromDevice(NULL),
  75. m_pColorProfileLibrary(NULL)
  76. {
  77. m_cPrnDataItems.QuadPart = 0;
  78. m_uliSeekPtr.QuadPart = 0;
  79. }
  80. /*++
  81. Title:
  82. ~TPrnStream
  83. Routine Description:
  84. Close printer if opened ; free TStream if created
  85. Arguments:
  86. None
  87. Return Value:
  88. Nothing
  89. --*/
  90. TPrnStream::
  91. ~TPrnStream(
  92. )
  93. {
  94. if(m_hPrinterHandle != INVALID_HANDLE_VALUE)
  95. {
  96. ClosePrinter(m_hPrinterHandle);
  97. }
  98. if(m_pIStream)
  99. {
  100. delete m_pIStream;
  101. }
  102. if(m_pPrnBinItem)
  103. {
  104. FreeMem(m_pPrnBinItem);
  105. }
  106. if (m_pColorProfileLibrary)
  107. {
  108. delete m_pColorProfileLibrary;
  109. }
  110. }
  111. /*++
  112. Title:
  113. BindPrnStream
  114. Routine Description:
  115. Open Printer , bind prinyter handle to WalkPrinter and create an TStream
  116. WalkPrinter can take a printer name or printer handle at constructing time
  117. It has also a default constructor explicit defined ; Printer handle can be binded later
  118. Arguments:
  119. Return Value:
  120. S_OK if succeeded,
  121. E_OUTOFMEMORY if failed to alloc mem
  122. an error code maped to a storage hresult
  123. --*/
  124. HRESULT
  125. TPrnStream::
  126. BindPrnStream(
  127. )
  128. {
  129. TStatusB bStatus;
  130. TStatus Status;
  131. HRESULT hr;
  132. DWORD dwAccess = 0;
  133. Status DBGCHK = sOpenPrinter( m_strPrnName,
  134. &dwAccess,
  135. &m_hPrinterHandle );
  136. DBGMSG( DBG_TRACE, ( "Printer Name : %x "TSTR" File: "TSTR" \n" , m_hPrinterHandle , (LPCTSTR)m_strPrnName , (LPCTSTR)m_strFileName) );
  137. if(dwAccess == PRINTER_ALL_ACCESS)
  138. {
  139. DBGMSG( DBG_TRACE, ( "Printer ALL Access Granted!!!\n" ) );
  140. }
  141. else
  142. {
  143. DBGMSG( DBG_TRACE, ( "Printer READ Access Granted!!!\n" ) );
  144. }
  145. if(Status == 0)
  146. {
  147. BindToPrinter(m_hPrinterHandle);
  148. m_pIStream = new TStream(m_strFileName);
  149. bStatus DBGCHK = (m_pIStream != NULL);
  150. if(bStatus)
  151. {
  152. DBGMSG( DBG_TRACE, ( "BINDING SUCCEEDED!!!\n "));
  153. hr = S_OK;
  154. }
  155. else
  156. {
  157. m_pIStream = NULL;
  158. m_hPrinterHandle = INVALID_HANDLE_VALUE;
  159. hr = E_OUTOFMEMORY;
  160. }
  161. }
  162. else
  163. {
  164. hr = TStream::MapWin32ErrorCodeToHRes(GetLastError());
  165. }
  166. if (SUCCEEDED(hr))
  167. {
  168. hr = InitalizeColorProfileLibrary();
  169. }
  170. return hr;
  171. }
  172. /*++
  173. Title:
  174. UnBindPrnStream
  175. Routine Description:
  176. Close printer if opened , removefile if created , delete
  177. Arguments:
  178. None
  179. Return Value:
  180. S_OK if succeeded,
  181. a Win32 Error (generated by DeleteFile) mapped to a HRESULT if failed
  182. --*/
  183. HRESULT
  184. TPrnStream::
  185. UnBindPrnStream(
  186. )
  187. {
  188. TStatusH hr;
  189. hr DBGNOCHK = S_OK;
  190. if(m_hPrinterHandle != INVALID_HANDLE_VALUE)
  191. {
  192. ClosePrinter(m_hPrinterHandle);
  193. m_hPrinterHandle = INVALID_HANDLE_VALUE;
  194. }
  195. if(m_pIStream)
  196. {
  197. hr DBGCHK = m_pIStream->DestroyFile();
  198. }
  199. return hr;
  200. }
  201. /*++
  202. Title:
  203. SetEndOfPrnStream
  204. Routine Description:
  205. Set the end of PrnStream; In the case when overwrite an existing file, EOF must be set in order to trubcate the file at
  206. the actual dimension of the info written
  207. Arguments:
  208. None
  209. Return Value:
  210. TRUE if succeeded,
  211. --*/
  212. BOOL
  213. TPrnStream::
  214. SetEndOfPrnStream(
  215. )
  216. {
  217. return m_pIStream->bSetEndOfFile();
  218. }
  219. /*++
  220. Title:
  221. CheckPrinterNameIntegrity
  222. Routine Description:
  223. Read printer name from file and compare with name specified at binding
  224. If they are different , depending on how FORCE or RESOLVE flags are set the new name will be resolved or forced.
  225. If no name solving is specified , return error
  226. Func called at restoring time
  227. Arguments:
  228. Flags - flags specified at restoring time ; should specify who printer name conflicts are handles
  229. Return Value:
  230. S_OK if succeeded
  231. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  232. --*/
  233. HRESULT
  234. TPrnStream::
  235. CheckPrinterNameIntegrity(
  236. IN DWORD Flags
  237. )
  238. {
  239. TStatusB bStatus;
  240. TString strStoredPrnName;
  241. TStatusH hr;
  242. //
  243. // m_ResolveCase will indicate how to solve printer name conflicts
  244. // if one of <printer name resolving> flags are set, set m_ResolveCase
  245. //
  246. if(Flags & PRST_RESOLVE_NAME)
  247. {
  248. m_ResolveCase |= TPrnStream::kResolveName;
  249. }
  250. else if(Flags & PRST_FORCE_NAME)
  251. {
  252. m_ResolveCase |= TPrnStream::kForceName;
  253. }
  254. hr DBGCHK = ReadPrnName(strStoredPrnName);
  255. if(SUCCEEDED(hr))
  256. {
  257. if(_tcsicmp( m_strPrnName, strStoredPrnName) != 0)
  258. {
  259. if(m_ResolveCase & TPrnStream::kResolveName)
  260. {
  261. DBGMSG(DBG_TRACE , ("RESOLVE for "TSTR"\n" , (LPCTSTR)m_strPrnName));
  262. hr DBGNOCHK = S_OK;
  263. }
  264. else if(m_ResolveCase & TPrnStream::kForceName)
  265. {
  266. DBGMSG(DBG_TRACE , ("FORCE to "TSTR"\n" , (LPCTSTR)strStoredPrnName));
  267. m_strPrnName.bUpdate(strStoredPrnName);
  268. hr DBGNOCHK = S_OK;
  269. }
  270. else
  271. {
  272. hr DBGNOCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_PRN_NAME_CONFLICT);
  273. }
  274. }
  275. }
  276. return hr;
  277. }
  278. /*++
  279. Title:
  280. PortNameCase
  281. Routine Description:
  282. Set m_ResolveCase to TPrnStream::kResolvePort if resolve port option is set
  283. Arguments:
  284. Flags - this function is called with flags specified for RestorePrinterInfo at restoring time
  285. Return Value:
  286. Nothing
  287. --*/
  288. VOID
  289. TPrnStream::
  290. PortNameCase(
  291. IN DWORD Flags
  292. )
  293. {
  294. if(Flags & PRST_RESOLVE_PORT)
  295. {
  296. m_ResolveCase |= TPrnStream::kResolvePort;
  297. }
  298. }
  299. /*++
  300. Title:
  301. ShareNameCase
  302. Routine Description:
  303. Set m_ResolveCase to TPrnStream::kGenerateShare if resolve port option is set
  304. Arguments:
  305. Flags - this function is called with flags specified for RestorePrinterInfo at restoring time
  306. Return Value:
  307. Nothing
  308. --*/
  309. VOID
  310. TPrnStream::
  311. ShareNameCase(
  312. IN DWORD Flags
  313. )
  314. {
  315. if(Flags & PRST_RESOLVE_SHARE)
  316. {
  317. m_ResolveCase |= TPrnStream::kGenerateShare;
  318. }
  319. else if(Flags & PRST_DONT_GENERATE_SHARE)
  320. {
  321. m_ResolveCase |= TPrnStream::kUntouchShare;
  322. }
  323. }
  324. /*++
  325. Title:
  326. StorePrinterInfo
  327. Routine Description:
  328. Define restoring function table and calls storing functions based on flag value
  329. Arguments:
  330. flags - flags that specifies that functions should be called
  331. Return Value:
  332. S_OK if succeded
  333. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  334. --*/
  335. HRESULT
  336. TPrnStream::
  337. StorePrinterInfo(
  338. IN DWORD Flags,
  339. OUT DWORD& StoredFlags
  340. )
  341. {
  342. TStatusH hr;
  343. hr DBGNOCHK = S_OK;
  344. static PrstFunctEntry StoreFunctTable [] = {
  345. {PRST_PRINTER_INFO_2, &TPrnStream::StorePrnInfo2},
  346. {PRST_PRINTER_INFO_7, &TPrnStream::StorePrnInfo7},
  347. {PRST_COLOR_PROF, &TPrnStream::StoreColorProfiles},
  348. {PRST_PRINTER_DATA, &TPrnStream::StorePrnData},
  349. {PRST_PRINTER_SEC, &TPrnStream::StorePrnSecurity},
  350. {PRST_PRINTER_DEVMODE, &TPrnStream::StorePrnDevMode},
  351. {PRST_USER_DEVMODE, &TPrnStream::StoreUserDevMode},
  352. {0, NULL}};
  353. hr DBGCHK = WriteHeader(Flags);
  354. //
  355. // initialize the flags that were successfully stored with 0
  356. //
  357. StoredFlags = 0;
  358. for(int idx = 0 ; StoreFunctTable[idx].iKeyWord && SUCCEEDED(hr); idx++)
  359. {
  360. if(Flags & StoreFunctTable[idx].iKeyWord)
  361. {
  362. hr DBGCHK = (this->*StoreFunctTable[idx].pPrstFunc)();
  363. if(SUCCEEDED(hr))
  364. {
  365. StoredFlags |= StoreFunctTable[idx].iKeyWord;
  366. }
  367. }
  368. }
  369. if(SUCCEEDED(hr))
  370. {
  371. //
  372. // Truncate file; maybe the file was overwrited
  373. //
  374. SetEndOfPrnStream();
  375. }
  376. else
  377. {
  378. //
  379. //delete file if storing didn't succeed
  380. //
  381. UnBindPrnStream();
  382. }
  383. return hr;
  384. }
  385. /*++
  386. Title:
  387. QueryPrinterInfo
  388. Routine Description:
  389. query a file for stored settings
  390. Arguments:
  391. Flags - specify what settings to query
  392. PrstInfo - Structure where read settings will be dumped
  393. Return Value:
  394. S_OK if succeeded
  395. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  396. --*/
  397. HRESULT
  398. TPrnStream::
  399. QueryPrinterInfo(
  400. IN PrinterPersistentQueryFlag Flags,
  401. OUT PersistentInfo *pPrstInfo
  402. )
  403. {
  404. TStatusH hr;
  405. BOOL bInsidePI2;
  406. static QueryFunctEntry QueryFunctTable [] = {
  407. {PRST_PRINTER_INFO_2, &TPrnStream::ReadPrnInfo2},
  408. {PRST_PRINTER_INFO_7, &TPrnStream::ReadPrnInfo7},
  409. {PRST_COLOR_PROF, &TPrnStream::ReadColorProfiles},
  410. {PRST_PRINTER_SEC, &TPrnStream::ReadPrnSecurity},
  411. {PRST_PRINTER_DEVMODE, &TPrnStream::ReadPrnInfo8},
  412. {0, NULL}};
  413. //
  414. // delete in case QueryPrinterInfo was previously called
  415. // m_pPrnBinItem store a PrnBinInfo block when Query ;
  416. // it has to be deleted between to Querys and at destruction time
  417. //
  418. if(m_pPrnBinItem)
  419. {
  420. delete m_pPrnBinItem;
  421. }
  422. hr DBGNOCHK = S_OK;
  423. for(int idx = 0 ; QueryFunctTable[idx].iKeyWord && SUCCEEDED(hr); idx++)
  424. {
  425. if(Flags & QueryFunctTable[idx].iKeyWord)
  426. {
  427. hr DBGCHK = (this->*QueryFunctTable[idx].pReadFunct)(&m_pPrnBinItem);
  428. if(SUCCEEDED(hr))
  429. {
  430. DBGMSG( DBG_TRACE, ( "QueryPrinterInfo: pReadFunct OK \n"));
  431. pPrstInfo->pi2 = reinterpret_cast<PRINTER_INFO_2*>(reinterpret_cast<LPBYTE>(m_pPrnBinItem) + m_pPrnBinItem->pData);
  432. }
  433. else
  434. {
  435. DBGMSG( DBG_TRACE, ( "QueryPrinterInfo: pReadFunct FAILED \n"));
  436. }
  437. }
  438. }
  439. return hr;
  440. }
  441. /*++
  442. Title:
  443. RestorePrinterInfo
  444. Routine Description:
  445. Handle port name conflicts by calling PortNameCase before any restoring
  446. Define restoring function table and calls restoring functions based on flag value
  447. Arguments:
  448. flags - flags that specifies that functions should be called
  449. Return Value:
  450. S_OK if succeded
  451. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  452. --*/
  453. HRESULT
  454. TPrnStream::
  455. RestorePrinterInfo(
  456. IN DWORD Flags,
  457. OUT DWORD& RestoredFlags
  458. )
  459. {
  460. TStatusH hr;
  461. hr DBGNOCHK = S_OK;
  462. static PrstFunctEntry RestoreFunctTable [] = {
  463. {PRST_PRINTER_INFO_2, &TPrnStream::RestorePrnInfo2},
  464. {PRST_COLOR_PROF, &TPrnStream::RestoreColorProfiles},
  465. {PRST_PRINTER_DEVMODE, &TPrnStream::RestorePrnDevMode},
  466. {PRST_PRINTER_INFO_7, &TPrnStream::RestorePrnInfo7},
  467. {PRST_PRINTER_DATA, &TPrnStream::RestorePrnData},
  468. {PRST_PRINTER_SEC, &TPrnStream::RestorePrnSecurity},
  469. {PRST_USER_DEVMODE, &TPrnStream::RestoreUserDevMode},
  470. {0, NULL}};
  471. //
  472. // initialize the flags that were successfully stored with 0
  473. //
  474. RestoredFlags = 0;
  475. //
  476. // if PRST_RESOLVE_PORT is set , update m_ResolveCase so RestorePrnInfo2 can act properly
  477. //
  478. PortNameCase(Flags);
  479. //
  480. // if PRST_RESOLVE_SHARE is set , update m_ResolveCase so RestorePrnInfo2 can act properly
  481. //
  482. ShareNameCase(Flags);
  483. for(int idx = 0 ; RestoreFunctTable[idx].iKeyWord && SUCCEEDED(hr); idx++)
  484. {
  485. if(Flags & RestoreFunctTable[idx].iKeyWord)
  486. {
  487. hr DBGCHK = (this->*RestoreFunctTable[idx].pPrstFunc)();
  488. if(SUCCEEDED(hr))
  489. {
  490. RestoredFlags |= RestoreFunctTable[idx].iKeyWord;
  491. }
  492. }
  493. }
  494. return hr;
  495. }
  496. /*++
  497. Title:
  498. bStorePrnInfo2
  499. Routine Description:
  500. Build an item based on P_I_2 and write it into the stream
  501. Arguments:
  502. None
  503. Return Value:
  504. S_OK if succeded
  505. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  506. --*/
  507. HRESULT
  508. TPrnStream::
  509. StorePrnInfo2(
  510. VOID
  511. )
  512. {
  513. DWORD cbSize;
  514. TStatusH hr;
  515. TStatusB bStatus;
  516. LPPRINTER_INFO_2 lpPrinterInfo2 = NULL;
  517. //
  518. // Get P_I_2
  519. //
  520. cbSize = 1;
  521. if(bStatus DBGCHK = bGetPrinter(m_hPrinter,
  522. 2,
  523. reinterpret_cast<PVOID*>(&lpPrinterInfo2),
  524. &cbSize))
  525. {
  526. DBGMSG( DBG_TRACE, ("StorePrnInfo2 %d \n" , cbSize) );
  527. hr DBGCHK = WritePrnInfo2(lpPrinterInfo2, cbSize);
  528. FreeMem(lpPrinterInfo2);
  529. }
  530. else
  531. {
  532. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_GET_PI2);
  533. }
  534. return hr;
  535. }
  536. /*++
  537. Title:
  538. bRestorePrnInfo2
  539. Routine Description:
  540. Apply P_I_2 settings read from stream to binded printer
  541. Arguments:
  542. None
  543. Return Value:
  544. S_OK if succeded
  545. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  546. --*/
  547. HRESULT
  548. TPrnStream::
  549. RestorePrnInfo2(
  550. VOID
  551. )
  552. {
  553. PrnBinInfo* pSourcePI2 = NULL;
  554. TStatusH hr;
  555. TStatusB bStatus;
  556. PRINTER_INFO_2* pDestinationPI2 = NULL;
  557. DWORD cbSize = 0;
  558. //
  559. // Reads settings stored in stream
  560. //
  561. hr DBGCHK = ReadPrnInfo2(&pSourcePI2);
  562. if(SUCCEEDED(hr))
  563. {
  564. cbSize = 1;
  565. bStatus DBGCHK = bGetPrinter(m_hPrinter,
  566. 2,
  567. reinterpret_cast<PVOID*>(&pDestinationPI2),
  568. &cbSize);
  569. if(bStatus)
  570. {
  571. LPTSTR* ppszStoredPrnName = &(reinterpret_cast<PRINTER_INFO_2*>(
  572. reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData)->pPrinterName
  573. );
  574. LPTSTR* ppShareName = &(reinterpret_cast<PRINTER_INFO_2*>(
  575. reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData)->pShareName
  576. );
  577. LPTSTR* ppPortName = &(reinterpret_cast<PRINTER_INFO_2*>(
  578. reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData)->pPortName
  579. );
  580. LPTSTR* ppPrintProcessor = &(reinterpret_cast<PRINTER_INFO_2*>(
  581. reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData)->pPrintProcessor
  582. );
  583. LPDWORD pAttributes = &(reinterpret_cast<PRINTER_INFO_2*>(
  584. reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData)->Attributes
  585. );
  586. DBGMSG(DBG_TRACE , (" Stored Prn Name: "TSTR" Share:"TSTR"\n" , *ppszStoredPrnName , *ppShareName));
  587. //
  588. // check against printer name
  589. //
  590. if( _tcsicmp( pDestinationPI2->pPrinterName, *ppszStoredPrnName ) != 0)
  591. {
  592. if(m_ResolveCase & kResolveName)
  593. {
  594. // RESOLVE!!!
  595. // if printer name differs from printer name stored into file ,
  596. // update read structure with open printer
  597. //
  598. DBGMSG(DBG_TRACE , (" RESOLVE Printer : "TSTR" Share:"TSTR" old : "TSTR"\n" , *ppszStoredPrnName , *ppShareName , pDestinationPI2->pShareName));
  599. *ppszStoredPrnName = pDestinationPI2->pPrinterName;
  600. }
  601. else if(m_ResolveCase & kForceName)
  602. {
  603. // FORCE!!!
  604. // if printer name differs from printer name stored into file ,
  605. // let printer name and share name as they are in the stored file
  606. //
  607. DBGMSG(DBG_TRACE , (" FORCE Printer : "TSTR" Share:"TSTR"\n" , *ppszStoredPrnName , *ppShareName));
  608. }
  609. else
  610. {
  611. //
  612. // if printer name differs from printer name stored into file ,
  613. // return error ; printer names are different but the flags are not used
  614. //
  615. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_PI2);
  616. goto End;
  617. }
  618. }
  619. //
  620. // if resolve port option was set , port name from the printer configuration settings to be ignored in lieu of
  621. // the port name that printer curently has
  622. //
  623. if(m_ResolveCase & kResolvePort)
  624. {
  625. *ppPortName = pDestinationPI2->pPortName;;
  626. }
  627. //
  628. // if the print processor from the printer configuration settings differs from the curent installed print processor
  629. // just ignore it
  630. //
  631. if( _tcsicmp( pDestinationPI2->pPrintProcessor, *ppPrintProcessor) != 0 )
  632. {
  633. *ppPrintProcessor = pDestinationPI2->pPrintProcessor;
  634. }
  635. if((reinterpret_cast<PRINTER_INFO_2*>(reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData))->pDevMode)
  636. {
  637. (reinterpret_cast<PRINTER_INFO_2*>(reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData))->pDevMode = NULL;
  638. DBGMSG(DBG_TRACE , (" Reset devmode to NULL!\n" ));
  639. }
  640. //
  641. // Set printer with read settings
  642. //
  643. bStatus DBGCHK = SetPrinter(m_hPrinter,
  644. 2,
  645. reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData,
  646. 0);
  647. //
  648. // If SetPrinter failed with ERROR_INVALID_SHARENAME and a resolve share flag is set,
  649. // retry call SetPrinter with a new generated share name
  650. //
  651. if(!bStatus &&
  652. (m_ResolveCase & ( kUntouchShare | kGenerateShare )) &&
  653. GetLastError() == ERROR_INVALID_SHARENAME)
  654. {
  655. TString strShareName;
  656. TString strPrinterName( pDestinationPI2->pPrinterName );
  657. //
  658. // If already shared, use the current share name
  659. // Even if generating share flag is set, don't create a new share name
  660. // as long as the printer is shared. The whole point of this share name generation is
  661. // to allow the printer to be shared, but since it is , don't waist any time.
  662. //
  663. if( pDestinationPI2->Attributes & PRINTER_ATTRIBUTE_SHARED &&
  664. pDestinationPI2->pShareName &&
  665. pDestinationPI2->pShareName[0] )
  666. {
  667. *ppShareName = pDestinationPI2->pShareName;
  668. *pAttributes |= PRINTER_ATTRIBUTE_SHARED;
  669. }
  670. else
  671. {
  672. //
  673. // Resolve share name by generating a new share name
  674. //
  675. if(m_ResolveCase & kGenerateShare)
  676. {
  677. if( VALID_OBJ( strPrinterName ) )
  678. {
  679. bStatus DBGCHK = bNewShareName(pDestinationPI2->pServerName, strPrinterName, strShareName);
  680. *ppShareName = (LPTSTR)(LPCTSTR)(strShareName);
  681. *pAttributes |= PRINTER_ATTRIBUTE_SHARED;
  682. //
  683. // *ppShareName is NULL if bNewShareName fails
  684. //
  685. DBGMSG( DBG_TRACE, ( "Created share name for " TSTR " " TSTR "\n", (LPCTSTR)strPrinterName, (LPCTSTR)strShareName ) );
  686. }
  687. }
  688. //
  689. // Don't share it at all
  690. //
  691. if(m_ResolveCase & kUntouchShare)
  692. {
  693. *pAttributes &= ~PRINTER_ATTRIBUTE_SHARED;
  694. *ppShareName = NULL;
  695. }
  696. }
  697. //
  698. // Set printer with read settings
  699. //
  700. bStatus DBGCHK = SetPrinter(m_hPrinter,
  701. 2,
  702. reinterpret_cast<LPBYTE>(pSourcePI2) + pSourcePI2->pData,
  703. 0);
  704. DBGMSG(DBG_TRACE , (" RESOLVE Printer : "TSTR" Share:"TSTR"\n" , *ppszStoredPrnName , *ppShareName));
  705. }
  706. End:
  707. if(bStatus)
  708. {
  709. hr DBGNOCHK = S_OK;
  710. DBGMSG(DBG_TRACE , (" SetPrinter on level 2 succeeded!\n" ));
  711. }
  712. else
  713. {
  714. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_PI2);
  715. }
  716. FreeMem(pSourcePI2);
  717. if(pDestinationPI2 != NULL)
  718. {
  719. FreeMem(pDestinationPI2);
  720. }
  721. }
  722. else
  723. {
  724. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_PI2);
  725. }
  726. }
  727. return hr;
  728. }
  729. /*++
  730. Title:
  731. bStorePrnInfo7
  732. Routine Description:
  733. Build an item based on P_I_7 and write it into the stream
  734. Arguments:
  735. None
  736. Return Value:
  737. S_OK if succeded
  738. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  739. --*/
  740. HRESULT
  741. TPrnStream::
  742. StorePrnInfo7(
  743. VOID
  744. )
  745. {
  746. DWORD cbSize;
  747. TStatusH hr;
  748. TStatusB bStatus;
  749. LPPRINTER_INFO_7 lpPrinterInfo7 = NULL;
  750. //
  751. // Get P_I_7
  752. //
  753. cbSize = 1;
  754. bStatus DBGCHK = bGetPrinter(m_hPrinter,
  755. 7,
  756. reinterpret_cast<PVOID*>(&lpPrinterInfo7),
  757. &cbSize);
  758. if(bStatus)
  759. {
  760. //
  761. // remove DSPRINT_PENDING flags
  762. //
  763. lpPrinterInfo7->dwAction &= ~DSPRINT_PENDING;
  764. hr DBGCHK = WritePrnInfo7(lpPrinterInfo7, cbSize);
  765. FreeMem(lpPrinterInfo7);
  766. }
  767. else
  768. {
  769. if(GetLastError() == ERROR_INVALID_LEVEL)
  770. {
  771. hr DBGNOCHK = S_OK;
  772. }
  773. else
  774. {
  775. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_GET_PI7);
  776. }
  777. }
  778. return hr;
  779. }
  780. /*++
  781. Title:
  782. RestorePrnInfo7
  783. Routine Description:
  784. Apply P_I_7 settings read from stream to binded printer
  785. Arguments:
  786. None
  787. Return Value:
  788. S_OK if succeded
  789. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  790. --*/
  791. HRESULT
  792. TPrnStream::
  793. RestorePrnInfo7(
  794. VOID
  795. )
  796. {
  797. DWORD cbSize;
  798. PrnBinInfo* lpPrnBinItem = NULL;
  799. TStatusH hr;
  800. TStatusB bStatus;
  801. DWORD LastError;
  802. //
  803. // Reads settings stored in stream
  804. //
  805. hr DBGCHK = ReadPrnInfo7(&lpPrnBinItem);
  806. if(SUCCEEDED(hr) && lpPrnBinItem)
  807. {
  808. //
  809. // Set printer with read settings
  810. //
  811. bStatus DBGCHK = SetPrinter( m_hPrinter,
  812. 7,
  813. reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData,
  814. 0);
  815. LastError = GetLastError();
  816. if(LastError == ERROR_IO_PENDING ||
  817. LastError == ERROR_DS_UNAVAILABLE)
  818. {
  819. //
  820. // If the error is io pending the spooler
  821. // will publish in the background therefore we will silently fail.
  822. // and
  823. // The server must be stand alone and/or DirectoryService is not available.
  824. // Just continue.
  825. //
  826. hr DBGNOCHK = S_OK;
  827. }
  828. else
  829. {
  830. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_PI7);
  831. }
  832. FreeMem(lpPrnBinItem);
  833. }
  834. return hr;
  835. }
  836. /*++
  837. Title:
  838. StorePrnSecurity
  839. Routine Description:
  840. Build an item based on security descriptor and write it into the stream
  841. Arguments:
  842. None
  843. Return Value:
  844. S_OK if succeded
  845. PRN_PERSIST_ERROR_GET_SEC error code mapped to HRESULT(FACILITY_ITF) if failed
  846. --*/
  847. HRESULT
  848. TPrnStream::
  849. StorePrnSecurity(
  850. VOID
  851. )
  852. {
  853. DWORD cbSize;
  854. TStatusH hr;
  855. TStatusB bStatus;
  856. PRINTER_INFO_2* lpPrinterInfo2 = NULL;
  857. //
  858. // Get P_I_2
  859. //
  860. cbSize = 1;
  861. bStatus DBGCHK = bGetPrinter(m_hPrinter,
  862. 2,
  863. reinterpret_cast<PVOID*>(&lpPrinterInfo2),
  864. &cbSize);
  865. if(bStatus)
  866. {
  867. hr DBGCHK = WritePrnSecurity(lpPrinterInfo2, cbSize);
  868. FreeMem(lpPrinterInfo2);
  869. }
  870. else
  871. {
  872. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_GET_SEC);
  873. }
  874. return hr;
  875. }
  876. /*++
  877. Title:
  878. RestorePrnSecurity
  879. Routine Description:
  880. Apply security descriptor read from stream to binded printer
  881. Arguments:
  882. None
  883. Return Value:
  884. S_OK if succeded
  885. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  886. --*/
  887. HRESULT
  888. TPrnStream::
  889. RestorePrnSecurity(
  890. VOID
  891. )
  892. {
  893. DWORD cbSize;
  894. PRINTER_INFO_3 PrinterInfo3;
  895. PrnBinInfo* lpPrnBinItem = NULL;
  896. TStatusH hr;
  897. TStatusB bStatus;
  898. //
  899. // Reads settings stored in stream
  900. //
  901. hr DBGCHK = ReadPrnSecurity(&lpPrnBinItem);
  902. if(SUCCEEDED(hr))
  903. {
  904. PrinterInfo3.pSecurityDescriptor = reinterpret_cast<PSECURITY_DESCRIPTOR>(
  905. reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData
  906. );
  907. //
  908. // Set printer with read settings
  909. //
  910. bStatus DBGCHK = SetPrinter( m_hPrinter,
  911. 3,
  912. reinterpret_cast<LPBYTE>(&PrinterInfo3),
  913. 0);
  914. if(bStatus)
  915. {
  916. hr DBGNOCHK = S_OK;
  917. }
  918. else
  919. {
  920. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_SEC);
  921. }
  922. FreeMem(lpPrnBinItem);
  923. }
  924. return hr;
  925. }
  926. /*++
  927. Title:
  928. StoreUserDevMode
  929. Routine Description:
  930. Build an item based on user dev mode and write it into the stream
  931. Arguments:
  932. None
  933. Return Value:
  934. S_OK if succeded
  935. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  936. --*/
  937. HRESULT
  938. TPrnStream::
  939. StoreUserDevMode(
  940. VOID
  941. )
  942. {
  943. DWORD cbSize;
  944. TStatusH hr;
  945. TStatusB bStatus;
  946. LPPRINTER_INFO_9 lpPrinterInfo9 = NULL;
  947. //
  948. // Get P_I_9
  949. //
  950. cbSize = 1;
  951. bStatus DBGCHK = bGetPrinter(m_hPrinter,
  952. 9,
  953. reinterpret_cast<PVOID*>(&lpPrinterInfo9),
  954. &cbSize);
  955. if(bStatus)
  956. {
  957. //
  958. // call WritePrnInfo9 even if lpPrinterInfo9 is null ;
  959. // usually, when printer doesn't have a user mode attached ,is lpPrinterInfo9->pDevMode who is null
  960. // but still call it and check lpPrinterInfo9 == NULL on WritePrnInfo9, to act similar as lpPrinterInfo9->pDevMode == NULL
  961. //
  962. hr DBGCHK = WritePrnInfo9(lpPrinterInfo9, cbSize);
  963. FreeMem(lpPrinterInfo9);
  964. }
  965. else
  966. {
  967. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_GET_USR_DEVMODE);
  968. }
  969. return hr;
  970. }
  971. /*++
  972. Title:
  973. RestoreUserDevMode
  974. Routine Description:
  975. Apply user dev mode read from stream to binded printer
  976. Arguments:
  977. None
  978. Return Value:
  979. S_OK if succeded
  980. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  981. --*/
  982. HRESULT
  983. TPrnStream::
  984. RestoreUserDevMode(
  985. VOID
  986. )
  987. {
  988. PrnBinInfo* lpPrnBinItem = NULL;
  989. PRINTER_INFO_9 PrinterInfo9;
  990. TStatusH hr;
  991. TStatusB bStatus;
  992. DWORD cbSize;
  993. hr DBGNOCHK = E_FAIL;
  994. //
  995. // Reads settings stored in stream
  996. //
  997. hr DBGCHK = ReadPrnInfo9(&lpPrnBinItem);
  998. if(SUCCEEDED(hr))
  999. {
  1000. if(lpPrnBinItem != NULL)
  1001. {
  1002. PrinterInfo9.pDevMode = reinterpret_cast<DEVMODE*>(
  1003. reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData
  1004. );
  1005. }
  1006. else
  1007. {
  1008. //
  1009. // User dev mode can be null if there are no Printer prefferences set at the time the file is created
  1010. // We remove per user devmode by calling SetPrinter with pDevMode equal with NULL
  1011. //
  1012. DBGMSG(DBG_TRACE , ("NO USER DEVMODE STORED!!!\n"));
  1013. PrinterInfo9.pDevMode = NULL;
  1014. }
  1015. //
  1016. // Set printer with read settings
  1017. //
  1018. bStatus DBGCHK = SetPrinter( m_hPrinter,
  1019. 9,
  1020. reinterpret_cast<LPBYTE>(&PrinterInfo9),
  1021. 0);
  1022. if(bStatus)
  1023. {
  1024. hr DBGNOCHK = S_OK;
  1025. }
  1026. else
  1027. {
  1028. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_USR_DEVMODE);
  1029. }
  1030. FreeMem(lpPrnBinItem);
  1031. }
  1032. return hr;
  1033. }
  1034. /*++
  1035. Title:
  1036. StorePrnDevMode
  1037. Routine Description:
  1038. Build an item based on printer dev mode and write it into the stream
  1039. Arguments:
  1040. None
  1041. Return Value:
  1042. S_OK if succeded
  1043. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  1044. --*/
  1045. HRESULT
  1046. TPrnStream::
  1047. StorePrnDevMode(
  1048. VOID
  1049. )
  1050. {
  1051. DWORD cbSize;
  1052. TStatusH hr;
  1053. TStatusB bStatus;
  1054. LPPRINTER_INFO_8 lpPrinterInfo8 = NULL;
  1055. hr DBGNOCHK = E_FAIL;
  1056. //
  1057. // Get P_I_8
  1058. //
  1059. cbSize = 1;
  1060. bStatus DBGCHK = bGetPrinter(m_hPrinter,
  1061. 8,
  1062. reinterpret_cast<PVOID*>(&lpPrinterInfo8),
  1063. &cbSize);
  1064. if(bStatus)
  1065. {
  1066. bStatus DBGCHK = (lpPrinterInfo8->pDevMode != NULL);
  1067. if(bStatus)
  1068. {
  1069. hr DBGCHK = WritePrnInfo8(lpPrinterInfo8, cbSize);
  1070. }
  1071. FreeMem(lpPrinterInfo8);
  1072. }
  1073. if(FAILED(hr))
  1074. {
  1075. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_GET_PRN_DEVMODE);
  1076. }
  1077. return hr;
  1078. }
  1079. /*++
  1080. Title:
  1081. RestorePrnDevMode
  1082. Routine Description:
  1083. Apply printer dev mode read from stream to binded printer
  1084. Arguments:
  1085. None
  1086. Return Value:
  1087. S_OK if succeded
  1088. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  1089. --*/
  1090. HRESULT
  1091. TPrnStream::
  1092. RestorePrnDevMode(
  1093. VOID
  1094. )
  1095. {
  1096. DWORD cbSize;
  1097. PRINTER_INFO_8 PrinterInfo8;
  1098. PrnBinInfo* lpPrnBinItem = NULL;
  1099. TStatusH hr;
  1100. TStatusB bStatus;
  1101. BOOL bInsidePI2;
  1102. hr DBGNOCHK = E_FAIL;
  1103. //
  1104. // Reads settings stored in stream
  1105. //
  1106. hr DBGCHK = ReadPrnInfo8(&lpPrnBinItem);
  1107. if(SUCCEEDED(hr))
  1108. {
  1109. PrinterInfo8.pDevMode = reinterpret_cast<DEVMODE*>(
  1110. reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData
  1111. );
  1112. //
  1113. // Set printer with read settings
  1114. //
  1115. bStatus DBGCHK = SetPrinter( m_hPrinter,
  1116. 8,
  1117. reinterpret_cast<LPBYTE>(&PrinterInfo8),
  1118. 0);
  1119. if(bStatus)
  1120. {
  1121. hr DBGNOCHK = S_OK;
  1122. }
  1123. else
  1124. {
  1125. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_PRN_DEVMODE);
  1126. }
  1127. FreeMem(lpPrnBinItem);
  1128. }
  1129. return hr;
  1130. }
  1131. /*++
  1132. Title:
  1133. StoreColorProfiles
  1134. Routine Description:
  1135. strore a multi zero string with color profiles into stream
  1136. Arguments:
  1137. None
  1138. Return Value:
  1139. S_OK if succeded
  1140. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  1141. --*/
  1142. HRESULT
  1143. TPrnStream::
  1144. StoreColorProfiles(
  1145. VOID
  1146. )
  1147. {
  1148. TStatusH hr;
  1149. TStatusB bStatus;
  1150. DWORD cbSize;
  1151. DWORD dwProfiles;
  1152. ENUMTYPE EnumType;
  1153. LPTSTR mszProfileNames;
  1154. ZeroMemory(&EnumType, sizeof(EnumType));
  1155. EnumType.dwSize = sizeof(EnumType);
  1156. EnumType.dwVersion = ENUM_TYPE_VERSION;
  1157. EnumType.dwFields = ET_DEVICENAME | ET_DEVICECLASS;
  1158. EnumType.pDeviceName = static_cast<LPCTSTR>(m_strPrnName);
  1159. EnumType.dwDeviceClass = CLASS_PRINTER;
  1160. cbSize = 0;
  1161. m_EnumColorProfiles(NULL, &EnumType, NULL, &cbSize, &dwProfiles);
  1162. mszProfileNames = (LPTSTR)AllocMem(cbSize);
  1163. bStatus DBGCHK = (mszProfileNames != NULL);
  1164. if(bStatus)
  1165. {
  1166. bStatus DBGCHK = m_EnumColorProfiles( NULL,
  1167. &EnumType,
  1168. reinterpret_cast<LPBYTE>(mszProfileNames),
  1169. &cbSize,
  1170. &dwProfiles);
  1171. if(bStatus)
  1172. {
  1173. hr DBGCHK = WriteColorProfiles(reinterpret_cast<LPBYTE>(mszProfileNames), cbSize);
  1174. }
  1175. else
  1176. {
  1177. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_GET_COLOR_PRF);
  1178. }
  1179. FreeMem(mszProfileNames);
  1180. }
  1181. else
  1182. {
  1183. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_GET_COLOR_PRF);
  1184. }
  1185. return hr;
  1186. }
  1187. /*++
  1188. Title:
  1189. DeleteColorProfiles
  1190. Routine Description:
  1191. deletes all profiles associated with printer
  1192. it is called on restoring color settings; needed because if a new color profile is added ,
  1193. settings from file will be restored on top ( #bug 274657)
  1194. it could work Ok without calling this function when P_I_2 is also restored, because there color profiles are "somehow" restored,
  1195. but even so, success was depending on the order of calls,which is bogus
  1196. Arguments:
  1197. None
  1198. Return Value:
  1199. S_OK if succeded
  1200. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  1201. --*/
  1202. BOOL
  1203. TPrnStream::
  1204. DeleteColorProfiles(
  1205. VOID
  1206. )
  1207. {
  1208. TStatusB bStatus;
  1209. DWORD cbSize;
  1210. DWORD cbPrfSize;
  1211. DWORD dwProfiles;
  1212. ENUMTYPE EnumType;
  1213. LPTSTR mszProfileNames;
  1214. ZeroMemory(&EnumType, sizeof(EnumType));
  1215. EnumType.dwSize = sizeof(EnumType);
  1216. EnumType.dwVersion = ENUM_TYPE_VERSION;
  1217. EnumType.dwFields = ET_DEVICENAME | ET_DEVICECLASS;
  1218. EnumType.pDeviceName = static_cast<LPCTSTR>(m_strPrnName);
  1219. EnumType.dwDeviceClass = CLASS_PRINTER;
  1220. cbSize = 0;
  1221. m_EnumColorProfiles(NULL, &EnumType, NULL, &cbSize, &dwProfiles);
  1222. mszProfileNames = (LPTSTR)AllocMem(cbSize);
  1223. bStatus DBGCHK = (mszProfileNames != NULL);
  1224. if(bStatus)
  1225. {
  1226. bStatus DBGCHK = m_EnumColorProfiles( NULL,
  1227. &EnumType,
  1228. reinterpret_cast<LPBYTE>(mszProfileNames),
  1229. &cbSize,
  1230. &dwProfiles);
  1231. if(bStatus)
  1232. {
  1233. LPTSTR pszProfileName = mszProfileNames;
  1234. for(bStatus DBGNOCHK = TRUE ,cbPrfSize = 0; (cbPrfSize < cbSize) && bStatus;)
  1235. {
  1236. //
  1237. // skip last two zeros
  1238. //
  1239. if(_tcsclen(pszProfileName) > 0)
  1240. {
  1241. DBGMSG( DBG_TRACE, ( "DisassociateColorProfileWithDevice "TSTR" :: " TSTR " \n" ,
  1242. static_cast<LPCTSTR>(m_strPrnName) , pszProfileName ));
  1243. bStatus DBGCHK = m_DisassociateColorProfileFromDevice(NULL, pszProfileName, m_strPrnName);
  1244. }
  1245. cbPrfSize += (_tcsclen(pszProfileName) + 2) * sizeof(TCHAR);
  1246. pszProfileName = pszProfileName + _tcsclen(pszProfileName) + 1;
  1247. }
  1248. }
  1249. FreeMem(mszProfileNames);
  1250. }
  1251. return bStatus;
  1252. }
  1253. /*++
  1254. Title:
  1255. RestoreColorProfiles
  1256. Routine Description:
  1257. Reads multi zero string from stream and for every sz calls AssociateColorProfileWithDevice
  1258. Arguments:
  1259. NONE
  1260. Return Value:
  1261. S_OK if succeded
  1262. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  1263. --*/
  1264. HRESULT
  1265. TPrnStream::
  1266. RestoreColorProfiles(
  1267. VOID
  1268. )
  1269. {
  1270. DWORD cSize;
  1271. DWORD i;
  1272. LPTSTR pszProfileName;
  1273. LPTSTR aszProfileNames;
  1274. PrnBinInfo* lpPrnBinItem = NULL;
  1275. TStatusH hr;
  1276. TStatusB bStatus(DBG_WARN, ERROR_INSUFFICIENT_BUFFER);
  1277. hr DBGCHK = ReadColorProfiles(&lpPrnBinItem);
  1278. if(SUCCEEDED(hr))
  1279. {
  1280. //
  1281. // first delete color profiles assoc with printer; fix for bug 274657
  1282. //
  1283. bStatus DBGCHK = DeleteColorProfiles();
  1284. if(bStatus)
  1285. {
  1286. aszProfileNames = reinterpret_cast<LPTSTR>(reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData);
  1287. cSize = lpPrnBinItem->cbData/sizeof(TCHAR);
  1288. //
  1289. // Traverse multisz string from tail to head starting with the first zero.
  1290. // I relay on the fact that multisz is terminated by 2 zeros.
  1291. // Default color profile is last color profile associated and we should preserve this setting.
  1292. //
  1293. for( bStatus DBGNOCHK = TRUE, i = 2; i <= cSize && bStatus; )
  1294. {
  1295. pszProfileName = aszProfileNames + cSize - i;
  1296. if( *(pszProfileName - 1) == 0 || (i == cSize) )
  1297. {
  1298. DBGMSG( DBG_TRACE, ( "AssociateColorProfileWithDevice "TSTR" :: " TSTR " \n" ,
  1299. static_cast<LPCTSTR>(m_strPrnName) , pszProfileName ));
  1300. bStatus DBGCHK = m_AssociateColorProfileWithDevice(NULL, pszProfileName, m_strPrnName);
  1301. hr DBGCHK = bStatus ? S_OK : MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_COLOR_PRF);
  1302. }
  1303. i++;
  1304. }
  1305. }
  1306. FreeMem(lpPrnBinItem);
  1307. }
  1308. return hr;
  1309. }
  1310. /*++
  1311. Title:
  1312. WritePrnData
  1313. Routine Description:
  1314. Build an PrnBinInfo item from key and value and write it into stream, at current position
  1315. steps:
  1316. WriteHeader: if header is not wrriten into file , write it down
  1317. Read from header number of items currently written
  1318. Read from header where prn data items begins
  1319. If no other items where written,get current position and after items storing, update header with start position
  1320. Build an PrnBinInfo item and write it into stream, at current position
  1321. Increase number of written items and Update header
  1322. Arguments:
  1323. pKey - key name ;
  1324. pValueName - key value ;
  1325. cbValueName - count bytes of pValueName
  1326. dwType - type
  1327. pData - actually data
  1328. cbData - count bytes of pData
  1329. Return Value:
  1330. S_OK if succeded
  1331. --*/
  1332. HRESULT
  1333. TPrnStream::
  1334. WritePrnData(
  1335. IN LPCTSTR pKey,
  1336. IN LPCTSTR pValueName,
  1337. IN DWORD cbValueName,
  1338. IN DWORD dwType,
  1339. IN LPBYTE pData,
  1340. IN DWORD cbData
  1341. )
  1342. {
  1343. ULARGE_INTEGER culiPrnDataItems;
  1344. ULARGE_INTEGER uliCurrentPos;
  1345. ULARGE_INTEGER uliPrnDataRoot;
  1346. TStatusB bStatus;
  1347. TStatusH hr;
  1348. bStatus DBGNOCHK = TRUE;
  1349. //
  1350. // Read from header number of items currently written
  1351. //
  1352. hr DBGCHK = ReadFromHeader(kcItems, &culiPrnDataItems);
  1353. if(SUCCEEDED(hr))
  1354. {
  1355. //
  1356. // Read from header where info begins in stream
  1357. //
  1358. hr DBGCHK = ReadFromHeader(kPrnDataRoot, &uliPrnDataRoot);
  1359. if(SUCCEEDED(hr))
  1360. {
  1361. if(uliPrnDataRoot.QuadPart == 0)
  1362. {
  1363. // Get current seek position ; it will be stored in header
  1364. //
  1365. DBGMSG( DBG_TRACE, ( "TPrnStream::bWritePrnData:: First prn data item!\n " ));
  1366. hr DBGCHK = GetCurrentPosition(uliCurrentPos);
  1367. }
  1368. if(SUCCEEDED(hr))
  1369. {
  1370. //
  1371. // Store item
  1372. //
  1373. hr DBGCHK = WriteItem( pKey,
  1374. pValueName,
  1375. cbValueName,
  1376. ktREG_TYPE + dwType,
  1377. pData,
  1378. cbData);
  1379. if(SUCCEEDED(hr))
  1380. {
  1381. //
  1382. // Updates number of items and start position in case that bWritePrnData succeded
  1383. // and it was the first prn data item written
  1384. //
  1385. culiPrnDataItems.QuadPart++;
  1386. hr DBGCHK = UpdateHeader(TPrnStream::kcItems, culiPrnDataItems);
  1387. if(SUCCEEDED(hr) && uliPrnDataRoot.QuadPart == 0)
  1388. {
  1389. //
  1390. // Update header with position where item begins if it was the first prn data item written
  1391. //
  1392. hr DBGCHK = UpdateHeader(TPrnStream::kPrnDataRoot, uliCurrentPos);
  1393. }
  1394. }
  1395. }
  1396. }
  1397. }
  1398. return hr;
  1399. }
  1400. /*++
  1401. Title:
  1402. ReadNextPrnData
  1403. Routine Description:
  1404. Read a printer data item from stream
  1405. Arguments:
  1406. Param pointers will point inside of lpBuffer:
  1407. pKey - key name ;not null
  1408. pValueName - key value ;not null
  1409. cbValueName - count bytes of pValueName
  1410. dwType - type
  1411. pData - actually data
  1412. cbData - count bytes of pData
  1413. lpBuffer - a null ptr that will contain ptr to read item;
  1414. must be deallocated by the caller if function succeed
  1415. Return Value:
  1416. S_OK if succeded
  1417. PRN_PERSIST_ERROR code mapped to HRESULT(FACILITY_ITF) if failed
  1418. --*/
  1419. HRESULT
  1420. TPrnStream::
  1421. ReadNextPrnData(
  1422. OUT LPTSTR& lpszKey,
  1423. OUT LPTSTR& lpszVal,
  1424. OUT DWORD& dwType,
  1425. OUT LPBYTE& lpbData,
  1426. OUT DWORD& cbSize,
  1427. OUT LPBYTE& lpBuffer ORPHAN
  1428. )
  1429. {
  1430. TStatusH hr;
  1431. PrnBinInfo* lpPrnBinItem = NULL;
  1432. lpszKey = NULL;
  1433. lpszVal = NULL;
  1434. lpbData = NULL;
  1435. lpBuffer = NULL;
  1436. cbSize = 0;
  1437. //
  1438. // Initialization!!!
  1439. // m_cIndex is current item for reading ; m_cPrnDataItems is number of items in stream ( entry in header )
  1440. // chesk to see if no items where read or if all itemes where read and m_cIndex passed the printers data area in stream
  1441. //
  1442. if((m_cPrnDataItems.QuadPart == 0) || (m_cIndex > m_cPrnDataItems.QuadPart))
  1443. {
  1444. //
  1445. // Read from header number of printer data items in stream
  1446. //
  1447. hr DBGCHK = ReadFromHeader(kcItems, &m_cPrnDataItems);
  1448. if(FAILED(hr))
  1449. {
  1450. goto End;
  1451. }
  1452. //
  1453. // Read from header where info begins in stream
  1454. // m_uliSeekPtr seek ptr will be always positioned where item begins
  1455. //
  1456. hr DBGCHK = ReadFromHeader(kPrnDataRoot, &m_uliSeekPtr);
  1457. if(FAILED(hr))
  1458. {
  1459. goto End;
  1460. }
  1461. m_cIndex = 0;
  1462. }
  1463. if(m_cIndex == m_cPrnDataItems.QuadPart)
  1464. {
  1465. DBGMSG( DBG_TRACE, ( "bReadNextPrnData :: Reach end of prn data items \n" ));
  1466. hr DBGNOCHK = STG_E_SEEKERROR;
  1467. //
  1468. // this way I indicate that I reached the end ;
  1469. // next call will see that m_cIndex > m_cPrnDataItems.QuadPart and will do the same as if
  1470. // I call this first time
  1471. //
  1472. m_cIndex++;
  1473. }
  1474. else
  1475. {
  1476. //
  1477. // dwSeekPtr will be set to the position where next prn data item begins
  1478. //
  1479. hr DBGCHK = ReadItemFromPosition(m_uliSeekPtr, lpPrnBinItem);
  1480. if(SUCCEEDED(hr))
  1481. {
  1482. m_cIndex++;
  1483. lpszKey = reinterpret_cast<LPTSTR>(reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pKey);
  1484. lpszVal = reinterpret_cast<LPTSTR>(reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pValue);
  1485. lpbData = reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData;
  1486. cbSize = lpPrnBinItem->cbData;
  1487. dwType = lpPrnBinItem->dwType - ktREG_TYPE;
  1488. }
  1489. }
  1490. End:
  1491. if(FAILED(hr) && hr != STG_E_SEEKERROR)
  1492. {
  1493. //
  1494. // build my own result ; it will override STG_ results
  1495. //
  1496. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_READ_PRNDATA);
  1497. }
  1498. return hr;
  1499. }
  1500. /*++
  1501. Title:
  1502. WritePrnInfo2
  1503. Routine Description:
  1504. Build an item based on P_I_2 and write it into the stream
  1505. Convert P_I_2 into a flat buffer( LPTSTR -> offsets)
  1506. Build a PrnBinInfo item and write it into stream
  1507. Arguments:
  1508. lpPrinterInfo2 - ptr to P_I_2
  1509. cbPI2Size - P_I_2 buff size
  1510. Return Value:
  1511. S_OK if succeded
  1512. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  1513. --*/
  1514. HRESULT
  1515. TPrnStream::
  1516. WritePrnInfo2(
  1517. IN PRINTER_INFO_2* lpPrinterInfo2,
  1518. IN DWORD cbPI2Size
  1519. )
  1520. {
  1521. DWORD dwWritten;
  1522. ULARGE_INTEGER uliCurrentPos;
  1523. TStatusH hr;
  1524. TStatusB bStatus;
  1525. hr DBGNOCHK = E_FAIL;
  1526. bStatus DBGCHK = (lpPrinterInfo2 != NULL);
  1527. if(bStatus)
  1528. {
  1529. //
  1530. // Get item's start position
  1531. //
  1532. hr DBGCHK = GetCurrentPosition(uliCurrentPos);
  1533. if(SUCCEEDED(hr))
  1534. {
  1535. //
  1536. // Convert P_I_2 to flat buffer
  1537. //
  1538. lpPrinterInfo2->pSecurityDescriptor = 0;
  1539. MarshallDownStructure(reinterpret_cast<LPBYTE>(lpPrinterInfo2),
  1540. PrinterInfo2Fields,
  1541. sizeof(PRINTER_INFO_2),
  1542. RPC_CALL);
  1543. //
  1544. // Writes flat buffer into stream (WriteItem builds PrnBinInfo)
  1545. //
  1546. hr DBGCHK = WriteItem(NULL, NULL, 0, ktPrnInfo2 ,reinterpret_cast<LPBYTE>(lpPrinterInfo2), cbPI2Size);
  1547. if(SUCCEEDED(hr))
  1548. {
  1549. //
  1550. // Update header entry with start position in stream
  1551. //
  1552. hr DBGCHK = UpdateHeader(kPrnInfo2, uliCurrentPos);
  1553. //
  1554. // Printer name entry in header will point inside PI2
  1555. // if PI2 is not stored , printer name will be stored like an usual item
  1556. //
  1557. if(SUCCEEDED(hr))
  1558. {
  1559. //uliCurrentPos.QuadPart += OFFSETOF(PRINTER_INFO_2, pPrinterName);
  1560. hr DBGCHK = UpdateHeader(kPrnName, uliCurrentPos);
  1561. }
  1562. }
  1563. }
  1564. }
  1565. if(FAILED(hr))
  1566. {
  1567. //
  1568. // build my own result
  1569. //
  1570. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_WRITE_PI2);
  1571. }
  1572. return hr;
  1573. }
  1574. /*++
  1575. Title:
  1576. WritePrnName
  1577. Routine Description:
  1578. Build a PrnBinInfo item from printer name and write it into stream
  1579. Arguments:
  1580. None
  1581. Return Value:
  1582. S_OK if succeded
  1583. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  1584. --*/
  1585. HRESULT
  1586. TPrnStream::
  1587. WritePrnName(
  1588. VOID
  1589. )
  1590. {
  1591. ULARGE_INTEGER uliCurrentPos;
  1592. TStatusH hr;
  1593. hr DBGNOCHK = E_FAIL;
  1594. //
  1595. // Get item's start position
  1596. //
  1597. hr DBGCHK = GetCurrentPosition(uliCurrentPos);
  1598. if(SUCCEEDED(hr))
  1599. {
  1600. //
  1601. // Writes flat buffer into stream (WriteItem builds PrnBinInfo)
  1602. //
  1603. hr DBGCHK = WriteItem( NULL,
  1604. NULL,
  1605. 0,
  1606. ktPrnName ,
  1607. reinterpret_cast<LPBYTE>(const_cast<LPTSTR>(static_cast<LPCTSTR>(m_strPrnName))),
  1608. (m_strPrnName.uLen() + 1) * sizeof(TCHAR));
  1609. if(SUCCEEDED(hr))
  1610. {
  1611. hr DBGCHK = UpdateHeader(kPrnName, uliCurrentPos);
  1612. }
  1613. }
  1614. if(FAILED(hr))
  1615. {
  1616. //
  1617. // build my own result
  1618. //
  1619. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_WRITE_PI2);
  1620. }
  1621. return hr;
  1622. }
  1623. /*++
  1624. Title:
  1625. ReadPrnInfo2
  1626. Routine Description:
  1627. Reads the P_I_2 entry in stream ;
  1628. Arguments:
  1629. lppPrnBinItem - pointer to readed item; NULL if no settings stored ;
  1630. Return Value:
  1631. S_OK if succeded
  1632. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  1633. --*/
  1634. HRESULT
  1635. TPrnStream::
  1636. ReadPrnInfo2(
  1637. OUT PrnBinInfo** lppPrnBinItem
  1638. )
  1639. {
  1640. PrnBinInfo* lpPrnBinItem = NULL;
  1641. ULARGE_INTEGER uliSeekPtr;
  1642. TStatusH hr;
  1643. TStatusB bStatus;
  1644. hr DBGNOCHK = E_FAIL;
  1645. bStatus DBGCHK = TRUE;
  1646. //
  1647. // Read from header where info begins in stream
  1648. //
  1649. hr DBGCHK = ReadFromHeader(kPrnInfo2, &uliSeekPtr);
  1650. if(SUCCEEDED(hr))
  1651. {
  1652. //
  1653. // if ReadFromHeader returns a S_OK and dwSeekPtr is zero, it means that nothing is stored
  1654. //
  1655. if(uliSeekPtr.QuadPart > 0)
  1656. {
  1657. //
  1658. // Read an item from specified position
  1659. //
  1660. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  1661. if(SUCCEEDED(hr))
  1662. {
  1663. hr DBGCHK = MarshallUpItem(lpPrnBinItem);
  1664. }
  1665. }
  1666. else
  1667. {
  1668. hr DBGCHK = E_FAIL;
  1669. }
  1670. }
  1671. if(FAILED(hr))
  1672. {
  1673. if( lpPrnBinItem )
  1674. {
  1675. FreeMem(lpPrnBinItem);
  1676. }
  1677. *lppPrnBinItem = NULL;
  1678. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_READ_PI7);
  1679. }
  1680. else
  1681. {
  1682. *lppPrnBinItem = lpPrnBinItem;
  1683. }
  1684. return hr;
  1685. }
  1686. /*++
  1687. Title:
  1688. ReadPrnName
  1689. Routine Description:
  1690. Reads the P_I_2 entry in stream; if not P_I_2 settings stored , reads PrnName entry
  1691. Arguments:
  1692. strPrnName - printer name read from file
  1693. Return Value:
  1694. S_OK if succeded
  1695. An error code from an API converted to HRESULT
  1696. --*/
  1697. HRESULT
  1698. TPrnStream::
  1699. ReadPrnName(
  1700. OUT TString& strPrnName
  1701. )
  1702. {
  1703. PrnBinInfo* lpPrnBinItem = NULL;
  1704. TStatusH hr;
  1705. ULARGE_INTEGER uliSeekPtr;
  1706. LPTSTR lpszPrnName;
  1707. //
  1708. // Reads PRINTER_INFO_2 settings stored in stream.
  1709. // Printer Name is not stored if PRINTER_INFO_2 are stored.
  1710. //
  1711. hr DBGCHK = ReadPrnInfo2(&lpPrnBinItem);
  1712. if(SUCCEEDED(hr))
  1713. {
  1714. //
  1715. // printer name points inside P_I_2
  1716. //
  1717. DBGMSG( DBG_TRACE, ( "PrnName inside P_I2 \n"));
  1718. lpszPrnName = (reinterpret_cast<PRINTER_INFO_2*>(reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData)->pPrinterName);
  1719. hr DBGCHK = strPrnName.bUpdate(lpszPrnName) ? S_OK : E_FAIL;
  1720. DBGMSG( DBG_TRACE, ( "PrnName "TSTR" \n" , static_cast<LPCTSTR>(strPrnName)));
  1721. }
  1722. else
  1723. {
  1724. //
  1725. // Reads the Header entry for Printer name.
  1726. //
  1727. hr DBGCHK = ReadFromHeader(kPrnName, &uliSeekPtr);
  1728. if(SUCCEEDED(hr))
  1729. {
  1730. //
  1731. // if ReadFromHeader returns a S_OK and dwSeekPtr is zero, it means that nothing is stored
  1732. //
  1733. if(uliSeekPtr.QuadPart > 0)
  1734. {
  1735. //
  1736. // Read an item from specified position
  1737. //
  1738. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  1739. if(SUCCEEDED(hr))
  1740. {
  1741. DBGMSG( DBG_TRACE, ( "ReadPrnName from %d %d \n" , uliSeekPtr.HighPart, uliSeekPtr.LowPart));
  1742. hr DBGCHK = strPrnName.bUpdate(reinterpret_cast<LPTSTR>(reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData)) ?
  1743. S_OK : E_FAIL;
  1744. DBGMSG( DBG_TRACE, ( "PrnName "TSTR" \n" , static_cast<LPCTSTR>(strPrnName)));
  1745. }
  1746. else
  1747. {
  1748. hr DBGCHK = E_FAIL;
  1749. }
  1750. }
  1751. else
  1752. {
  1753. hr DBGCHK = E_FAIL;
  1754. }
  1755. }
  1756. }
  1757. if (lpPrnBinItem)
  1758. {
  1759. FreeMem(lpPrnBinItem);
  1760. }
  1761. return hr;
  1762. }
  1763. /*++
  1764. Title:
  1765. WritePrnInfo7
  1766. Routine Description:
  1767. Build an item based on P_I_7 and write it into the stream
  1768. PRINTER_INFO_7.pszObjectGUID set on NULL because at restoring it has to be null -> no flat pointer conversion needed
  1769. Arguments:
  1770. lpPrinterInfo7 - ptr to P_I_7
  1771. cbPI7Size - P_I_7 buff actual size
  1772. Return Value:
  1773. S_OK if succeded
  1774. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  1775. --*/
  1776. HRESULT
  1777. TPrnStream::
  1778. WritePrnInfo7(
  1779. IN PRINTER_INFO_7* lpPrinterInfo7,
  1780. IN DWORD cbPI7Size
  1781. )
  1782. {
  1783. DWORD dwWritten;
  1784. ULARGE_INTEGER uliCurrentPos;
  1785. TStatusB bStatus;
  1786. TStatusH hr;
  1787. hr DBGNOCHK = E_FAIL;
  1788. bStatus DBGCHK = (lpPrinterInfo7 != NULL);
  1789. if(bStatus)
  1790. {
  1791. //
  1792. // Get item's start position
  1793. //
  1794. hr DBGCHK = GetCurrentPosition(uliCurrentPos);
  1795. if(SUCCEEDED(hr))
  1796. {
  1797. //
  1798. // Convert P_I_7 to flat buffer
  1799. //
  1800. lpPrinterInfo7->pszObjectGUID = NULL;
  1801. MarshallDownStructure(reinterpret_cast<LPBYTE>(lpPrinterInfo7),
  1802. PrinterInfo7Fields,
  1803. sizeof(PRINTER_INFO_7),
  1804. RPC_CALL);
  1805. //
  1806. // Writes flat buffer into stream (WriteItem builds PrnBinInfo)
  1807. //
  1808. hr DBGCHK = WriteItem(NULL, NULL, 0, ktPrnInfo7 ,reinterpret_cast<LPBYTE>(lpPrinterInfo7), cbPI7Size);
  1809. //
  1810. // Update header entry with start position in stream
  1811. //
  1812. if(SUCCEEDED(hr))
  1813. {
  1814. hr DBGCHK = UpdateHeader(kPrnInfo7, uliCurrentPos);
  1815. }
  1816. }
  1817. }
  1818. if(FAILED(hr))
  1819. {
  1820. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_WRITE_PI7);
  1821. }
  1822. return hr;
  1823. }
  1824. /*++
  1825. Title:
  1826. ReadPrnInfo7
  1827. Routine Description:
  1828. Reads the P_I_7 entry in stream
  1829. Arguments:
  1830. lppPrnBinItem - pointer to readed item; NULL if no settings stored
  1831. Return Value:
  1832. S_OK if succeded
  1833. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  1834. --*/
  1835. HRESULT
  1836. TPrnStream::
  1837. ReadPrnInfo7(
  1838. OUT PrnBinInfo** lppPrnBinItem
  1839. )
  1840. {
  1841. PrnBinInfo* lpPrnBinItem = NULL;
  1842. ULARGE_INTEGER uliSeekPtr;
  1843. TStatusB bStatus;
  1844. TStatusH hr;
  1845. hr DBGNOCHK = E_FAIL;
  1846. //
  1847. // Read from header where info begins in stream
  1848. //
  1849. hr DBGCHK = ReadFromHeader(kPrnInfo7, &uliSeekPtr);
  1850. if(SUCCEEDED(hr))
  1851. {
  1852. //
  1853. // if ReadFromHeader returns a S_OK and dwSeekPtr is zero, it means that nothing is stored
  1854. // function will succeed
  1855. //
  1856. if(uliSeekPtr.QuadPart > 0)
  1857. {
  1858. //
  1859. // Read an item from specified position
  1860. //
  1861. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  1862. if(SUCCEEDED(hr))
  1863. {
  1864. hr DBGCHK = MarshallUpItem(lpPrnBinItem);
  1865. }
  1866. }
  1867. else
  1868. {
  1869. hr DBGCHK = E_FAIL;
  1870. }
  1871. }
  1872. if(FAILED(hr))
  1873. {
  1874. *lppPrnBinItem = NULL;
  1875. if( lpPrnBinItem )
  1876. {
  1877. FreeMem(lpPrnBinItem);
  1878. }
  1879. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_READ_PI7);
  1880. }
  1881. else
  1882. {
  1883. *lppPrnBinItem = lpPrnBinItem;
  1884. }
  1885. return hr;
  1886. }
  1887. /*++
  1888. Title:
  1889. WritePrnSecurity
  1890. Routine Description:
  1891. Build an item based on SecurityDescriptor and write it into the stream
  1892. Arguments:
  1893. lpPrinterInfo2 - ptr to P_I_2
  1894. cbPI2Size - P_I_2 buff size
  1895. Return Value:
  1896. S_OK if succeded
  1897. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  1898. --*/
  1899. HRESULT
  1900. TPrnStream::
  1901. WritePrnSecurity(
  1902. IN PRINTER_INFO_2* lpPrinterInfo2,
  1903. IN DWORD cbPI2Size
  1904. )
  1905. {
  1906. DWORD cbSize;
  1907. DWORD dwWritten;
  1908. ULARGE_INTEGER uliCurrentPos;
  1909. TStatusB bStatus;
  1910. TStatusH hr;
  1911. hr DBGNOCHK = E_FAIL;
  1912. bStatus DBGCHK = (lpPrinterInfo2 != NULL);
  1913. if(bStatus)
  1914. {
  1915. //
  1916. // Get item's start position
  1917. //
  1918. hr DBGCHK = GetCurrentPosition(uliCurrentPos);
  1919. if(SUCCEEDED(hr))
  1920. {
  1921. if(lpPrinterInfo2->pSecurityDescriptor != NULL)
  1922. {
  1923. cbSize = GetSecurityDescriptorLength(lpPrinterInfo2->pSecurityDescriptor);
  1924. bStatus DBGCHK =( cbSize >= SECURITY_DESCRIPTOR_MIN_LENGTH);
  1925. //
  1926. // alloc mem for flat buffer
  1927. //
  1928. if(bStatus)
  1929. {
  1930. //
  1931. // Writes flat buffer into stream (WriteItem builds PrnBinInfo)
  1932. //
  1933. hr DBGCHK = WriteItem( NULL,
  1934. NULL,
  1935. 0,
  1936. ktSecurity ,
  1937. reinterpret_cast<LPBYTE>(lpPrinterInfo2->pSecurityDescriptor),
  1938. cbSize);
  1939. if(SUCCEEDED(hr))
  1940. {
  1941. //
  1942. // Update header entry with start position in stream
  1943. //
  1944. hr DBGCHK = UpdateHeader(kSecurity, uliCurrentPos);
  1945. }
  1946. }
  1947. else
  1948. {
  1949. hr DBGCHK = E_FAIL;
  1950. }
  1951. }
  1952. }
  1953. }
  1954. if(FAILED(hr))
  1955. {
  1956. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_WRITE_SEC);
  1957. }
  1958. return hr;
  1959. }
  1960. /*++
  1961. Title:
  1962. ReadPrnSecurity
  1963. Routine Description:
  1964. Reads the Security entry in stream
  1965. Arguments:
  1966. lppPrnBinItem - pointer to readed item; NULL if no settings stored ;
  1967. Return Value:
  1968. S_OK if succeded
  1969. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  1970. --*/
  1971. HRESULT
  1972. TPrnStream::
  1973. ReadPrnSecurity(
  1974. OUT PrnBinInfo** ppPrnBinItem
  1975. )
  1976. {
  1977. PrnBinInfo* lpPrnBinItem;
  1978. ULARGE_INTEGER uliSeekPtr;
  1979. TStatusH hr;
  1980. hr DBGNOCHK = E_FAIL;
  1981. //
  1982. // Read from header where info begins in stream
  1983. //
  1984. hr DBGCHK = ReadFromHeader(kSecurity, &uliSeekPtr);
  1985. if(SUCCEEDED(hr))
  1986. {
  1987. //
  1988. // if ReadFromHeader returns a S_OK and dwSeekPtr is zero, it means that nothing is stored
  1989. //
  1990. if(uliSeekPtr.QuadPart > 0)
  1991. {
  1992. //
  1993. // Read an item from specified position
  1994. //
  1995. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  1996. }
  1997. else
  1998. {
  1999. hr DBGCHK = E_FAIL;
  2000. }
  2001. }
  2002. if(FAILED(hr))
  2003. {
  2004. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_READ_SEC);
  2005. *ppPrnBinItem = NULL;
  2006. }
  2007. else
  2008. {
  2009. *ppPrnBinItem = lpPrnBinItem;
  2010. }
  2011. return hr;
  2012. }
  2013. /*++
  2014. Title:
  2015. WritePrnInfo8
  2016. Routine Description:
  2017. Call WriteDevMode to write devmode into stream
  2018. Arguments:
  2019. lpPrinterInfo8 - ptr to P_I_8
  2020. cbSize - P_I_8 buffer actual size
  2021. Return Value:
  2022. S_OK if succeded
  2023. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  2024. --*/
  2025. HRESULT
  2026. TPrnStream::
  2027. WritePrnInfo8(
  2028. IN PRINTER_INFO_8* lpPrinterInfo8,
  2029. IN DWORD cbSize
  2030. )
  2031. {
  2032. TStatusB bStatus;
  2033. TStatusH hr;
  2034. hr DBGNOCHK = E_FAIL;
  2035. bStatus DBGCHK = (lpPrinterInfo8 != NULL) && (lpPrinterInfo8->pDevMode != NULL);
  2036. if(bStatus)
  2037. {
  2038. hr DBGCHK = WriteDevMode( lpPrinterInfo8->pDevMode,
  2039. lpPrinterInfo8->pDevMode->dmSize + lpPrinterInfo8->pDevMode->dmDriverExtra,
  2040. kPrnDevMode);
  2041. }
  2042. if(FAILED(hr))
  2043. {
  2044. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_WRITE_PRN_DEVMODE);
  2045. }
  2046. return hr;
  2047. }
  2048. /*++
  2049. Title:
  2050. ReadPrnInfo8
  2051. Routine Description:
  2052. Reads the Printer Dev Mode entry in stream
  2053. Arguments:
  2054. lppPrnBinItem - pointer to readed item; NULL if no settings stored ;
  2055. bInsidePI2 - TRUE if global dev mode was inside P_I_2 item
  2056. Return Value:
  2057. S_OK if succeded
  2058. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  2059. --*/
  2060. HRESULT
  2061. TPrnStream::
  2062. ReadPrnInfo8(
  2063. OUT PrnBinInfo** lppPrnBinItem
  2064. )
  2065. {
  2066. PrnBinInfo* lpPrnBinItem;
  2067. ULARGE_INTEGER uliSeekPtr;
  2068. TStatusH hr;
  2069. hr DBGNOCHK = E_FAIL;
  2070. //
  2071. // Read from header where info begins in stream
  2072. //
  2073. hr DBGCHK = ReadFromHeader(kPrnDevMode, &uliSeekPtr);
  2074. if(SUCCEEDED(hr))
  2075. {
  2076. if(uliSeekPtr.QuadPart == 0)
  2077. {
  2078. //
  2079. // no dev mode stored
  2080. //
  2081. hr DBGCHK = E_FAIL;
  2082. }
  2083. else
  2084. {
  2085. //
  2086. // Read an item from specified position
  2087. //
  2088. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  2089. }
  2090. }
  2091. if(FAILED(hr))
  2092. {
  2093. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_READ_PRN_DEVMODE);
  2094. *lppPrnBinItem = NULL;
  2095. }
  2096. else
  2097. {
  2098. *lppPrnBinItem = lpPrnBinItem;
  2099. }
  2100. return hr;
  2101. }
  2102. /*++
  2103. Title:
  2104. WritePrnInfo9
  2105. Routine Description:
  2106. Call WriteDevMode to write devmode into stream
  2107. Arguments:
  2108. lpPrinterInfo9 - ptr to P_I_9
  2109. cbSize - P_I_9 buff size
  2110. Return Value:
  2111. S_OK if succeded
  2112. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  2113. --*/
  2114. HRESULT
  2115. TPrnStream::
  2116. WritePrnInfo9(
  2117. IN PRINTER_INFO_9* lpPrinterInfo9,
  2118. IN DWORD cbSize
  2119. )
  2120. {
  2121. TStatusB bStatus;
  2122. TStatusH hr;
  2123. ULARGE_INTEGER uliCurrentPos;
  2124. hr DBGNOCHK = E_FAIL;
  2125. bStatus DBGCHK = (lpPrinterInfo9 != NULL) && (lpPrinterInfo9->pDevMode != NULL);
  2126. if(bStatus)
  2127. {
  2128. hr DBGCHK = WriteDevMode( lpPrinterInfo9->pDevMode,
  2129. lpPrinterInfo9->pDevMode->dmSize + lpPrinterInfo9->pDevMode->dmDriverExtra,
  2130. kUserDevMode);
  2131. }
  2132. else
  2133. {
  2134. //
  2135. // set entry in header to a dummy value to show that dev mode was null
  2136. //
  2137. DBGMSG(DBG_TRACE , ("WritePrnInfo9 NO USER DEVMODE\n"));
  2138. //
  2139. // fix for bug 273541
  2140. // For the case when per user dev mode is null , update the header with a special value ,
  2141. // to signal that per user dev mode was stored in file.
  2142. //
  2143. uliCurrentPos.HighPart = -1;
  2144. uliCurrentPos.LowPart = -1;
  2145. hr DBGCHK = UpdateHeader(kUserDevMode, uliCurrentPos);
  2146. }
  2147. if(FAILED(hr))
  2148. {
  2149. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_WRITE_USR_DEVMODE);
  2150. }
  2151. return hr;
  2152. }
  2153. /*++
  2154. Title:
  2155. ReadPrnInfo9
  2156. Routine Description:
  2157. Reads the User Dev Mode entry in stream
  2158. Arguments:
  2159. lppPrnBinItem - pointer to readed item; NULL if no settings stored ;
  2160. Return Value:
  2161. S_OK if succeded
  2162. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  2163. --*/
  2164. HRESULT
  2165. TPrnStream::
  2166. ReadPrnInfo9(
  2167. OUT PrnBinInfo** ppPrnBinItem
  2168. )
  2169. {
  2170. PrnBinInfo* lpPrnBinItem = NULL;
  2171. ULARGE_INTEGER uliSeekPtr;
  2172. TStatusH hr;
  2173. hr DBGNOCHK = E_FAIL;
  2174. //
  2175. // Read from header where info begins in stream
  2176. //
  2177. hr DBGCHK = ReadFromHeader(kUserDevMode, &uliSeekPtr);
  2178. if(SUCCEEDED(hr))
  2179. {
  2180. if(uliSeekPtr.QuadPart == 0)
  2181. {
  2182. //
  2183. // no dev mode stored because no flags were specified
  2184. //
  2185. hr DBGCHK = E_FAIL;
  2186. }
  2187. else if(uliSeekPtr.LowPart == -1 && uliSeekPtr.HighPart == -1)
  2188. {
  2189. //
  2190. // dev mode was null at the time it was stored ( no Printing Prefferences set )
  2191. //
  2192. hr DBGNOCHK = S_OK;
  2193. *ppPrnBinItem = NULL;
  2194. }
  2195. else
  2196. {
  2197. //
  2198. // Read an item from specified position
  2199. //
  2200. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  2201. }
  2202. }
  2203. if(FAILED(hr))
  2204. {
  2205. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_READ_USR_DEVMODE);
  2206. *ppPrnBinItem = NULL;
  2207. }
  2208. else
  2209. {
  2210. *ppPrnBinItem = lpPrnBinItem;
  2211. }
  2212. return hr;
  2213. }
  2214. /*++
  2215. Title:
  2216. WriteColorProfiles
  2217. Routine Description:
  2218. Build a PrnBinInfo item from a multi sz string that contains color profiles names
  2219. Arguments:
  2220. lpProfiles - ptr to multi zero string
  2221. cbSize - multi zero string size
  2222. Return Value:
  2223. S_OK if succeded
  2224. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  2225. --*/
  2226. HRESULT
  2227. TPrnStream::
  2228. WriteColorProfiles(
  2229. IN LPBYTE lpProfiles,
  2230. IN DWORD cbSize
  2231. )
  2232. {
  2233. ULARGE_INTEGER uliCurrentPos;
  2234. TStatusB bStatus;
  2235. TStatusH hr;
  2236. hr DBGNOCHK = E_FAIL;
  2237. bStatus DBGCHK = (lpProfiles != NULL);
  2238. if(bStatus)
  2239. {
  2240. //
  2241. // Get item's start position
  2242. //
  2243. hr DBGCHK = GetCurrentPosition(uliCurrentPos);
  2244. if(SUCCEEDED(hr))
  2245. {
  2246. //
  2247. // Writes profiles(MULTI_SZ) into stream (WriteItem builds PrnBinInfo)
  2248. //
  2249. hr DBGCHK = WriteItem(NULL, NULL, 0, ktColorProfile, lpProfiles, cbSize);
  2250. //
  2251. // Update header entry with start position in stream
  2252. //
  2253. if(SUCCEEDED(hr))
  2254. {
  2255. hr DBGCHK = UpdateHeader(kColorProfile, uliCurrentPos);
  2256. }
  2257. }
  2258. }
  2259. if(FAILED(hr))
  2260. {
  2261. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_WRITE_COLOR_PRF);
  2262. }
  2263. return hr;
  2264. }
  2265. /*++
  2266. Title:
  2267. ReadColorProfiles
  2268. Routine Description:
  2269. Reads the color profile entry in stream
  2270. Arguments:
  2271. lppPrnBinItem - pointer to readed item; NULL if no settings stored ;
  2272. Return Value:
  2273. S_OK if succeded
  2274. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  2275. --*/
  2276. HRESULT
  2277. TPrnStream::
  2278. ReadColorProfiles(
  2279. OUT PrnBinInfo** ppPrnBinItem
  2280. )
  2281. {
  2282. PrnBinInfo* lpPrnBinItem;
  2283. ULARGE_INTEGER uliSeekPtr;
  2284. TStatusH hr;
  2285. //
  2286. // Read from header where info begins in stream
  2287. //
  2288. hr DBGCHK = ReadFromHeader(kColorProfile, &uliSeekPtr);
  2289. if(SUCCEEDED(hr))
  2290. {
  2291. if(uliSeekPtr.QuadPart > 0)
  2292. {
  2293. //
  2294. // Read an item from specified position
  2295. //
  2296. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  2297. }
  2298. else
  2299. {
  2300. hr DBGCHK = E_FAIL;
  2301. }
  2302. }
  2303. if(FAILED(hr))
  2304. {
  2305. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_READ_COLOR_PRF);
  2306. *ppPrnBinItem = NULL;
  2307. }
  2308. else
  2309. {
  2310. *ppPrnBinItem = lpPrnBinItem;
  2311. }
  2312. return hr;
  2313. }
  2314. /*++
  2315. Title:
  2316. WriteHeader
  2317. Routine Description:
  2318. Write header at the begining of file ; the header is null initialized
  2319. steps:
  2320. Write header into the stream; this is the very first writing operation
  2321. It reserves space at the beginning of stream for writing info about items inside the stream
  2322. StorePrintreInfo function will call WriteHeader before any other writing operation
  2323. If P_I_2 flag is NOT specified , write printre name as item ; if it is , printe name will be stored with P_I_2
  2324. Arguments:
  2325. Flags - flags specified at storing time ; needed for printer name handling
  2326. Return Value:
  2327. S_OK if succeded
  2328. An error code from an API converted to HRESULT
  2329. --*/
  2330. HRESULT
  2331. TPrnStream::
  2332. WriteHeader(
  2333. IN DWORD Flags
  2334. )
  2335. {
  2336. PrnHeader PrinterHeader;
  2337. DWORD dwSize = 0;
  2338. LARGE_INTEGER liStart = {0};
  2339. TStatusH hr;
  2340. TStatusB bStatus;
  2341. // Init hr with S_OK;if header is already written in stream, this will be the return value
  2342. //
  2343. hr DBGNOCHK = S_OK;
  2344. //
  2345. // m_bHeaderWritten indicates if header was written into file
  2346. //
  2347. if(!m_bHeaderWritten)
  2348. {
  2349. //
  2350. // Output the header. This basically reserves
  2351. // space at the beginning of the stream to store
  2352. // the item-count.
  2353. //
  2354. PrinterHeader.pPrnName.QuadPart = 0;
  2355. PrinterHeader.pPrnDataRoot.QuadPart = 0;
  2356. PrinterHeader.cItems.QuadPart = 0;
  2357. PrinterHeader.pUserDevMode.QuadPart = 0;
  2358. PrinterHeader.pPrnDevMode.QuadPart = 0;
  2359. PrinterHeader.pPrnInfo2.QuadPart = 0;
  2360. PrinterHeader.pPrnInfo7.QuadPart = 0;
  2361. PrinterHeader.pSecurity.QuadPart = 0;
  2362. PrinterHeader.pColorProfileSettings.QuadPart = 0;
  2363. //
  2364. // Make sure our header is positioned at the beginning of the stream.
  2365. //
  2366. hr DBGCHK = m_pIStream->Seek( liStart, STREAM_SEEK_SET, NULL );
  2367. //
  2368. // Write the header
  2369. //
  2370. if(SUCCEEDED(hr))
  2371. {
  2372. hr DBGCHK = m_pIStream->Write((LPBYTE)&PrinterHeader, sizeof(PrnHeader), &dwSize);
  2373. //
  2374. // indicates if header was written into file
  2375. //
  2376. m_bHeaderWritten = TRUE;
  2377. //
  2378. // write printer info into an entry if P_I_2 is not stored.
  2379. // if it is , prn name in header will point inside P_I_2
  2380. //
  2381. if(SUCCEEDED(hr) && !(Flags & PRST_PRINTER_INFO_2))
  2382. {
  2383. hr DBGCHK = WritePrnName();
  2384. }
  2385. }
  2386. DBGMSG( DBG_TRACE ,( "WriteHeader %x !!!\n" , hr));
  2387. }
  2388. return hr;
  2389. }
  2390. #if DBG
  2391. VOID
  2392. TPrnStream::
  2393. CheckHeader (
  2394. IN TPrnStream::EHeaderEntryType eHeaderEntryType,
  2395. IN ULARGE_INTEGER uliInfo
  2396. )
  2397. {
  2398. TStatusH hr;
  2399. ULARGE_INTEGER uliPtr;
  2400. EHeaderEntryType HeaderEntries[] = { kPrnDataRoot,
  2401. kcItems,
  2402. kUserDevMode,
  2403. kPrnDevMode,
  2404. kPrnInfo2,
  2405. kPrnInfo7,
  2406. kSecurity,
  2407. kColorProfile };
  2408. for( DWORD i = 0; i < sizeof (HeaderEntries) / sizeof (DWORD); i++ )
  2409. {
  2410. hr DBGCHK = ReadFromHeader(HeaderEntries[i], &uliPtr);
  2411. if (SUCCEEDED(hr)) {
  2412. //
  2413. // PI2 and Printer Name can point to the same location. Don't do this check!
  2414. //
  2415. if ( ! ( HeaderEntries[i] == kPrnInfo2 && eHeaderEntryType == kPrnName ) ||
  2416. ( HeaderEntries[i] == kPrnName && eHeaderEntryType == kPrnInfo2) ) {
  2417. if( (uliPtr.LowPart && uliPtr.LowPart == uliInfo.LowPart ) || (uliPtr.HighPart && uliPtr.HighPart == uliInfo.HighPart) ) {
  2418. DBGMSG( DBG_TRACE,("*******CheckHeader: %d overwrites %d\n" , eHeaderEntryType , HeaderEntries[i]));
  2419. }
  2420. }
  2421. }
  2422. }
  2423. }
  2424. #endif
  2425. /*++
  2426. Title:
  2427. UpdateHeader
  2428. Routine Description:
  2429. Write Info at specified entry in header
  2430. Current position in stream in not modified after this call
  2431. Arguments:
  2432. eHeaderEntryType - Specify entry in header
  2433. uliInfo - Can be a pointer inside stream or a number of items
  2434. Return Value:
  2435. S_OK if succeded
  2436. An error code from an API converted to HRESULT
  2437. --*/
  2438. HRESULT
  2439. TPrnStream::
  2440. UpdateHeader(
  2441. IN TPrnStream::EHeaderEntryType eHeaderEntryType,
  2442. IN ULARGE_INTEGER uliInfo
  2443. )
  2444. {
  2445. DWORD dwSize;
  2446. ULARGE_INTEGER uliCurrentPosition;
  2447. ULARGE_INTEGER uliLastCurrentPosition;
  2448. LARGE_INTEGER liStart;
  2449. TStatusH hr;
  2450. #if DBG
  2451. CheckHeader(eHeaderEntryType, uliInfo);
  2452. #endif
  2453. // Saves current position into stream
  2454. //
  2455. hr DBGCHK = GetCurrentPosition(uliCurrentPosition);
  2456. if(SUCCEEDED(hr))
  2457. {
  2458. //
  2459. // Position stream pointer into the header on the specified entry
  2460. //
  2461. liStart.LowPart = eHeaderEntryType * sizeof(LARGE_INTEGER);
  2462. liStart.HighPart = 0;
  2463. hr DBGCHK = m_pIStream->Seek( liStart , STREAM_SEEK_SET, NULL );
  2464. DBGMSG( DBG_TRACE,("TPrnStream::UpdateHeader\n Update at %d with %d\n" , liStart.LowPart , uliInfo));
  2465. //
  2466. // Setup the header information.
  2467. //
  2468. if(SUCCEEDED(hr))
  2469. {
  2470. hr DBGCHK = m_pIStream->Write(reinterpret_cast<LPVOID>(&uliInfo), sizeof(LARGE_INTEGER), &dwSize);
  2471. }
  2472. //
  2473. // Restore stream current pointer (even if writing failed)
  2474. //
  2475. liStart.QuadPart = uliCurrentPosition.QuadPart;
  2476. hr DBGCHK = m_pIStream->Seek( liStart, STREAM_SEEK_SET, &uliLastCurrentPosition );
  2477. SPLASSERT( uliCurrentPosition.LowPart == uliLastCurrentPosition.LowPart );
  2478. SPLASSERT( uliCurrentPosition.HighPart == uliLastCurrentPosition.HighPart );
  2479. }
  2480. return hr;
  2481. }
  2482. /*++
  2483. Title:
  2484. ReadFromHeader
  2485. Routine Description:
  2486. Read Info from specified entry in header
  2487. Current position in stream in not modified after this call
  2488. Arguments:
  2489. eHeaderEntryType - Specify entry in header
  2490. puliInfo - holds the value found in header at position kHeaderEntryType
  2491. Return Value:
  2492. S_OK if succeded
  2493. An error code from an API converted to HRESULT
  2494. --*/
  2495. HRESULT
  2496. TPrnStream::
  2497. ReadFromHeader(
  2498. IN TPrnStream::EHeaderEntryType kHeaderEntryType,
  2499. OUT ULARGE_INTEGER* puliInfo
  2500. )
  2501. {
  2502. DWORD dwSize;
  2503. ULARGE_INTEGER uliEntryInfo;
  2504. ULARGE_INTEGER uliCurrentPos;
  2505. LARGE_INTEGER liStart;
  2506. TStatusH hr;
  2507. DBGMSG( DBG_NONE, ( "Read Header!\n"));
  2508. //
  2509. // Save current pos
  2510. //
  2511. hr DBGCHK = GetCurrentPosition(uliCurrentPos);
  2512. if(SUCCEEDED(hr))
  2513. {
  2514. //
  2515. // seek pointer has to point to kHeaderEntryType into IStream
  2516. //
  2517. liStart.LowPart = kHeaderEntryType * sizeof(LARGE_INTEGER);
  2518. liStart.HighPart = 0;
  2519. hr DBGCHK = m_pIStream->Seek( liStart , STREAM_SEEK_SET, NULL );
  2520. //
  2521. // Read from header entry a DWORD
  2522. //
  2523. if(SUCCEEDED(hr))
  2524. {
  2525. hr DBGCHK = m_pIStream->Read(&uliEntryInfo, sizeof(LARGE_INTEGER), &dwSize);
  2526. if(SUCCEEDED(hr))
  2527. {
  2528. puliInfo->QuadPart = uliEntryInfo.QuadPart;
  2529. }
  2530. else
  2531. {
  2532. DBGMSG( DBG_TRACE, ( "Read Header! FAILED !!!\n"));
  2533. }
  2534. //
  2535. // Restore stream current pointer (even if reading failed)
  2536. //
  2537. liStart.QuadPart = uliCurrentPos.QuadPart;
  2538. hr DBGCHK = m_pIStream->Seek( liStart , STREAM_SEEK_SET, NULL );
  2539. }
  2540. }
  2541. return hr;
  2542. }
  2543. /*++
  2544. Title:
  2545. WriteDevMode
  2546. Routine Description:
  2547. Build a PrnBinInfo item from ->DevMode and write it into stream
  2548. Arguments:
  2549. lpDevMode - ptr to DEVMODE
  2550. cbSize - buff size
  2551. eDevModeType - type : user / printer
  2552. Return Value:
  2553. S_OK if succeded
  2554. An error code from an API converted to HRESULT
  2555. --*/
  2556. HRESULT
  2557. TPrnStream::
  2558. WriteDevMode(
  2559. IN PDEVMODE lpDevMode,
  2560. IN DWORD cbSize,
  2561. IN EHeaderEntryType eDevModeType
  2562. )
  2563. {
  2564. ULARGE_INTEGER uliCurrentPos;
  2565. TStatusB bStatus;
  2566. TStatusH hr;
  2567. //
  2568. // Get item's start position
  2569. //
  2570. hr DBGCHK = GetCurrentPosition(uliCurrentPos);
  2571. if(SUCCEEDED(hr))
  2572. {
  2573. //
  2574. // Writes devmode into stream (WriteItem builds PrnBinInfo)
  2575. //
  2576. hr DBGCHK = WriteItem( NULL,
  2577. NULL,
  2578. 0,
  2579. ktDevMode,
  2580. reinterpret_cast<LPBYTE>(lpDevMode),
  2581. cbSize);
  2582. //
  2583. // Update header entry with start position in stream
  2584. //
  2585. if(SUCCEEDED(hr))
  2586. {
  2587. hr DBGCHK = UpdateHeader(eDevModeType, uliCurrentPos);
  2588. }
  2589. }
  2590. return hr;
  2591. }
  2592. /*++
  2593. Title:
  2594. AdjustItemSizeForWin64
  2595. Routine Description:
  2596. The item will be reallocated on Win64.
  2597. When the file is generated on Win32, the item's size must be adjusted
  2598. so that the 64bit stucture will fit in.
  2599. The design doesn't allow to differenciate between files generated on Win32
  2600. and Win64, therefore the adjustment will be always performed for
  2601. Win64 up marshalling .
  2602. Arguments:
  2603. lpPrnBinItem -- reference to a pointer to the item to be adjusted.
  2604. Return Value:
  2605. S_OK if succeded
  2606. A Win32 error code converted to HRESULT
  2607. --*/
  2608. HRESULT
  2609. TPrnStream::
  2610. AdjustItemSizeForWin64(
  2611. IN OUT PrnBinInfo *&lpPrnBinItem,
  2612. IN FieldInfo *pFieldInfo,
  2613. IN SIZE_T cbSize,
  2614. OUT SIZE_T &cbDifference
  2615. )
  2616. {
  2617. TStatusB bStatus;
  2618. TStatusH hr(DBG_WARN, HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
  2619. SIZE_T cbWin32Size = 0;
  2620. SIZE_T cbWin64Size = cbSize;
  2621. PrnBinInfo *lpNewPrnBinItem = NULL;
  2622. switch (kPointerSize)
  2623. {
  2624. case kSpl32Ptr:
  2625. {
  2626. cbDifference = 0;
  2627. hr DBGNOCHK = S_OK;
  2628. break;
  2629. }
  2630. case kSpl64Ptr:
  2631. {
  2632. //
  2633. // Adjust item only on Win64
  2634. //
  2635. lpNewPrnBinItem = NULL;
  2636. bStatus DBGCHK = GetShrinkedSize(pFieldInfo, &cbWin32Size);
  2637. if ( bStatus )
  2638. {
  2639. //
  2640. // Calculate the quantity the item must grow with.
  2641. // It it the difference between the PRINTER_INFO_n size on
  2642. // Win64 and Win32.
  2643. //
  2644. cbDifference = cbWin64Size - cbWin32Size;
  2645. //
  2646. // Allocate a bufer that will hold the adjusted item.
  2647. //
  2648. lpNewPrnBinItem = (PrnBinInfo*)AllocMem(lpPrnBinItem->cbSize + (DWORD)cbDifference);
  2649. bStatus DBGCHK = !!lpNewPrnBinItem;
  2650. if ( bStatus )
  2651. {
  2652. //
  2653. // Copy the old item's content in the new buffer.
  2654. //
  2655. CopyMemory( lpNewPrnBinItem, lpPrnBinItem, lpPrnBinItem->cbSize);
  2656. //
  2657. // This memory move will make room for Win64 PRINTER_INFO_n to grow
  2658. // without corrupting data.
  2659. // Source: the spot right after flatened Win32 structure, which will
  2660. // contain data for items generated on Win32.
  2661. // Destination: the spot righ after Win64 structure. PRINTER_INFO_n data
  2662. // comes after this spot on Win64.
  2663. //
  2664. MoveMemory( (LPBYTE)lpNewPrnBinItem + lpNewPrnBinItem->pData + cbWin64Size,
  2665. (LPBYTE)lpNewPrnBinItem + lpNewPrnBinItem->pData + cbWin32Size,
  2666. lpNewPrnBinItem->cbData - cbWin32Size);
  2667. //
  2668. // Adjust new item's size.
  2669. //
  2670. lpNewPrnBinItem->cbData += (DWORD)cbDifference;
  2671. //
  2672. // Free the memory for the old item.
  2673. //
  2674. FreeMem(lpPrnBinItem);
  2675. lpPrnBinItem = lpNewPrnBinItem;
  2676. }
  2677. }
  2678. if(bStatus)
  2679. {
  2680. hr DBGNOCHK = S_OK;
  2681. }
  2682. else
  2683. {
  2684. hr DBGCHK = HRESULT_FROM_WIN32(GetLastError());
  2685. }
  2686. break;
  2687. }
  2688. default:
  2689. {
  2690. //
  2691. // Invalid pointer size; should not occur.
  2692. //
  2693. hr DBGCHK = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  2694. break;
  2695. }
  2696. }
  2697. return hr;
  2698. }
  2699. /*++
  2700. Title:
  2701. MarshallUpItem
  2702. Routine Description:
  2703. Convert a "flat" PRINTER_INFO_2 item to an "alive" item.
  2704. Pointers inside PRINTER_INFO_2 data be converted to offsets before the item
  2705. is persisted in the file. The format of the flatened item must be the same
  2706. between Win64 and Win32,since the file will roam across TS servers.
  2707. Arguments:
  2708. lpPrnBinItem -- reference to a pointer to the item to be converted;
  2709. Return Value:
  2710. S_OK if succeded
  2711. A Win32 error code converted to HRESULT
  2712. --*/
  2713. HRESULT
  2714. TPrnStream::
  2715. MarshallUpItem (
  2716. IN OUT PrnBinInfo*& lpPrnBinItem
  2717. )
  2718. {
  2719. TStatusB bStatus;
  2720. TStatusH hr(DBG_WARN, HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
  2721. SIZE_T cbDifference = 0;
  2722. SIZE_T cbSize;
  2723. FieldInfo *pPrinterInfoFields;
  2724. bStatus DBGCHK = !!lpPrnBinItem;
  2725. if(bStatus)
  2726. {
  2727. switch (lpPrnBinItem->dwType)
  2728. {
  2729. case ktPrnInfo2:
  2730. {
  2731. cbSize = sizeof(PRINTER_INFO_2);
  2732. pPrinterInfoFields = PrinterInfo2Fields;
  2733. break;
  2734. }
  2735. case ktPrnInfo7:
  2736. {
  2737. cbSize = sizeof(PRINTER_INFO_7);
  2738. pPrinterInfoFields = PrinterInfo7Fields;
  2739. break;
  2740. }
  2741. default:
  2742. {
  2743. bStatus DBGCHK = FALSE;
  2744. break;
  2745. }
  2746. }
  2747. if(bStatus)
  2748. {
  2749. //
  2750. // This item will be reallocated when marshalled on Win64.
  2751. // On Win64, the item's size must be increased with
  2752. // the difference between strcuture's size on Win64 and Win32.
  2753. // The item could have been generated on Win32 and there is no room
  2754. // left for the structure to expand.
  2755. //
  2756. hr DBGCHK = AdjustItemSizeForWin64(lpPrnBinItem, pPrinterInfoFields, cbSize, cbDifference);
  2757. if(SUCCEEDED(hr))
  2758. {
  2759. bStatus DBGCHK = MarshallUpStructure((LPBYTE)lpPrnBinItem + lpPrnBinItem->pData,
  2760. pPrinterInfoFields,
  2761. cbSize,
  2762. RPC_CALL);
  2763. if(bStatus)
  2764. {
  2765. hr DBGNOCHK = S_OK;
  2766. }
  2767. else
  2768. {
  2769. hr DBGCHK = HRESULT_FROM_WIN32(GetLastError());
  2770. }
  2771. //
  2772. // If the item was adjusted, the pointers inside PRINTER_INFO_2 must be adjusted as well.
  2773. // AdjustPointers cannot be executed before marshalling because the structure is still flat
  2774. // as on Win32 and the pointers are not in their Win64 location.
  2775. //
  2776. if ( bStatus && cbDifference )
  2777. {
  2778. AdjustPointers ( (LPBYTE)lpPrnBinItem + lpPrnBinItem->pData,
  2779. pPrinterInfoFields,
  2780. cbDifference);
  2781. }
  2782. }
  2783. }
  2784. }
  2785. return hr;
  2786. }
  2787. /*++
  2788. Title:
  2789. AlignSize
  2790. Routine Description:
  2791. align a sice to DWORD size
  2792. Arguments:
  2793. cbSize - size to align
  2794. Return Value:
  2795. cbSize - value to align
  2796. --*/
  2797. DWORD
  2798. TPrnStream::
  2799. AlignSize(
  2800. IN DWORD cbSize
  2801. )
  2802. {
  2803. return((cbSize)+3)&~3;
  2804. }
  2805. /*++
  2806. Title:
  2807. StorePrnData
  2808. Routine Description:
  2809. Writes into stream printer data;
  2810. calls bInternalWalk that browse the registry key and to store the printer(registry) settings
  2811. WalkIn and WalkPost virtual methods of WalkPrinterData over-rided to store value data
  2812. Arguments:
  2813. None
  2814. Return Value:
  2815. S_OK if succeded
  2816. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  2817. --*/
  2818. HRESULT
  2819. TPrnStream::
  2820. StorePrnData(
  2821. VOID
  2822. )
  2823. {
  2824. TString strNullKey(_T(""));
  2825. DWORD cItems = 0;
  2826. TStatusB bStatus;
  2827. //
  2828. // Proceed bInternalWalk for NULL key
  2829. //
  2830. bStatus DBGCHK = strNullKey.bValid();
  2831. if(bStatus)
  2832. {
  2833. cItems = 0;
  2834. bStatus DBGCHK = bInternalWalk(strNullKey, &cItems);
  2835. }
  2836. return bStatus ? S_OK : MakePrnPersistHResult(PRN_PERSIST_ERROR_WRITE_PRNDATA);
  2837. }
  2838. /*++
  2839. Title:
  2840. bRestorePrnData
  2841. Routine Description:
  2842. Restore printer data from file;
  2843. Call ReadNextPrnData until all items are browsed in stream
  2844. Arguments:
  2845. None
  2846. Return Value:
  2847. S_OK if succeded
  2848. PRN_PERSIST_ERROR error code mapped to HRESULT(FACILITY_ITF) if failed
  2849. --*/
  2850. HRESULT
  2851. TPrnStream::
  2852. RestorePrnData(
  2853. VOID
  2854. )
  2855. {
  2856. LPTSTR lpszKey;
  2857. LPTSTR lpszVal;
  2858. DWORD dwType;
  2859. LPBYTE lpbData;
  2860. DWORD cDataSize;
  2861. LPBYTE lpPrinterBinInfo;
  2862. TStatusB bStatus;
  2863. TStatus Status;
  2864. TStatusH hr(DBG_WARN, STG_E_SEEKERROR);
  2865. bStatus DBGNOCHK = TRUE;
  2866. while(bStatus)
  2867. {
  2868. hr DBGCHK = ReadNextPrnData(lpszKey, lpszVal, dwType, lpbData, cDataSize, lpPrinterBinInfo);
  2869. DBGMSG( DBG_TRACE, ( "bReadNextPrnData :: key " TSTR " value " TSTR " \n" ,(LPCTSTR)lpszKey , (LPCTSTR)lpszVal ));
  2870. bStatus DBGCHK = SUCCEEDED(hr);
  2871. if(bStatus)
  2872. {
  2873. Status DBGCHK = SetPrinterDataExW(m_hPrinter,
  2874. lpszKey,
  2875. lpszVal,
  2876. dwType,
  2877. lpbData,
  2878. cDataSize);
  2879. if(Status != ERROR_SUCCESS)
  2880. {
  2881. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_RESTORE_PRNDATA);
  2882. }
  2883. FreeMem(lpPrinterBinInfo);
  2884. }
  2885. if(hr == STG_E_SEEKERROR)
  2886. {
  2887. //
  2888. // End of Prn Data
  2889. //
  2890. hr DBGNOCHK = S_OK;
  2891. }
  2892. }
  2893. return hr;
  2894. }
  2895. /*++
  2896. Title:
  2897. bWalkPost
  2898. Routine Description:
  2899. call bWriteKeyData : store key values into stream
  2900. Arguments:
  2901. strKey - name of the key to walk
  2902. lpcItems - if not null , outs number of items actually written
  2903. Return Value:
  2904. TRUE if succeded
  2905. --*/
  2906. BOOL
  2907. TPrnStream::
  2908. bWalkPost (
  2909. IN TString& strKey,
  2910. OUT LPDWORD lpcItems
  2911. )
  2912. {
  2913. DBGMSG( DBG_TRACE, ( "WALK POST :: " TSTR "\n" , (LPCTSTR)strKey ));
  2914. return bWriteKeyData(strKey, lpcItems);
  2915. }
  2916. /*++
  2917. Title:
  2918. bWalkIn
  2919. Routine Description:
  2920. call bWriteKeyData : store key values into stream
  2921. Arguments:
  2922. strKey - name of the key to walk
  2923. lpcItems - if not null , outs number of items actually written
  2924. Return Value:
  2925. TRUE if succeded
  2926. --*/
  2927. BOOL
  2928. TPrnStream::
  2929. bWalkIn (
  2930. IN TString& strKey,
  2931. OUT LPDWORD lpcItems
  2932. )
  2933. {
  2934. DBGMSG( DBG_TRACE, ( "WALK IN :: " TSTR "\n" , (LPCTSTR)strKey ));
  2935. return bWriteKeyData(strKey, lpcItems);
  2936. }
  2937. /*++
  2938. Title:
  2939. WriteKeyData
  2940. Routine Description:
  2941. Writes into stream all values for a given key name;
  2942. calls EnumPrinterDataEx and browse PRINTER_ENUM_VALUES array
  2943. Arguments:
  2944. strKey - name of the key to write
  2945. lpcItems - if not null , outs number of items actually written
  2946. Return Value:
  2947. TRUE if succeded
  2948. --*/
  2949. BOOL
  2950. TPrnStream::
  2951. bWriteKeyData(
  2952. IN LPCTSTR lpszKey,
  2953. OUT LPDWORD lpcItems OPTIONAL
  2954. )
  2955. {
  2956. *lpcItems = 0;
  2957. LPPRINTER_ENUM_VALUES apevData;
  2958. UINT idx;
  2959. DWORD dwRet;
  2960. DWORD cbSize;
  2961. DWORD cbNeededSize;
  2962. DWORD cItems = 0;
  2963. TStatus Status(ERROR_MORE_DATA);
  2964. TStatusB bStatus;
  2965. //
  2966. // Only write data if we are given a valid-key.
  2967. //
  2968. if((lpszKey == NULL) || (*lpszKey == _T('\0')))
  2969. {
  2970. bStatus DBGNOCHK = TRUE;
  2971. goto End;
  2972. }
  2973. //
  2974. // Determine the size necessary to store the enumerated data.
  2975. //
  2976. cbSize = 0;
  2977. Status DBGCHK = EnumPrinterDataEx(m_hPrinter, lpszKey, NULL, 0, &cbNeededSize, &cItems);
  2978. //
  2979. // Current key has no values
  2980. //
  2981. if(cbNeededSize == 0 && Status == ERROR_MORE_DATA)
  2982. {
  2983. bStatus DBGNOCHK = TRUE;
  2984. goto End;
  2985. }
  2986. //
  2987. // If current key has values, then proceed to enumerate and write the values into stream
  2988. //
  2989. if(cbNeededSize && (Status == ERROR_MORE_DATA))
  2990. {
  2991. if(apevData = (LPPRINTER_ENUM_VALUES)AllocMem(cbNeededSize)) //AllocBytes
  2992. {
  2993. //
  2994. // Enumerate all values for the specified key. This
  2995. // returns an array of value-structs.
  2996. //
  2997. Status DBGCHK = EnumPrinterDataExW( m_hPrinter,
  2998. lpszKey,
  2999. reinterpret_cast<LPBYTE>(apevData),
  3000. cbNeededSize,
  3001. &cbSize,
  3002. &cItems);
  3003. bStatus DBGCHK = (Status == ERROR_SUCCESS) && (cbNeededSize == cbSize);
  3004. //
  3005. // Enumerate all data for the specified key and write to the stream.
  3006. //
  3007. // Write all the values for this key.
  3008. //
  3009. for(idx = 0; (idx < cItems) && bStatus; idx++)
  3010. {
  3011. bStatus DBGCHK = bWriteKeyValue(static_cast<LPCTSTR>(lpszKey), apevData + idx);
  3012. }
  3013. *lpcItems = bStatus ? cItems : 0;
  3014. FreeMem(apevData);
  3015. }
  3016. }
  3017. End:
  3018. return bStatus;
  3019. }
  3020. /*++
  3021. Title:
  3022. bWriteKeyValue
  3023. Routine Description:
  3024. Writes into stream a value with it's data for a given key name
  3025. (Write key/value name and PRINTER_ENUM_VALUES into stream)
  3026. Arguments:
  3027. lpszKey - Key name
  3028. lpPEV - pointer to PRINTER_ENUM_VALUES assoc with key
  3029. Return Value:
  3030. TRUE if succeded
  3031. --*/
  3032. BOOL
  3033. TPrnStream::
  3034. bWriteKeyValue(
  3035. IN LPCTSTR lpszKey,
  3036. IN LPPRINTER_ENUM_VALUES lpPEV
  3037. )
  3038. {
  3039. TStatusB bStatus;
  3040. TStatusH hr;
  3041. hr DBGCHK = WritePrnData( lpszKey,
  3042. lpPEV->pValueName,
  3043. lpPEV->cbValueName,
  3044. lpPEV->dwType,
  3045. lpPEV->pData,
  3046. lpPEV->cbData);
  3047. bStatus DBGCHK = SUCCEEDED(hr);
  3048. return bStatus;
  3049. }
  3050. /*++
  3051. Title:
  3052. WriteItem
  3053. Routine Description:
  3054. Build a PrnBinInfo item and write it into stream, at current position
  3055. Arguments:
  3056. pKey - key name ; null for items other than printer data
  3057. pValueName - key value ; null for items other than printer data
  3058. cbValueName - count bytes of pValueName
  3059. dwType - type
  3060. pData - actually data
  3061. cbData - count bytes of pData
  3062. Return Value:
  3063. S_OK if succeded
  3064. An error code from an API converted to HRESULT
  3065. --*/
  3066. HRESULT
  3067. TPrnStream::
  3068. WriteItem(
  3069. IN LPCTSTR pKey,
  3070. IN LPCTSTR pValueName,
  3071. IN DWORD cbValueName,
  3072. IN DWORD dwType,
  3073. IN LPBYTE pData,
  3074. IN DWORD cbData
  3075. )
  3076. {
  3077. DWORD cbKeySize;
  3078. DWORD cbKey;
  3079. DWORD cbName;
  3080. DWORD cbSize;
  3081. DWORD dwWritten;
  3082. PrnBinInfo* lppbi;
  3083. TStatusH hr;
  3084. TStatusB bStatus;
  3085. // Calculate aligned sizes for the key-name and key-value strings.
  3086. //
  3087. DBGMSG( DBG_TRACE, ( "TPrnStream::WriteItem\n KEY: " TSTR "" , pKey ));
  3088. DBGMSG( DBG_TRACE, ( "VALUE: " TSTR "\n" , pValueName ));
  3089. cbKeySize = (pKey != NULL) ? (_tcslen(pKey) + 1) * sizeof(TCHAR) : 0;
  3090. cbKey = AlignSize(cbKeySize);
  3091. cbName = AlignSize(cbValueName);
  3092. // Calculate size necessary to hold our PrnBinInfo information
  3093. // which is written into stream.
  3094. //
  3095. cbSize = sizeof(PrnBinInfo) + cbKey + cbName + cbData;
  3096. cbSize = AlignSize(cbSize);
  3097. //
  3098. // Allocate space for the structure.
  3099. //
  3100. lppbi = (PrnBinInfo*)AllocMem(cbSize);
  3101. bStatus DBGCHK = (lppbi != NULL);
  3102. if(bStatus)
  3103. {
  3104. //
  3105. // Initialize the structure elements. Since this information
  3106. // is written to file, we must take care to convert the
  3107. // pointers to byte-offsets.
  3108. //
  3109. lppbi->cbSize = cbSize;
  3110. lppbi->dwType = dwType;
  3111. lppbi->pKey = sizeof(PrnBinInfo);
  3112. lppbi->pValue = lppbi->pKey + cbKey;
  3113. lppbi->pData = lppbi->pValue + cbName;
  3114. lppbi->cbData = cbData;
  3115. CopyMemory(reinterpret_cast<LPBYTE>(lppbi) + lppbi->pKey , pKey , cbKeySize);
  3116. CopyMemory(reinterpret_cast<LPBYTE>(lppbi) + lppbi->pValue, pValueName, cbValueName);
  3117. CopyMemory(reinterpret_cast<LPBYTE>(lppbi) + lppbi->pData , pData , cbData);
  3118. hr DBGCHK = m_pIStream->Write(lppbi, lppbi->cbSize, &dwWritten);
  3119. FreeMem(lppbi);
  3120. }
  3121. else
  3122. {
  3123. hr DBGCHK = E_OUTOFMEMORY;
  3124. }
  3125. return hr ;
  3126. }
  3127. /*++
  3128. Title:
  3129. ReadItem
  3130. Routine Description:
  3131. Read an item from a current position in stream
  3132. Arguments:
  3133. Param pointers will point inside of lpBuffer:
  3134. pKey - key name ; null for items other than printer data
  3135. pValueName - key value ; null for items other than printer data
  3136. cbValueName - count bytes of pValueName
  3137. dwType - type
  3138. pData - actually data
  3139. cbData - count bytes of pData
  3140. lpBuffer - a null ptr that will contain ptr to read item;
  3141. must be deallocated by the caller if function succeed
  3142. Return Value:
  3143. S_OK if succeded
  3144. An error code from an API converted to HRESULT
  3145. --*/
  3146. HRESULT
  3147. TPrnStream::
  3148. ReadItem(
  3149. OUT LPTSTR& lpszKey,
  3150. OUT LPTSTR& lpszVal,
  3151. OUT DWORD& dwType,
  3152. OUT LPBYTE& lpbData,
  3153. OUT DWORD& cbSize,
  3154. OUT LPBYTE& lpBuffer
  3155. )
  3156. {
  3157. ULARGE_INTEGER uliSeekPtr;
  3158. TStatusH hr;
  3159. PrnBinInfo* lpPrnBinItem = NULL;
  3160. lpszKey = NULL;
  3161. lpszVal = NULL;
  3162. lpbData = NULL;
  3163. lpBuffer = NULL;
  3164. hr DBGCHK = GetCurrentPosition(uliSeekPtr);
  3165. if(SUCCEEDED(hr))
  3166. {
  3167. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  3168. if(SUCCEEDED(hr))
  3169. {
  3170. lpszKey = reinterpret_cast<LPTSTR>(reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pKey);
  3171. lpszVal = reinterpret_cast<LPTSTR>(reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pValue);
  3172. lpbData = reinterpret_cast<LPBYTE>(lpPrnBinItem) + lpPrnBinItem->pData;
  3173. cbSize = lpPrnBinItem->cbData;
  3174. dwType = lpPrnBinItem->dwType - ktREG_TYPE;
  3175. lpBuffer = reinterpret_cast<LPBYTE>(lpPrnBinItem);
  3176. }
  3177. }
  3178. else
  3179. {
  3180. hr DBGNOCHK = E_UNEXPECTED;
  3181. }
  3182. return hr;
  3183. }
  3184. /*++
  3185. Title:
  3186. ReadItemFromPosition
  3187. Routine Description:
  3188. Read an item from a given position in stream
  3189. Set seek pointer at the begining of the item
  3190. Read item's size
  3191. Set seek pointer at the begining of the item
  3192. Read item
  3193. uliSeekPtr will contain the seek pointer value after item's reading
  3194. Arguments:
  3195. uliSeekPtr - in start of item ; outs current seek ptr
  3196. lpPrnBinItem - ptr to read item
  3197. Return Value:
  3198. S_OK if succeded
  3199. An error code from an API converted to HRESULT
  3200. --*/
  3201. HRESULT
  3202. TPrnStream::
  3203. ReadItemFromPosition(
  3204. IN OUT ULARGE_INTEGER& uliSeekPtr,
  3205. OUT PrnBinInfo *& pPrnBinItem
  3206. )
  3207. {
  3208. DWORD cbReadedSize;
  3209. DWORD cbSize = 0;
  3210. LARGE_INTEGER liStart = {0};
  3211. TStatusH hr;
  3212. pPrnBinItem = NULL;
  3213. //
  3214. // Position seek pointer to where the item begins
  3215. //
  3216. liStart.QuadPart = uliSeekPtr.QuadPart;
  3217. hr DBGCHK = m_pIStream->Seek(liStart, STREAM_SEEK_SET, NULL);
  3218. if(SUCCEEDED(hr))
  3219. {
  3220. //
  3221. // Read size of item
  3222. //
  3223. hr DBGCHK = m_pIStream->Read(&cbSize, sizeof(DWORD), &cbReadedSize);
  3224. DBGMSG( DBG_TRACE, ("TPrnStream::ReadItemFromPosition\n Read item's size %d\n" ,cbSize) );
  3225. if(SUCCEEDED(hr))
  3226. {
  3227. //
  3228. // Go for start position again
  3229. //
  3230. hr DBGCHK = m_pIStream->Seek( liStart , STREAM_SEEK_SET, NULL );
  3231. if(SUCCEEDED(hr))
  3232. {
  3233. pPrnBinItem = (PrnBinInfo*)AllocMem(cbSize);
  3234. hr DBGCHK = pPrnBinItem ? S_OK : E_OUTOFMEMORY;
  3235. if(SUCCEEDED(hr))
  3236. {
  3237. hr DBGCHK = m_pIStream->Read(reinterpret_cast<LPBYTE>(pPrnBinItem), cbSize, &cbReadedSize);
  3238. SUCCEEDED(hr) ? GetCurrentPosition(uliSeekPtr) : FreeMem(pPrnBinItem);
  3239. }
  3240. }
  3241. }
  3242. }
  3243. return hr;
  3244. }
  3245. /*++
  3246. Title:
  3247. GetCurrentPosition
  3248. Routine Description:
  3249. Gets the current value of seek pointer into IStream
  3250. Arguments:
  3251. uliCurrentPosition - outs current seek ptr
  3252. Return Value:
  3253. TRUE if succeded
  3254. --*/
  3255. HRESULT
  3256. TPrnStream::
  3257. GetCurrentPosition(
  3258. OUT ULARGE_INTEGER& uliCurrentPosition
  3259. )
  3260. {
  3261. LARGE_INTEGER liMove = {0};
  3262. TStatusH hr;
  3263. uliCurrentPosition.QuadPart = 0;
  3264. hr DBGCHK = m_pIStream->Seek( liMove , STREAM_SEEK_CUR, &uliCurrentPosition );
  3265. return hr;
  3266. }
  3267. /*++
  3268. Title:
  3269. GetItemSize
  3270. Routine Description:
  3271. read item's size from stream
  3272. Arguments:
  3273. kHeaderEntryType - specify entry in header associated with item
  3274. Return Value:
  3275. item's size if succeeded or -1 if failed
  3276. --*/
  3277. DWORD
  3278. TPrnStream::
  3279. GetItemSize(
  3280. IN TPrnStream::EHeaderEntryType kHeaderEntryType
  3281. )
  3282. {
  3283. DWORD cbItemSize;
  3284. PrnBinInfo* lpPrnBinItem;
  3285. ULARGE_INTEGER uliSeekPtr;
  3286. TStatusH hr;
  3287. TStatusB bStatus;
  3288. cbItemSize = 0;
  3289. //
  3290. // Read from header where info begins in stream
  3291. //
  3292. hr DBGCHK = ReadFromHeader(kHeaderEntryType, &uliSeekPtr);
  3293. //
  3294. // if ReadFromHeader returns a S_OK and dwSeekPtr is zero, it means that nothing is stored
  3295. //
  3296. if(FAILED(hr))
  3297. {
  3298. cbItemSize = -1;
  3299. }
  3300. else
  3301. {
  3302. if(uliSeekPtr.QuadPart > 0)
  3303. //
  3304. // Read an item from specified position
  3305. //
  3306. hr DBGCHK = ReadItemFromPosition(uliSeekPtr, lpPrnBinItem);
  3307. if(FAILED(hr))
  3308. {
  3309. cbItemSize = -1;
  3310. }
  3311. else
  3312. {
  3313. cbItemSize = lpPrnBinItem->cbSize;
  3314. }
  3315. }
  3316. return cbItemSize;
  3317. }
  3318. /*++
  3319. Title:
  3320. InitalizeColorProfileLibrary
  3321. Routine Description:
  3322. Loads and gets the needed procedure address for the color profile related
  3323. functions. This library is explicitly loaded and un loaded to impove
  3324. load performce for winspool.drv. Note winspool.drv is a common dll loaded
  3325. by many applications so loading less libraries is a good thing.
  3326. Arguments:
  3327. None.
  3328. Return Value:
  3329. An HRESULT
  3330. --*/
  3331. HRESULT
  3332. TPrnStream::
  3333. InitalizeColorProfileLibrary(
  3334. VOID
  3335. )
  3336. {
  3337. HRESULT hRetval = E_FAIL;
  3338. m_pColorProfileLibrary = new TLibrary(L"mscms.dll");
  3339. hRetval = m_pColorProfileLibrary && m_pColorProfileLibrary->bValid() ? S_OK : E_OUTOFMEMORY;
  3340. if (SUCCEEDED(hRetval))
  3341. {
  3342. m_EnumColorProfiles = (pfnEnumColorProfilesW)m_pColorProfileLibrary->pfnGetProc("EnumColorProfilesW");
  3343. m_AssociateColorProfileWithDevice = (pfnAssociateColorProfileWithDeviceW)m_pColorProfileLibrary->pfnGetProc("AssociateColorProfileWithDeviceW");
  3344. m_DisassociateColorProfileFromDevice = (pfnDisassociateColorProfileFromDeviceW)m_pColorProfileLibrary->pfnGetProc("DisassociateColorProfileFromDeviceW");
  3345. if (!m_EnumColorProfiles || !m_AssociateColorProfileWithDevice || !m_DisassociateColorProfileFromDevice)
  3346. {
  3347. hRetval = HRESULT_FROM_WIN32(ERROR_PROC_NOT_FOUND);
  3348. }
  3349. }
  3350. return hRetval;
  3351. }
  3352. /*++
  3353. Routine Description:
  3354. Opens printer for specified access.
  3355. Arguments:
  3356. pszPrinter - Name of printer to open. szNULL or NULL implies local server.
  3357. pdwAccess - On entry, holds desired access (pointer to 0 indicates
  3358. maximal access). On successful exit, holds access granted.
  3359. If the call fails, this value is undefined.
  3360. phPrinter - Returns the open printer handle. On failure, this value
  3361. is set to NULL.
  3362. Return Value:
  3363. STATUS - win32 error code or ERROR_SUCCESS if successful.
  3364. --*/
  3365. STATUS
  3366. TPrnStream::
  3367. sOpenPrinter(
  3368. LPCTSTR pszPrinter,
  3369. PDWORD pdwAccess,
  3370. PHANDLE phPrinter
  3371. )
  3372. {
  3373. STATUS Status = ERROR_SUCCESS;
  3374. TStatusB bOpen( DBG_WARN,
  3375. ERROR_ACCESS_DENIED,
  3376. RPC_S_SERVER_UNAVAILABLE,
  3377. ERROR_INVALID_PRINTER_NAME );
  3378. bOpen DBGNOCHK = FALSE;
  3379. static const DWORD adwAccessPrinter[] = {
  3380. PRINTER_ALL_ACCESS,
  3381. PRINTER_READ,
  3382. READ_CONTROL,
  3383. 0,
  3384. };
  3385. static const DWORD adwAccessServer[] = {
  3386. SERVER_ALL_ACCESS,
  3387. SERVER_READ,
  3388. 0,
  3389. };
  3390. PRINTER_DEFAULTS Defaults;
  3391. Defaults.pDatatype = NULL;
  3392. Defaults.pDevMode = NULL;
  3393. if( pszPrinter && !pszPrinter[0] ){
  3394. //
  3395. // szNull indicates local server also; change it to
  3396. // NULL since OpenPrinter only likes NULL.
  3397. //
  3398. pszPrinter = NULL;
  3399. }
  3400. //
  3401. // Now determine whether we are opening a server or a printer.
  3402. // This is very messy. Look for NULL or two beginning
  3403. // backslashes and none thereafter to indicate a server.
  3404. //
  3405. PDWORD pdwAccessTypes;
  3406. if( !pszPrinter ||
  3407. ( pszPrinter[0] == TEXT( '\\' ) &&
  3408. pszPrinter[1] == TEXT( '\\' ) &&
  3409. !_tcschr( &pszPrinter[2], TEXT( '\\' )))){
  3410. pdwAccessTypes = (PDWORD)adwAccessServer;
  3411. } else {
  3412. pdwAccessTypes = (PDWORD)adwAccessPrinter;
  3413. }
  3414. if( *pdwAccess ){
  3415. Defaults.DesiredAccess = *pdwAccess;
  3416. bOpen DBGCHK = OpenPrinter( (LPTSTR)pszPrinter,
  3417. phPrinter,
  3418. &Defaults );
  3419. if( !bOpen ){
  3420. Status = GetLastError();
  3421. }
  3422. } else {
  3423. //
  3424. // If no access is specified, then attempt to retrieve the
  3425. // maximal access.
  3426. //
  3427. UINT i;
  3428. for( i = 0; !bOpen && pdwAccessTypes[i]; ++i ){
  3429. Defaults.DesiredAccess = pdwAccessTypes[i];
  3430. bOpen DBGCHK = OpenPrinter( (LPTSTR)pszPrinter,
  3431. phPrinter,
  3432. &Defaults );
  3433. if( bOpen ){
  3434. //
  3435. // Return the access requested by the successful OpenPrinter.
  3436. // On failure, this value is 0 (*pdwAccess undefined).
  3437. //
  3438. *pdwAccess = pdwAccessTypes[i];
  3439. break;
  3440. }
  3441. Status = GetLastError();
  3442. if( ERROR_ACCESS_DENIED != Status )
  3443. break;
  3444. }
  3445. }
  3446. if( !bOpen ){
  3447. SPLASSERT( Status );
  3448. *phPrinter = NULL;
  3449. return Status;
  3450. }
  3451. SPLASSERT( *phPrinter );
  3452. return ERROR_SUCCESS;
  3453. }
  3454. /*++
  3455. Routine Description:
  3456. Gets printer information, reallocing as necessary.
  3457. Arguments:
  3458. hPrinter - Printer to query.
  3459. dwLevel - PRINTER_INFO_x level to retrieve.
  3460. ppvBuffer - Buffer to store information. If *ppvBuffer is
  3461. NULL, then it is allocated. On failure, this buffer is
  3462. freed and NULLed
  3463. pcbBuffer - Initial buffer size. On exit, actual.
  3464. Return Value:
  3465. TRUE = success, FALSE = fail.
  3466. --*/
  3467. BOOL
  3468. TPrnStream::
  3469. bGetPrinter(
  3470. IN HANDLE hPrinter,
  3471. IN DWORD dwLevel,
  3472. IN OUT PVOID* ppvBuffer,
  3473. IN OUT PDWORD pcbBuffer
  3474. )
  3475. {
  3476. DWORD cbNeeded;
  3477. enum
  3478. {
  3479. kMaxPrinterInfo2 = 0x1000,
  3480. kExtraPrinterBufferBytes = 0x80
  3481. };
  3482. //
  3483. // Pre-initialize *pcbPrinter if it's not set.
  3484. //
  3485. if( !*pcbBuffer ){
  3486. *pcbBuffer = kMaxPrinterInfo2;
  3487. }
  3488. Retry:
  3489. SPLASSERT( *pcbBuffer < 0x100000 );
  3490. if( !( *ppvBuffer )){
  3491. *ppvBuffer = (PVOID)AllocMem( *pcbBuffer );
  3492. if( !*ppvBuffer ){
  3493. *pcbBuffer = 0;
  3494. return FALSE;
  3495. }
  3496. }
  3497. if( !GetPrinter( hPrinter,
  3498. dwLevel,
  3499. (PBYTE)*ppvBuffer,
  3500. *pcbBuffer,
  3501. &cbNeeded )){
  3502. FreeMem( *ppvBuffer );
  3503. *ppvBuffer = NULL;
  3504. if( GetLastError() != ERROR_INSUFFICIENT_BUFFER ){
  3505. *pcbBuffer = 0;
  3506. return FALSE;
  3507. }
  3508. *pcbBuffer = cbNeeded + kExtraPrinterBufferBytes;
  3509. SPLASSERT( *pcbBuffer < 0x100000 );
  3510. goto Retry;
  3511. }
  3512. return TRUE;
  3513. }
  3514. BOOL
  3515. TPrnStream::
  3516. bNewShareName(
  3517. IN LPCTSTR lpszServer,
  3518. IN LPCTSTR lpszBaseShareName,
  3519. OUT TString &strShareName
  3520. )
  3521. {
  3522. BOOL bReturn = FALSE;
  3523. if( lpszServer && lpszBaseShareName )
  3524. {
  3525. HRESULT hr = CoInitialize(NULL);
  3526. BOOL bInitializedCOM = SUCCEEDED(hr);
  3527. TCHAR szBuffer[255];
  3528. IPrintUIServices *pPrintUI = NULL;
  3529. if( SUCCEEDED(hr) &&
  3530. SUCCEEDED(hr = CoCreateInstance(CLSID_PrintUIShellExtension, 0, CLSCTX_INPROC_SERVER,
  3531. IID_IPrintUIServices, (void**)&pPrintUI)) &&
  3532. pPrintUI &&
  3533. SUCCEEDED(hr = pPrintUI->GenerateShareName(lpszServer, lpszBaseShareName, szBuffer, COUNTOF(szBuffer))) )
  3534. {
  3535. strShareName.bUpdate(szBuffer);
  3536. bReturn = TRUE;
  3537. }
  3538. else
  3539. {
  3540. SetLastError(HRESULT_CODE(hr));
  3541. }
  3542. if( pPrintUI )
  3543. {
  3544. pPrintUI->Release();
  3545. }
  3546. if( bInitializedCOM )
  3547. {
  3548. CoUninitialize();
  3549. }
  3550. }
  3551. return bReturn;
  3552. }