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.

1164 lines
35 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, *buf should point to the last available byte in the buffer.
  141. *
  142. \*****************************************************************************/
  143. VOID _ppinfo_set_str(
  144. LPTSTR *dest,
  145. LPCTSTR src,
  146. LPTSTR *buf)
  147. {
  148. if (src != NULL) {
  149. // Place string at end of buffer. This performs pointer
  150. // arithmatic, so the offsets are TCHAR in size.
  151. //
  152. (*buf) -= lstrlen(src);
  153. DBG_ASSERT( ((DWORD_PTR)dest < (DWORD_PTR)*buf) ,
  154. (TEXT("String fill overrun in _ppinfo_set_str"))
  155. );
  156. lstrcpy(*buf, src);
  157. // Place string address in structure and save pointer to new
  158. // last available byte.
  159. //
  160. *dest = *buf;
  161. (*buf)--;
  162. } else {
  163. *dest = TEXT('\0');
  164. }
  165. }
  166. /*****************************************************************************\
  167. * _ppinfo_describe_provider (Local Routine)
  168. *
  169. * Fills a PRINTER_INFO_1 structure with information about the print provider.
  170. * Returns TRUE if successful. Otherwise, it returns FALSE. Extended error
  171. * information is available from GetLastError.
  172. *
  173. \*****************************************************************************/
  174. BOOL _ppinfo_describe_provider(
  175. LPPRINTER_INFO_1 pInfo,
  176. DWORD cbSize,
  177. LPDWORD pcbNeeded,
  178. LPDWORD pcbReturned)
  179. {
  180. LPTSTR pszString;
  181. // Calculate the space needed (in bytes) that is necessary to
  182. // store the information for the print-processor.
  183. //
  184. *pcbNeeded = sizeof(PRINTER_INFO_1) +
  185. utlStrSize(g_szDescription) +
  186. utlStrSize(g_szProviderName) +
  187. utlStrSize(g_szComment);
  188. if (*pcbNeeded > cbSize) {
  189. *pcbReturned = 0;
  190. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: _describe_provider: Not enough memory")));
  191. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  192. return FALSE;
  193. }
  194. // Initialize the fields which do not need to copy strings.
  195. //
  196. pInfo->Flags = (PRINTER_ENUM_ICON1 | PRINTER_ENUM_CONTAINER);
  197. //
  198. // Hide this provider from the UI, there is nothing underneath to enumerate.
  199. //
  200. #if WINNT32
  201. pInfo->Flags |= PRINTER_ENUM_HIDE;
  202. #endif
  203. // Set the string information. First set the (pszString) pointer
  204. // to the first location at the end of the buffer which will store
  205. // the string.
  206. //
  207. pszString = ENDOFBUFFER(pInfo, cbSize);
  208. _ppinfo_set_str(&pInfo->pDescription, g_szDescription , &pszString);
  209. _ppinfo_set_str(&pInfo->pName , g_szProviderName, &pszString);
  210. _ppinfo_set_str(&pInfo->pComment , g_szComment , &pszString);
  211. // Return the number of structures copied.
  212. //
  213. *pcbReturned = 1;
  214. return TRUE;
  215. }
  216. /*****************************************************************************\
  217. * _ppinfo_net_get_info (Local Routine)
  218. *
  219. * Fills a supplied PRINTER_INFO_2 structure with all the information
  220. * we can dig up on the specified IPP1 print server.
  221. *
  222. * Takes a pointer to PPRINTER_INFO_2 which is allocated to be the correct size
  223. *
  224. * Returns TRUE if successful, FALSE if otherwise.
  225. *
  226. \*****************************************************************************/
  227. BOOL _ppinfo_net_get_info(
  228. IN PCINETMONPORT pIniPort,
  229. OUT PPRINTER_INFO_2 *ppInfo,
  230. OUT LPDWORD lpBufAllocated,
  231. IN ALLOCATORFN pAllocator)
  232. {
  233. PRINTER_INFO_2 pi2;
  234. PPRINTER_INFO_2 pInfo;
  235. LPTSTR pszString;
  236. LPCTSTR pszPortName;
  237. DWORD dwAllocSize;
  238. BOOL bRet = FALSE;
  239. // Make a server-call to get the printer-information.
  240. //
  241. DBG_ASSERT( ppInfo, (TEXT("_ppinfo_net_get_info passed in NULL LPPI2 *")) );
  242. DBG_ASSERT( pAllocator, (TEXT("_ppinfo_net_get_info passed in NULL Allocator")) );
  243. DBG_ASSERT( lpBufAllocated, (TEXT("_ppinfo_net_get_info passed in NULL buffer allocated return size")) );
  244. *ppInfo = NULL; // NULL out ppInfo, just in case
  245. *lpBufAllocated = 0; // Set allocated size to zero
  246. ZeroMemory(&pi2, sizeof(PRINTER_INFO_2));
  247. if (!ppinfo_Get(pIniPort, &pi2))
  248. goto BailOut;
  249. pszPortName = pIniPort->GetPortName();
  250. dwAllocSize = ( ( pi2.pPrinterName ? lstrlen( pi2.pPrinterName) + 1 : 0) +
  251. ( pszPortName ? lstrlen( pszPortName ) + 1 : 0) +
  252. ( pi2.pDriverName ? lstrlen( pi2.pDriverName ) + 1 : 0) +
  253. 7 * 1 ) * sizeof(TCHAR) + sizeof(PRINTER_INFO_2);
  254. pInfo = (PPRINTER_INFO_2)pAllocator( dwAllocSize );
  255. if (NULL == pInfo)
  256. goto Cleanup;
  257. pszString = ENDOFBUFFER( pInfo, dwAllocSize );
  258. // Set non-string entries.
  259. //
  260. pInfo->cJobs = pi2.cJobs;
  261. pInfo->Status = pi2.Status;
  262. pInfo->pDevMode = NULL;
  263. pInfo->pSecurityDescriptor = NULL;
  264. #if 0
  265. pInfo->Attributes = PRINTER_ATTRIBUTE_SHARED;
  266. #else
  267. pInfo->Attributes = PRINTER_ATTRIBUTE_NETWORK;
  268. #endif
  269. pInfo->Priority = pi2.Priority;
  270. pInfo->StartTime = pi2.StartTime;
  271. pInfo->UntilTime = pi2.UntilTime;
  272. pInfo->AveragePPM = pi2.AveragePPM;
  273. // Set any remaining fields that we can't fill to reasonable values.
  274. //
  275. _ppinfo_set_str(&pInfo->pPrinterName , pi2.pPrinterName , &pszString);
  276. _ppinfo_set_str(&pInfo->pShareName , g_szEmptyString , &pszString);
  277. _ppinfo_set_str(&pInfo->pPortName , pszPortName , &pszString);
  278. _ppinfo_set_str(&pInfo->pDriverName , pi2.pDriverName , &pszString);
  279. _ppinfo_set_str(&pInfo->pComment , g_szEmptyString , &pszString);
  280. _ppinfo_set_str(&pInfo->pLocation , g_szEmptyString , &pszString);
  281. _ppinfo_set_str(&pInfo->pSepFile , g_szEmptyString , &pszString);
  282. _ppinfo_set_str(&pInfo->pPrintProcessor, g_szEmptyString , &pszString);
  283. _ppinfo_set_str(&pInfo->pDatatype , g_szEmptyString , &pszString);
  284. _ppinfo_set_str(&pInfo->pParameters , g_szEmptyString , &pszString);
  285. *lpBufAllocated = dwAllocSize; // Set the size to what we have allocated
  286. *ppInfo = pInfo; // Return the allocated structure
  287. // Since we've allocated our strings in ppinfo_get, we will need
  288. // to explicitly free them.
  289. //
  290. bRet = TRUE;
  291. Cleanup:
  292. if (pi2.pPrinterName) memFreeStr(pi2.pPrinterName);
  293. if (pi2.pDriverName) memFreeStr(pi2.pDriverName);
  294. BailOut:
  295. return bRet;
  296. }
  297. /*****************************************************************************\
  298. * _ppinfo_calc_level1 (Local Routine)
  299. *
  300. * Calculates the amount of buffer space needed to store a single level 1
  301. * GetPrinter() result buffer.
  302. *
  303. \*****************************************************************************/
  304. DWORD _ppinfo_calc_level1(
  305. PPRINTER_INFO_2 pSrcInfo)
  306. {
  307. DWORD cbSize;
  308. //
  309. // Figure out how many bytes of buffer space we're going to need.
  310. //
  311. cbSize = sizeof(PRINTER_INFO_1) +
  312. utlStrSize(g_szEmptyString) + // description
  313. utlStrSize(pSrcInfo->pPrinterName) + // name
  314. utlStrSize(pSrcInfo->pComment); // comment
  315. return cbSize;
  316. }
  317. /*****************************************************************************\
  318. * _ppinfo_calc_level2 (Local Routine)
  319. *
  320. * Calculates the amount of buffer space needed to
  321. * store a single level 2 GetPrinter() result buffer.
  322. *
  323. \*****************************************************************************/
  324. DWORD _ppinfo_calc_level2(
  325. LPCTSTR pszServerName,
  326. PPRINTER_INFO_2 pSrcInfo)
  327. {
  328. DWORD cbSize;
  329. LPDEVMODE pDevmode;
  330. //
  331. // Figure out how many bytes of buffer space we're going to need.
  332. //
  333. cbSize = sizeof(PRINTER_INFO_2) +
  334. utlStrSize(pszServerName) + // Server Name
  335. utlStrSize(pSrcInfo->pPrinterName) + // Printer Name
  336. utlStrSize(pSrcInfo->pShareName) + // Share Name
  337. utlStrSize(pSrcInfo->pPortName) + // Port Name
  338. utlStrSize(pSrcInfo->pDriverName) + // Driver Name
  339. utlStrSize(pSrcInfo->pComment) + // Comment
  340. utlStrSize(pSrcInfo->pLocation) + // Location
  341. utlStrSize(pSrcInfo->pSepFile) + // Separator file
  342. utlStrSize(pSrcInfo->pPrintProcessor) + // Print processor
  343. utlStrSize(pSrcInfo->pDatatype) + // Data type
  344. utlStrSize(pSrcInfo->pParameters); // Parameters
  345. if (pSrcInfo->pDevMode != NULL) {
  346. pDevmode = pSrcInfo->pDevMode;
  347. cbSize += pDevmode->dmSize + pDevmode->dmDriverExtra;
  348. }
  349. return cbSize;
  350. }
  351. #if WINNT32
  352. /*****************************************************************************\
  353. * _ppinfo_calc_level4 (Local Routine)
  354. *
  355. * Calculates the amount of buffer space needed to
  356. * store a single level 4 GetPrinter() result buffer.
  357. *
  358. \*****************************************************************************/
  359. DWORD _ppinfo_calc_level4(
  360. PPRINTER_INFO_2 pSrcInfo)
  361. {
  362. DWORD cbSize;
  363. //
  364. // Figure out how many bytes of buffer space we're going to need.
  365. //
  366. cbSize = sizeof(PRINTER_INFO_4) +
  367. utlStrSize(pSrcInfo->pPrinterName) + // Printer Name
  368. utlStrSize(pSrcInfo->pServerName);
  369. return cbSize;
  370. }
  371. #endif
  372. /*****************************************************************************\
  373. * _ppinfo_calc_level2 (Local Routine)
  374. *
  375. * Calculates the amount of buffer space needed to
  376. * store a single level 5 GetPrinter() result buffer.
  377. *
  378. \*****************************************************************************/
  379. DWORD _ppinfo_calc_level5(
  380. PPRINTER_INFO_2 pSrcInfo)
  381. {
  382. DWORD cbSize;
  383. //
  384. // Figure out how many bytes of buffer space we're going to need.
  385. //
  386. cbSize = sizeof(PRINTER_INFO_5) +
  387. utlStrSize(pSrcInfo->pPrinterName) + // Printer Name
  388. utlStrSize(pSrcInfo->pPortName);
  389. return cbSize;
  390. }
  391. /*****************************************************************************\
  392. * _ppinfo_build_level1 (Local Routine)
  393. *
  394. * Given a pointer to a source PRINTER_INFO_2 structure, a
  395. * destination PRINTER_INFO_1 structure and a pointer to the
  396. * start of string storage space, fills the PRINTER_INFO_1 structure.
  397. *
  398. * Called by GetPrinter and EnumPrinters, level 1. Returns an
  399. * LPSTR pointer to the last available data byte remaining in the
  400. * buffer.
  401. *
  402. \*****************************************************************************/
  403. LPTSTR _ppinfo_build_level1(
  404. PPRINTER_INFO_2 pSrcInfo,
  405. PPRINTER_INFO_1 pDstInfo,
  406. LPTSTR pszString)
  407. {
  408. // Flags.
  409. //
  410. pDstInfo->Flags = PRINTER_ENUM_CONTAINER;
  411. #if WINNT32
  412. pDstInfo->Flags |= PRINTER_ENUM_HIDE;
  413. #endif
  414. // Description
  415. //
  416. // CODEWORK - The Win32 structure has a field for "description" that has
  417. // no equivalent in the network printer info structure. What do we
  418. // really want here? For now, I'm copying in an empty string as a
  419. // placeholder.
  420. //
  421. _ppinfo_set_str(&pDstInfo->pDescription, g_szEmptyString , &pszString);
  422. _ppinfo_set_str(&pDstInfo->pName , pSrcInfo->pPrinterName, &pszString);
  423. _ppinfo_set_str(&pDstInfo->pComment , pSrcInfo->pComment , &pszString);
  424. return pszString;
  425. }
  426. /*****************************************************************************\
  427. * _ppinfo_build_level2 (Local Routine)
  428. *
  429. * Given a server name, a pointer to a source PRINTER_INFO_2
  430. * structure, a destination PRINTER_INFO_2 structure and a pointer to
  431. * the start of string storage space, fills the PRINTER_INFO_2 structure.
  432. *
  433. * Called by GetPrinter and EnumPrinters, level 2. Returns an
  434. * LPTSTR pointer to the last available data char in the data buffer.
  435. *
  436. \*****************************************************************************/
  437. LPTSTR _ppinfo_build_level2(
  438. LPCTSTR pszServerName,
  439. PPRINTER_INFO_2 pSrcInfo,
  440. PPRINTER_INFO_2 pDstInfo,
  441. LPTSTR pszString)
  442. {
  443. // Set non-string entries.
  444. //
  445. pDstInfo->pSecurityDescriptor = NULL;
  446. pDstInfo->Attributes = pSrcInfo->Attributes;
  447. pDstInfo->Priority = pSrcInfo->Priority;
  448. pDstInfo->DefaultPriority = pSrcInfo->Priority;
  449. pDstInfo->StartTime = pSrcInfo->StartTime;
  450. pDstInfo->UntilTime = pSrcInfo->UntilTime;
  451. pDstInfo->Status = pSrcInfo->Status;
  452. pDstInfo->cJobs = pSrcInfo->cJobs;
  453. pDstInfo->AveragePPM = pSrcInfo->AveragePPM;
  454. // Copy the required data to the Win 32 PRINTER_INFO_2 structure.
  455. //
  456. // SPECWORK - several of these fields are filled with "" placeholders.
  457. // We probably need to put real information in some of them.
  458. // The current inetpp protocol does not supply this information to us.
  459. //
  460. _ppinfo_set_str(&pDstInfo->pServerName , pszServerName , &pszString);
  461. _ppinfo_set_str(&pDstInfo->pPrinterName , pSrcInfo->pPrinterName , &pszString);
  462. _ppinfo_set_str(&pDstInfo->pShareName , pSrcInfo->pShareName , &pszString);
  463. _ppinfo_set_str(&pDstInfo->pPortName , pSrcInfo->pPortName , &pszString);
  464. _ppinfo_set_str(&pDstInfo->pDriverName , pSrcInfo->pDriverName , &pszString);
  465. _ppinfo_set_str(&pDstInfo->pComment , pSrcInfo->pComment , &pszString);
  466. _ppinfo_set_str(&pDstInfo->pLocation , pSrcInfo->pLocation , &pszString);
  467. _ppinfo_set_str(&pDstInfo->pSepFile , pSrcInfo->pSepFile , &pszString);
  468. _ppinfo_set_str(&pDstInfo->pPrintProcessor, pSrcInfo->pPrintProcessor, &pszString);
  469. _ppinfo_set_str(&pDstInfo->pDatatype , pSrcInfo->pDatatype , &pszString);
  470. _ppinfo_set_str(&pDstInfo->pParameters , pSrcInfo->pParameters , &pszString);
  471. // If a devmode exist, then it will need to be copied as well.
  472. //
  473. if (pSrcInfo->pDevMode != NULL) {
  474. memCopy((LPSTR *)&pDstInfo->pDevMode,
  475. (LPSTR)pSrcInfo->pDevMode,
  476. pSrcInfo->pDevMode->dmSize + pSrcInfo->pDevMode->dmDriverExtra,
  477. (LPSTR *)&pszString);
  478. } else {
  479. pDstInfo->pDevMode = NULL;
  480. }
  481. return pszString;
  482. }
  483. #if WINNT32
  484. /*****************************************************************************\
  485. * _ppinfo_build_level4 (Local Routine)
  486. *
  487. * Given a server name, a pointer to a source PRINTER_INFO_2
  488. * structure, a destination PRINTER_INFO_5 structure and a pointer to
  489. * the start of string storage space, fills the PRINTER_INFO_4 structure.
  490. *
  491. * Called by GetPrinter and EnumPrinters, level 2. Returns an
  492. * LPTSTR pointer to the last available data char in the data buffer.
  493. *
  494. \*****************************************************************************/
  495. LPTSTR _ppinfo_build_level4(
  496. PPRINTER_INFO_2 pSrcInfo,
  497. PPRINTER_INFO_4 pDstInfo,
  498. LPTSTR pszString)
  499. {
  500. // Set non-string entries.
  501. //
  502. pDstInfo->Attributes = pSrcInfo->Attributes;
  503. // Copy the required data to the Win 32 PRINTER_INFO_4 structure.
  504. //
  505. _ppinfo_set_str(&pDstInfo->pPrinterName, pSrcInfo->pPrinterName, &pszString);
  506. _ppinfo_set_str(&pDstInfo->pServerName , pSrcInfo->pServerName , &pszString);
  507. return pszString;
  508. }
  509. #endif
  510. /*****************************************************************************\
  511. * _ppinfo_build_level5 (Local Routine)
  512. *
  513. * Given a server name, a pointer to a source PRINTER_INFO_2
  514. * structure, a destination PRINTER_INFO_5 structure and a pointer to
  515. * the start of string storage space, fills the PRINTER_INFO_5 structure.
  516. *
  517. * Called by GetPrinter and EnumPrinters, level 2. Returns an
  518. * LPTSTR pointer to the last available data char in the data buffer.
  519. *
  520. \*****************************************************************************/
  521. LPTSTR _ppinfo_build_level5(
  522. PPRINTER_INFO_2 pSrcInfo,
  523. PPRINTER_INFO_5 pDstInfo,
  524. LPTSTR pszString)
  525. {
  526. // Set non-string entries.
  527. //
  528. pDstInfo->Attributes = pSrcInfo->Attributes;
  529. pDstInfo->DeviceNotSelectedTimeout = 0;
  530. pDstInfo->TransmissionRetryTimeout = 0;
  531. // Copy the required data to the Win 32 PRINTER_INFO_5 structure.
  532. //
  533. _ppinfo_set_str(&pDstInfo->pPrinterName, pSrcInfo->pPrinterName, &pszString);
  534. _ppinfo_set_str(&pDstInfo->pPortName , pSrcInfo->pPortName , &pszString);
  535. return pszString;
  536. }
  537. /*****************************************************************************\
  538. * _ppinfo_get_level1 (Local Routine)
  539. *
  540. * Given pInfo, a block of information on a printer returned by a
  541. * DosPrintQGetInfo call, fill a PRINTER_INFO_1 structure. Returns
  542. * TRUE if successful, FALSE otherwise. Places the number of bytes
  543. * of (lpbBuffer) used in the DWORD pointed to by (pcbNeeded).
  544. *
  545. \*****************************************************************************/
  546. BOOL _ppinfo_get_level1(
  547. PPRINTER_INFO_2 pSrcInfo,
  548. LPBYTE lpbBuffer,
  549. DWORD cbBuf,
  550. LPDWORD pcbNeeded)
  551. {
  552. // Figure out how many bytes of buffer space we're going to need.
  553. // Set error code and return failure if we don't have enough.
  554. //
  555. *pcbNeeded = _ppinfo_calc_level1(pSrcInfo);
  556. if (*pcbNeeded > cbBuf) {
  557. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  558. return FALSE;
  559. }
  560. // Copy the required data from the structure to the Win32
  561. // structure.
  562. //
  563. _ppinfo_build_level1(pSrcInfo,
  564. (PPRINTER_INFO_1)lpbBuffer,
  565. ENDOFBUFFER(lpbBuffer, cbBuf));
  566. return TRUE;
  567. }
  568. /*****************************************************************************\
  569. * _ppinfo_get_level2 (Local Routine)
  570. *
  571. * Given pInfo, a block of information on a printer returned by a
  572. * PrintQGetInfo call, fill a PRINTER_INFO_2 structure. Returns
  573. * TRUE if successful, FALSE otherwise. Places the number of bytes of
  574. * (lpbBuffer) used in the DWORD pointed to by (pcbNeeded).
  575. *
  576. \*****************************************************************************/
  577. BOOL _ppinfo_get_level2(
  578. PPRINTER_INFO_2 pSrcInfo,
  579. LPBYTE lpbBuffer,
  580. DWORD cbBuf,
  581. LPDWORD pcbNeeded)
  582. {
  583. // Figure out how many bytes of buffer space we're going to need.
  584. // Set error code and return failure if we don't have enough.
  585. //
  586. *pcbNeeded = _ppinfo_calc_level2(g_szEmptyString, pSrcInfo);
  587. if (*pcbNeeded > cbBuf) {
  588. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  589. return FALSE;
  590. }
  591. //
  592. // Copy the required data to the Win 32 PRINTER_INFO_2 structure.
  593. //
  594. _ppinfo_build_level2(g_szEmptyString,
  595. pSrcInfo,
  596. (PPRINTER_INFO_2)lpbBuffer,
  597. ENDOFBUFFER(lpbBuffer, cbBuf));
  598. return TRUE;
  599. }
  600. #if WINNT32
  601. /*****************************************************************************\
  602. * _ppinfo_get_level4 (Local Routine)
  603. *
  604. * Given pInfo, a block of information on a printer returned by a
  605. * PrintQGetInfo call, fill a PRINTER_INFO_4 structure. Returns
  606. * TRUE if successful, FALSE otherwise. Places the number of bytes of
  607. * (lpbBuffer) used in the DWORD pointed to by (pcbNeeded).
  608. *
  609. \*****************************************************************************/
  610. BOOL _ppinfo_get_level4(
  611. PPRINTER_INFO_2 pSrcInfo,
  612. LPBYTE lpbBuffer,
  613. DWORD cbBuf,
  614. LPDWORD pcbNeeded)
  615. {
  616. // Figure out how many bytes of buffer space we're going to need.
  617. // Set error code and return failure if we don't have enough.
  618. //
  619. *pcbNeeded = _ppinfo_calc_level4(pSrcInfo);
  620. if (*pcbNeeded > cbBuf) {
  621. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  622. return FALSE;
  623. }
  624. //
  625. // Copy the required data to the Win 32 PRINTER_INFO_2 structure.
  626. //
  627. _ppinfo_build_level4(pSrcInfo,
  628. (PPRINTER_INFO_4)lpbBuffer,
  629. ENDOFBUFFER(lpbBuffer, cbBuf));
  630. return TRUE;
  631. }
  632. #endif
  633. /*****************************************************************************\
  634. * _ppinfo_get_level5 (Local Routine)
  635. *
  636. * Given pInfo, a block of information on a printer returned by a
  637. * PrintQGetInfo call, fill a PRINTER_INFO_5 structure. Returns
  638. * TRUE if successful, FALSE otherwise. Places the number of bytes of
  639. * (lpbBuffer) used in the DWORD pointed to by (pcbNeeded).
  640. *
  641. \*****************************************************************************/
  642. BOOL _ppinfo_get_level5(
  643. PPRINTER_INFO_2 pSrcInfo,
  644. LPBYTE lpbBuffer,
  645. DWORD cbBuf,
  646. LPDWORD pcbNeeded)
  647. {
  648. // Figure out how many bytes of buffer space we're going to need.
  649. // Set error code and return failure if we don't have enough.
  650. //
  651. *pcbNeeded = _ppinfo_calc_level5(pSrcInfo);
  652. if (*pcbNeeded > cbBuf) {
  653. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  654. return FALSE;
  655. }
  656. //
  657. // Copy the required data to the Win 32 PRINTER_INFO_2 structure.
  658. //
  659. _ppinfo_build_level5(pSrcInfo,
  660. (PPRINTER_INFO_5)lpbBuffer,
  661. ENDOFBUFFER(lpbBuffer, cbBuf));
  662. return TRUE;
  663. }
  664. #if WINNT32
  665. /*****************************************************************************\
  666. * _ppinfo_enumprinters_NT (Local Routine)
  667. *
  668. * This is the WinNT specific routine for EnumPrinters.
  669. *
  670. *
  671. \*****************************************************************************/
  672. BOOL _ppinfo_enumprinters(
  673. DWORD dwType,
  674. LPTSTR pszName,
  675. DWORD dwLevel,
  676. LPBYTE pPrinterEnum,
  677. DWORD cbBuf,
  678. LPDWORD pcbNeeded,
  679. LPDWORD pcbReturned)
  680. {
  681. BOOL bReturn = FALSE;
  682. // Throw back enumeration requests that we don't handle. The routing
  683. // layer above us is specifically looking for the ERROR_INVALID_NAME.
  684. //
  685. if (dwType & PRINTER_ENUM_NOTFORUS)
  686. goto enum_name_failure;
  687. // If the request is one that we handle, but the caller didn't supply
  688. // a printer name, we'll fail. Again, to keep things going as the
  689. // router expects, we must return an ERROR_INVALID_NAME condition.
  690. //
  691. if (utlStrSize(pszName) == 0) {
  692. if ((dwLevel == PRINT_LEVEL_1) && (dwType & PRINTER_ENUM_NAME)) {
  693. return _ppinfo_describe_provider((LPPRINTER_INFO_1)pPrinterEnum,
  694. cbBuf,
  695. pcbNeeded,
  696. pcbReturned);
  697. } else {
  698. goto enum_name_failure;
  699. }
  700. } else {
  701. if ((dwLevel == PRINT_LEVEL_1) && (dwType & PRINTER_ENUM_NAME)) {
  702. // In this case, the user has asked us to enumerate the
  703. // printers in some domain. Until we decide what we really want
  704. // to do. We'll simply return success with an empty enumeration.
  705. //
  706. goto enum_empty_success;
  707. }
  708. }
  709. // Check Remote enumeration. Remote enumeration valid only if
  710. // it's a level-1 printer.
  711. //
  712. if (dwType & PRINTER_ENUM_REMOTE) {
  713. if (dwLevel != PRINT_LEVEL_1) {
  714. goto enum_level_failure;
  715. } else {
  716. // In this case, the user has asked us to enumerate the
  717. // printers in our domain. Until we decide what we really
  718. // want to do, we'll simply return success with an empty
  719. // enumeration.
  720. //
  721. goto enum_empty_success;
  722. }
  723. } else if (dwType & PRINTER_ENUM_CONNECTIONS) {
  724. // In this case, the user has asked us to enumerate our favorite
  725. // connections.
  726. //
  727. enum_empty_success:
  728. *pcbNeeded = 0;
  729. *pcbReturned = 0;
  730. return TRUE;
  731. }
  732. DBG_MSG(DBG_LEV_INFO, (TEXT("Info: PPEnumPrinters: Type(%ld) Name(%s) Level(%ld)"), dwType, pszName, dwLevel));
  733. // Check print-levels. These are error cases. We should
  734. // really have performed the enumeration above.
  735. //
  736. switch (dwLevel) {
  737. case PRINT_LEVEL_1:
  738. case PRINT_LEVEL_2:
  739. enum_name_failure:
  740. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: PPEnumPrinters: Invalid Name")));
  741. SetLastError(ERROR_INVALID_NAME);
  742. break;
  743. default:
  744. enum_level_failure:
  745. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: PPEnumPrinters: Invalid Level: %d"), dwLevel));
  746. SetLastError(ERROR_INVALID_LEVEL);
  747. break;
  748. }
  749. return FALSE;
  750. }
  751. #else
  752. /*****************************************************************************\
  753. * _ppinfo_enumprinters_95 (Local Routine)
  754. *
  755. * This is the Win95 specific routine for EnumPrinters.
  756. *
  757. *
  758. \*****************************************************************************/
  759. BOOL _ppinfo_enumprinters(
  760. DWORD dwType,
  761. LPTSTR pszName,
  762. DWORD dwLevel,
  763. LPBYTE pPrinterEnum,
  764. DWORD cbBuf,
  765. LPDWORD pcbNeeded,
  766. LPDWORD pcbReturned)
  767. {
  768. BOOL bReturn = FALSE;
  769. // Throw back enumeration requests that we don't handle. The routing
  770. // layer above us is specifically looking for the ERROR_INVALID_NAME.
  771. //
  772. if (dwType & PRINTER_ENUM_NOTFORUS)
  773. goto enum_name_failure;
  774. // If the request is one that we handle, but the caller didn't supply
  775. // a printer name, we'll fail. Again, to keep things going as the
  776. // router expects, we must return an ERROR_INVALID_NAME condition.
  777. //
  778. if (utlStrSize(pszName) == 0) {
  779. if ((dwLevel == PRINT_LEVEL_1) && (dwType & PRINTER_ENUM_NAME)) {
  780. return _ppinfo_describe_provider((LPPRINTER_INFO_1)pPrinterEnum,
  781. cbBuf,
  782. pcbNeeded,
  783. pcbReturned);
  784. } else if (dwType & PRINTER_ENUM_REMOTE) {
  785. // In this case, the user has asked us to enumerate the printers
  786. // in our domain. Until we decide what we really want to do, we'll
  787. // simply return success with an empty enumeration.
  788. //
  789. *pcbNeeded = 0;
  790. *pcbReturned = 0;
  791. return TRUE;
  792. } else {
  793. goto enum_name_failure;
  794. }
  795. }
  796. DBG_MSG(DBG_LEV_INFO, (TEXT("Info: PPEnumPrinters: Type(%ld) Name(%s) Level(%ld)"), dwType, pszName, dwLevel));
  797. // One last special case to test for -- did they ask us to
  798. // enumerate ourselves (the provider) by name?
  799. //
  800. if ((dwLevel == PRINT_LEVEL_1) && (dwType & PRINTER_ENUM_NAME)) {
  801. if (lstrcmp(pszName, g_szProviderName) == 0) {
  802. return _ppinfo_describe_provider((LPPRINTER_INFO_1)pPrinterEnum,
  803. cbBuf,
  804. pcbNeeded,
  805. pcbReturned);
  806. }
  807. }
  808. // Check print-levels. These are error cases. We should
  809. // really have performed the enumeration above.
  810. //
  811. switch (dwLevel) {
  812. case PRINT_LEVEL_1:
  813. case PRINT_LEVEL_2:
  814. enum_name_failure:
  815. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: PPEnumPrinters: Invalid Name")));
  816. SetLastError(ERROR_INVALID_NAME);
  817. break;
  818. default:
  819. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: PPEnumPrinters: Invalid Level: %d"), dwLevel));
  820. SetLastError(ERROR_INVALID_LEVEL);
  821. break;
  822. }
  823. return FALSE;
  824. }
  825. #endif
  826. /*****************************************************************************\
  827. * PPEnumPrinters
  828. *
  829. * Enumerates the available printers. Returns TRUE if successful. Otherwise,
  830. * it returns FALSE.
  831. *
  832. * NOTE: Supports level 2 PRINTER_INFO to provide Point-and-Print
  833. * functionality.
  834. *
  835. \*****************************************************************************/
  836. BOOL PPEnumPrinters(
  837. DWORD dwType,
  838. LPTSTR pszName,
  839. DWORD dwLevel,
  840. LPBYTE pPrinterEnum,
  841. DWORD cbBuf,
  842. LPDWORD pcbNeeded,
  843. LPDWORD pcbReturned)
  844. {
  845. DBG_MSG(DBG_LEV_CALLTREE, (TEXT("Call: PPEnumPrinters: Type(%d) Level(%d) Name(%s)"), dwType, dwLevel, (pszName ? pszName : TEXT("<NULL>"))));
  846. return _ppinfo_enumprinters(dwType,
  847. pszName,
  848. dwLevel,
  849. pPrinterEnum,
  850. cbBuf,
  851. pcbNeeded,
  852. pcbReturned);
  853. }
  854. /*****************************************************************************\
  855. * PPGetPrinter
  856. *
  857. * Retrieves information about a printer. Returns TRUE if successful, FALSE
  858. * if an error occurred. NOTE: Supports level 2 Printer_INFO to provide
  859. * Point and Print functionality for Chicago.
  860. *
  861. \*****************************************************************************/
  862. BOOL PPGetPrinter(
  863. HANDLE hPrinter,
  864. DWORD dwLevel,
  865. LPBYTE lpbPrinter,
  866. DWORD cbBuf,
  867. LPDWORD pcbNeeded)
  868. {
  869. PCINETMONPORT pIniPort;
  870. PPRINTER_INFO_2 pSrcInfo;
  871. DWORD cbSrcSize;
  872. DWORD dwTemp;
  873. BOOL bResult = FALSE;
  874. DBG_MSG(DBG_LEV_CALLTREE, (TEXT("Call: PPGetPrinter: Printer(%08lX) Level(%ld)"), hPrinter, dwLevel));
  875. if (pcbNeeded)
  876. *pcbNeeded = 0;
  877. semEnterCrit();
  878. // Make sure we have a valid printer handle.
  879. //
  880. if (pIniPort = utlValidatePrinterHandle(hPrinter)) {
  881. if (pIniPort->BeginReadGetPrinterCache (&pSrcInfo)) {
  882. // Reformat the data according to the requested info Level.
  883. //
  884. switch (dwLevel) {
  885. case PRINT_LEVEL_1:
  886. bResult = _ppinfo_get_level1(pSrcInfo, lpbPrinter, cbBuf, pcbNeeded);
  887. break;
  888. case PRINT_LEVEL_2:
  889. bResult = _ppinfo_get_level2(pSrcInfo, lpbPrinter, cbBuf, pcbNeeded);
  890. break;
  891. #if WINNT32
  892. case PRINT_LEVEL_4:
  893. bResult = _ppinfo_get_level4(pSrcInfo, lpbPrinter, cbBuf, pcbNeeded);
  894. break;
  895. #endif
  896. case PRINT_LEVEL_5:
  897. bResult = _ppinfo_get_level5(pSrcInfo, lpbPrinter, cbBuf, pcbNeeded);
  898. break;
  899. default:
  900. DBG_MSG(DBG_LEV_WARN, (TEXT("Warn: PPGetPrinter: Invalid Level")));
  901. SetLastError(ERROR_INVALID_LEVEL);
  902. bResult = FALSE;
  903. break;
  904. }
  905. }
  906. pIniPort->EndReadGetPrinterCache ();
  907. if (GetLastError() == ERROR_ACCESS_DENIED) {
  908. pIniPort->InvalidateGetPrinterCache ();
  909. }
  910. }
  911. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
  912. pcbNeeded &&
  913. *pcbNeeded == 0) {
  914. // We can't set ERROR_INSUFFICIENT_BUFFER here since it was an internal error
  915. // and we are not reporting a size
  916. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  917. }
  918. semLeaveCrit();
  919. return bResult;
  920. }