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.

1443 lines
31 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. All rights reserved.
  4. Module Name:
  5. data.hxx
  6. Abstract:
  7. Queries the printer for Item data.
  8. Author:
  9. Albert Ting (AlbertT) 27-Jan-1995
  10. Revision History:
  11. --*/
  12. #ifndef _DATA_HXX
  13. #define _DATA_HXX
  14. class VDataNotify;
  15. class VDataRefresh;
  16. class MDataClient;
  17. class TPrintLib;
  18. /********************************************************************
  19. The FieldTable translates a DATA_INDEX index into a field value.
  20. The DATA_INDEX is used in GetInfo.
  21. ********************************************************************/
  22. typedef struct FIELD_TABLE {
  23. UINT cFields;
  24. PFIELD pFields;
  25. } *PFIELD_TABLE;
  26. /********************************************************************
  27. ITEM and PRINTER changes.
  28. When a change occurs, a callback is called with a ITEM_CHANGE or
  29. CONTAINER_CHANGE parameter that indicates how the object changed.
  30. ********************************************************************/
  31. enum ITEM_CHANGE {
  32. kItemNull, // Prevent 0 message value.
  33. kItemCreate, // Item being created.
  34. kItemDelete, // Item being deleted.
  35. kItemPosition, // Item position changed.
  36. kItemInfo, // Affects list/icon and report view.
  37. kItemAttributes, // Affects report view only (not list/icon view).
  38. kItemName, // Item name changed.
  39. kItemSecurity, // Item security change.
  40. };
  41. enum CONTAINER_CHANGE {
  42. kContainerNull,
  43. kContainerConnectStatus, // Connect state changed -> add to title bar
  44. kContainerErrorStatus, // Error occured -> add to status bar
  45. kContainerServerName, // Server name changed
  46. kContainerName, // Container name changed
  47. kContainerStatus, // Container status changed -> add to title bar
  48. kContainerAttributes, // Attributes changed
  49. kContainerStateVar, // StateVar additions
  50. kContainerNewBlock, // New data block available
  51. /********************************************************************
  52. The following are synchronous, but may be called from
  53. any thread.
  54. ********************************************************************/
  55. //
  56. // UI should release all references to VData data. This occurs
  57. // either at the start of a refresh, or when VData is being deleted.
  58. // Called from any thread.
  59. // INFO = VOID
  60. //
  61. kContainerClearItems,
  62. //
  63. // Refresh data has been completely sent to UI thread; called from
  64. // UI thread only.
  65. // INFO = VOID
  66. //
  67. kContainerRefreshComplete,
  68. //
  69. // Reload based on new hBlock; called from UI thread only.
  70. // INFO = cItems.
  71. //
  72. // A drastic change has occured to the datastore. The data object
  73. // now contains INFO new items. During this call, the client
  74. // should release all pointer references to old objects and
  75. // reload the UI with the new objects.
  76. //
  77. // It will get a RefreshComplete when the reload has completed.
  78. //
  79. kContainerReloadItems
  80. };
  81. /********************************************************************
  82. Connect status codes and map.
  83. Note: if you change or move any of the CONNECT_STATUS k* contants,
  84. you must update the CONNECT_STATUS_MAP. Used by queue.cxx code.
  85. ********************************************************************/
  86. enum CONNECT_STATUS {
  87. kConnectStatusNull = 0,
  88. kConnectStatusInvalidPrinterName,
  89. kConnectStatusAccessDenied,
  90. kConnectStatusOpenError,
  91. kConnectStatusOpen,
  92. kConnectStatusInitialize,
  93. kConnectStatusRefresh,
  94. kConnectStatusCommand,
  95. kConnectStatusPoll
  96. };
  97. #define CONNECT_STATUS_MAP { \
  98. 0, \
  99. IDS_SB_INVALID_PRINTER_NAME, \
  100. IDS_SB_ACCESS_DENIED, \
  101. IDS_SB_OPEN_ERROR, \
  102. IDS_SB_OPEN, \
  103. IDS_SB_INITIALIZE, \
  104. IDS_SB_REFRESH, \
  105. IDS_SB_COMMAND, \
  106. IDS_SB_POLL \
  107. }
  108. typedef HANDLE HITEM, *PHITEM; // Opaque packet holding job item info.
  109. typedef UINT DATA_INDEX, *PDATA_INDEX; // Selector for printer data.
  110. /********************************************************************
  111. MDataClient
  112. User of Data structure supports this interface. Both the
  113. Queue and Printer support this interface.
  114. The support could be placed in Queue only, allowing Data to
  115. talk through Printer.Queue, but the lifetime of Queue is managed
  116. through Printer, so we must still talk through printer.
  117. (The lifetime of Printer is identical to Data.)
  118. ********************************************************************/
  119. class VInfoClient {
  120. public:
  121. /********************************************************************
  122. Callbacks for VData
  123. vContainerChanged( ContainerChange, Info )
  124. Indicates something Container wide has changed.
  125. May be called from UI, Notify, or Worker thread.
  126. vItemChanged( ItemChange, hItem, Info, InfoNew );
  127. Indicates that a single Item has changed and needs to be
  128. refreshed.
  129. Only called from UI thread.
  130. ********************************************************************/
  131. //
  132. // Something printer wide has changed. Notify the UI thread.
  133. // This call must return quickly, and can not use any
  134. // SendMessages since it acquires the printer critical section.
  135. //
  136. virtual
  137. VOID
  138. vContainerChanged(
  139. CONTAINER_CHANGE ContainerChange,
  140. INFO Info
  141. ) = 0;
  142. //
  143. // A single Item has changed (or possibly moved). Notify the
  144. // UI that it needs to refresh. Always called from UI thread.
  145. //
  146. virtual
  147. VOID
  148. vItemChanged(
  149. ITEM_CHANGE ItemChange,
  150. HITEM hItem,
  151. INFO Info,
  152. INFO InfoNew
  153. ) = 0;
  154. /********************************************************************
  155. Saving and restoring selections.
  156. ********************************************************************/
  157. //
  158. // When all Items change, the client needs to save its solections,
  159. // refresh, then restore selections. After we call vContainerChanged
  160. // with new Items, we restore the selections.
  161. //
  162. // These calls are _non-reentrant_ since they are called from the
  163. // UI thread.
  164. //
  165. virtual
  166. VOID
  167. vSaveSelections(
  168. VOID
  169. ) = 0;
  170. virtual
  171. VOID
  172. vRestoreSelections(
  173. VOID
  174. ) = 0;
  175. /********************************************************************
  176. Creation of TData{Refresh/Notify}.
  177. ********************************************************************/
  178. virtual
  179. VDataNotify*
  180. pNewNotify(
  181. MDataClient* pDataClient
  182. ) const = 0;
  183. virtual
  184. VDataRefresh*
  185. pNewRefresh(
  186. MDataClient* pDataClient
  187. ) const = 0;
  188. };
  189. class MDataClient : public VInfoClient {
  190. SIGNATURE( 'dtc' )
  191. public:
  192. virtual
  193. LPTSTR
  194. pszServerName(
  195. LPTSTR pszServerBuffer
  196. ) const = 0;
  197. virtual
  198. LPTSTR
  199. pszPrinterName(
  200. LPTSTR pszServerBuffer
  201. ) const = 0;
  202. virtual
  203. HANDLE
  204. hPrinter(
  205. VOID
  206. ) const = 0;
  207. virtual
  208. HANDLE
  209. hPrinterNew(
  210. VOID
  211. ) const = 0;
  212. virtual
  213. BOOL
  214. bGetPrintLib(
  215. TRefLock<TPrintLib> &refLock
  216. ) const = 0;
  217. };
  218. /********************************************************************
  219. VData provides an abstraction layer for retrieving data and
  220. notifications from a printer. The TPrinter object gets the
  221. hPrinter and hEvent, then allows VData to reference them.
  222. The state of the notification is managed through the following
  223. worker functions:
  224. svStart - Begins the notification
  225. svEnd - Ends the notification
  226. svRefresh - Refreshs data about the connection
  227. These worker functions return a STATEVAR. The printer/
  228. notification is managed as a simple state machine. When
  229. a call fails, the StateVar indicates what should happen
  230. next (it is not intended to return error code information).
  231. The VData will retrieve a Item buffer using GetItem. To retrieve
  232. specific field data about a Item (such as page count, time
  233. submitted, etc.), call GetInfo with the field index.
  234. GetItem - Gets an hItem based on Item order index.
  235. GetInfo - Gets info about a particular hItem.
  236. GetId - Gets Item id about a particular hItem.
  237. GetNaturalIndex - Gets the natural index of a ItemId.
  238. For example,
  239. hItem = pData->GetItem( NaturalIndex );
  240. if( hItem ){
  241. Info = GetInfo( hItem, DataIndexForName );
  242. }
  243. if( Info.pszData ){
  244. OutputDebugString( Info.pszData );
  245. }
  246. The VData* type _must_ call vRefreshComplete (inherited from
  247. VData*) as soon as a refresh has occurred, but before it
  248. re-initializes the notification scheme. This allows the client
  249. to know the boundary between pre-refresh notifications and
  250. post-refresh.
  251. ********************************************************************/
  252. class VData : public MNotifyWork {
  253. SIGNATURE( 'dtv' )
  254. public:
  255. CAutoHandlePrinterNotify m_shNotify;
  256. /********************************************************************
  257. Creation and deletion should be handled from pNew and
  258. vDelete rather than the regular new and delete, since
  259. we create a derived class that is determined at runtime.
  260. ********************************************************************/
  261. static
  262. STATEVAR
  263. svNew(
  264. IN MDataClient* pDataClient,
  265. IN STATEVAR StateVar,
  266. OUT VData*& pData
  267. );
  268. VOID
  269. vDelete(
  270. VOID
  271. );
  272. BOOL
  273. bValid(
  274. VOID
  275. ) const;
  276. COUNT
  277. cItems(
  278. VOID
  279. ) const
  280. {
  281. return UIGuard._cItems;
  282. }
  283. /********************************************************************
  284. Data retrievers: called from UI thread.
  285. ********************************************************************/
  286. virtual
  287. HITEM
  288. GetItem(
  289. NATURAL_INDEX NaturalIndex
  290. ) const = 0;
  291. virtual
  292. HITEM
  293. GetNextItem(
  294. HITEM hItem
  295. ) const = 0;
  296. virtual
  297. INFO
  298. GetInfo(
  299. HITEM hItem,
  300. DATA_INDEX DataIndex
  301. ) const = 0;
  302. virtual
  303. IDENT
  304. GetId(
  305. HITEM hItem
  306. ) const = 0;
  307. virtual
  308. NATURAL_INDEX
  309. GetNaturalIndex(
  310. IDENT id,
  311. PHITEM phItem
  312. ) const = 0;
  313. /********************************************************************
  314. Item block manipulators.
  315. vBlockProcess - A block that has been given to the client via
  316. vBlockAdd should now be consumed by calling vBlockProcess.
  317. ********************************************************************/
  318. VOID
  319. vBlockProcess(
  320. VOID
  321. );
  322. /********************************************************************
  323. Executes in worker threads.
  324. ********************************************************************/
  325. virtual
  326. STATEVAR
  327. svNotifyStart(
  328. STATEVAR StateVar
  329. ) = 0;
  330. virtual
  331. STATEVAR
  332. svNotifyEnd(
  333. STATEVAR StateVar
  334. ) = 0;
  335. virtual
  336. STATEVAR
  337. svRefresh(
  338. STATEVAR StateVar
  339. ) = 0;
  340. protected:
  341. struct UI_GUARD {
  342. COUNT _cItems;
  343. } UIGuard;
  344. class TBlock {
  345. friend VData;
  346. SIGNATURE( 'dabl' )
  347. SAFE_NEW
  348. ALWAYS_VALID
  349. private:
  350. DLINK( TBlock, Block );
  351. DWORD _dwParam1;
  352. DWORD _dwParam2;
  353. HANDLE _hBlock;
  354. TBlock(
  355. DWORD dwParam1,
  356. DWORD dwParam2,
  357. HANDLE hBlock
  358. );
  359. ~TBlock(
  360. VOID
  361. );
  362. };
  363. MDataClient* _pDataClient;
  364. PFIELD_TABLE _pFieldTable;
  365. DLINK_BASE( TBlock, Block, Block );
  366. TRefLock<TPrintLib> _pPrintLib;
  367. VData(
  368. MDataClient* pDataClient,
  369. PFIELD_TABLE pFieldTable
  370. );
  371. virtual
  372. ~VData(
  373. VOID
  374. );
  375. VOID
  376. vBlockAdd(
  377. DWORD dwParam1,
  378. DWORD dwParam2,
  379. HANDLE hBlock
  380. );
  381. virtual
  382. VOID
  383. vBlockDelete(
  384. HANDLE hBlock
  385. ) = 0;
  386. virtual
  387. VOID
  388. vBlockProcessImp(
  389. DWORD dwParam1,
  390. DWORD dwParam2,
  391. HBLOCK hBlock
  392. ) = 0;
  393. private:
  394. //
  395. // Virtual definition for MNotifyWork.
  396. //
  397. HANDLE
  398. hEvent(
  399. VOID
  400. ) const;
  401. static
  402. CCSLock&
  403. csData(
  404. VOID
  405. )
  406. {
  407. return *gpCritSec;
  408. }
  409. };
  410. /********************************************************************
  411. VDataRefresh implements the downlevel version: it receives
  412. a single DWORD value for notifications and completely refreshes
  413. all Items when a change occurs.
  414. ********************************************************************/
  415. class VDataRefresh : public VData {
  416. SIGNATURE( 'dtrv' )
  417. public:
  418. VDataRefresh(
  419. MDataClient* pDataClient,
  420. PFIELD_TABLE pFieldTable,
  421. DWORD fdwWatch
  422. );
  423. ~VDataRefresh(
  424. VOID
  425. );
  426. /********************************************************************
  427. Exported services (statics) for related data refresh functions.
  428. ********************************************************************/
  429. static
  430. BOOL
  431. bEnumJobs(
  432. IN HANDLE hPrinter,
  433. IN DWORD dwLevel,
  434. IN OUT PVOID* ppvBuffer, CHANGE
  435. IN OUT PDWORD pcbBuffer,
  436. OUT PDWORD pcJobs
  437. );
  438. static
  439. BOOL
  440. bEnumPrinters(
  441. IN DWORD dwFlags,
  442. IN LPCTSTR pszServer,
  443. IN DWORD dwLevel,
  444. IN OUT PVOID* ppvBuffer,
  445. IN OUT PDWORD pcbBuffer,
  446. OUT PDWORD pcPrinters
  447. );
  448. static
  449. BOOL
  450. bEnumDrivers(
  451. IN LPCTSTR pszServer,
  452. IN LPCTSTR pszEnvironment,
  453. IN DWORD dwLevel,
  454. IN OUT PVOID *ppvBuffer, CHANGE
  455. IN OUT PDWORD pcbBuffer,
  456. OUT PDWORD pcDrivers
  457. );
  458. static
  459. BOOL
  460. bGetPrinter(
  461. IN HANDLE hPrinter,
  462. IN DWORD dwLevel,
  463. IN OUT PVOID* ppvBuffer,
  464. IN OUT PDWORD pcbBuffer
  465. );
  466. static
  467. BOOL
  468. bGetJob(
  469. IN HANDLE hPrinter,
  470. IN DWORD dwJobId,
  471. IN DWORD dwLevel,
  472. IN OUT PVOID* ppvBuffer,
  473. IN OUT PDWORD pcbBuffer
  474. );
  475. static
  476. BOOL
  477. bGetPrinterDriver(
  478. IN HANDLE hPrinter,
  479. IN LPCTSTR pszEnvironment,
  480. IN DWORD dwLevel,
  481. IN OUT PVOID* ppvBuffer,
  482. IN OUT PDWORD pcbBuffer
  483. );
  484. static
  485. BOOL
  486. bGetDefaultDevMode(
  487. IN HANDLE hPrinter,
  488. IN LPCTSTR pszPrinterName,
  489. OUT PDEVMODE *ppDevMode,
  490. IN BOOL bFillWithDefault = FALSE
  491. );
  492. static
  493. BOOL
  494. bEnumPorts(
  495. IN LPCTSTR pszServer,
  496. IN DWORD dwLevel,
  497. IN OUT PVOID *ppvPorts, CHANGE
  498. IN OUT PDWORD pcbPorts,
  499. OUT PDWORD pcPorts
  500. );
  501. static
  502. BOOL
  503. bEnumPortsMaxLevel(
  504. IN LPCTSTR pszServer,
  505. IN PDWORD pdwLevel,
  506. IN OUT PVOID *ppvPorts, CHANGE
  507. IN OUT PDWORD pcbPorts,
  508. OUT PDWORD pcPorts
  509. );
  510. static
  511. BOOL
  512. bEnumMonitors(
  513. IN LPCTSTR pszServer,
  514. IN DWORD dwLevel,
  515. IN OUT PVOID *ppvMonitors, CHANGE
  516. IN OUT PDWORD pcbMonitors,
  517. OUT PDWORD pcMonitors
  518. );
  519. /********************************************************************
  520. Executes in worker threads.
  521. ********************************************************************/
  522. STATEVAR
  523. svNotifyStart(
  524. STATEVAR StateVar
  525. );
  526. STATEVAR
  527. svNotifyEnd(
  528. STATEVAR StateVar
  529. );
  530. protected:
  531. enum _CONSTANTS {
  532. kInitialJobHint = 0x400,
  533. kInitialPrinterHint = 0x400,
  534. kInitialDriverHint = 0x400,
  535. kExtraJobBufferBytes = 0x80,
  536. kExtraPrinterBufferBytes = 0x80,
  537. kMaxPrinterInfo2 = 0x1000,
  538. kInitialDriverInfo3Hint = 0x400,
  539. kEnumPortsHint = 0x1000,
  540. kEnumMonitorsHint = 0x400,
  541. };
  542. private:
  543. DWORD _fdwWatch;
  544. struct EXEC_GUARD {
  545. //
  546. // We need a separate hPrinter for notifications since downlevel
  547. // print providers that don't support F*PCN will default to
  548. // WaitForPrinterChange. The WPC call is synchronous and
  549. // may take a long time (10 sec->1 min). Since RPC synchronizes
  550. // handle access, this make the Get/Enum call very slow.
  551. //
  552. VAR( HANDLE, hPrinterWait );
  553. } ExecGuard;
  554. /********************************************************************
  555. Notify support (callbacks when object is notified).
  556. ********************************************************************/
  557. VOID
  558. vProcessNotifyWork(
  559. TNotify* pNotify
  560. );
  561. };
  562. /********************************************************************
  563. There are two flavors: Jobs and Printers
  564. TDataRJob: Handles print queues (item unit = print job).
  565. TDataRPrinter: Handles server view/print folder (item = printer)
  566. ********************************************************************/
  567. class TDataRJob : public VDataRefresh {
  568. SIGNATURE( 'dtrj' )
  569. public:
  570. enum CONSTANTS {
  571. kfdwWatch = PRINTER_CHANGE_JOB | PRINTER_CHANGE_PRINTER
  572. };
  573. TDataRJob(
  574. MDataClient* pDataClient
  575. );
  576. ~TDataRJob(
  577. VOID
  578. );
  579. /********************************************************************
  580. Data retrievers.
  581. ********************************************************************/
  582. HITEM
  583. GetItem(
  584. NATURAL_INDEX NaturalIndex
  585. ) const;
  586. HITEM
  587. GetNextItem(
  588. HITEM hItem
  589. ) const;
  590. INFO
  591. GetInfo(
  592. HITEM hItem,
  593. DATA_INDEX DataIndex
  594. ) const;
  595. IDENT
  596. GetId(
  597. HITEM hItem
  598. ) const;
  599. NATURAL_INDEX
  600. GetNaturalIndex(
  601. IDENT id,
  602. PHITEM phItem
  603. ) const;
  604. /********************************************************************
  605. Block manipulators.
  606. ********************************************************************/
  607. VOID
  608. vBlockDelete(
  609. HBLOCK hBlock
  610. );
  611. VOID
  612. vBlockProcessImp(
  613. DWORD dwParam1,
  614. DWORD dwParam2,
  615. HBLOCK hBlock
  616. );
  617. /********************************************************************
  618. Executes in worker threads.
  619. ********************************************************************/
  620. STATEVAR
  621. svRefresh(
  622. STATEVAR StateVar
  623. );
  624. private:
  625. //
  626. // All fields here are guarded by ExecGuard.
  627. //
  628. struct EXEC_GUARD {
  629. VAR( COUNTB, cbJobHint );
  630. } ExecGuard;
  631. //
  632. // All fields here are accessed only from the UI thread.
  633. //
  634. struct UI_GUARD {
  635. VAR( PJOB_INFO_2, pJobs );
  636. } UIGuard;
  637. };
  638. class TDataRPrinter: public VDataRefresh {
  639. SIGNATURE( 'dtrp' )
  640. public:
  641. //
  642. // Keep it simple: we could just watch for PRINTER_CHANGE_ADD_PRINTER
  643. // and PRINTER_CHANGE_DELETE_PRINTER in the non-details view,
  644. // but that only helps us w/ NT 3.1, 3.5 servers. (3.51 support
  645. // FFPCN, and lm/wfw/win95 trigger full notifications anyway).
  646. //
  647. enum CONSTANTS {
  648. kfdwWatch = PRINTER_CHANGE_PRINTER
  649. };
  650. TDataRPrinter(
  651. MDataClient* pDataClient
  652. );
  653. ~TDataRPrinter(
  654. VOID
  655. );
  656. static
  657. BOOL
  658. bSinglePrinter(
  659. LPCTSTR pszDataSource
  660. );
  661. /********************************************************************
  662. Data retrievers.
  663. ********************************************************************/
  664. HITEM
  665. GetItem(
  666. NATURAL_INDEX NaturalIndex
  667. ) const;
  668. HITEM
  669. GetNextItem(
  670. HITEM hItem
  671. ) const;
  672. INFO
  673. GetInfo(
  674. HITEM hItem,
  675. DATA_INDEX DataIndex
  676. ) const;
  677. IDENT
  678. GetId(
  679. HITEM hItem
  680. ) const;
  681. NATURAL_INDEX
  682. GetNaturalIndex(
  683. IDENT id,
  684. PHITEM phItem
  685. ) const;
  686. /********************************************************************
  687. Block manipulators.
  688. ********************************************************************/
  689. VOID
  690. vBlockDelete(
  691. HBLOCK hBlock
  692. );
  693. VOID
  694. vBlockProcessImp(
  695. DWORD dwParam1,
  696. DWORD dwParam2,
  697. HBLOCK hBlock
  698. );
  699. /********************************************************************
  700. Executes in worker threads.
  701. ********************************************************************/
  702. STATEVAR
  703. svRefresh(
  704. STATEVAR StateVar
  705. );
  706. private:
  707. //
  708. // Used to determine whether EnumPrinters or GetPrinter
  709. // should be called.
  710. //
  711. BOOL _bSinglePrinter;
  712. //
  713. // All fields here are guarded by ExecGuard.
  714. //
  715. struct EXEC_GUARD {
  716. VAR( COUNTB, cbPrinterHint );
  717. } ExecGuard;
  718. //
  719. // All fields here are accessed only from the UI thread.
  720. //
  721. struct UI_GUARD {
  722. VAR( PPRINTER_INFO_2, pPrinters );
  723. } UIGuard;
  724. };
  725. /********************************************************************
  726. VDataNotify implements the uplevel version: with eacph
  727. notification, it receives information about the change and
  728. doesn't need to refresh the entire buffer.
  729. ********************************************************************/
  730. class VDataNotify : public VData {
  731. SIGNATURE( 'dtnv' )
  732. public:
  733. VDataNotify(
  734. MDataClient* pDataClient,
  735. PFIELD_TABLE pFieldTable,
  736. DWORD TypeItem
  737. );
  738. ~VDataNotify(
  739. VOID
  740. );
  741. class TItemData {
  742. public:
  743. VAR( IDENT, Id );
  744. VAR( VDataNotify*, pDataNotify );
  745. DLINK( TItemData, ItemData );
  746. static TItemData*
  747. pNew(
  748. VDataNotify* pDataNotify,
  749. IDENT Id
  750. );
  751. VOID
  752. vDelete(
  753. VOID
  754. );
  755. //
  756. // Must be last, since variable size.
  757. //
  758. INFO _aInfo[1];
  759. private:
  760. //
  761. // Not defined; always use pNew since this isn't a
  762. // first-class class.
  763. //
  764. TItemData();
  765. };
  766. /********************************************************************
  767. Data retrievers.
  768. ********************************************************************/
  769. HITEM
  770. GetItem(
  771. NATURAL_INDEX NaturalIndex
  772. ) const;
  773. HITEM
  774. GetNextItem(
  775. HITEM hItem
  776. ) const;
  777. INFO
  778. GetInfo(
  779. HITEM hItem,
  780. DATA_INDEX DataIndex
  781. ) const;
  782. IDENT
  783. GetId(
  784. HITEM hItem
  785. ) const;
  786. NATURAL_INDEX
  787. GetNaturalIndex(
  788. IDENT id,
  789. PHITEM phItem
  790. ) const;
  791. /********************************************************************
  792. Block manipulators.
  793. ********************************************************************/
  794. VOID
  795. vBlockDelete(
  796. HBLOCK hBlock
  797. );
  798. VOID
  799. vBlockProcessImp(
  800. DWORD dwParam1,
  801. DWORD dwParam2,
  802. HBLOCK hBlock
  803. );
  804. /********************************************************************
  805. Executes in worker threads.
  806. ********************************************************************/
  807. STATEVAR
  808. svNotifyStart(
  809. STATEVAR StateVar
  810. );
  811. STATEVAR
  812. svNotifyEnd(
  813. STATEVAR StateVar
  814. );
  815. STATEVAR
  816. svRefresh(
  817. STATEVAR StateVar
  818. );
  819. protected:
  820. //
  821. // The linked list data structure is not very efficient if we
  822. // continually need to look up Ids. Each data field from the
  823. // notification comes in single pieces (name, size, etc.), but
  824. // they are clumped, so the cache prevents duplicate lookups.
  825. //
  826. // Since we are in the UI thread, we don't have to worry about
  827. // items being deleted while the cache is used.
  828. //
  829. typedef struct CACHE {
  830. TItemData* pItemData;
  831. IDENT Id;
  832. NATURAL_INDEX NaturalIndex;
  833. BOOL bNew;
  834. } PCACHE;
  835. //
  836. // All fields here are accessed only from the UI thread.
  837. //
  838. struct UI_GUARD {
  839. DLINK_BASE( TItemData, ItemData, ItemData );
  840. } UIGuard;
  841. //
  842. // Allow a derived class to override the creation of a new
  843. // pItemData. In the normal case, just call the TItemData->pNew.
  844. //
  845. virtual
  846. TItemData*
  847. pNewItemData(
  848. VDataNotify* pDataNotify,
  849. IDENT Id
  850. )
  851. {
  852. return TItemData::pNew( pDataNotify, Id );
  853. }
  854. /********************************************************************
  855. Standard method of updating a pInfo.
  856. ********************************************************************/
  857. VOID
  858. vUpdateInfoData(
  859. IN const PPRINTER_NOTIFY_INFO_DATA pData,
  860. IN TABLE Table,
  861. IN PINFO pInfo
  862. );
  863. private:
  864. enum PROCESS_TYPE {
  865. kProcessRefresh,
  866. kProcessIncremental
  867. };
  868. //
  869. // Indicates the *_NOTIFY_TYPE that applies to items.
  870. //
  871. DWORD _TypeItem;
  872. /********************************************************************
  873. Notify support (callbacks when object is notified).
  874. ********************************************************************/
  875. VOID
  876. vProcessNotifyWork(
  877. TNotify* pNotify
  878. );
  879. virtual
  880. PPRINTER_NOTIFY_OPTIONS
  881. pNotifyOptions(
  882. VOID
  883. ) = 0;
  884. //
  885. // Returns TRUE if item should be deleted.
  886. //
  887. virtual
  888. BOOL
  889. bUpdateInfo(
  890. const PPRINTER_NOTIFY_INFO_DATA pData,
  891. DATA_INDEX DataIndex,
  892. CACHE& Cache
  893. ) = 0;
  894. /*++
  895. Routine Description:
  896. Requests the child update a particular item.
  897. Arguments:
  898. pData - New data about the item stored in Cache.
  899. DataIndex - DataIndex that pData refers to.
  900. Cache - Cached information about the item, including
  901. pItemData, Id, NaturalIndex, and bNew (indicates whether
  902. the item is a new one or not; set when a new item is
  903. added and for all subsequent notifications that
  904. immediately follow it in the same notification block.
  905. Return Value:
  906. TRUE if item should be deleted, FALSE otherwise.
  907. --*/
  908. /********************************************************************
  909. Private member functions.
  910. ********************************************************************/
  911. TItemData*
  912. GetItem(
  913. IDENT Id,
  914. NATURAL_INDEX* pNaturalIndex
  915. );
  916. BOOL
  917. bItemProcess(
  918. const PPRINTER_NOTIFY_INFO_DATA pData,
  919. CACHE& Cache
  920. );
  921. VOID
  922. vContainerProcess(
  923. const PPRINTER_NOTIFY_INFO_DATA pData
  924. );
  925. VOID
  926. vDeleteAllItemData(
  927. VOID
  928. );
  929. #if DBG
  930. VOID
  931. vDbgOutputInfo(
  932. const PPRINTER_NOTIFY_INFO pInfo
  933. );
  934. #endif
  935. friend VDataNotify::TItemData;
  936. };
  937. /********************************************************************
  938. DataNotify tables.
  939. Define the visible columns in the UI, and also the extra fields
  940. that follow it.
  941. We maintain two conceptual arrays, and therefore two index types
  942. (one for each array):
  943. COLUMN: Array of Fields corresponding to the UI columns.
  944. DATA_INDEX: Array of Fields corresponding to a Item's data
  945. structure.
  946. The DATA_INDEX array is a superset of the COLUMN array: i.e., for all
  947. valid COLUMN, aFieldColumn[COLUMN] == aFieldIndex[COLUMN].
  948. The entire next block is highly self-dependent. Adding/deleting,
  949. or changing a field must be done very carefully.
  950. These definitions are in the classes next to the constants.
  951. ********************************************************************/
  952. /********************************************************************
  953. There are two flavors: Jobs and Printers
  954. TDataRJob: Handles print queues (job unit = print job).
  955. TDataRPrinter: Handles server view/print folder (job unit = printer)
  956. ********************************************************************/
  957. class TDataNJob : public VDataNotify {
  958. friend TDataRJob;
  959. SIGNATURE( 'dtnj' )
  960. public:
  961. enum CONSTANTS {
  962. kFieldOtherSize = 4,
  963. kTypeSize = 2,
  964. #define JOB_COLUMN_FIELDS \
  965. JOB_NOTIFY_FIELD_DOCUMENT, \
  966. JOB_NOTIFY_FIELD_STATUS_STRING, \
  967. JOB_NOTIFY_FIELD_USER_NAME, \
  968. JOB_NOTIFY_FIELD_TOTAL_PAGES, \
  969. JOB_NOTIFY_FIELD_TOTAL_BYTES, \
  970. JOB_NOTIFY_FIELD_SUBMITTED, \
  971. JOB_NOTIFY_FIELD_PORT_NAME
  972. kColumnFieldsSize = 7,
  973. #define JOB_INDEX_EXTRA_FIELDS \
  974. JOB_NOTIFY_FIELD_PAGES_PRINTED, \
  975. JOB_NOTIFY_FIELD_BYTES_PRINTED, \
  976. JOB_NOTIFY_FIELD_POSITION, \
  977. JOB_NOTIFY_FIELD_STATUS
  978. kIndexExtraFieldsSize = 4,
  979. kIndexPagesPrinted = kColumnFieldsSize,
  980. kIndexBytesPrinted = kColumnFieldsSize + 1,
  981. kIndexStatus = kColumnFieldsSize + 3,
  982. kFieldTableSize = kColumnFieldsSize +
  983. kIndexExtraFieldsSize
  984. };
  985. TDataNJob(
  986. MDataClient* pDataClient
  987. );
  988. ~TDataNJob(
  989. VOID
  990. );
  991. private:
  992. static PRINTER_NOTIFY_OPTIONS gNotifyOptions;
  993. static FIELD gaFieldOther[kFieldOtherSize];
  994. static PRINTER_NOTIFY_OPTIONS_TYPE gaNotifyOptionsType[kTypeSize];
  995. static FIELD_TABLE gFieldTable;
  996. static FIELD gaFields[kFieldTableSize+1];
  997. PPRINTER_NOTIFY_OPTIONS
  998. pNotifyOptions(
  999. VOID
  1000. )
  1001. {
  1002. return &gNotifyOptions;
  1003. }
  1004. BOOL
  1005. bUpdateInfo(
  1006. const PPRINTER_NOTIFY_INFO_DATA pData,
  1007. DATA_INDEX DataIndex,
  1008. CACHE& Cache
  1009. );
  1010. };
  1011. class TDataNPrinter: public VDataNotify {
  1012. friend TDataRPrinter;
  1013. SIGNATURE( 'dtnp' )
  1014. public:
  1015. enum CONSTANTS {
  1016. kTypeSize = 1,
  1017. #define PRINTER_COLUMN_FIELDS \
  1018. PRINTER_NOTIFY_FIELD_PRINTER_NAME, \
  1019. PRINTER_NOTIFY_FIELD_CJOBS, \
  1020. PRINTER_NOTIFY_FIELD_STATUS, \
  1021. PRINTER_NOTIFY_FIELD_COMMENT, \
  1022. PRINTER_NOTIFY_FIELD_LOCATION, \
  1023. PRINTER_NOTIFY_FIELD_DRIVER_NAME, \
  1024. PRINTER_NOTIFY_FIELD_PORT_NAME, \
  1025. PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
  1026. kIndexPrinterName = 0,
  1027. kIndexCJobs,
  1028. kIndexStatus,
  1029. kIndexComment,
  1030. kIndexLocation,
  1031. kIndexModel,
  1032. kIndexPort,
  1033. kIndexSecurity,
  1034. kColumnFieldsSize = 8,
  1035. #define PRINTER_INDEX_EXTRA_FIELDS \
  1036. PRINTER_NOTIFY_FIELD_ATTRIBUTES
  1037. kIndexExtraFieldsSize = 1,
  1038. kIndexAttributes = kColumnFieldsSize,
  1039. kFieldTableSize = kColumnFieldsSize +
  1040. kIndexExtraFieldsSize
  1041. };
  1042. TDataNPrinter(
  1043. MDataClient* pDataClient
  1044. );
  1045. ~TDataNPrinter(
  1046. VOID
  1047. );
  1048. private:
  1049. static PRINTER_NOTIFY_OPTIONS gNotifyOptions;
  1050. static PRINTER_NOTIFY_OPTIONS_TYPE gaNotifyOptionsType[kTypeSize];
  1051. static FIELD_TABLE gFieldTable;
  1052. static FIELD gaFields[kFieldTableSize+1];
  1053. TItemData*
  1054. pNewItemData(
  1055. VDataNotify* pDataNotify,
  1056. IDENT Id
  1057. );
  1058. PPRINTER_NOTIFY_OPTIONS
  1059. pNotifyOptions(
  1060. VOID
  1061. )
  1062. {
  1063. return &gNotifyOptions;
  1064. }
  1065. BOOL
  1066. bUpdateInfo(
  1067. const PPRINTER_NOTIFY_INFO_DATA pData,
  1068. DATA_INDEX DataIndex,
  1069. CACHE& Cache
  1070. );
  1071. };
  1072. #endif // ndef _DATA_HXX