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.

1063 lines
34 KiB

  1. /*****************************************************************************\
  2. * MODULE: ppinfo.c
  3. *
  4. * This module contains the print-information routines.
  5. *
  6. *
  7. * Copyright (C) 1996-1997 Microsoft Corporation
  8. * Copyright (C) 1996-1997 Hewlett Packard
  9. *
  10. * History:
  11. * 09-Jun-1993 JonMarb Created
  12. * 07-Oct-1996 HWP-Guys Initiated port from win95 to winNT
  13. *
  14. \*****************************************************************************/
  15. #include "precomp.h"
  16. #include "priv.h"
  17. /*****************************************************************************\
  18. * ppprn_IppGetRsp (Local Callback Routine)
  19. *
  20. * Retrieves a GetPrinter response from the IPP server
  21. *
  22. \*****************************************************************************/
  23. BOOL CALLBACK ppinfo_IppGetRsp(
  24. CAnyConnection *pConnection,
  25. HINTERNET hReq,
  26. PCINETMONPORT pIniPort,
  27. LPARAM lParam)
  28. {
  29. HANDLE hIpp;
  30. DWORD dwRet;
  31. DWORD cbRd;
  32. LPBYTE lpDta;
  33. DWORD cbDta;
  34. LPIPPRET_PRN lpRsp;
  35. DWORD cbRsp;
  36. BYTE bBuf[MAX_IPP_BUFFER];
  37. BOOL bRet = FALSE;
  38. if (hIpp = WebIppRcvOpen(IPP_RET_GETPRN)) {
  39. while (TRUE) {
  40. cbRd = 0;
  41. if (pIniPort->ReadFile (pConnection, hReq, (LPVOID)bBuf, sizeof(bBuf), &cbRd) && cbRd) {
  42. dwRet = WebIppRcvData(hIpp, bBuf, cbRd, (LPBYTE*)&lpRsp, &cbRsp, &lpDta, &cbDta);
  43. switch (dwRet) {
  44. case WEBIPP_OK:
  45. if (!lpRsp) {
  46. SetLastError (ERROR_INVALID_DATA);
  47. }
  48. else if ((bRet = lpRsp->bRet) == FALSE)
  49. SetLastError(lpRsp->dwLastError);
  50. else {
  51. pIniPort->SetPowerUpTime (lpRsp->pi.ipp.dwPowerUpTime);
  52. ((LPPRINTER_INFO_2)lParam)->Status = lpRsp->pi.pi2.Status;
  53. ((LPPRINTER_INFO_2)lParam)->cJobs = lpRsp->pi.pi2.cJobs;
  54. ((LPPRINTER_INFO_2)lParam)->pPrinterName = memAllocStr(lpRsp->pi.pi2.pPrinterName);
  55. ((LPPRINTER_INFO_2)lParam)->pDriverName = memAllocStr(lpRsp->pi.pi2.pDriverName);
  56. }
  57. WebIppFreeMem(lpRsp);
  58. goto EndGetRsp;
  59. case WEBIPP_MOREDATA:
  60. // Need to do another read to fullfill our header-response.
  61. //
  62. break;
  63. default:
  64. DBG_MSG(DBG_LEV_ERROR, (TEXT("ppinfo_IppGetRsp - Err : Receive Data Error (dwRet=%d, LE=%d)"),
  65. dwRet, WebIppGetError(hIpp)));
  66. SetLastError(ERROR_INVALID_DATA);
  67. goto EndGetRsp;
  68. }
  69. } else {
  70. goto EndGetRsp;
  71. }
  72. }
  73. EndGetRsp:
  74. WebIppRcvClose(hIpp);
  75. } else {
  76. SetLastError(ERROR_OUTOFMEMORY);
  77. }
  78. return bRet;
  79. }
  80. /*****************************************************************************\
  81. * ppinfo_Get (Local Routine)
  82. *
  83. * Gets printer info from server.
  84. *
  85. \*****************************************************************************/
  86. BOOL ppinfo_Get(
  87. PCINETMONPORT pIniPort,
  88. LPPRINTER_INFO_2 ppi2)
  89. {
  90. PIPPREQ_GETPRN pgp;
  91. REQINFO ri;
  92. DWORD dwRet;
  93. LPBYTE lpIpp;
  94. DWORD cbIpp;
  95. LPCTSTR lpszUri;
  96. BOOL bRet = FALSE;
  97. lpszUri = pIniPort->GetPortName();
  98. // Create our ipp-reqest-structure.
  99. //
  100. if (pgp = WebIppCreateGetPrnReq(0, lpszUri)) {
  101. // Convert the reqest to IPP, and perform the
  102. // post.
  103. //
  104. ZeroMemory(&ri, sizeof(REQINFO));
  105. ri.cpReq = CP_UTF8;
  106. ri.idReq = IPP_REQ_GETPRN;
  107. ri.fReq[0] = IPP_REQALL;
  108. ri.fReq[1] = IPP_REQALL;
  109. dwRet = WebIppSndData(IPP_REQ_GETPRN,
  110. &ri,
  111. (LPBYTE)pgp,
  112. pgp->cbSize,
  113. &lpIpp,
  114. &cbIpp);
  115. // The request-structure has been converted to IPP format,
  116. // so it is ready to go to the server.
  117. //
  118. if (dwRet == WEBIPP_OK) {
  119. bRet = pIniPort->SendReq(lpIpp,
  120. cbIpp,
  121. ppinfo_IppGetRsp,
  122. (LPARAM)ppi2,
  123. TRUE);
  124. WebIppFreeMem(lpIpp);
  125. } else {
  126. SetLastError(ERROR_OUTOFMEMORY);
  127. }
  128. WebIppFreeMem(pgp);
  129. } else {
  130. SetLastError(ERROR_OUTOFMEMORY);
  131. }
  132. return bRet;
  133. }
  134. /*****************************************************************************\
  135. * _ppinfo_set_str (Local Routine)
  136. *
  137. * Copies strings into a Win32 format buffer -- a structure at the front of
  138. * the buffer and strings packed into the end.
  139. *
  140. * On entry,
  141. * dest points to the place to write the string offset in the buffer.
  142. * src points to a null terminated string, can be NULL.
  143. * *buf should point to the last available byte in the buffer.
  144. *
  145. * Asumption:
  146. * This routine assumes that the memory between dest and *buf are availabe
  147. * for the string data.
  148. *
  149. \*****************************************************************************/
  150. VOID _ppinfo_set_str(
  151. LPTSTR *dest,
  152. LPCTSTR src,
  153. LPTSTR *buf)
  154. {
  155. if (src != NULL) {
  156. size_t uSize = lstrlen(src);
  157. //
  158. // If the destination pointer is greater than or equal to buffer pointer adjusted
  159. // by the length of the string the string will overflow the buffer. If this
  160. // happens we place a null as the destination pointer. This routine
  161. // really should return a failure code, to inform the caller an error error
  162. // happened.
  163. //
  164. if ((DWORD_PTR)dest >= (DWORD_PTR)((*buf) - uSize))
  165. {
  166. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: String fill overrun in _ppinfo_set_str")));
  167. *dest = TEXT('\0');
  168. }
  169. else
  170. {
  171. // Place string at end of buffer. This performs pointer
  172. // arithmatic, so the offsets are TCHAR in size.
  173. //
  174. (*buf) -= uSize;
  175. //
  176. // Copy the string data.
  177. //
  178. StringCchCopy(*buf, uSize+1, src);
  179. // Place string address in structure and save pointer to new
  180. // last available byte.
  181. //
  182. *dest = *buf;
  183. (*buf)--;
  184. }
  185. } else {
  186. *dest = TEXT('\0');
  187. }
  188. }
  189. /*****************************************************************************\
  190. * _ppinfo_describe_provider (Local Routine)
  191. *
  192. * Fills a PRINTER_INFO_1 structure with information about the print provider.
  193. * Returns TRUE if successful. Otherwise, it returns FALSE. Extended error
  194. * information is available from GetLastError.
  195. *
  196. \*****************************************************************************/
  197. BOOL _ppinfo_describe_provider(
  198. LPPRINTER_INFO_1 pInfo,
  199. DWORD cbSize,
  200. LPDWORD pcbNeeded,
  201. LPDWORD pcbReturned)
  202. {
  203. LPTSTR pszString;
  204. // Calculate the space needed (in bytes) that is necessary to
  205. // store the information for the print-processor.
  206. //
  207. *pcbNeeded = sizeof(PRINTER_INFO_1) +
  208. utlStrSize(g_szDescription) +
  209. utlStrSize(g_szProviderName) +
  210. utlStrSize(g_szComment);
  211. if (*pcbNeeded > cbSize) {
  212. *pcbReturned = 0;
  213. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: _describe_provider: Not enough memory")));
  214. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  215. return FALSE;
  216. }
  217. // Initialize the fields which do not need to copy strings.
  218. //
  219. pInfo->Flags = (PRINTER_ENUM_ICON1 | PRINTER_ENUM_CONTAINER);
  220. //
  221. // Hide this provider from the UI, there is nothing underneath to enumerate.
  222. //
  223. pInfo->Flags |= PRINTER_ENUM_HIDE;
  224. // Set the string information. First set the (pszString) pointer
  225. // to the first location at the end of the buffer which will store
  226. // the string.
  227. //
  228. pszString = ENDOFBUFFER(pInfo, cbSize);
  229. _ppinfo_set_str(&pInfo->pDescription, g_szDescription , &pszString);
  230. _ppinfo_set_str(&pInfo->pName , g_szProviderName, &pszString);
  231. _ppinfo_set_str(&pInfo->pComment , g_szComment , &pszString);
  232. // Return the number of structures copied.
  233. //
  234. *pcbReturned = 1;
  235. return TRUE;
  236. }
  237. /*****************************************************************************\
  238. * _ppinfo_net_get_info (Local Routine)
  239. *
  240. * Fills a supplied PRINTER_INFO_2 structure with all the information
  241. * we can dig up on the specified IPP1 print server.
  242. *
  243. * Takes a pointer to PPRINTER_INFO_2 which is allocated to be the correct size
  244. *
  245. * Returns TRUE if successful, FALSE if otherwise.
  246. *
  247. \*****************************************************************************/
  248. BOOL _ppinfo_net_get_info(
  249. IN PCINETMONPORT pIniPort,
  250. OUT PPRINTER_INFO_2 *ppInfo,
  251. OUT LPDWORD lpBufAllocated,
  252. IN ALLOCATORFN pAllocator)
  253. {
  254. PRINTER_INFO_2 pi2;
  255. PPRINTER_INFO_2 pInfo;
  256. LPTSTR pszString;
  257. LPCTSTR pszPortName;
  258. DWORD dwAllocSize;
  259. BOOL bRet = FALSE;
  260. // Make a server-call to get the printer-information.
  261. //
  262. DBG_ASSERT( ppInfo, (TEXT("_ppinfo_net_get_info passed in NULL LPPI2 *")) );
  263. DBG_ASSERT( pAllocator, (TEXT("_ppinfo_net_get_info passed in NULL Allocator")) );
  264. DBG_ASSERT( lpBufAllocated, (TEXT("_ppinfo_net_get_info passed in NULL buffer allocated return size")) );
  265. *ppInfo = NULL; // NULL out ppInfo, just in case
  266. *lpBufAllocated = 0; // Set allocated size to zero
  267. ZeroMemory(&pi2, sizeof(PRINTER_INFO_2));
  268. if (!ppinfo_Get(pIniPort, &pi2))
  269. goto BailOut;
  270. pszPortName = pIniPort->GetPortName();
  271. dwAllocSize = ( ( pi2.pPrinterName ? lstrlen( pi2.pPrinterName) + 1 : 0) +
  272. ( pszPortName ? lstrlen( pszPortName ) + 1 : 0) +
  273. ( pi2.pDriverName ? lstrlen( pi2.pDriverName ) + 1 : 0) +
  274. 7 * 1 ) * sizeof(TCHAR) + sizeof(PRINTER_INFO_2);
  275. pInfo = (PPRINTER_INFO_2)pAllocator( dwAllocSize );
  276. if (NULL == pInfo)
  277. goto Cleanup;
  278. pszString = ENDOFBUFFER( pInfo, dwAllocSize );
  279. // Set non-string entries.
  280. //
  281. pInfo->cJobs = pi2.cJobs;
  282. pInfo->Status = pi2.Status;
  283. pInfo->pDevMode = NULL;
  284. pInfo->pSecurityDescriptor = NULL;
  285. pInfo->Attributes = PRINTER_ATTRIBUTE_NETWORK;
  286. pInfo->Priority = pi2.Priority;
  287. pInfo->StartTime = pi2.StartTime;
  288. pInfo->UntilTime = pi2.UntilTime;
  289. pInfo->AveragePPM = pi2.AveragePPM;
  290. // Set any remaining fields that we can't fill to reasonable values.
  291. //
  292. _ppinfo_set_str(&pInfo->pPrinterName , pi2.pPrinterName , &pszString);
  293. _ppinfo_set_str(&pInfo->pShareName , g_szEmptyString , &pszString);
  294. _ppinfo_set_str(&pInfo->pPortName , pszPortName , &pszString);
  295. _ppinfo_set_str(&pInfo->pDriverName , pi2.pDriverName , &pszString);
  296. _ppinfo_set_str(&pInfo->pComment , g_szEmptyString , &pszString);
  297. _ppinfo_set_str(&pInfo->pLocation , g_szEmptyString , &pszString);
  298. _ppinfo_set_str(&pInfo->pSepFile , g_szEmptyString , &pszString);
  299. _ppinfo_set_str(&pInfo->pPrintProcessor, g_szEmptyString , &pszString);
  300. _ppinfo_set_str(&pInfo->pDatatype , g_szEmptyString , &pszString);
  301. _ppinfo_set_str(&pInfo->pParameters , g_szEmptyString , &pszString);
  302. *lpBufAllocated = dwAllocSize; // Set the size to what we have allocated
  303. *ppInfo = pInfo; // Return the allocated structure
  304. // Since we've allocated our strings in ppinfo_get, we will need
  305. // to explicitly free them.
  306. //
  307. bRet = TRUE;
  308. Cleanup:
  309. if (pi2.pPrinterName) memFreeStr(pi2.pPrinterName);
  310. if (pi2.pDriverName) memFreeStr(pi2.pDriverName);
  311. BailOut:
  312. return bRet;
  313. }
  314. /*****************************************************************************\
  315. * _ppinfo_calc_level1 (Local Routine)
  316. *
  317. * Calculates the amount of buffer space needed to store a single level 1
  318. * GetPrinter() result buffer.
  319. *
  320. \*****************************************************************************/
  321. DWORD _ppinfo_calc_level1(
  322. PPRINTER_INFO_2 pSrcInfo)
  323. {
  324. DWORD cbSize;
  325. //
  326. // Figure out how many bytes of buffer space we're going to need.
  327. //
  328. cbSize = sizeof(PRINTER_INFO_1) +
  329. utlStrSize(g_szEmptyString) + // description
  330. utlStrSize(pSrcInfo->pPrinterName) + // name
  331. utlStrSize(pSrcInfo->pComment); // comment
  332. return cbSize;
  333. }
  334. /*****************************************************************************\
  335. * _ppinfo_calc_level2 (Local Routine)
  336. *
  337. * Calculates the amount of buffer space needed to
  338. * store a single level 2 GetPrinter() result buffer.
  339. *
  340. \*****************************************************************************/
  341. DWORD _ppinfo_calc_level2(
  342. LPCTSTR pszServerName,
  343. PPRINTER_INFO_2 pSrcInfo)
  344. {
  345. DWORD cbSize;
  346. LPDEVMODE pDevmode;
  347. //
  348. // Figure out how many bytes of buffer space we're going to need.
  349. //
  350. cbSize = sizeof(PRINTER_INFO_2) +
  351. utlStrSize(pszServerName) + // Server Name
  352. utlStrSize(pSrcInfo->pPrinterName) + // Printer Name
  353. utlStrSize(pSrcInfo->pShareName) + // Share Name
  354. utlStrSize(pSrcInfo->pPortName) + // Port Name
  355. utlStrSize(pSrcInfo->pDriverName) + // Driver Name
  356. utlStrSize(pSrcInfo->pComment) + // Comment
  357. utlStrSize(pSrcInfo->pLocation) + // Location
  358. utlStrSize(pSrcInfo->pSepFile) + // Separator file
  359. utlStrSize(pSrcInfo->pPrintProcessor) + // Print processor
  360. utlStrSize(pSrcInfo->pDatatype) + // Data type
  361. utlStrSize(pSrcInfo->pParameters); // Parameters
  362. if (pSrcInfo->pDevMode != NULL) {
  363. pDevmode = pSrcInfo->pDevMode;
  364. cbSize += pDevmode->dmSize + pDevmode->dmDriverExtra;
  365. }
  366. return cbSize;
  367. }
  368. /*****************************************************************************\
  369. * _ppinfo_calc_level4 (Local Routine)
  370. *
  371. * Calculates the amount of buffer space needed to
  372. * store a single level 4 GetPrinter() result buffer.
  373. *
  374. \*****************************************************************************/
  375. DWORD _ppinfo_calc_level4(
  376. PPRINTER_INFO_2 pSrcInfo)
  377. {
  378. DWORD cbSize;
  379. //
  380. // Figure out how many bytes of buffer space we're going to need.
  381. //
  382. cbSize = sizeof(PRINTER_INFO_4) +
  383. utlStrSize(pSrcInfo->pPrinterName) + // Printer Name
  384. utlStrSize(pSrcInfo->pServerName);
  385. return cbSize;
  386. }
  387. /*****************************************************************************\
  388. * _ppinfo_calc_level2 (Local Routine)
  389. *
  390. * Calculates the amount of buffer space needed to
  391. * store a single level 5 GetPrinter() result buffer.
  392. *
  393. \*****************************************************************************/
  394. DWORD _ppinfo_calc_level5(
  395. PPRINTER_INFO_2 pSrcInfo)
  396. {
  397. DWORD cbSize;
  398. //
  399. // Figure out how many bytes of buffer space we're going to need.
  400. //
  401. cbSize = sizeof(PRINTER_INFO_5) +
  402. utlStrSize(pSrcInfo->pPrinterName) + // Printer Name
  403. utlStrSize(pSrcInfo->pPortName);
  404. return cbSize;
  405. }
  406. /*****************************************************************************\
  407. * _ppinfo_build_level1 (Local Routine)
  408. *
  409. * Given a pointer to a source PRINTER_INFO_2 structure, a
  410. * destination PRINTER_INFO_1 structure and a pointer to the
  411. * start of string storage space, fills the PRINTER_INFO_1 structure.
  412. *
  413. * Called by GetPrinter and EnumPrinters, level 1. Returns an
  414. * LPSTR pointer to the last available data byte remaining in the
  415. * buffer.
  416. *
  417. \*****************************************************************************/
  418. LPTSTR _ppinfo_build_level1(
  419. PPRINTER_INFO_2 pSrcInfo,
  420. PPRINTER_INFO_1 pDstInfo,
  421. LPTSTR pszString)
  422. {
  423. // Flags.
  424. //
  425. pDstInfo->Flags = PRINTER_ENUM_CONTAINER;
  426. pDstInfo->Flags |= PRINTER_ENUM_HIDE;
  427. // Description
  428. //
  429. // CODEWORK - The Win32 structure has a field for "description" that has
  430. // no equivalent in the network printer info structure. What do we
  431. // really want here? For now, I'm copying in an empty string as a
  432. // placeholder.
  433. //
  434. _ppinfo_set_str(&pDstInfo->pDescription, g_szEmptyString , &pszString);
  435. _ppinfo_set_str(&pDstInfo->pName , pSrcInfo->pPrinterName, &pszString);
  436. _ppinfo_set_str(&pDstInfo->pComment , pSrcInfo->pComment , &pszString);
  437. return pszString;
  438. }
  439. /*****************************************************************************\
  440. * _ppinfo_build_level2 (Local Routine)
  441. *
  442. * Given a server name, a pointer to a source PRINTER_INFO_2
  443. * structure, a destination PRINTER_INFO_2 structure and a pointer to
  444. * the start of string storage space, fills the PRINTER_INFO_2 structure.
  445. *
  446. * Called by GetPrinter and EnumPrinters, level 2. Returns an
  447. * LPTSTR pointer to the last available data char in the data buffer.
  448. *
  449. \*****************************************************************************/
  450. LPTSTR _ppinfo_build_level2(
  451. LPCTSTR pszServerName,
  452. PPRINTER_INFO_2 pSrcInfo,
  453. PPRINTER_INFO_2 pDstInfo,
  454. LPTSTR pszString)
  455. {
  456. // Set non-string entries.
  457. //
  458. pDstInfo->pSecurityDescriptor = NULL;
  459. pDstInfo->Attributes = pSrcInfo->Attributes;
  460. pDstInfo->Priority = pSrcInfo->Priority;
  461. pDstInfo->DefaultPriority = pSrcInfo->Priority;
  462. pDstInfo->StartTime = pSrcInfo->StartTime;
  463. pDstInfo->UntilTime = pSrcInfo->UntilTime;
  464. pDstInfo->Status = pSrcInfo->Status;
  465. pDstInfo->cJobs = pSrcInfo->cJobs;
  466. pDstInfo->AveragePPM = pSrcInfo->AveragePPM;
  467. // Copy the required data to the Win 32 PRINTER_INFO_2 structure.
  468. //
  469. // SPECWORK - several of these fields are filled with "" placeholders.
  470. // We probably need to put real information in some of them.
  471. // The current inetpp protocol does not supply this information to us.
  472. //
  473. _ppinfo_set_str(&pDstInfo->pServerName , pszServerName , &pszString);
  474. _ppinfo_set_str(&pDstInfo->pPrinterName , pSrcInfo->pPrinterName , &pszString);
  475. _ppinfo_set_str(&pDstInfo->pShareName , pSrcInfo->pShareName , &pszString);
  476. _ppinfo_set_str(&pDstInfo->pPortName , pSrcInfo->pPortName , &pszString);
  477. _ppinfo_set_str(&pDstInfo->pDriverName , pSrcInfo->pDriverName , &pszString);
  478. _ppinfo_set_str(&pDstInfo->pComment , pSrcInfo->pComment , &pszString);
  479. _ppinfo_set_str(&pDstInfo->pLocation , pSrcInfo->pLocation , &pszString);
  480. _ppinfo_set_str(&pDstInfo->pSepFile , pSrcInfo->pSepFile , &pszString);
  481. _ppinfo_set_str(&pDstInfo->pPrintProcessor, pSrcInfo->pPrintProcessor, &pszString);
  482. _ppinfo_set_str(&pDstInfo->pDatatype , pSrcInfo->pDatatype , &pszString);
  483. _ppinfo_set_str(&pDstInfo->pParameters , pSrcInfo->pParameters , &pszString);
  484. // If a devmode exist, then it will need to be copied as well.
  485. //
  486. if (pSrcInfo->pDevMode != NULL) {
  487. memCopy((LPSTR *)&pDstInfo->pDevMode,
  488. (LPSTR)pSrcInfo->pDevMode,
  489. pSrcInfo->pDevMode->dmSize + pSrcInfo->pDevMode->dmDriverExtra,
  490. (LPSTR *)&pszString);
  491. } else {
  492. pDstInfo->pDevMode = NULL;
  493. }
  494. return pszString;
  495. }
  496. /*****************************************************************************\
  497. * _ppinfo_build_level4 (Local Routine)
  498. *
  499. * Given a server name, a pointer to a source PRINTER_INFO_2
  500. * structure, a destination PRINTER_INFO_5 structure and a pointer to
  501. * the start of string storage space, fills the PRINTER_INFO_4 structure.
  502. *
  503. * Called by GetPrinter and EnumPrinters, level 2. Returns an
  504. * LPTSTR pointer to the last available data char in the data buffer.
  505. *
  506. \*****************************************************************************/
  507. LPTSTR _ppinfo_build_level4(
  508. PPRINTER_INFO_2 pSrcInfo,
  509. PPRINTER_INFO_4 pDstInfo,
  510. LPTSTR pszString)
  511. {
  512. // Set non-string entries.
  513. //
  514. pDstInfo->Attributes = pSrcInfo->Attributes;
  515. // Copy the required data to the Win 32 PRINTER_INFO_4 structure.
  516. //
  517. _ppinfo_set_str(&pDstInfo->pPrinterName, pSrcInfo->pPrinterName, &pszString);
  518. _ppinfo_set_str(&pDstInfo->pServerName , pSrcInfo->pServerName , &pszString);
  519. return pszString;
  520. }
  521. /*****************************************************************************\
  522. * _ppinfo_build_level5 (Local Routine)
  523. *
  524. * Given a server name, a pointer to a source PRINTER_INFO_2
  525. * structure, a destination PRINTER_INFO_5 structure and a pointer to
  526. * the start of string storage space, fills the PRINTER_INFO_5 structure.
  527. *
  528. * Called by GetPrinter and EnumPrinters, level 2. Returns an
  529. * LPTSTR pointer to the last available data char in the data buffer.
  530. *
  531. \*****************************************************************************/
  532. LPTSTR _ppinfo_build_level5(
  533. PPRINTER_INFO_2 pSrcInfo,
  534. PPRINTER_INFO_5 pDstInfo,
  535. LPTSTR pszString)
  536. {
  537. // Set non-string entries.
  538. //
  539. pDstInfo->Attributes = pSrcInfo->Attributes;
  540. pDstInfo->DeviceNotSelectedTimeout = 0;
  541. pDstInfo->TransmissionRetryTimeout = 0;
  542. // Copy the required data to the Win 32 PRINTER_INFO_5 structure.
  543. //
  544. _ppinfo_set_str(&pDstInfo->pPrinterName, pSrcInfo->pPrinterName, &pszString);
  545. _ppinfo_set_str(&pDstInfo->pPortName , pSrcInfo->pPortName , &pszString);
  546. return pszString;
  547. }
  548. /*****************************************************************************\
  549. * _ppinfo_get_level1 (Local Routine)
  550. *
  551. * Given pInfo, a block of information on a printer returned by a
  552. * DosPrintQGetInfo call, fill a PRINTER_INFO_1 structure. Returns
  553. * TRUE if successful, FALSE otherwise. Places the number of bytes
  554. * of (lpbBuffer) used in the DWORD pointed to by (pcbNeeded).
  555. *
  556. \*****************************************************************************/
  557. BOOL _ppinfo_get_level1(
  558. PPRINTER_INFO_2 pSrcInfo,
  559. LPBYTE lpbBuffer,
  560. DWORD cbBuf,
  561. LPDWORD pcbNeeded)
  562. {
  563. // Figure out how many bytes of buffer space we're going to need.
  564. // Set error code and return failure if we don't have enough.
  565. //
  566. *pcbNeeded = _ppinfo_calc_level1(pSrcInfo);
  567. if (*pcbNeeded > cbBuf) {
  568. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  569. return FALSE;
  570. }
  571. // Copy the required data from the structure to the Win32
  572. // structure.
  573. //
  574. _ppinfo_build_level1(pSrcInfo,
  575. (PPRINTER_INFO_1)lpbBuffer,
  576. ENDOFBUFFER(lpbBuffer, cbBuf));
  577. return TRUE;
  578. }
  579. /*****************************************************************************\
  580. * _ppinfo_get_level2 (Local Routine)
  581. *
  582. * Given pInfo, a block of information on a printer returned by a
  583. * PrintQGetInfo call, fill a PRINTER_INFO_2 structure. Returns
  584. * TRUE if successful, FALSE otherwise. Places the number of bytes of
  585. * (lpbBuffer) used in the DWORD pointed to by (pcbNeeded).
  586. *
  587. \*****************************************************************************/
  588. BOOL _ppinfo_get_level2(
  589. PPRINTER_INFO_2 pSrcInfo,
  590. LPBYTE lpbBuffer,
  591. DWORD cbBuf,
  592. LPDWORD pcbNeeded)
  593. {
  594. // Figure out how many bytes of buffer space we're going to need.
  595. // Set error code and return failure if we don't have enough.
  596. //
  597. *pcbNeeded = _ppinfo_calc_level2(g_szEmptyString, pSrcInfo);
  598. if (*pcbNeeded > cbBuf) {
  599. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  600. return FALSE;
  601. }
  602. //
  603. // Copy the required data to the Win 32 PRINTER_INFO_2 structure.
  604. //
  605. _ppinfo_build_level2(g_szEmptyString,
  606. pSrcInfo,
  607. (PPRINTER_INFO_2)lpbBuffer,
  608. ENDOFBUFFER(lpbBuffer, cbBuf));
  609. return TRUE;
  610. }
  611. /*****************************************************************************\
  612. * _ppinfo_get_level4 (Local Routine)
  613. *
  614. * Given pInfo, a block of information on a printer returned by a
  615. * PrintQGetInfo call, fill a PRINTER_INFO_4 structure. Returns
  616. * TRUE if successful, FALSE otherwise. Places the number of bytes of
  617. * (lpbBuffer) used in the DWORD pointed to by (pcbNeeded).
  618. *
  619. \*****************************************************************************/
  620. BOOL _ppinfo_get_level4(
  621. PPRINTER_INFO_2 pSrcInfo,
  622. LPBYTE lpbBuffer,
  623. DWORD cbBuf,
  624. LPDWORD pcbNeeded)
  625. {
  626. // Figure out how many bytes of buffer space we're going to need.
  627. // Set error code and return failure if we don't have enough.
  628. //
  629. *pcbNeeded = _ppinfo_calc_level4(pSrcInfo);
  630. if (*pcbNeeded > cbBuf) {
  631. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  632. return FALSE;
  633. }
  634. //
  635. // Copy the required data to the Win 32 PRINTER_INFO_2 structure.
  636. //
  637. _ppinfo_build_level4(pSrcInfo,
  638. (PPRINTER_INFO_4)lpbBuffer,
  639. ENDOFBUFFER(lpbBuffer, cbBuf));
  640. return TRUE;
  641. }
  642. /*****************************************************************************\
  643. * _ppinfo_get_level5 (Local Routine)
  644. *
  645. * Given pInfo, a block of information on a printer returned by a
  646. * PrintQGetInfo call, fill a PRINTER_INFO_5 structure. Returns
  647. * TRUE if successful, FALSE otherwise. Places the number of bytes of
  648. * (lpbBuffer) used in the DWORD pointed to by (pcbNeeded).
  649. *
  650. \*****************************************************************************/
  651. BOOL _ppinfo_get_level5(
  652. PPRINTER_INFO_2 pSrcInfo,
  653. LPBYTE lpbBuffer,
  654. DWORD cbBuf,
  655. LPDWORD pcbNeeded)
  656. {
  657. // Figure out how many bytes of buffer space we're going to need.
  658. // Set error code and return failure if we don't have enough.
  659. //
  660. *pcbNeeded = _ppinfo_calc_level5(pSrcInfo);
  661. if (*pcbNeeded > cbBuf) {
  662. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  663. return FALSE;
  664. }
  665. //
  666. // Copy the required data to the Win 32 PRINTER_INFO_2 structure.
  667. //
  668. _ppinfo_build_level5(pSrcInfo,
  669. (PPRINTER_INFO_5)lpbBuffer,
  670. ENDOFBUFFER(lpbBuffer, cbBuf));
  671. return TRUE;
  672. }
  673. /*****************************************************************************\
  674. * _ppinfo_enumprinters_NT (Local Routine)
  675. *
  676. * This is the WinNT specific routine for EnumPrinters.
  677. *
  678. *
  679. \*****************************************************************************/
  680. BOOL _ppinfo_enumprinters(
  681. DWORD dwType,
  682. LPTSTR pszName,
  683. DWORD dwLevel,
  684. LPBYTE pPrinterEnum,
  685. DWORD cbBuf,
  686. LPDWORD pcbNeeded,
  687. LPDWORD pcbReturned)
  688. {
  689. BOOL bReturn = FALSE;
  690. // Throw back enumeration requests that we don't handle. The routing
  691. // layer above us is specifically looking for the ERROR_INVALID_NAME.
  692. //
  693. if (dwType & PRINTER_ENUM_NOTFORUS)
  694. goto enum_name_failure;
  695. // If the request is one that we handle, but the caller didn't supply
  696. // a printer name, we'll fail. Again, to keep things going as the
  697. // router expects, we must return an ERROR_INVALID_NAME condition.
  698. //
  699. if (utlStrSize(pszName) == 0) {
  700. if ((dwLevel == PRINT_LEVEL_1) && (dwType & PRINTER_ENUM_NAME)) {
  701. return _ppinfo_describe_provider((LPPRINTER_INFO_1)pPrinterEnum,
  702. cbBuf,
  703. pcbNeeded,
  704. pcbReturned);
  705. } else {
  706. goto enum_name_failure;
  707. }
  708. } else {
  709. if ((dwLevel == PRINT_LEVEL_1) && (dwType & PRINTER_ENUM_NAME)) {
  710. // In this case, the user has asked us to enumerate the
  711. // printers in some domain. Until we decide what we really want
  712. // to do. We'll simply return success with an empty enumeration.
  713. //
  714. goto enum_empty_success;
  715. }
  716. }
  717. // Check Remote enumeration. Remote enumeration valid only if
  718. // it's a level-1 printer.
  719. //
  720. if (dwType & PRINTER_ENUM_REMOTE) {
  721. if (dwLevel != PRINT_LEVEL_1) {
  722. goto enum_level_failure;
  723. } else {
  724. // In this case, the user has asked us to enumerate the
  725. // printers in our domain. Until we decide what we really
  726. // want to do, we'll simply return success with an empty
  727. // enumeration.
  728. //
  729. goto enum_empty_success;
  730. }
  731. } else if (dwType & PRINTER_ENUM_CONNECTIONS) {
  732. // In this case, the user has asked us to enumerate our favorite
  733. // connections.
  734. //
  735. enum_empty_success:
  736. *pcbNeeded = 0;
  737. *pcbReturned = 0;
  738. return TRUE;
  739. }
  740. DBG_MSG(DBG_LEV_INFO, (TEXT("Info: PPEnumPrinters: Type(%ld) Name(%s) Level(%ld)"), dwType, pszName, dwLevel));
  741. // Check print-levels. These are error cases. We should
  742. // really have performed the enumeration above.
  743. //
  744. switch (dwLevel) {
  745. case PRINT_LEVEL_1:
  746. case PRINT_LEVEL_2:
  747. enum_name_failure:
  748. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: PPEnumPrinters: Invalid Name")));
  749. SetLastError(ERROR_INVALID_NAME);
  750. break;
  751. default:
  752. enum_level_failure:
  753. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: PPEnumPrinters: Invalid Level: %d"), dwLevel));
  754. SetLastError(ERROR_INVALID_LEVEL);
  755. break;
  756. }
  757. return FALSE;
  758. }
  759. /*****************************************************************************\
  760. * PPEnumPrinters
  761. *
  762. * Enumerates the available printers. Returns TRUE if successful. Otherwise,
  763. * it returns FALSE.
  764. *
  765. * NOTE: Supports level 2 PRINTER_INFO to provide Point-and-Print
  766. * functionality.
  767. *
  768. \*****************************************************************************/
  769. BOOL PPEnumPrinters(
  770. DWORD dwType,
  771. LPTSTR pszName,
  772. DWORD dwLevel,
  773. LPBYTE pPrinterEnum,
  774. DWORD cbBuf,
  775. LPDWORD pcbNeeded,
  776. LPDWORD pcbReturned)
  777. {
  778. DBG_MSG(DBG_LEV_CALLTREE, (TEXT("Call: PPEnumPrinters: Type(%d) Level(%d) Name(%s)"), dwType, dwLevel, (pszName ? pszName : TEXT("<NULL>"))));
  779. return _ppinfo_enumprinters(dwType,
  780. pszName,
  781. dwLevel,
  782. pPrinterEnum,
  783. cbBuf,
  784. pcbNeeded,
  785. pcbReturned);
  786. }
  787. /*****************************************************************************\
  788. * PPGetPrinter
  789. *
  790. * Retrieves information about a printer. Returns TRUE if successful, FALSE
  791. * if an error occurred. NOTE: Supports level 2 Printer_INFO to provide
  792. * Point and Print functionality for Chicago.
  793. *
  794. \*****************************************************************************/
  795. BOOL PPGetPrinter(
  796. HANDLE hPrinter,
  797. DWORD dwLevel,
  798. LPBYTE lpbPrinter,
  799. DWORD cbBuf,
  800. LPDWORD pcbNeeded)
  801. {
  802. PCINETMONPORT pIniPort;
  803. PPRINTER_INFO_2 pSrcInfo;
  804. DWORD cbSrcSize;
  805. DWORD dwTemp;
  806. BOOL bResult = FALSE;
  807. DBG_MSG(DBG_LEV_CALLTREE, (TEXT("Call: PPGetPrinter: Printer(%08lX) Level(%ld)"), hPrinter, dwLevel));
  808. if (pcbNeeded)
  809. *pcbNeeded = 0;
  810. semEnterCrit();
  811. // Make sure we have a valid printer handle.
  812. //
  813. if (pIniPort = utlValidatePrinterHandle(hPrinter)) {
  814. if (pIniPort->BeginReadGetPrinterCache (&pSrcInfo)) {
  815. // Reformat the data according to the requested info Level.
  816. //
  817. switch (dwLevel) {
  818. case PRINT_LEVEL_1:
  819. bResult = _ppinfo_get_level1(pSrcInfo, lpbPrinter, cbBuf, pcbNeeded);
  820. break;
  821. case PRINT_LEVEL_2:
  822. bResult = _ppinfo_get_level2(pSrcInfo, lpbPrinter, cbBuf, pcbNeeded);
  823. break;
  824. case PRINT_LEVEL_4:
  825. bResult = _ppinfo_get_level4(pSrcInfo, lpbPrinter, cbBuf, pcbNeeded);
  826. break;
  827. case PRINT_LEVEL_5:
  828. bResult = _ppinfo_get_level5(pSrcInfo, lpbPrinter, cbBuf, pcbNeeded);
  829. break;
  830. default:
  831. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: PPGetPrinter: Invalid Level")));
  832. SetLastError(ERROR_INVALID_LEVEL);
  833. bResult = FALSE;
  834. break;
  835. }
  836. }
  837. pIniPort->EndReadGetPrinterCache ();
  838. if (GetLastError() == ERROR_ACCESS_DENIED) {
  839. pIniPort->InvalidateGetPrinterCache ();
  840. }
  841. }
  842. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  843. pcbNeeded &&
  844. *pcbNeeded == 0) {
  845. // We can't set ERROR_INSUFFICIENT_BUFFER here since it was an internal error
  846. // and we are not reporting a size
  847. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  848. }
  849. semLeaveCrit();
  850. return bResult;
  851. }