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.

1011 lines
22 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. cenumjob.cxx
  5. Abstract:
  6. Contains methods for implementing the Enumeration of print jobs on a
  7. printer. Has methods for the CWinNTPrintJobsCollection object
  8. as well as the CWinNTJobsEnumVar object.
  9. Author:
  10. Ram Viswanathan (ramv) 11-28-95
  11. Revision History:
  12. --*/
  13. #include "winnt.hxx"
  14. #pragma hdrstop
  15. CWinNTPrintJobsCollection::CWinNTPrintJobsCollection()
  16. {
  17. _pDispMgr = NULL;
  18. _pCJobsEnumVar = NULL;
  19. ENLIST_TRACKING(CWinNTPrintJobsCollection);
  20. }
  21. CWinNTPrintJobsCollection::~CWinNTPrintJobsCollection()
  22. {
  23. DWORD fStatus;
  24. //
  25. // close the printer and destroy sub objects
  26. //
  27. if(_pszADsPrinterPath){
  28. FreeADsStr(_pszADsPrinterPath);
  29. }
  30. if(_pszPrinterName){
  31. FreeADsStr(_pszPrinterName);
  32. }
  33. if (_hPrinter){
  34. fStatus = ClosePrinter(_hPrinter);
  35. }
  36. delete _pDispMgr;
  37. }
  38. HRESULT
  39. CWinNTPrintJobsCollection::Create(LPWSTR pszADsPrinterPath,
  40. CWinNTCredentials& Credentials,
  41. CWinNTPrintJobsCollection
  42. ** ppCWinNTPrintJobsCollection )
  43. {
  44. BOOL fStatus = FALSE, LastError;
  45. HANDLE hPrinter = NULL;
  46. PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE| READ_CONTROL};
  47. HRESULT hr;
  48. CWinNTPrintJobsCollection *pCWinNTJobsCollection = NULL;
  49. POBJECTINFO pObjectInfo = NULL;
  50. TCHAR szUncPrinterName[MAX_PATH];
  51. //
  52. // create the jobs collection object
  53. //
  54. pCWinNTJobsCollection = new CWinNTPrintJobsCollection();
  55. if(pCWinNTJobsCollection == NULL) {
  56. hr = E_OUTOFMEMORY;
  57. goto error;
  58. }
  59. hr = BuildObjectInfo(pszADsPrinterPath,
  60. &pObjectInfo
  61. );
  62. BAIL_ON_FAILURE(hr);
  63. pCWinNTJobsCollection->_Credentials = Credentials;
  64. hr = pCWinNTJobsCollection->_Credentials.RefServer(
  65. pObjectInfo->ComponentArray[1]);
  66. BAIL_ON_FAILURE(hr);
  67. hr = PrinterNameFromObjectInfo(pObjectInfo,
  68. szUncPrinterName
  69. );
  70. BAIL_ON_FAILURE(hr);
  71. pCWinNTJobsCollection->_pszPrinterName =
  72. AllocADsStr(szUncPrinterName);
  73. if(!(pCWinNTJobsCollection->_pszPrinterName)){
  74. hr = E_OUTOFMEMORY;
  75. goto error;
  76. }
  77. pCWinNTJobsCollection->_pszADsPrinterPath =
  78. AllocADsStr(pszADsPrinterPath);
  79. if(!(pCWinNTJobsCollection->_pszADsPrinterPath)){
  80. hr = E_OUTOFMEMORY;
  81. goto error;
  82. }
  83. //
  84. // open printer and set the handle to the appropriate value
  85. //
  86. fStatus = OpenPrinter(szUncPrinterName,
  87. &hPrinter,
  88. &PrinterDefaults
  89. );
  90. if (!fStatus) {
  91. LastError = GetLastError();
  92. switch (LastError) {
  93. case ERROR_ACCESS_DENIED:
  94. {
  95. PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE};
  96. fStatus = OpenPrinter(szUncPrinterName,
  97. &hPrinter,
  98. &PrinterDefaults
  99. );
  100. if (!fStatus) {
  101. hr = HRESULT_FROM_WIN32(GetLastError());
  102. }
  103. break;
  104. }
  105. default:
  106. hr = HRESULT_FROM_WIN32(GetLastError());
  107. break;
  108. }
  109. }
  110. BAIL_ON_FAILURE(hr);
  111. pCWinNTJobsCollection->_hPrinter = hPrinter;
  112. pCWinNTJobsCollection->_pDispMgr = new CAggregatorDispMgr;
  113. if (pCWinNTJobsCollection->_pDispMgr == NULL){
  114. hr = E_OUTOFMEMORY;
  115. goto error;
  116. }
  117. hr = LoadTypeInfoEntry(pCWinNTJobsCollection->_pDispMgr,
  118. LIBID_ADs,
  119. IID_IADsCollection,
  120. (IADsCollection *)pCWinNTJobsCollection,
  121. DISPID_NEWENUM
  122. );
  123. BAIL_ON_FAILURE(hr);
  124. *ppCWinNTPrintJobsCollection =pCWinNTJobsCollection;
  125. if(pObjectInfo){
  126. FreeObjectInfo(pObjectInfo);
  127. }
  128. RRETURN(hr);
  129. error:
  130. delete pCWinNTJobsCollection;
  131. if(pObjectInfo){
  132. FreeObjectInfo(pObjectInfo);
  133. }
  134. RRETURN_EXP_IF_ERR(hr);
  135. }
  136. /* IUnknown methods for jobs collection object */
  137. STDMETHODIMP
  138. CWinNTPrintJobsCollection::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  139. {
  140. if(!ppvObj)
  141. {
  142. RRETURN(E_POINTER);
  143. }
  144. if (IsEqualIID(riid, IID_IUnknown))
  145. {
  146. *ppvObj = this;
  147. }
  148. else if (IsEqualIID(riid, IID_IDispatch))
  149. {
  150. *ppvObj = (IDispatch *)this;
  151. }
  152. else if (IsEqualIID(riid, IID_ISupportErrorInfo))
  153. {
  154. *ppvObj = (ISupportErrorInfo FAR *) this;
  155. }
  156. else if (IsEqualIID(riid, IID_IADsCollection))
  157. {
  158. *ppvObj = (IADsCollection FAR *)this;
  159. }
  160. else
  161. {
  162. *ppvObj = NULL;
  163. return E_NOINTERFACE;
  164. }
  165. ((LPUNKNOWN)*ppvObj)->AddRef();
  166. RRETURN(S_OK);
  167. }
  168. /* ISupportErrorInfo method */
  169. STDMETHODIMP
  170. CWinNTPrintJobsCollection::InterfaceSupportsErrorInfo(
  171. THIS_ REFIID riid
  172. )
  173. {
  174. if (IsEqualIID(riid, IID_IADsCollection)) {
  175. RRETURN(S_OK);
  176. } else {
  177. RRETURN(S_FALSE);
  178. }
  179. }
  180. DEFINE_IDispatch_Implementation(CWinNTPrintJobsCollection);
  181. /* IADsCollection methods */
  182. STDMETHODIMP
  183. CWinNTPrintJobsCollection::get__NewEnum(THIS_ IUnknown * FAR* retval)
  184. {
  185. HRESULT hr;
  186. CWinNTJobsEnumVar *pCJobsEnumVar = NULL;
  187. if(!retval){
  188. RRETURN_EXP_IF_ERR(E_POINTER);
  189. }
  190. *retval = NULL;
  191. hr = CWinNTJobsEnumVar::Create(_hPrinter,
  192. _pszADsPrinterPath,
  193. _Credentials,
  194. &pCJobsEnumVar);
  195. if (FAILED(hr)) {
  196. goto error;
  197. }
  198. ADsAssert(pCJobsEnumVar);
  199. _pCJobsEnumVar = pCJobsEnumVar;
  200. hr = _pCJobsEnumVar->QueryInterface(IID_IUnknown,
  201. (void **)retval
  202. );
  203. BAIL_ON_FAILURE(hr);
  204. _pCJobsEnumVar->Release();
  205. RRETURN(S_OK);
  206. error:
  207. delete pCJobsEnumVar;
  208. RRETURN_EXP_IF_ERR(hr);
  209. }
  210. STDMETHODIMP
  211. CWinNTPrintJobsCollection::GetObject(THIS_ BSTR bstrJobName,
  212. VARIANT *pvar)
  213. {
  214. HRESULT hr;
  215. DWORD dwJobId;
  216. IDispatch *pDispatch = NULL;
  217. if(!bstrJobName || !pvar){
  218. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  219. }
  220. dwJobId = (DWORD)_wtol(bstrJobName);
  221. hr = CWinNTPrintJob::CreatePrintJob(_pszADsPrinterPath,
  222. dwJobId,
  223. ADS_OBJECT_BOUND,
  224. IID_IDispatch,
  225. _Credentials,
  226. (void **)&pDispatch);
  227. BAIL_IF_ERROR(hr);
  228. //
  229. // stick this IDispatch pointer into caller provided variant
  230. //
  231. VariantInit(pvar);
  232. V_VT(pvar) = VT_DISPATCH;
  233. V_DISPATCH(pvar) = pDispatch;
  234. cleanup:
  235. RRETURN_EXP_IF_ERR(hr);
  236. }
  237. STDMETHODIMP
  238. CWinNTPrintJobsCollection::Add(THIS_ BSTR bstrName, VARIANT varNewItem)
  239. {
  240. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  241. }
  242. STDMETHODIMP
  243. CWinNTPrintJobsCollection::Remove(THIS_ BSTR bstrJobName)
  244. {
  245. DWORD dwJobId;
  246. HRESULT hr = S_OK;
  247. HANDLE hPrinter = NULL;
  248. BOOL fStatus = FALSE;
  249. PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE};
  250. if(! bstrJobName){
  251. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  252. }
  253. //
  254. // convert the job name into a jobid
  255. //
  256. dwJobId = (DWORD)_wtol(bstrJobName);
  257. fStatus = OpenPrinter((LPTSTR)_pszPrinterName,
  258. &hPrinter,
  259. &PrinterDefaults
  260. );
  261. if (!fStatus) {
  262. hr = HRESULT_FROM_WIN32(GetLastError());
  263. goto cleanup;
  264. }
  265. //
  266. // use JOB_CONTROL_DELETE instead of JOB_CONTROL_CANCEL as DELETE works
  267. // even when a print job has been restarted while CANCEL won't
  268. //
  269. fStatus = SetJob (hPrinter,
  270. dwJobId,
  271. 0,
  272. NULL,
  273. JOB_CONTROL_DELETE
  274. );
  275. if (!fStatus) {
  276. hr = HRESULT_FROM_WIN32(GetLastError());
  277. goto cleanup;
  278. }
  279. cleanup:
  280. if (hPrinter) {
  281. ClosePrinter(hPrinter);
  282. }
  283. RRETURN (hr);
  284. }
  285. //
  286. // CWinNTJobsEnumVar methods follow
  287. //
  288. //+---------------------------------------------------------------------------
  289. //
  290. // Function: CWinNTJobsEnumVar::CWinNTJobsEnumVar
  291. //
  292. // Synopsis:
  293. //
  294. //
  295. // Arguments:
  296. //
  297. //
  298. // Returns:
  299. //
  300. // Modifies:
  301. //
  302. // History: 11-22-95 RamV Created.
  303. //
  304. //----------------------------------------------------------------------------
  305. CWinNTJobsEnumVar::CWinNTJobsEnumVar()
  306. {
  307. _pszADsPrinterPath = NULL;
  308. _pSafeArray = NULL;
  309. _cElements = 0;
  310. _lLBound = 0;
  311. _lCurrentPosition = _lLBound;
  312. ENLIST_TRACKING(CWinNTJobsEnumVar);
  313. }
  314. //+---------------------------------------------------------------------------
  315. //
  316. // Function: CWinNTJobsEnumVar::~CWinNTJobsEnumVar
  317. //
  318. // Synopsis:
  319. //
  320. //
  321. // Arguments:
  322. //
  323. // Returns:
  324. //
  325. // Modifies:
  326. //
  327. // History: 11-22-95 RamV Created.
  328. //
  329. //----------------------------------------------------------------------------
  330. CWinNTJobsEnumVar::~CWinNTJobsEnumVar()
  331. {
  332. if (_pSafeArray != NULL)
  333. SafeArrayDestroy(_pSafeArray);
  334. _pSafeArray = NULL;
  335. if(_pszADsPrinterPath){
  336. FreeADsStr(_pszADsPrinterPath);
  337. }
  338. }
  339. HRESULT CWinNTJobsEnumVar::Create(HANDLE hPrinter,
  340. LPTSTR szADsPrinterPath,
  341. CWinNTCredentials& Credentials,
  342. CWinNTJobsEnumVar ** ppCJobsEnumVar)
  343. {
  344. //
  345. // This function uses the handle to the printer to query for the
  346. // number of jobs(cJobs) on the printer, It uses the returned value
  347. // to create a safearray of cJobs number of Job Objects.
  348. //
  349. HRESULT hr;
  350. BOOL fStatus = FALSE;
  351. PRINTER_DEFAULTS PrinterDefaults = {0, 0, PRINTER_ACCESS_USE| READ_CONTROL};
  352. OBJECTINFO ObjectInfo;
  353. CLexer Lexer(szADsPrinterPath);
  354. CWinNTJobsEnumVar FAR* pCJobsEnumVar = NULL;
  355. *ppCJobsEnumVar = NULL;
  356. memset((void*)&ObjectInfo, 0, sizeof(OBJECTINFO));
  357. pCJobsEnumVar = new CWinNTJobsEnumVar();
  358. if (pCJobsEnumVar == NULL){
  359. hr = E_OUTOFMEMORY;
  360. goto error;
  361. }
  362. pCJobsEnumVar->_pszADsPrinterPath = AllocADsStr(szADsPrinterPath);
  363. if (!(pCJobsEnumVar->_pszADsPrinterPath)){
  364. hr = E_OUTOFMEMORY;
  365. goto error;
  366. }
  367. hr = Object(&Lexer, &ObjectInfo);
  368. BAIL_ON_FAILURE(hr);
  369. pCJobsEnumVar->_Credentials = Credentials;
  370. // We want the next-to-last element in the array.
  371. ADsAssert(ObjectInfo.NumComponents >= 2);
  372. hr = pCJobsEnumVar->_Credentials.RefServer(
  373. ObjectInfo.ComponentArray[(ObjectInfo.NumComponents - 1) - 1]);
  374. BAIL_ON_FAILURE(hr);
  375. //
  376. // Fill in the safearray with relevant information here
  377. //
  378. hr = FillSafeArray(hPrinter, szADsPrinterPath, pCJobsEnumVar->_Credentials,
  379. pCJobsEnumVar);
  380. BAIL_ON_FAILURE(hr);
  381. *ppCJobsEnumVar = pCJobsEnumVar;
  382. //
  383. // Free the objectInfo data
  384. //
  385. FreeObjectInfo( &ObjectInfo, TRUE );
  386. RRETURN(S_OK);
  387. error:
  388. //
  389. // Free the objectInfo data
  390. //
  391. FreeObjectInfo( &ObjectInfo, TRUE );
  392. delete pCJobsEnumVar;
  393. RRETURN_EXP_IF_ERR(hr);
  394. }
  395. //+------------------------------------------------------------------------
  396. //
  397. // Function: CWinNTJobsEnumVar::QueryInterface
  398. //
  399. // Synopsis:
  400. //
  401. // Arguments: [iid]
  402. // [ppv]
  403. //
  404. // Returns: HRESULT
  405. //
  406. // Modifies:
  407. //
  408. // History: 11-22-95 RamV Created.
  409. //
  410. //----------------------------------------------------------------------------
  411. STDMETHODIMP
  412. CWinNTJobsEnumVar::QueryInterface(REFIID iid, void FAR* FAR* ppv)
  413. {
  414. if(!ppv){
  415. RRETURN(E_POINTER);
  416. }
  417. *ppv = NULL;
  418. if (iid == IID_IUnknown )
  419. {
  420. *ppv = this;
  421. }
  422. else if(iid == IID_IEnumVARIANT)
  423. {
  424. *ppv = (IEnumVARIANT *)this;
  425. }
  426. else
  427. {
  428. return E_NOINTERFACE;
  429. }
  430. AddRef();
  431. RRETURN(S_OK);
  432. }
  433. //+---------------------------------------------------------------------------
  434. //
  435. // Function: CWinNTJobsEnumVar::Next
  436. //
  437. // Synopsis: Returns cElements number of requested Job objects in the
  438. // array supplied in pvar.
  439. //
  440. // Arguments: [cElements] -- The number of elements requested by client
  441. // [pvar] -- ptr to array of VARIANTs to for return objects
  442. // [pcElementFetched] -- if non-NULL, then number of elements
  443. // -- actually returned is placed here
  444. //
  445. // Returns: HRESULT -- S_OK if number of elements requested are returned
  446. // -- S_FALSE if number of elements is < requested
  447. //
  448. // Modifies:
  449. //
  450. // History: 11-27-95 RamV Created.
  451. //
  452. //----------------------------------------------------------------------------
  453. STDMETHODIMP
  454. CWinNTJobsEnumVar::Next(ULONG ulNumElementsRequested,
  455. VARIANT FAR* pvar,
  456. ULONG FAR* pulNumFetched)
  457. {
  458. HRESULT hresult;
  459. ULONG l;
  460. LONG lNewCurrent;
  461. ULONG lNumFetched;
  462. if (pulNumFetched != NULL)
  463. *pulNumFetched = 0;
  464. //
  465. // Initialize the elements to be returned
  466. //
  467. for (l=0; l<ulNumElementsRequested; l++)
  468. VariantInit(&pvar[l]);
  469. //
  470. // Get each element and place it into the return array
  471. // Don't request more than we have
  472. //
  473. for (lNewCurrent=_lCurrentPosition, lNumFetched=0;
  474. lNewCurrent<(LONG)(_lLBound+_cElements) &&
  475. lNumFetched < ulNumElementsRequested;
  476. lNewCurrent++, lNumFetched++){
  477. hresult = SafeArrayGetElement(_pSafeArray, &lNewCurrent,
  478. &pvar[lNumFetched]);
  479. //
  480. // Something went wrong!!!
  481. //
  482. if (FAILED(hresult)){
  483. for (l=0; l<ulNumElementsRequested; l++)
  484. VariantClear(&pvar[l]);
  485. ADsAssert(hresult == S_FALSE);
  486. return(S_FALSE);
  487. } // End of If Failed
  488. }
  489. //
  490. // Tell the caller how many we got (which may be less than the number
  491. // requested), and save the current position
  492. //
  493. if (pulNumFetched != NULL)
  494. *pulNumFetched = lNumFetched;
  495. _lCurrentPosition = lNewCurrent;
  496. //
  497. // If we're returning less than they asked for return S_FALSE, but
  498. // they still have the data (S_FALSE is a success code)
  499. //
  500. return (lNumFetched < ulNumElementsRequested) ?
  501. S_FALSE
  502. : S_OK;
  503. }
  504. //+---------------------------------------------------------------------------
  505. //
  506. // Function: CWinNTJobsEnumVar::Skip
  507. //
  508. // Synopsis:
  509. //
  510. // Arguments: [cElements]
  511. //
  512. // Returns: HRESULT
  513. //
  514. // Modifies:
  515. //
  516. // History: 11-22-95 RamV Created.
  517. //
  518. //----------------------------------------------------------------------------
  519. STDMETHODIMP
  520. CWinNTJobsEnumVar::Skip(ULONG cElements)
  521. {
  522. //
  523. // Skip the number of elements requested
  524. //
  525. _lCurrentPosition += cElements;
  526. //
  527. // if we went outside of the boundaries unskip
  528. //
  529. if (_lCurrentPosition > (LONG)(_lLBound +_cElements)){
  530. _lCurrentPosition = _lLBound +_cElements;
  531. return (S_FALSE);
  532. }
  533. else
  534. RRETURN(S_OK);
  535. }
  536. //+---------------------------------------------------------------------------
  537. //
  538. // Function: CWinNTJobsEnumVar::Reset
  539. //
  540. // Synopsis:
  541. //
  542. // Arguments: []
  543. //
  544. // Returns: HRESULT
  545. //
  546. // Modifies:
  547. //
  548. // History:
  549. //
  550. //----------------------------------------------------------------------------
  551. STDMETHODIMP
  552. CWinNTJobsEnumVar::Reset()
  553. {
  554. //
  555. //Just move the CurrentPosition to the lower array boundary
  556. //
  557. _lCurrentPosition = _lLBound;
  558. RRETURN(S_OK);
  559. }
  560. //+---------------------------------------------------------------------------
  561. //
  562. // Function: CWinNTJobsEnumVar::Clone
  563. //
  564. // Synopsis:
  565. //
  566. // Arguments: [pCollection]
  567. // [ppEnumVariant]
  568. //
  569. // Returns: HRESULT
  570. //
  571. // Modifies:
  572. //
  573. // History: 11-22-95 RamV Created.
  574. //
  575. //----------------------------------------------------------------------------
  576. STDMETHODIMP
  577. CWinNTJobsEnumVar::Clone(IEnumVARIANT FAR* FAR* ppenum)
  578. {
  579. RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
  580. }
  581. HRESULT FillSafeArray(HANDLE hPrinter,
  582. LPTSTR szPrinterPath,
  583. CWinNTCredentials& Credentials,
  584. CWinNTJobsEnumVar *pJobsEnumVar )
  585. {
  586. BOOL fStatus = FALSE;
  587. DWORD dwPassed =0, dwNeeded = 0;
  588. DWORD dwcJobs; // Number of jobs in print queue
  589. LPPRINTER_INFO_2 pPrinterInfo2;
  590. DWORD dwError = 0, LastError =0;
  591. LPBYTE pMem = NULL;
  592. LPBYTE lpbJobs = NULL;
  593. DWORD cbBuf =0;
  594. DWORD dwReturned =0;
  595. CWinNTPrintJob *pCWinNTPrintJob = NULL;
  596. SAFEARRAYBOUND sabound[1];
  597. IDispatch *pDispatch;
  598. VARIANT v;
  599. LONG l;
  600. HRESULT hr = S_OK;
  601. LPJOB_INFO_1 lpJobInfo1 = NULL;
  602. if(hPrinter == NULL){
  603. RRETURN_EXP_IF_ERR(HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE));
  604. }
  605. VariantInit(&v);
  606. //
  607. // First Get info from printer to determine the number of jobs.
  608. // AjayR: 10-01-99. We always expect this call to fail but tell
  609. // us how much memory is needed !!!
  610. //
  611. fStatus = GetPrinter(hPrinter,
  612. 2,
  613. (LPBYTE)pMem,
  614. dwPassed,
  615. &dwNeeded
  616. );
  617. if (!fStatus) {
  618. LastError = GetLastError();
  619. switch (LastError) {
  620. case ERROR_INSUFFICIENT_BUFFER:
  621. if (pMem){
  622. FreeADsMem(pMem);
  623. }
  624. dwPassed = dwNeeded;
  625. pMem = (LPBYTE)AllocADsMem(dwPassed);
  626. if (!pMem) {
  627. hr = E_OUTOFMEMORY;
  628. break;
  629. }
  630. fStatus = GetPrinter(hPrinter,
  631. 2,
  632. (LPBYTE)pMem,
  633. dwPassed,
  634. &dwNeeded
  635. );
  636. if (!fStatus) {
  637. hr = HRESULT_FROM_WIN32(GetLastError());
  638. }
  639. break;
  640. default:
  641. hr = HRESULT_FROM_WIN32(GetLastError());;
  642. break;
  643. }
  644. }
  645. if(FAILED(hr))
  646. goto error;
  647. pPrinterInfo2 =(LPPRINTER_INFO_2)pMem;
  648. dwcJobs = pPrinterInfo2->cJobs;
  649. fStatus = MyEnumJobs(hPrinter,
  650. 0, // First job you want
  651. dwcJobs,
  652. 1, //Job Info level
  653. &lpbJobs,
  654. &cbBuf,
  655. &dwReturned
  656. );
  657. if(!fStatus){
  658. hr =HRESULT_FROM_WIN32(GetLastError());
  659. goto error;
  660. }
  661. //
  662. // Use the array bound as the number of jobs returned, not
  663. // the number of jobs you requested, this may have changed!
  664. //
  665. sabound[0].cElements = dwReturned;
  666. sabound[0].lLbound = 0;
  667. //
  668. // Create a one dimensional SafeArray
  669. //
  670. pJobsEnumVar->_pSafeArray = SafeArrayCreate(VT_VARIANT, 1, sabound);
  671. if (pJobsEnumVar->_pSafeArray == NULL){
  672. hr = E_OUTOFMEMORY;
  673. goto error;
  674. }
  675. //
  676. // for each of the Jobs retrieved create the appropriate structure
  677. //
  678. for(l=0; l<(LONG)dwReturned; l++){
  679. lpJobInfo1 = (LPJOB_INFO_1)(lpbJobs +l*sizeof(JOB_INFO_1));
  680. hr = CWinNTPrintJob::CreatePrintJob(
  681. szPrinterPath,
  682. lpJobInfo1->JobId,
  683. ADS_OBJECT_BOUND,
  684. IID_IDispatch,
  685. Credentials,
  686. (void **)&pDispatch
  687. );
  688. if(FAILED(hr)){
  689. break;
  690. }
  691. VariantInit(&v);
  692. V_VT(&v) = VT_DISPATCH;
  693. V_DISPATCH(&v) = pDispatch;
  694. //
  695. // Stick the caller provided data into the end of the SafeArray
  696. //
  697. hr = SafeArrayPutElement(pJobsEnumVar->_pSafeArray, &l, &v);
  698. VariantClear(&v);
  699. if (FAILED(hr)){
  700. break;
  701. }
  702. pJobsEnumVar->_cElements++;
  703. }
  704. BAIL_ON_FAILURE(hr);
  705. if (pMem) {
  706. FreeADsMem(pMem);
  707. }
  708. if(lpbJobs){
  709. FreeADsMem(lpbJobs);
  710. }
  711. RRETURN(S_OK);
  712. error:
  713. if (pMem) {
  714. FreeADsMem(pMem);
  715. }
  716. //
  717. // Free the buffer you just allocated
  718. //
  719. if (lpbJobs){
  720. FreeADsMem(lpbJobs);
  721. }
  722. //
  723. // Destroy the safearray
  724. //
  725. if(pJobsEnumVar->_pSafeArray != NULL)
  726. SafeArrayDestroy(pJobsEnumVar->_pSafeArray);
  727. VariantClear(&v);
  728. RRETURN_EXP_IF_ERR(hr);
  729. }
  730. BOOL
  731. MyEnumJobs(HANDLE hPrinter,
  732. DWORD dwFirstJob,
  733. DWORD dwNoJobs,
  734. DWORD dwLevel,
  735. LPBYTE *lplpbJobs,
  736. DWORD *pcbBuf,
  737. LPDWORD lpdwReturned
  738. )
  739. {
  740. BOOL fStatus = FALSE;
  741. DWORD dwNeeded = 0;
  742. DWORD dwError = 0;
  743. fStatus = EnumJobs(hPrinter,
  744. dwFirstJob,
  745. dwNoJobs,
  746. dwLevel,
  747. *lplpbJobs,
  748. *pcbBuf,
  749. &dwNeeded,
  750. lpdwReturned
  751. );
  752. if (!fStatus) {
  753. if ((dwError = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) {
  754. if (*lplpbJobs) {
  755. FreeADsMem( *lplpbJobs );
  756. }
  757. *lplpbJobs = (LPBYTE)AllocADsMem(dwNeeded);
  758. if (!*lplpbJobs) {
  759. *pcbBuf = 0;
  760. return(FALSE);
  761. }
  762. *pcbBuf = dwNeeded;
  763. fStatus = EnumJobs(hPrinter,
  764. dwFirstJob,
  765. dwNoJobs,
  766. dwLevel,
  767. *lplpbJobs,
  768. *pcbBuf,
  769. &dwNeeded,
  770. lpdwReturned
  771. );
  772. if (!fStatus) {
  773. return(FALSE);
  774. }else {
  775. return(TRUE);
  776. }
  777. }else {
  778. return(FALSE);
  779. }
  780. }else {
  781. return(TRUE);
  782. }
  783. }