Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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