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.

1023 lines
23 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. // Check the out parameter to ensure it is valid
  466. //
  467. if (!pvar)
  468. {
  469. //
  470. // Returning S_FALSE to indicate that we aren't returning
  471. // as many elements as requested.
  472. //
  473. return(S_FALSE);
  474. }
  475. //
  476. // Initialize the elements to be returned
  477. //
  478. for (l=0; l<ulNumElementsRequested; l++)
  479. VariantInit(&pvar[l]);
  480. //
  481. // Get each element and place it into the return array
  482. // Don't request more than we have
  483. //
  484. for (lNewCurrent=_lCurrentPosition, lNumFetched=0;
  485. lNewCurrent<(LONG)(_lLBound+_cElements) &&
  486. lNumFetched < ulNumElementsRequested;
  487. lNewCurrent++, lNumFetched++){
  488. hresult = SafeArrayGetElement(_pSafeArray, &lNewCurrent,
  489. &pvar[lNumFetched]);
  490. //
  491. // Something went wrong!!!
  492. //
  493. if (FAILED(hresult)){
  494. for (l=0; l<ulNumElementsRequested; l++)
  495. VariantClear(&pvar[l]);
  496. ADsAssert(hresult == S_FALSE);
  497. return(S_FALSE);
  498. } // End of If Failed
  499. }
  500. //
  501. // Tell the caller how many we got (which may be less than the number
  502. // requested), and save the current position
  503. //
  504. if (pulNumFetched != NULL)
  505. *pulNumFetched = lNumFetched;
  506. _lCurrentPosition = lNewCurrent;
  507. //
  508. // If we're returning less than they asked for return S_FALSE, but
  509. // they still have the data (S_FALSE is a success code)
  510. //
  511. return (lNumFetched < ulNumElementsRequested) ?
  512. S_FALSE
  513. : S_OK;
  514. }
  515. //+---------------------------------------------------------------------------
  516. //
  517. // Function: CWinNTJobsEnumVar::Skip
  518. //
  519. // Synopsis:
  520. //
  521. // Arguments: [cElements]
  522. //
  523. // Returns: HRESULT
  524. //
  525. // Modifies:
  526. //
  527. // History: 11-22-95 RamV Created.
  528. //
  529. //----------------------------------------------------------------------------
  530. STDMETHODIMP
  531. CWinNTJobsEnumVar::Skip(ULONG cElements)
  532. {
  533. //
  534. // Skip the number of elements requested
  535. //
  536. _lCurrentPosition += cElements;
  537. //
  538. // if we went outside of the boundaries unskip
  539. //
  540. if (_lCurrentPosition > (LONG)(_lLBound +_cElements)){
  541. _lCurrentPosition = _lLBound +_cElements;
  542. return (S_FALSE);
  543. }
  544. else
  545. RRETURN(S_OK);
  546. }
  547. //+---------------------------------------------------------------------------
  548. //
  549. // Function: CWinNTJobsEnumVar::Reset
  550. //
  551. // Synopsis:
  552. //
  553. // Arguments: []
  554. //
  555. // Returns: HRESULT
  556. //
  557. // Modifies:
  558. //
  559. // History:
  560. //
  561. //----------------------------------------------------------------------------
  562. STDMETHODIMP
  563. CWinNTJobsEnumVar::Reset()
  564. {
  565. //
  566. //Just move the CurrentPosition to the lower array boundary
  567. //
  568. _lCurrentPosition = _lLBound;
  569. RRETURN(S_OK);
  570. }
  571. //+---------------------------------------------------------------------------
  572. //
  573. // Function: CWinNTJobsEnumVar::Clone
  574. //
  575. // Synopsis:
  576. //
  577. // Arguments: [pCollection]
  578. // [ppEnumVariant]
  579. //
  580. // Returns: HRESULT
  581. //
  582. // Modifies:
  583. //
  584. // History: 11-22-95 RamV Created.
  585. //
  586. //----------------------------------------------------------------------------
  587. STDMETHODIMP
  588. CWinNTJobsEnumVar::Clone(IEnumVARIANT FAR* FAR* ppenum)
  589. {
  590. RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_SUPPORTED);
  591. }
  592. HRESULT FillSafeArray(HANDLE hPrinter,
  593. LPTSTR szPrinterPath,
  594. CWinNTCredentials& Credentials,
  595. CWinNTJobsEnumVar *pJobsEnumVar )
  596. {
  597. BOOL fStatus = FALSE;
  598. DWORD dwPassed =0, dwNeeded = 0;
  599. DWORD dwcJobs; // Number of jobs in print queue
  600. LPPRINTER_INFO_2 pPrinterInfo2;
  601. DWORD dwError = 0, LastError =0;
  602. LPBYTE pMem = NULL;
  603. LPBYTE lpbJobs = NULL;
  604. DWORD cbBuf =0;
  605. DWORD dwReturned =0;
  606. CWinNTPrintJob *pCWinNTPrintJob = NULL;
  607. SAFEARRAYBOUND sabound[1];
  608. IDispatch *pDispatch;
  609. VARIANT v;
  610. LONG l;
  611. HRESULT hr = S_OK;
  612. LPJOB_INFO_1 lpJobInfo1 = NULL;
  613. if(hPrinter == NULL){
  614. RRETURN_EXP_IF_ERR(HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE));
  615. }
  616. VariantInit(&v);
  617. //
  618. // First Get info from printer to determine the number of jobs.
  619. // AjayR: 10-01-99. We always expect this call to fail but tell
  620. // us how much memory is needed !!!
  621. //
  622. fStatus = GetPrinter(hPrinter,
  623. 2,
  624. (LPBYTE)pMem,
  625. dwPassed,
  626. &dwNeeded
  627. );
  628. if (!fStatus) {
  629. LastError = GetLastError();
  630. switch (LastError) {
  631. case ERROR_INSUFFICIENT_BUFFER:
  632. if (pMem){
  633. FreeADsMem(pMem);
  634. }
  635. dwPassed = dwNeeded;
  636. pMem = (LPBYTE)AllocADsMem(dwPassed);
  637. if (!pMem) {
  638. hr = E_OUTOFMEMORY;
  639. break;
  640. }
  641. fStatus = GetPrinter(hPrinter,
  642. 2,
  643. (LPBYTE)pMem,
  644. dwPassed,
  645. &dwNeeded
  646. );
  647. if (!fStatus) {
  648. hr = HRESULT_FROM_WIN32(GetLastError());
  649. }
  650. break;
  651. default:
  652. hr = HRESULT_FROM_WIN32(GetLastError());;
  653. break;
  654. }
  655. }
  656. if(FAILED(hr))
  657. goto error;
  658. pPrinterInfo2 =(LPPRINTER_INFO_2)pMem;
  659. dwcJobs = pPrinterInfo2->cJobs;
  660. fStatus = MyEnumJobs(hPrinter,
  661. 0, // First job you want
  662. dwcJobs,
  663. 1, //Job Info level
  664. &lpbJobs,
  665. &cbBuf,
  666. &dwReturned
  667. );
  668. if(!fStatus){
  669. hr =HRESULT_FROM_WIN32(GetLastError());
  670. goto error;
  671. }
  672. //
  673. // Use the array bound as the number of jobs returned, not
  674. // the number of jobs you requested, this may have changed!
  675. //
  676. sabound[0].cElements = dwReturned;
  677. sabound[0].lLbound = 0;
  678. //
  679. // Create a one dimensional SafeArray
  680. //
  681. pJobsEnumVar->_pSafeArray = SafeArrayCreate(VT_VARIANT, 1, sabound);
  682. if (pJobsEnumVar->_pSafeArray == NULL){
  683. hr = E_OUTOFMEMORY;
  684. goto error;
  685. }
  686. //
  687. // for each of the Jobs retrieved create the appropriate structure
  688. //
  689. for(l=0; l<(LONG)dwReturned; l++){
  690. lpJobInfo1 = (LPJOB_INFO_1)(lpbJobs +l*sizeof(JOB_INFO_1));
  691. hr = CWinNTPrintJob::CreatePrintJob(
  692. szPrinterPath,
  693. lpJobInfo1->JobId,
  694. ADS_OBJECT_BOUND,
  695. IID_IDispatch,
  696. Credentials,
  697. (void **)&pDispatch
  698. );
  699. if(FAILED(hr)){
  700. break;
  701. }
  702. VariantInit(&v);
  703. V_VT(&v) = VT_DISPATCH;
  704. V_DISPATCH(&v) = pDispatch;
  705. //
  706. // Stick the caller provided data into the end of the SafeArray
  707. //
  708. hr = SafeArrayPutElement(pJobsEnumVar->_pSafeArray, &l, &v);
  709. VariantClear(&v);
  710. if (FAILED(hr)){
  711. break;
  712. }
  713. pJobsEnumVar->_cElements++;
  714. }
  715. BAIL_ON_FAILURE(hr);
  716. if (pMem) {
  717. FreeADsMem(pMem);
  718. }
  719. if(lpbJobs){
  720. FreeADsMem(lpbJobs);
  721. }
  722. RRETURN(S_OK);
  723. error:
  724. if (pMem) {
  725. FreeADsMem(pMem);
  726. }
  727. //
  728. // Free the buffer you just allocated
  729. //
  730. if (lpbJobs){
  731. FreeADsMem(lpbJobs);
  732. }
  733. //
  734. // Destroy the safearray
  735. //
  736. if(pJobsEnumVar->_pSafeArray != NULL)
  737. SafeArrayDestroy(pJobsEnumVar->_pSafeArray);
  738. VariantClear(&v);
  739. RRETURN_EXP_IF_ERR(hr);
  740. }
  741. BOOL
  742. MyEnumJobs(HANDLE hPrinter,
  743. DWORD dwFirstJob,
  744. DWORD dwNoJobs,
  745. DWORD dwLevel,
  746. LPBYTE *lplpbJobs,
  747. DWORD *pcbBuf,
  748. LPDWORD lpdwReturned
  749. )
  750. {
  751. BOOL fStatus = FALSE;
  752. DWORD dwNeeded = 0;
  753. DWORD dwError = 0;
  754. fStatus = EnumJobs(hPrinter,
  755. dwFirstJob,
  756. dwNoJobs,
  757. dwLevel,
  758. *lplpbJobs,
  759. *pcbBuf,
  760. &dwNeeded,
  761. lpdwReturned
  762. );
  763. if (!fStatus) {
  764. if ((dwError = GetLastError()) == ERROR_INSUFFICIENT_BUFFER) {
  765. if (*lplpbJobs) {
  766. FreeADsMem( *lplpbJobs );
  767. }
  768. *lplpbJobs = (LPBYTE)AllocADsMem(dwNeeded);
  769. if (!*lplpbJobs) {
  770. *pcbBuf = 0;
  771. return(FALSE);
  772. }
  773. *pcbBuf = dwNeeded;
  774. fStatus = EnumJobs(hPrinter,
  775. dwFirstJob,
  776. dwNoJobs,
  777. dwLevel,
  778. *lplpbJobs,
  779. *pcbBuf,
  780. &dwNeeded,
  781. lpdwReturned
  782. );
  783. if (!fStatus) {
  784. return(FALSE);
  785. }else {
  786. return(TRUE);
  787. }
  788. }else {
  789. return(FALSE);
  790. }
  791. }else {
  792. return(TRUE);
  793. }
  794. }