Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1010 lines
16 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1998 - 1998
  3. All rights reserved.
  4. Module Name:
  5. splperst.cxx
  6. Abstract:
  7. Implementation of spooler persisting code
  8. IPrnStream & IStream
  9. Author:
  10. Adina Trufinescu (AdinaTru) 4-Nov-1998
  11. Revision History:
  12. Lazar Ivanov (LazarI) Jul-2000 - moved from printui.
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include "prnprst.hxx"
  17. #include <initguid.h>
  18. #include "winprtp.h"
  19. ////////////////////////////////////////
  20. // class TPrnPersist
  21. //
  22. class TPrnPersist: public IPrnStream,
  23. public IStream
  24. {
  25. public:
  26. TPrnPersist(
  27. VOID
  28. );
  29. ~TPrnPersist(
  30. VOID
  31. );
  32. /***********
  33. IUnknown
  34. ***********/
  35. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  36. STDMETHODIMP_(ULONG) AddRef();
  37. STDMETHODIMP_(ULONG) Release();
  38. /***********
  39. IPrnStream
  40. ***********/
  41. STDMETHODIMP
  42. BindPrinterAndFile(
  43. IN LPCTSTR pszPrinter,
  44. LPCTSTR pszFile
  45. );
  46. STDMETHODIMP
  47. StorePrinterInfo(
  48. IN DWORD Flag
  49. );
  50. STDMETHODIMP
  51. RestorePrinterInfo(
  52. IN DWORD Flag
  53. );
  54. STDMETHODIMP
  55. QueryPrinterInfo(
  56. IN PrinterPersistentQueryFlag Flag,
  57. OUT PersistentInfo *pPrstInfo
  58. );
  59. /***********
  60. IStream
  61. ***********/
  62. HRESULT STDMETHODCALLTYPE
  63. Read( // IMPLEMENTED
  64. VOID * pv,
  65. ULONG cb,
  66. ULONG * pcbRead
  67. );
  68. HRESULT STDMETHODCALLTYPE
  69. Write( //IMPLEMENTED
  70. VOID const* pv,
  71. ULONG cb,
  72. ULONG * pcbWritten
  73. );
  74. HRESULT STDMETHODCALLTYPE
  75. Seek( //IMPLEMENTED
  76. LARGE_INTEGER dlibMove,
  77. DWORD dwOrigin,
  78. ULARGE_INTEGER * plibNewPosition
  79. );
  80. HRESULT STDMETHODCALLTYPE
  81. SetSize(
  82. ULARGE_INTEGER nSize
  83. );
  84. HRESULT STDMETHODCALLTYPE
  85. CopyTo( //NOT_IMPLEMENTED
  86. LPSTREAM pStrm,
  87. ULARGE_INTEGER cb,
  88. ULARGE_INTEGER * pcbRead,
  89. ULARGE_INTEGER * pcbWritten
  90. );
  91. HRESULT STDMETHODCALLTYPE
  92. Commit( //NOT_IMPLEMENTED
  93. IN DWORD dwFlags
  94. );
  95. HRESULT STDMETHODCALLTYPE
  96. Revert( //NOT_IMPLEMENTED
  97. VOID
  98. );
  99. HRESULT STDMETHODCALLTYPE
  100. LockRegion( //NOT_IMPLEMENTED
  101. ULARGE_INTEGER cbOffset,
  102. ULARGE_INTEGER cbLength,
  103. DWORD dwFlags
  104. );
  105. HRESULT STDMETHODCALLTYPE
  106. UnlockRegion( //NOT_IMPLEMENTED
  107. ULARGE_INTEGER cbOffset,
  108. ULARGE_INTEGER cbLength,
  109. DWORD dwFlags
  110. );
  111. HRESULT STDMETHODCALLTYPE
  112. Stat( //NOT_IMPLEMENTED
  113. STATSTG * pStatStg,
  114. DWORD dwFlags
  115. );
  116. HRESULT STDMETHODCALLTYPE
  117. Clone( //NOT_IMPLEMENTED
  118. OUT LPSTREAM * ppStrm
  119. );
  120. private:
  121. LONG m_cRef;
  122. TPrinterPersist *_pPrnPersist;
  123. };
  124. TPrnPersist::
  125. TPrnPersist(
  126. VOID
  127. ): m_cRef(1),
  128. _pPrnPersist(NULL)
  129. {
  130. }
  131. TPrnPersist::
  132. ~TPrnPersist(
  133. VOID
  134. )
  135. {
  136. if( _pPrnPersist )
  137. {
  138. delete _pPrnPersist;
  139. }
  140. }
  141. /***********
  142. IUnknown
  143. ***********/
  144. STDMETHODIMP TPrnPersist::QueryInterface(REFIID riid, void **ppv)
  145. {
  146. // standard implementation
  147. if( !ppv )
  148. {
  149. return E_INVALIDARG;
  150. }
  151. *ppv = NULL;
  152. if( IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IPrnStream) )
  153. {
  154. *ppv = static_cast<IPrnStream*>(this);
  155. }
  156. else if( IsEqualIID(riid, IID_IStream) )
  157. {
  158. *ppv = static_cast<IStream*>(this);
  159. }
  160. else
  161. {
  162. return E_NOINTERFACE;
  163. }
  164. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  165. return S_OK;
  166. }
  167. STDMETHODIMP_(ULONG) TPrnPersist::AddRef()
  168. {
  169. // standard implementation
  170. return InterlockedIncrement(&m_cRef);
  171. }
  172. STDMETHODIMP_(ULONG) TPrnPersist::Release()
  173. {
  174. // standard implementation
  175. ULONG cRefs = InterlockedDecrement(&m_cRef);
  176. if( 0 == cRefs )
  177. {
  178. delete this;
  179. }
  180. return cRefs;
  181. }
  182. /*++
  183. Name:
  184. TPrnPersist::BindPrinterAndFile
  185. Description:
  186. Creates a PrnStream object if it don't exists and bind it to a printer and a file
  187. Arguments:
  188. printer name
  189. file name
  190. Return Value:
  191. S_OK if succeeded
  192. --*/
  193. STDMETHODIMP
  194. TPrnPersist::
  195. BindPrinterAndFile(
  196. IN LPCTSTR pszPrinter,
  197. IN LPCTSTR pszFile
  198. )
  199. {
  200. HRESULT hr = E_FAIL;
  201. //
  202. // Create the PrnStream location object if this is the first call.
  203. //
  204. if (!_pPrnPersist)
  205. {
  206. _pPrnPersist = new TPrinterPersist;
  207. }
  208. //
  209. // Invoke the BindPrinterAndFile method if the printer stream
  210. // object was create successfully.
  211. //
  212. if (_pPrnPersist != NULL)
  213. {
  214. DBGMSG(DBG_TRACE , ("TPrnPersist::BindPrinterAndFile \n"));
  215. hr = _pPrnPersist->BindPrinterAndFile(pszPrinter, pszFile);
  216. }
  217. else
  218. {
  219. hr = E_OUTOFMEMORY;
  220. }
  221. DBGMSG(DBG_TRACE , ("TPrnPersist::BindPrinterAndFile %x \n" , hr));
  222. return hr;
  223. }
  224. /*++
  225. Name:
  226. TPrnPersist::StorePrinterInfo
  227. Description:
  228. Creates a PrnStream object if it don't exists and invoke StorePrinterInfo
  229. Arguments:
  230. flags that specifies what settings to store
  231. Return Value:
  232. S_OK if succeeded
  233. --*/
  234. STDMETHODIMP
  235. TPrnPersist::
  236. StorePrinterInfo(
  237. IN DWORD Flag
  238. )
  239. {
  240. TStatusH hr;
  241. hr DBGNOCHK = E_FAIL;
  242. DWORD StoredFlags;
  243. //
  244. // Create the PrnStream location object if this is the first call.
  245. //
  246. if (!_pPrnPersist)
  247. {
  248. _pPrnPersist = new TPrinterPersist;
  249. }
  250. //
  251. // Invoke the stote info method if the printer stream
  252. // object was create successfully.
  253. //
  254. DBGMSG(DBG_TRACE , ("TPrnPersist::StorePrinterInfo Flag %x \n" , Flag));
  255. if(_pPrnPersist != NULL)
  256. {
  257. if (VALID_PTR(_pPrnPersist))
  258. {
  259. //
  260. // Winlogon calls this function for TS. We need to catch any possbile exception,
  261. // otherwise we may cause BSOD.
  262. //
  263. __try
  264. {
  265. hr DBGCHK = _pPrnPersist->StorePrinterInfo(Flag, StoredFlags);
  266. }
  267. __except(EXCEPTION_EXECUTE_HANDLER)
  268. {
  269. DBGMSG(DBG_WARNING, ("TPrnPersist::StorePrinterInfo exception %x\n", GetExceptionCode()));
  270. hr DBGCHK = E_FAIL;
  271. }
  272. }
  273. else
  274. {
  275. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
  276. }
  277. }
  278. else
  279. {
  280. hr DBGCHK = E_OUTOFMEMORY;
  281. }
  282. return hr;
  283. }
  284. /*++
  285. Name:
  286. TPrnPersist::RestorePrinterInfo
  287. Description:
  288. Creates a PrnStream object if it don't exists and invoke RestorePrinterInfo
  289. Arguments:
  290. flags that specifies what settings to restore
  291. Return Value:
  292. S_OK if succeeded
  293. --*/
  294. STDMETHODIMP
  295. TPrnPersist::
  296. RestorePrinterInfo(
  297. IN DWORD Flag
  298. )
  299. {
  300. TStatusH hr;
  301. //
  302. // Create the Prnstream location object if this is the first call.
  303. //
  304. if (!_pPrnPersist)
  305. {
  306. _pPrnPersist = new TPrinterPersist;
  307. }
  308. //
  309. // Invoke the restore info method if the printer stream
  310. // object was created successfully.
  311. //
  312. if(_pPrnPersist != NULL)
  313. {
  314. if (VALID_PTR(_pPrnPersist))
  315. {
  316. //
  317. // Winlogon calls this function on the machine where TS runs. If the file from which
  318. // we restore the settings is corrupted, we must protect us against AVs that can occur
  319. // while accessing bad data.
  320. //
  321. __try
  322. {
  323. hr DBGCHK = _pPrnPersist->SafeRestorePrinterInfo(Flag);
  324. }
  325. __except(EXCEPTION_EXECUTE_HANDLER)
  326. {
  327. DBGMSG(DBG_WARNING, ("TPrnPersist::SafeRestorePrinterInfo exception %x\n", GetExceptionCode()));
  328. hr DBGCHK = E_FAIL;
  329. }
  330. }
  331. else
  332. {
  333. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
  334. }
  335. }
  336. else
  337. {
  338. hr DBGCHK = E_OUTOFMEMORY;
  339. }
  340. return hr;
  341. }
  342. /*++
  343. Name:
  344. TPrnPersist::QueryPrinterInfo
  345. Description:
  346. Creates a PrnStream object if it don't exists and invoke QueryPrinterInfo
  347. Arguments:
  348. flags that specifies what settings to query
  349. Return Value:
  350. S_OK if succeeded
  351. --*/
  352. STDMETHODIMP
  353. TPrnPersist::
  354. QueryPrinterInfo(
  355. IN PrinterPersistentQueryFlag Flag,
  356. OUT PersistentInfo *pPrstInfo
  357. )
  358. {
  359. TStatusH hr;
  360. hr DBGNOCHK = E_FAIL;
  361. //
  362. // Create the Prnstream location object if this is the first call.
  363. //
  364. if (!_pPrnPersist)
  365. {
  366. _pPrnPersist = new TPrinterPersist;
  367. }
  368. //
  369. // Invoke the query info method if the printer stream
  370. // object was create successfully.
  371. //
  372. if(_pPrnPersist != NULL)
  373. {
  374. if (VALID_PTR(_pPrnPersist))
  375. {
  376. __try
  377. {
  378. hr DBGCHK = _pPrnPersist->QueryPrinterInfo(Flag , pPrstInfo);
  379. }
  380. __except(EXCEPTION_EXECUTE_HANDLER)
  381. {
  382. DBGMSG(DBG_WARNING, ("TPrnPersist::QueryPrinterInfo exception %x\n", GetExceptionCode()));
  383. hr DBGCHK = E_FAIL;
  384. }
  385. }
  386. else
  387. {
  388. hr DBGCHK = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
  389. }
  390. }
  391. else
  392. {
  393. hr DBGCHK = E_OUTOFMEMORY;
  394. }
  395. return hr;
  396. }
  397. /*++
  398. Name:
  399. TPrnPersist::Read
  400. Description:
  401. Creates a PrnStream object if it don't exists and invoke Read
  402. Arguments:
  403. pv - The buffer that the bytes are read into
  404. cb - The offset in the stream to begin reading from.
  405. pcbRead - The number of bytes to read
  406. Return Value:
  407. S_OK if succeeded
  408. --*/
  409. STDMETHODIMP
  410. TPrnPersist::
  411. Read(
  412. VOID * pv,
  413. ULONG cb,
  414. ULONG * pcbRead
  415. )
  416. {
  417. HRESULT hr = E_FAIL;
  418. //
  419. // Create the Prnstream location object if this is the first call.
  420. //
  421. if (!_pPrnPersist)
  422. {
  423. _pPrnPersist = new TPrinterPersist;
  424. }
  425. //
  426. // Invoke the read method if the printer stream
  427. // object was create successfully.
  428. //
  429. if(_pPrnPersist != NULL)
  430. {
  431. if (VALID_PTR(_pPrnPersist))
  432. {
  433. hr = _pPrnPersist->Read(pv, cb, pcbRead);
  434. }
  435. else
  436. {
  437. hr = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
  438. }
  439. }
  440. else
  441. {
  442. hr = E_OUTOFMEMORY;
  443. }
  444. return hr;
  445. }
  446. /*++
  447. Name:
  448. TPrnPersist::Write
  449. Description:
  450. Creates a PrnStream object if it don't exists and invoke Write
  451. Arguments:
  452. pv - The buffer to write from.
  453. cb - The offset in the array to begin writing from
  454. pcbRead - The number of bytes to write
  455. Return Value:
  456. S_OK if succeeded
  457. --*/
  458. STDMETHODIMP
  459. TPrnPersist::
  460. Write(
  461. VOID const* pv,
  462. ULONG cb,
  463. ULONG * pcbWritten
  464. )
  465. {
  466. HRESULT hr = E_FAIL;
  467. //
  468. // Create the Prnstream location object if this is the first call.
  469. //
  470. if (!_pPrnPersist)
  471. {
  472. _pPrnPersist = new TPrinterPersist;
  473. }
  474. //
  475. // Invoke the write method if the printer stream
  476. // object was create successfully.
  477. //
  478. if(_pPrnPersist != NULL)
  479. {
  480. if (VALID_PTR(_pPrnPersist))
  481. {
  482. hr = _pPrnPersist->Write(pv, cb, pcbWritten);
  483. }
  484. else
  485. {
  486. hr = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
  487. }
  488. }
  489. else
  490. {
  491. hr = E_OUTOFMEMORY;
  492. }
  493. return hr;
  494. }
  495. /*++
  496. Name:
  497. TPrnPersist::Seek
  498. Description:
  499. Creates a PrnStream object if it don't exists and invoke Seek
  500. Arguments:
  501. dlibMove - The offset relative to dwOrigin
  502. dwOrigin - The origin of the offset
  503. plibNewPosition - Pointer to value of the new seek pointer from the beginning of the stream
  504. Return Value:
  505. S_OK if succeeded
  506. --*/
  507. STDMETHODIMP
  508. TPrnPersist::
  509. Seek(
  510. LARGE_INTEGER dlibMove,
  511. DWORD dwOrigin,
  512. ULARGE_INTEGER * plibNewPosition
  513. )
  514. {
  515. HRESULT hr = E_FAIL;
  516. //
  517. // Create the Prnstream location object if this is the first call.
  518. //
  519. if (!_pPrnPersist)
  520. {
  521. _pPrnPersist = new TPrinterPersist;
  522. }
  523. //
  524. // Invoke the seek method if the printer stream
  525. // object was create successfully.
  526. //
  527. if(_pPrnPersist != NULL)
  528. {
  529. if (VALID_PTR(_pPrnPersist))
  530. {
  531. hr = _pPrnPersist->Seek(dlibMove, dwOrigin, plibNewPosition);
  532. }
  533. else
  534. {
  535. hr = MakePrnPersistHResult(PRN_PERSIST_ERROR_UNBOUND);
  536. }
  537. }
  538. else
  539. {
  540. hr = E_OUTOFMEMORY;
  541. }
  542. return hr;
  543. }
  544. /*++
  545. Name:
  546. TPrnPersist::SetSize
  547. Description:
  548. Arguments:
  549. Return Value:
  550. E_NOTIMPL
  551. --*/
  552. STDMETHODIMP
  553. TPrnPersist::
  554. SetSize(
  555. ULARGE_INTEGER nSize
  556. )
  557. {
  558. return E_NOTIMPL;
  559. }
  560. /*++
  561. Name:
  562. TPrnPersist::CopyTo
  563. Description:
  564. Arguments:
  565. Return Value:
  566. E_NOTIMPL
  567. --*/
  568. STDMETHODIMP
  569. TPrnPersist::
  570. CopyTo(
  571. LPSTREAM pStrm,
  572. ULARGE_INTEGER cb,
  573. ULARGE_INTEGER * pcbRead,
  574. ULARGE_INTEGER * pcbWritten
  575. )
  576. {
  577. return E_NOTIMPL;
  578. }
  579. /*++
  580. Name:
  581. TPrnPersist::Commit
  582. Description:
  583. Arguments:
  584. Return Value:
  585. E_NOTIMPL
  586. --*/
  587. STDMETHODIMP
  588. TPrnPersist::
  589. Commit(
  590. IN DWORD dwFlags
  591. )
  592. {
  593. return E_NOTIMPL;
  594. }
  595. /*++
  596. Name:
  597. TPrnPersist::Revert
  598. Description:
  599. Arguments:
  600. Return Value:
  601. E_NOTIMPL
  602. --*/
  603. STDMETHODIMP
  604. TPrnPersist::
  605. Revert(
  606. VOID
  607. )
  608. {
  609. return E_NOTIMPL;
  610. }
  611. /*++
  612. Name:
  613. TPrnPersist::LockRegion
  614. Description:
  615. Arguments:
  616. Return Value:
  617. E_NOTIMPL
  618. --*/
  619. STDMETHODIMP
  620. TPrnPersist::
  621. LockRegion(
  622. ULARGE_INTEGER cbOffset,
  623. ULARGE_INTEGER cbLength,
  624. DWORD dwFlags
  625. )
  626. {
  627. return E_NOTIMPL;
  628. }
  629. /*++
  630. Name:
  631. TPrnPersist::UnlockRegion
  632. Description:
  633. Arguments:
  634. Return Value:
  635. E_NOTIMPL
  636. --*/
  637. STDMETHODIMP
  638. TPrnPersist::
  639. UnlockRegion(
  640. ULARGE_INTEGER cbOffset,
  641. ULARGE_INTEGER cbLength,
  642. DWORD dwFlags
  643. )
  644. {
  645. return E_NOTIMPL;
  646. }
  647. /*++
  648. Name:
  649. TPrnPersist::Stat
  650. Description:
  651. Arguments:
  652. Return Value:
  653. E_NOTIMPL
  654. --*/
  655. STDMETHODIMP
  656. TPrnPersist::
  657. Stat(
  658. STATSTG * pStatStg,
  659. DWORD dwFlags
  660. )
  661. {
  662. return E_NOTIMPL;
  663. }
  664. /*++
  665. Name:
  666. TPrnPersist::Clone
  667. Description:
  668. Arguments:
  669. Return Value:
  670. E_NOTIMPL
  671. --*/
  672. STDMETHODIMP
  673. TPrnPersist::
  674. Clone(
  675. LPSTREAM * ppStrm
  676. )
  677. {
  678. return E_NOTIMPL;
  679. }
  680. #ifdef __cplusplus
  681. extern "C" {
  682. #endif
  683. // forward declarations....
  684. HRESULT TPrnPersist_CreateInstance(REFIID riid, void **ppv);
  685. BOOL WebPnpEntry(LPCTSTR lpszCmdLine);
  686. BOOL WebPnpPostEntry(BOOL fConnection, LPCTSTR lpszBinFile, LPCTSTR lpszPortName, LPCTSTR lpszPrtName);
  687. /*++
  688. Name:
  689. TPrnPersist_CreateInstance
  690. Description:
  691. creates an instance of TPrnPersist
  692. Arguments:
  693. Return Value:
  694. S_OK on sucsess or OLE error on failure.
  695. --*/
  696. HRESULT TPrnPersist_CreateInstance(
  697. IN REFIID riid,
  698. OUT void **ppv
  699. )
  700. {
  701. HRESULT hr = E_INVALIDARG;
  702. if( ppv )
  703. {
  704. *ppv = NULL;
  705. TPrnPersist *pObj = new TPrnPersist;
  706. if( pObj )
  707. {
  708. hr = pObj->QueryInterface( riid, ppv );
  709. pObj->Release( );
  710. }
  711. else
  712. {
  713. hr = E_OUTOFMEMORY;
  714. }
  715. }
  716. return hr;
  717. }
  718. /*++
  719. Name:
  720. PrintUIWebPnpEntry
  721. Description:
  722. wrapper around WebPnpEntry
  723. Arguments:
  724. Return Value:
  725. S_OK on sucsess or OLE error on failure.
  726. --*/
  727. HRESULT PrintUIWebPnpEntry(
  728. LPCTSTR lpszCmdLine
  729. )
  730. {
  731. return WebPnpEntry(lpszCmdLine) ? S_OK : E_FAIL;
  732. }
  733. /*++
  734. Name:
  735. PrintUIWebPnpPostEntry
  736. Description:
  737. wrapper around WebPnpPostEntry
  738. Arguments:
  739. Return Value:
  740. S_OK on sucsess or OLE error on failure.
  741. --*/
  742. HRESULT PrintUIWebPnpPostEntry(BOOL fConnection, LPCTSTR lpszBinFile, LPCTSTR lpszPortName, LPCTSTR lpszPrtName)
  743. {
  744. return WebPnpPostEntry(fConnection, lpszBinFile, lpszPortName, lpszPrtName) ? S_OK : E_FAIL;
  745. }
  746. /*++
  747. Name:
  748. PrintUICreateInstance
  749. Description:
  750. wrapper around TPrnPersist_CreateInstance
  751. Arguments:
  752. Return Value:
  753. S_OK on sucsess or OLE error on failure.
  754. --*/
  755. HRESULT PrintUICreateInstance(REFIID riid, void **ppv)
  756. {
  757. return TPrnPersist_CreateInstance(riid, ppv);
  758. }
  759. #ifdef __cplusplus
  760. }
  761. #endif