4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend, Huw D M Davies
16 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(winspool)
22 CRITICAL_SECTION PRINT32_RegistryBlocker;
24 typedef struct _OPENEDPRINTERA
28 LPPRINTER_DEFAULTSA lpDefault;
29 } OPENEDPRINTERA, *LPOPENEDPRINTERA;
31 /* The OpenedPrinter Table dynamic array */
32 static HDPA pOpenedPrinterDPA = NULL;
34 extern HDPA (WINAPI* WINSPOOL_DPA_CreateEx) (INT, HANDLE);
35 extern LPVOID (WINAPI* WINSPOOL_DPA_GetPtr) (const HDPA, INT);
36 extern INT (WINAPI* WINSPOOL_DPA_InsertPtr) (const HDPA, INT, LPVOID);
38 static char Printers[] =
39 "System\\CurrentControlSet\\control\\Print\\Printers\\";
40 static char Drivers[] =
41 "System\\CurrentControlSet\\control\\Print\\Environments\\Windows 4.0\\Drivers\\"; /* Hmm, well */
43 /******************************************************************
44 * WINSPOOL_GetOpenedPrinterEntryA
45 * Get the first place empty in the opened printer table
47 static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterEntryA()
50 LPOPENEDPRINTERA pOpenedPrinter;
53 * Create the opened printers' handle dynamic array.
55 if (!pOpenedPrinterDPA)
57 pOpenedPrinterDPA = WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
58 for (i = 0; i < 10; i++)
60 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
62 sizeof(OPENEDPRINTERA));
63 pOpenedPrinter->hPrinter = -1;
64 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
69 * Search for a handle not yet allocated.
71 for (i = 0; i < pOpenedPrinterDPA->nItemCount; i++)
73 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, i);
75 if (pOpenedPrinter->hPrinter == -1)
77 pOpenedPrinter->hPrinter = i + 1;
78 return pOpenedPrinter;
83 * Didn't find one, insert new element in the array.
85 if (i == pOpenedPrinterDPA->nItemCount)
87 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
89 sizeof(OPENEDPRINTERA));
90 pOpenedPrinter->hPrinter = i + 1;
91 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
92 return pOpenedPrinter;
98 /******************************************************************
99 * WINSPOOL_GetOpenedPrinterA
100 * Get the pointer to the opened printer referred by the handle
102 static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterA(int printerHandle)
104 LPOPENEDPRINTERA pOpenedPrinter;
106 if(!pOpenedPrinterDPA) return NULL;
107 if((printerHandle <=0) ||
108 (printerHandle > (pOpenedPrinterDPA->nItemCount - 1)))
111 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, printerHandle-1);
113 return pOpenedPrinter;
116 /******************************************************************
117 * DeviceCapabilities32A [WINSPOOL.151]
120 INT WINAPI DeviceCapabilitiesA(LPCSTR pDeivce,LPCSTR pPort, WORD cap,
121 LPSTR pOutput, LPDEVMODEA lpdm)
124 ret = GDI_CallDeviceCapabilities16(pDeivce, pPort, cap, pOutput, lpdm);
126 /* If DC_PAPERSIZE map POINT16s to POINTs */
127 if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
128 POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
130 memcpy(tmp, pOutput, ret * sizeof(POINT16));
131 for(i = 0; i < ret; i++)
132 CONV_POINT16TO32(tmp + i, (POINT*)pOutput + i);
133 HeapFree( GetProcessHeap(), 0, tmp );
139 /*****************************************************************************
140 * DeviceCapabilities32W
142 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
143 WORD fwCapability, LPWSTR pOutput,
144 const DEVMODEW *pDevMode)
146 FIXME("(%p,%p,%d,%p,%p): stub\n",
147 pDevice, pPort, fwCapability, pOutput, pDevMode);
151 /******************************************************************
152 * DocumentProperties32A [WINSPOOL.155]
155 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
156 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
157 LPDEVMODEA pDevModeInput,DWORD fMode )
159 LPOPENEDPRINTERA lpOpenedPrinter;
160 LPSTR lpName = pDeviceName;
162 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
163 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
167 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
168 if(!lpOpenedPrinter) {
169 SetLastError(ERROR_INVALID_HANDLE);
172 lpName = lpOpenedPrinter->lpsPrinterName;
175 return GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
176 pDevModeInput, NULL, fMode);
181 /*****************************************************************************
182 * DocumentProperties32W
184 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
186 LPDEVMODEW pDevModeOutput,
187 LPDEVMODEW pDevModeInput, DWORD fMode)
189 FIXME("(%d,%d,%s,%p,%p,%ld): stub\n",
190 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
196 /******************************************************************
197 * OpenPrinter32A [WINSPOOL.196]
200 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
201 LPPRINTER_DEFAULTSA pDefault)
203 /* Not implemented: use the DesiredAccess of pDefault to set
204 the access rights to the printer */
206 LPOPENEDPRINTERA lpOpenedPrinter;
207 HKEY hkeyPrinters, hkeyPrinter;
209 if (!lpPrinterName) {
210 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault);
211 SetLastError(ERROR_INVALID_PARAMETER);
215 TRACE("(printerName: %s, pDefault %p\n", lpPrinterName, pDefault);
217 /* Check Printer exists */
218 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
220 ERR("Can't create Printers key\n");
221 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
225 if(RegOpenKeyA(hkeyPrinters, lpPrinterName, &hkeyPrinter)
227 WARN("Can't find printer `%s' in registry\n", lpPrinterName);
228 RegCloseKey(hkeyPrinters);
229 SetLastError(ERROR_INVALID_PARAMETER);
232 RegCloseKey(hkeyPrinter);
233 RegCloseKey(hkeyPrinters);
235 if(!phPrinter) /* This seems to be what win95 does anyway */
238 /* Get a place in the opened printer buffer*/
239 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntryA();
240 if(!lpOpenedPrinter) {
241 ERR("Can't allocate printer slot\n");
242 SetLastError(ERROR_OUTOFMEMORY);
246 /* Get the name of the printer */
247 lpOpenedPrinter->lpsPrinterName =
248 HEAP_strdupA( GetProcessHeap(), 0, lpPrinterName );
250 /* Get the unique handle of the printer*/
251 *phPrinter = lpOpenedPrinter->hPrinter;
253 if (pDefault != NULL) {
254 lpOpenedPrinter->lpDefault =
255 HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA));
256 lpOpenedPrinter->lpDefault->pDevMode =
257 HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA));
258 memcpy(lpOpenedPrinter->lpDefault->pDevMode, pDefault->pDevMode,
260 lpOpenedPrinter->lpDefault->pDatatype =
261 HEAP_strdupA( GetProcessHeap(), 0, pDefault->pDatatype );
262 lpOpenedPrinter->lpDefault->DesiredAccess =
263 pDefault->DesiredAccess;
270 /******************************************************************
271 * OpenPrinter32W [WINSPOOL.197]
274 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
275 LPPRINTER_DEFAULTSW pDefault)
277 FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
279 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
283 /******************************************************************
284 * AddMonitor32A [WINSPOOL.107]
287 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
289 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
290 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
294 /******************************************************************
295 * DeletePrinterDriver32A [WINSPOOL.146]
299 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
301 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
302 debugstr_a(pDriverName));
303 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
308 /******************************************************************
309 * DeleteMonitor32A [WINSPOOL.135]
313 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
315 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
316 debugstr_a(pMonitorName));
317 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
322 /******************************************************************
323 * DeletePort32A [WINSPOOL.137]
327 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
329 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
330 debugstr_a(pPortName));
331 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
335 /******************************************************************************
336 * SetPrinter32W [WINSPOOL.214]
346 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
350 /******************************************************************************
351 * WritePrinter32 [WINSPOOL.223]
361 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
365 /*****************************************************************************
366 * AddForm32A [WINSPOOL.103]
368 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
370 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
374 /*****************************************************************************
375 * AddForm32W [WINSPOOL.104]
377 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
379 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
383 /*****************************************************************************
384 * AddJob32A [WINSPOOL.105]
386 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
387 DWORD cbBuf, LPDWORD pcbNeeded)
389 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
394 /*****************************************************************************
395 * AddJob32W [WINSPOOL.106]
397 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
400 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
405 /*****************************************************************************
406 * AddPrinter32A [WINSPOOL.117]
408 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
410 PRINTER_INFO_2A *pi = (PRINTER_INFO_2A *) pPrinter;
413 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
415 TRACE("(%s,%ld,%p)\n", pName, Level, pPrinter);
418 FIXME("pName = `%s' - unsupported\n", pName);
419 SetLastError(ERROR_INVALID_PARAMETER);
423 WARN("Level = %ld\n", Level);
424 SetLastError(ERROR_INVALID_LEVEL);
428 SetLastError(ERROR_INVALID_PARAMETER);
431 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
433 ERR("Can't create Printers key\n");
436 if(RegOpenKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
438 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
439 RegCloseKey(hkeyPrinter);
440 RegCloseKey(hkeyPrinters);
443 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
445 ERR("Can't create Drivers key\n");
446 RegCloseKey(hkeyPrinters);
449 if(RegOpenKeyA(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
451 WARN("Can't find driver `%s'\n", pi->pDriverName);
452 RegCloseKey(hkeyPrinters);
453 RegCloseKey(hkeyDrivers);
454 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
457 RegCloseKey(hkeyDriver);
458 RegCloseKey(hkeyDrivers);
459 if(strcasecmp(pi->pPrintProcessor, "WinPrint")) { /* FIXME */
460 WARN("Can't find processor `%s'\n", pi->pPrintProcessor);
461 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
462 RegCloseKey(hkeyPrinters);
465 if(RegCreateKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
467 WARN("Can't create printer `%s'\n", pi->pPrinterName);
468 SetLastError(ERROR_INVALID_PRINTER_NAME);
469 RegCloseKey(hkeyPrinters);
472 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
473 (LPSTR)&pi->Attributes, sizeof(DWORD));
474 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY,
475 (LPSTR)&pi->pDevMode,
476 pi->pDevMode ? pi->pDevMode->dmSize : 0);
477 RegSetValueExA(hkeyPrinter, "Description", 0, REG_SZ, pi->pComment, 0);
478 RegSetValueExA(hkeyPrinter, "Location", 0, REG_SZ, pi->pLocation, 0);
479 RegSetValueExA(hkeyPrinter, "Name", 0, REG_SZ, pi->pPrinterName, 0);
480 RegSetValueExA(hkeyPrinter, "Parameters", 0, REG_SZ, pi->pParameters, 0);
481 RegSetValueExA(hkeyPrinter, "Port", 0, REG_SZ, pi->pPortName, 0);
482 RegSetValueExA(hkeyPrinter, "Print Processor", 0, REG_SZ,
483 pi->pPrintProcessor, 0);
484 RegSetValueExA(hkeyPrinter, "Printer Driver", 0, REG_SZ, pi->pDriverName,
486 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
487 (LPSTR)&pi->Priority, sizeof(DWORD));
488 RegSetValueExA(hkeyPrinter, "Separator File", 0, REG_SZ, pi->pSepFile, 0);
489 RegSetValueExA(hkeyPrinter, "Share Name", 0, REG_SZ, pi->pShareName, 0);
490 RegSetValueExA(hkeyPrinter, "Start Time", 0, REG_DWORD,
491 (LPSTR)&pi->StartTime, sizeof(DWORD));
492 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
493 (LPSTR)&pi->Status, sizeof(DWORD));
494 RegSetValueExA(hkeyPrinter, "Until Time", 0, REG_DWORD,
495 (LPSTR)&pi->UntilTime, sizeof(DWORD));
497 RegCloseKey(hkeyPrinter);
498 RegCloseKey(hkeyPrinters);
499 if(!OpenPrinterA(pi->pPrinterName, &retval, NULL)) {
500 ERR("OpenPrinter failing\n");
506 /*****************************************************************************
507 * AddPrinter32W [WINSPOOL.122]
509 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
511 FIXME("(%p,%ld,%p): stub\n", pName, Level, pPrinter);
516 /*****************************************************************************
517 * ClosePrinter32 [WINSPOOL.126]
519 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
521 LPOPENEDPRINTERA lpOpenedPrinter;
523 TRACE("Handle %d\n", hPrinter);
525 if (!pOpenedPrinterDPA)
528 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
530 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
531 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
532 lpOpenedPrinter->lpsPrinterName = NULL;
534 /* Free the memory of lpDefault if it has been initialized*/
535 if(lpOpenedPrinter->lpDefault != NULL)
537 HeapFree(GetProcessHeap(), 0,
538 lpOpenedPrinter->lpDefault->pDevMode);
539 HeapFree(GetProcessHeap(), 0,
540 lpOpenedPrinter->lpDefault->pDatatype);
541 HeapFree(GetProcessHeap(), 0,
542 lpOpenedPrinter->lpDefault);
543 lpOpenedPrinter->lpDefault = NULL;
546 lpOpenedPrinter->hPrinter = -1;
553 /*****************************************************************************
554 * DeleteForm32A [WINSPOOL.133]
556 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
558 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
562 /*****************************************************************************
563 * DeleteForm32W [WINSPOOL.134]
565 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
567 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
571 /*****************************************************************************
572 * DeletePrinter32 [WINSPOOL.143]
574 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
576 FIXME("(%d): stub\n", hPrinter);
580 /*****************************************************************************
581 * SetPrinter32A [WINSPOOL.211]
583 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
586 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
590 /*****************************************************************************
591 * SetJob32A [WINSPOOL.209]
593 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
594 LPBYTE pJob, DWORD Command)
596 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
601 /*****************************************************************************
602 * SetJob32W [WINSPOOL.210]
604 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
605 LPBYTE pJob, DWORD Command)
607 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
612 /*****************************************************************************
613 * GetForm32A [WINSPOOL.181]
615 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
616 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
618 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
619 Level,pForm,cbBuf,pcbNeeded);
623 /*****************************************************************************
624 * GetForm32W [WINSPOOL.182]
626 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
627 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
629 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
630 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
634 /*****************************************************************************
635 * SetForm32A [WINSPOOL.207]
637 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
640 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
644 /*****************************************************************************
645 * SetForm32W [WINSPOOL.208]
647 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
650 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
654 /*****************************************************************************
655 * ReadPrinter32 [WINSPOOL.202]
657 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
658 LPDWORD pNoBytesRead)
660 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
664 /*****************************************************************************
665 * ResetPrinter32A [WINSPOOL.203]
667 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
669 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
673 /*****************************************************************************
674 * ResetPrinter32W [WINSPOOL.204]
676 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
678 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
683 /*****************************************************************************
684 * WINSPOOL_GetStringFromRegA
686 * Get ValueName from hkey storing result in str. buflen is space left in str
688 static BOOL WINSPOOL_GetStringFromRegA(HKEY hkey, LPCSTR ValueName, LPSTR ptr,
689 DWORD buflen, DWORD *needed)
691 DWORD sz = buflen, type;
694 ret = RegQueryValueExA(hkey, ValueName, 0, &type, ptr, &sz);
696 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
697 ERR("Got ret = %ld\n", ret);
704 /*********************************************************************
705 * WINSPOOL_GetPrinter_2A
707 * Fills out a PRINTER_INFO_2A struct storing the strings in buf.
709 static BOOL WINSPOOL_GetPrinter_2A(HKEY hkeyPrinter, PRINTER_INFO_2A *pi2,
710 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
712 DWORD size, left = cbBuf;
713 BOOL space = (cbBuf > 0);
718 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
719 if(space && size <= left) {
720 pi2->pPrinterName = ptr;
727 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, left, &size);
728 if(space && size <= left) {
729 pi2->pPortName = ptr;
736 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Printer Driver", ptr, left,
738 if(space && size <= left) {
739 pi2->pDriverName = ptr;
746 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Default DevMode", ptr, left,
748 if(space && size <= left) {
749 pi2->pDevMode = (LPDEVMODEA)ptr;
756 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Print Processor", ptr, left,
758 if(space && size <= left) {
759 pi2->pPrintProcessor = ptr;
766 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
767 memset(pi2, 0, sizeof(*pi2));
772 /*********************************************************************
773 * WINSPOOL_GetPrinter_4A
775 * Fills out a PRINTER_INFO_4A struct storing the strings in buf.
777 static BOOL WINSPOOL_GetPrinter_4A(HKEY hkeyPrinter, PRINTER_INFO_4A *pi4,
778 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
780 DWORD size, left = cbBuf;
781 BOOL space = (cbBuf > 0);
786 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
787 if(space && size <= left) {
788 pi4->pPrinterName = ptr;
796 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
797 memset(pi4, 0, sizeof(*pi4));
802 /*********************************************************************
803 * WINSPOOL_GetPrinter_5A
805 * Fills out a PRINTER_INFO_5A struct storing the strings in buf.
807 static BOOL WINSPOOL_GetPrinter_5A(HKEY hkeyPrinter, PRINTER_INFO_5A *pi5,
808 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
810 DWORD size, left = cbBuf;
811 BOOL space = (cbBuf > 0);
816 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
817 if(space && size <= left) {
818 pi5->pPrinterName = ptr;
825 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, left, &size);
826 if(space && size <= left) {
827 pi5->pPortName = ptr;
834 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
835 memset(pi5, 0, sizeof(*pi5));
840 /*****************************************************************************
841 * GetPrinterA [WINSPOOL.187]
843 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
844 DWORD cbBuf, LPDWORD pcbNeeded)
846 OPENEDPRINTERA *lpOpenedPrinter;
847 DWORD size, needed = 0;
849 HKEY hkeyPrinter, hkeyPrinters;
852 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
854 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
855 if(!lpOpenedPrinter) {
856 SetLastError(ERROR_INVALID_HANDLE);
859 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
861 ERR("Can't create Printers key\n");
864 if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
866 ERR("Can't find opened printer `%s' in registry\n",
867 lpOpenedPrinter->lpsPrinterName);
868 RegCloseKey(hkeyPrinters);
869 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
876 PRINTER_INFO_2A *pi2 = (PRINTER_INFO_2A *)pPrinter;
878 size = sizeof(PRINTER_INFO_2A);
880 ptr = pPrinter + size;
882 memset(pPrinter, 0, size);
887 ret = WINSPOOL_GetPrinter_2A(hkeyPrinter, pi2, ptr, cbBuf, &needed);
894 PRINTER_INFO_4A *pi4 = (PRINTER_INFO_4A *)pPrinter;
896 size = sizeof(PRINTER_INFO_4A);
898 ptr = pPrinter + size;
900 memset(pPrinter, 0, size);
905 ret = WINSPOOL_GetPrinter_4A(hkeyPrinter, pi4, ptr, cbBuf, &needed);
913 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A *)pPrinter;
915 size = sizeof(PRINTER_INFO_5A);
917 ptr = pPrinter + size;
919 memset(pPrinter, 0, size);
925 ret = WINSPOOL_GetPrinter_5A(hkeyPrinter, pi5, ptr, cbBuf, &needed);
931 FIXME("Unimplemented level %ld\n", Level);
932 SetLastError(ERROR_INVALID_LEVEL);
933 RegCloseKey(hkeyPrinters);
934 RegCloseKey(hkeyPrinter);
938 RegCloseKey(hkeyPrinter);
939 RegCloseKey(hkeyPrinters);
941 if(pcbNeeded) *pcbNeeded = needed;
943 SetLastError(ERROR_INSUFFICIENT_BUFFER);
948 /*****************************************************************************
949 * GetPrinterW [WINSPOOL.194]
951 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
952 DWORD cbBuf, LPDWORD pcbNeeded)
954 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
959 /******************************************************************
960 * EnumPrintersA [WINSPOOL.174]
962 * Enumerates the available printers, print servers and print
963 * providers, depending on the specified flags, name and level.
967 * If level is set to 1:
968 * Not implemented yet!
969 * Returns TRUE with an empty list.
971 * If level is set to 2:
972 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
973 * Returns an array of PRINTER_INFO_2 data structures in the
974 * lpbPrinters buffer. Note that according to MSDN also an
975 * OpenPrinter should be performed on every remote printer.
977 * If level is set to 4 (officially WinNT only):
978 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
979 * Fast: Only the registry is queried to retrieve printer names,
980 * no connection to the driver is made.
981 * Returns an array of PRINTER_INFO_4 data structures in the
982 * lpbPrinters buffer.
984 * If level is set to 5 (officially WinNT4/Win9x only):
985 * Fast: Only the registry is queried to retrieve printer names,
986 * no connection to the driver is made.
987 * Returns an array of PRINTER_INFO_5 data structures in the
988 * lpbPrinters buffer.
990 * If level set to 3 or 6+:
991 * returns zero (faillure!)
993 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
997 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
998 * - Only levels 2, 4 and 5 are implemented at the moment.
999 * - 16-bit printer drivers are not enumerated.
1000 * - Returned amount of bytes used/needed does not match the real Windoze
1001 * implementation (as in this implementation, all strings are part
1002 * of the buffer, whereas Win32 keeps them somewhere else)
1003 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1006 * - In a regular Wine installation, no registry settings for printers
1007 * exist, which makes this function return an empty list.
1009 BOOL WINAPI EnumPrintersA(
1010 DWORD dwType, /* Types of print objects to enumerate */
1011 LPSTR lpszName, /* name of objects to enumerate */
1012 DWORD dwLevel, /* type of printer info structure */
1013 LPBYTE lpbPrinters, /* buffer which receives info */
1014 DWORD cbBuf, /* max size of buffer in bytes */
1015 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
1016 LPDWORD lpdwReturned /* number of entries returned */
1020 HKEY hkeyPrinters, hkeyPrinter;
1021 char PrinterName[255];
1022 DWORD needed = 0, number = 0;
1023 DWORD used, i, left;
1027 memset(lpbPrinters, 0, cbBuf);
1031 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1032 FIXME("dwType = %08lx\n", dwType);
1033 SetLastError(ERROR_INVALID_FLAGS);
1037 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1039 ERR("Can't create Printers key\n");
1043 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1044 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1045 RegCloseKey(hkeyPrinters);
1046 ERR("Can't query Printers key\n");
1049 TRACE("Found %ld printers\n", number);
1053 RegCloseKey(hkeyPrinters);
1055 *lpdwReturned = number;
1059 used = number * sizeof(PRINTER_INFO_2A);
1062 used = number * sizeof(PRINTER_INFO_4A);
1065 used = number * sizeof(PRINTER_INFO_5A);
1069 SetLastError(ERROR_INVALID_LEVEL);
1070 RegCloseKey(hkeyPrinters);
1073 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1075 for(i = 0; i < number; i++) {
1076 if(RegEnumKeyA(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1078 ERR("Can't enum key number %ld\n", i);
1079 RegCloseKey(hkeyPrinters);
1082 if(RegOpenKeyA(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1084 ERR("Can't open key '%s'\n", PrinterName);
1085 RegCloseKey(hkeyPrinters);
1090 buf = lpbPrinters + used;
1091 left = cbBuf - used;
1099 WINSPOOL_GetPrinter_2A(hkeyPrinter, (PRINTER_INFO_2A *)pi, buf,
1102 if(pi) pi += sizeof(PRINTER_INFO_2A);
1105 WINSPOOL_GetPrinter_4A(hkeyPrinter, (PRINTER_INFO_4A *)pi, buf,
1108 if(pi) pi += sizeof(PRINTER_INFO_4A);
1111 WINSPOOL_GetPrinter_5A(hkeyPrinter, (PRINTER_INFO_5A *)pi, buf,
1114 if(pi) pi += sizeof(PRINTER_INFO_5A);
1117 ERR("Shouldn't be here!\n");
1118 RegCloseKey(hkeyPrinter);
1119 RegCloseKey(hkeyPrinters);
1122 RegCloseKey(hkeyPrinter);
1124 RegCloseKey(hkeyPrinters);
1130 memset(lpbPrinters, 0, cbBuf);
1131 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1135 *lpdwReturned = number;
1136 SetLastError(ERROR_SUCCESS);
1140 /******************************************************************
1141 * EnumPrintersW [WINSPOOL.175]
1144 BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
1145 DWORD dwLevel, LPBYTE lpbPrinters,
1146 DWORD cbBuf, LPDWORD lpdwNeeded,
1147 LPDWORD lpdwReturned)
1149 FIXME("Nearly empty stub\n");
1156 /*****************************************************************************
1157 * GetPrinterDriver32A [WINSPOOL.190]
1159 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1160 DWORD Level, LPBYTE pDriverInfo,
1161 DWORD cbBuf, LPDWORD pcbNeeded)
1163 OPENEDPRINTERA *lpOpenedPrinter;
1164 char DriverName[100];
1165 DWORD ret, type, size, dw, needed = 0;
1167 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
1169 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,pEnvironment,
1170 Level,pDriverInfo,cbBuf, pcbNeeded);
1172 ZeroMemory(pDriverInfo, cbBuf);
1174 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
1175 if(!lpOpenedPrinter) {
1176 SetLastError(ERROR_INVALID_HANDLE);
1180 FIXME("pEnvironment = `%s'\n", pEnvironment);
1181 SetLastError(ERROR_INVALID_ENVIRONMENT);
1184 if(Level < 1 || Level > 3) {
1185 SetLastError(ERROR_INVALID_LEVEL);
1188 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1190 ERR("Can't create Printers key\n");
1193 if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1195 ERR("Can't find opened printer `%s' in registry\n",
1196 lpOpenedPrinter->lpsPrinterName);
1197 RegCloseKey(hkeyPrinters);
1198 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1201 size = sizeof(DriverName);
1202 ret = RegQueryValueExA(hkeyPrinter, "Printer Driver", 0, &type, DriverName,
1204 RegCloseKey(hkeyPrinter);
1205 RegCloseKey(hkeyPrinters);
1206 if(ret != ERROR_SUCCESS) {
1207 ERR("Can't get DriverName for printer `%s'\n",
1208 lpOpenedPrinter->lpsPrinterName);
1211 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1213 ERR("Can't create Drivers key\n");
1216 if(RegOpenKeyA(hkeyDrivers, DriverName, &hkeyDriver)
1218 ERR("Can't find driver `%s' in registry\n", DriverName);
1219 RegCloseKey(hkeyDrivers);
1220 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1226 size = sizeof(DRIVER_INFO_1A);
1229 size = sizeof(DRIVER_INFO_2A);
1232 size = sizeof(DRIVER_INFO_3A);
1235 ERR("Invalid level\n");
1240 ptr = pDriverInfo + size;
1246 size = strlen(DriverName) + 1;
1249 strcpy(ptr, DriverName);
1251 ((DRIVER_INFO_1A *)pDriverInfo)->pName = ptr;
1253 ((DRIVER_INFO_2A *)pDriverInfo)->pName = ptr;
1259 DRIVER_INFO_2A *di2 = (DRIVER_INFO_2A *)pDriverInfo;
1262 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw,
1265 WARN("Can't get Version\n");
1269 size = strlen("Wine") + 1; /* FIXME */
1272 strcpy(ptr, "Wine");
1273 di2->pEnvironment = ptr;
1279 WINSPOOL_GetStringFromRegA(hkeyDriver, "Driver", ptr, cbBuf, &size);
1280 if(cbBuf && size <= cbBuf) {
1281 di2->pDriverPath = ptr;
1287 WINSPOOL_GetStringFromRegA(hkeyDriver, "Data File", ptr, cbBuf, &size);
1288 if(cbBuf && size <= cbBuf) {
1289 di2->pDataFile = ptr;
1295 WINSPOOL_GetStringFromRegA(hkeyDriver, "Configuration File", ptr,
1297 if(cbBuf && size <= cbBuf) {
1298 di2->pConfigFile = ptr;
1306 DRIVER_INFO_3A *di3 = (DRIVER_INFO_3A *)pDriverInfo;
1308 WINSPOOL_GetStringFromRegA(hkeyDriver, "Help File", ptr, cbBuf, &size);
1309 if(cbBuf && size <= cbBuf) {
1310 di3->pHelpFile = ptr;
1316 WINSPOOL_GetStringFromRegA(hkeyDriver, "Dependent Files", ptr, cbBuf,
1318 if(cbBuf && size <= cbBuf) {
1319 di3->pDependentFiles = ptr;
1325 WINSPOOL_GetStringFromRegA(hkeyDriver, "Monitor", ptr, cbBuf, &size);
1326 if(cbBuf && size <= cbBuf) {
1327 di3->pMonitorName = ptr;
1333 WINSPOOL_GetStringFromRegA(hkeyDriver, "DataType", ptr, cbBuf, &size);
1334 if(cbBuf && size <= cbBuf) {
1335 di3->pDefaultDataType = ptr;
1341 RegCloseKey(hkeyDriver);
1342 RegCloseKey(hkeyDrivers);
1344 if(pcbNeeded) *pcbNeeded = needed;
1345 if(cbBuf) return TRUE;
1346 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1350 /*****************************************************************************
1351 * GetPrinterDriver32W [WINSPOOL.193]
1353 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1354 DWORD Level, LPBYTE pDriverInfo,
1355 DWORD cbBuf, LPDWORD pcbNeeded)
1357 FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1358 Level,pDriverInfo,cbBuf, pcbNeeded);
1362 /*****************************************************************************
1363 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1365 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1366 DWORD Level, LPBYTE pDriverDirectory,
1367 DWORD cbBuf, LPDWORD pcbNeeded)
1371 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1372 pDriverDirectory, cbBuf, pcbNeeded);
1374 FIXME("pName = `%s' - unsupported\n", pName);
1375 SetLastError(ERROR_INVALID_PARAMETER);
1378 if(pEnvironment != NULL) {
1379 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
1380 SetLastError(ERROR_INVALID_ENVIRONMENT);
1383 if(Level != 1) /* win95 ignores this so we just carry on */
1384 WARN("Level = %ld - assuming 1\n", Level);
1386 /* FIXME should read from registry */
1387 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
1390 *pcbNeeded = needed;
1391 if(needed > cbBuf) {
1392 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1399 /*****************************************************************************
1400 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1402 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
1403 DWORD Level, LPBYTE pDriverDirectory,
1404 DWORD cbBuf, LPDWORD pcbNeeded)
1406 LPSTR pNameA = NULL, pEnvironmentA = NULL;
1410 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
1412 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
1413 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
1414 pDriverDirectory, cbBuf, pcbNeeded );
1416 HeapFree( GetProcessHeap(), 0, pNameA );
1418 HeapFree( GetProcessHeap(), 0, pEnvironment );
1423 /*****************************************************************************
1424 * AddPrinterDriver32A [WINSPOOL.120]
1426 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
1429 HKEY hkeyDrivers, hkeyName;
1431 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
1433 if(level != 2 && level != 3) {
1434 SetLastError(ERROR_INVALID_LEVEL);
1438 FIXME("pName= `%s' - unsupported\n", pName);
1439 SetLastError(ERROR_INVALID_PARAMETER);
1443 WARN("pDriverInfo == NULL");
1444 SetLastError(ERROR_INVALID_PARAMETER);
1449 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
1451 memset(&di3, 0, sizeof(di3));
1452 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
1455 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
1457 SetLastError(ERROR_INVALID_PARAMETER);
1460 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
1461 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
1462 if(!di3.pHelpFile) di3.pHelpFile = "";
1463 if(!di3.pMonitorName) di3.pMonitorName = "";
1465 if(di3.pEnvironment) {
1466 FIXME("pEnvironment = `%s'\n", di3.pEnvironment);
1467 SetLastError(ERROR_INVALID_ENVIRONMENT);
1470 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1472 ERR("Can't create Drivers key\n");
1476 if(level == 2) { /* apparently can't overwrite with level2 */
1477 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
1478 RegCloseKey(hkeyName);
1479 RegCloseKey(hkeyDrivers);
1480 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
1481 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
1485 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
1486 RegCloseKey(hkeyDrivers);
1487 ERR("Can't create Name key\n");
1490 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
1492 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
1493 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
1494 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
1496 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
1497 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
1498 di3.pDependentFiles, 0);
1499 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
1500 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
1501 RegCloseKey(hkeyName);
1502 RegCloseKey(hkeyDrivers);
1506 /*****************************************************************************
1507 * AddPrinterDriver32W [WINSPOOL.121]
1509 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
1512 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
1518 /*****************************************************************************
1519 * PrinterProperties [WINSPOOL.201]
1521 * Displays a dialog to set the properties of the printer.
1524 * nonzero on succes or zero on faillure
1527 * implemented as stub only
1529 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
1530 HANDLE hPrinter /* handle to printer object */
1532 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
1533 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1537 /*****************************************************************************
1538 * EnumJobsA [WINSPOOL.162]
1541 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
1542 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
1546 if(pcbNeeded) *pcbNeeded = 0;
1547 if(pcReturned) *pcReturned = 0;
1552 /*****************************************************************************
1553 * EnumJobsW [WINSPOOL.163]
1556 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
1557 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
1561 if(pcbNeeded) *pcbNeeded = 0;
1562 if(pcReturned) *pcReturned = 0;