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.

399 lines
7.0 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1998
  3. All rights reserved.
  4. Module Name:
  5. data.cxx
  6. Abstract:
  7. Holds VData functions.
  8. Currently hold static pNew function that determines which concrete
  9. VData class should be instantiated (determined at runtime).
  10. Also holds MNotifyWork virtual definition.
  11. Author:
  12. Albert Ting (AlbertT) 12-Jun-1995
  13. Revision History:
  14. --*/
  15. #include "precomp.hxx"
  16. #pragma hdrstop
  17. STATEVAR
  18. VData::
  19. svNew(
  20. MDataClient* pDataClient,
  21. STATEVAR StateVar,
  22. VData*& pData
  23. )
  24. /*++
  25. Routine Description:
  26. The VData tree uses the abstract class factory idiom. Clients
  27. create a class derived from MDataClient which support pNewNotify
  28. and pNewRefresh. Both these virtual fuctions create derived objects
  29. that are stored as base pointers in this class.
  30. This specific creation of derived VData classes without polluting
  31. VData or it's internals with switch statements or flags to determine
  32. which concrete class should be used.
  33. Create the data object. This will first create a TDataNotify;
  34. if that fails because it's a downlevel server, it will create
  35. a TDataRefresh.
  36. Arguments:
  37. StateVar - Current state of printer.
  38. pDataClient - Interface to data client.
  39. Return Value:
  40. VData* on success, NULL on failure.
  41. StateVar - State of printer, either:
  42. kExecReopen | kExecDelay if everything failed or,
  43. 0 if everything succeded (refresh already done).
  44. --*/
  45. {
  46. STATEVAR StateVarOrg = StateVar;
  47. //
  48. // First attempt an uplevel connection by instantiating a
  49. // TDataNotify. If that fails, then use downlevel.
  50. //
  51. pData = pDataClient->pNewNotify( pDataClient );
  52. //
  53. // If the object failed to initialize, reopen the printer.
  54. // We don't want to try the downlevel case, since we may have
  55. // failed due to lack of memory.
  56. //
  57. if( !VALID_PTR( pData )){
  58. //
  59. // Error, delay and put error message up.
  60. //
  61. goto Fail;
  62. }
  63. //
  64. // Attempt a refresh if the refresh is successful, then we are
  65. // talking to an uplevel server.
  66. //
  67. StateVar = pData->svNotifyStart( StateVar );
  68. //
  69. // If it's an access denied, then we can't open the printer.
  70. // (The open may succeed because of the spooler's caching.)
  71. //
  72. if( StateVar & TPrinter::kExecDelay &&
  73. GetLastError() == ERROR_ACCESS_DENIED ){
  74. return StateVar;
  75. }
  76. //
  77. // If a Reopen was not requested, continue trying to use it.
  78. //
  79. if( !( StateVar & TPrinter::kExecReopen )){
  80. StateVar = pData->svRefresh( StateVar );
  81. //
  82. // If a Reopen was not requested, then we succeeded and we can
  83. // use the newly created pData.
  84. //
  85. if( !( StateVar & TPrinter::kExecReopen )){
  86. return StateVar;
  87. }
  88. }
  89. //
  90. // The uplevel case failed; now assume it is downlevel and
  91. // create a TDataRefresh.
  92. //
  93. StateVar = StateVarOrg;
  94. //
  95. // Close notification and delete the notification.
  96. //
  97. pData->svNotifyEnd( StateVar );
  98. delete pData;
  99. pData = pDataClient->pNewRefresh( pDataClient );
  100. if( !VALID_PTR( pData )){
  101. goto Fail;
  102. }
  103. return pData->svNotifyStart( StateVar );
  104. Fail:
  105. delete pData;
  106. pData = NULL;
  107. return StateVar | TPrinter::kExecReopen | TPrinter::kExecDelay;
  108. }
  109. VOID
  110. VData::
  111. vDelete(
  112. VOID
  113. )
  114. /*++
  115. Routine Description:
  116. Delete the pData. We create a separate utility function to mirror
  117. svNew.
  118. Arguments:
  119. Return Value:
  120. --*/
  121. {
  122. SPLASSERT( !m_shNotify );
  123. delete this;
  124. }
  125. /********************************************************************
  126. VData ctr, dtr.
  127. ********************************************************************/
  128. VData::
  129. VData(
  130. MDataClient* pDataClient,
  131. PFIELD_TABLE pFieldTable
  132. ) : _pDataClient( pDataClient ),
  133. _pFieldTable( pFieldTable )
  134. {
  135. SPLASSERT( _pFieldTable );
  136. SPLASSERT( _pDataClient );
  137. UIGuard._cItems = 0;
  138. TStatusB bStatus;
  139. bStatus DBGCHK = pDataClient->bGetPrintLib(_pPrintLib);
  140. if( !bStatus ){
  141. DBGMSG( DBG_WARN, ( "VData::ctor bGetSingleton::ctor Failed %d\n", GetLastError( )));
  142. }
  143. }
  144. VData::
  145. ~VData(
  146. VOID
  147. )
  148. /*++
  149. Routine Description:
  150. Destroy the VData object.
  151. Arguments:
  152. Return Value:
  153. --*/
  154. {
  155. //
  156. // Remove all items from the UI now that we are about to delete
  157. // pData. We have shut down the notifications and cleared the
  158. // UI windows message queue, so this is safe.
  159. //
  160. _pDataClient->vContainerChanged( kContainerClearItems, kInfoNull );
  161. }
  162. BOOL
  163. VData::
  164. bValid(
  165. VOID
  166. ) const
  167. {
  168. //
  169. // Valid _pPrintLib pointer is our valid check.
  170. //
  171. return _pPrintLib.pGet() != NULL;
  172. }
  173. /********************************************************************
  174. Add and retrieve hBlocks.
  175. ********************************************************************/
  176. VData::
  177. TBlock::
  178. TBlock(
  179. IN DWORD dwParam1,
  180. IN DWORD dwParam2,
  181. IN HANDLE hBlock
  182. ) : _dwParam1( dwParam1 ), _dwParam2( dwParam2 ), _hBlock( hBlock )
  183. {
  184. }
  185. VData::
  186. TBlock::
  187. ~TBlock(
  188. VOID
  189. )
  190. {
  191. }
  192. VOID
  193. VData::
  194. vBlockAdd(
  195. IN DWORD dwParam1,
  196. IN DWORD dwParam2,
  197. IN HANDLE hBlock ADOPT
  198. )
  199. /*++
  200. Routine Description:
  201. Add block to linked list.
  202. Arguments:
  203. dwParam1 - dwParam to add.
  204. dwParam2 - dwParam to add.
  205. hBlock - hBlock to add.
  206. Return Value:
  207. --*/
  208. {
  209. TBlock* pBlock = new TBlock( dwParam1, dwParam2, hBlock );
  210. if( !VALID_PTR( pBlock )){
  211. delete pBlock;
  212. INFO Info;
  213. Info.dwData = TPrinter::kExecRefresh;
  214. //
  215. // Request a refresh with a delay, then delete the adopted hBlock.
  216. //
  217. _pDataClient->vContainerChanged( kContainerStateVar, Info );
  218. vBlockDelete( hBlock );
  219. return;
  220. }
  221. {
  222. CCSLock::Locker CSL( csData( ));
  223. Block_vAppend( pBlock );
  224. }
  225. //
  226. // Notify UI thread that there is more data.
  227. //
  228. _pDataClient->vContainerChanged( kContainerNewBlock, kInfoNull );
  229. }
  230. VOID
  231. VData::
  232. vBlockProcess(
  233. VOID
  234. )
  235. /*++
  236. Routine Description:
  237. Retrieve a block from our linked list. Only called from UI thread,
  238. or within a protective critical section.
  239. Arguments:
  240. Return Value:
  241. --*/
  242. {
  243. TBlock* pBlock;
  244. for( ; ; ){
  245. {
  246. CCSLock::Locker CSL( csData( ));
  247. pBlock = Block_pHead();
  248. if( pBlock ){
  249. Block_vDelink( pBlock );
  250. }
  251. }
  252. if( !pBlock ){
  253. break;
  254. }
  255. vBlockProcessImp( pBlock->_dwParam1,
  256. pBlock->_dwParam2,
  257. pBlock->_hBlock );
  258. delete pBlock;
  259. }
  260. }
  261. /********************************************************************
  262. MNotifyWork virtual functions.
  263. ********************************************************************/
  264. HANDLE
  265. VData::
  266. hEvent(
  267. VOID
  268. ) const
  269. /*++
  270. Routine Description:
  271. Virtual function to return the hNotify object back to MNotifyWork.
  272. Arguments:
  273. Return Value:
  274. --*/
  275. {
  276. return m_shNotify;
  277. }