4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
7 * Copyright 1999, 2000 Huw D M Davies
18 #include "wine/unicode.h"
19 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(winspool);
26 CRITICAL_SECTION PRINT32_RegistryBlocker;
28 typedef struct _OPENEDPRINTER
30 LPWSTR lpsPrinterName;
32 } OPENEDPRINTER, *LPOPENEDPRINTER;
34 /* The OpenedPrinter Table dynamic array */
35 static HDPA pOpenedPrinterDPA = NULL;
37 extern HDPA (WINAPI* WINSPOOL_DPA_CreateEx) (INT, HANDLE);
38 extern LPVOID (WINAPI* WINSPOOL_DPA_GetPtr) (const HDPA, INT);
39 extern INT (WINAPI* WINSPOOL_DPA_InsertPtr) (const HDPA, INT, LPVOID);
41 static char Printers[] =
42 "System\\CurrentControlSet\\control\\Print\\Printers\\";
43 static char Drivers[] =
44 "System\\CurrentControlSet\\control\\Print\\Environments\\Windows 4.0\\Drivers\\"; /* Hmm, well */
46 static WCHAR DefaultEnvironmentW[] = {'W','i','n','e',0};
48 static WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t',
49 'i','o','n',' ','F','i','l','e',0};
50 static WCHAR DatatypeW[] = {'D','a','t','a','t','y','p','e',0};
51 static WCHAR Data_FileW[] = {'D','a','t','a',' ','F','i','l','e',0};
52 static WCHAR Default_DevModeW[] = {'D','e','f','a','u','l','t',' ','D','e','v',
54 static WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F',
56 static WCHAR DescriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
57 static WCHAR DriverW[] = {'D','r','i','v','e','r',0};
58 static WCHAR Help_FileW[] = {'H','e','l','p',' ','F','i','l','e',0};
59 static WCHAR LocationW[] = {'L','o','c','a','t','i','o','n',0};
60 static WCHAR MonitorW[] = {'M','o','n','i','t','o','r',0};
61 static WCHAR NameW[] = {'N','a','m','e',0};
62 static WCHAR ParametersW[] = {'P','a','r','a','m','e','t','e','r','s',0};
63 static WCHAR PortW[] = {'P','o','r','t',0};
64 static WCHAR Print_ProcessorW[] = {'P','r','i','n','t',' ','P','r','o','c','e',
66 static WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i',
68 static WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F',
70 static WCHAR Share_NameW[] = {'S','h','a','r','e',' ','N','a','m','e',0};
71 static WCHAR WinPrintW[] = {'W','i','n','P','r','i','n','t',0};
73 /******************************************************************
74 * WINSPOOL_GetOpenedPrinterEntry
75 * Get the first place empty in the opened printer table
77 static LPOPENEDPRINTER WINSPOOL_GetOpenedPrinterEntry()
80 LPOPENEDPRINTER pOpenedPrinter;
83 * Create the opened printers' handle dynamic array.
85 if (!pOpenedPrinterDPA)
87 pOpenedPrinterDPA = WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
88 for (i = 0; i < 10; i++)
90 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
92 sizeof(OPENEDPRINTER));
93 pOpenedPrinter->hPrinter = -1;
94 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
99 * Search for a handle not yet allocated.
101 for (i = 0; i < pOpenedPrinterDPA->nItemCount; i++)
103 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, i);
105 if (pOpenedPrinter->hPrinter == -1)
107 pOpenedPrinter->hPrinter = i + 1;
108 return pOpenedPrinter;
113 * Didn't find one, insert new element in the array.
115 if (i == pOpenedPrinterDPA->nItemCount)
117 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
119 sizeof(OPENEDPRINTER));
120 pOpenedPrinter->hPrinter = i + 1;
121 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
122 return pOpenedPrinter;
128 /******************************************************************
129 * WINSPOOL_GetOpenedPrinter
130 * Get the pointer to the opened printer referred by the handle
132 static LPOPENEDPRINTER WINSPOOL_GetOpenedPrinter(int printerHandle)
134 LPOPENEDPRINTER pOpenedPrinter;
136 if(!pOpenedPrinterDPA) return NULL;
137 if((printerHandle <=0) ||
138 (printerHandle > (pOpenedPrinterDPA->nItemCount - 1)))
141 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, printerHandle-1);
143 return pOpenedPrinter;
146 /***********************************************************
149 static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA)
152 ptrdiff_t off_formname = (char *)dmA->dmFormName - (char *)dmA;
155 Formname = (dmA->dmSize > off_formname);
156 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
157 MultiByteToWideChar(CP_ACP, 0, dmA->dmDeviceName, -1, dmW->dmDeviceName,
160 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
161 dmA->dmSize - CCHDEVICENAME);
163 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
164 off_formname - CCHDEVICENAME);
165 MultiByteToWideChar(CP_ACP, 0, dmA->dmFormName, -1, dmW->dmFormName,
167 memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize -
168 (off_formname + CCHFORMNAME));
171 memcpy((char *)dmW + dmW->dmSize, (char *)dmA + dmA->dmSize,
176 /***********************************************************
178 * Creates a unicode copy of supplied devmode on heap
180 static LPDEVMODEW DEVMODEdupAtoW(HANDLE heap, const DEVMODEA *dmA)
185 ptrdiff_t off_formname;
188 if(!dmA) return NULL;
190 off_formname = (char *)dmA->dmFormName - (char *)dmA;
191 Formname = (dmA->dmSize > off_formname);
192 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
193 dmW = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmA->dmDriverExtra);
194 return DEVMODEcpyAtoW(dmW, dmA);
197 /***********************************************************
199 * Creates an ascii copy of supplied devmode on heap
201 static LPDEVMODEA DEVMODEdupWtoA(HANDLE heap, const DEVMODEW *dmW)
206 ptrdiff_t off_formname = (char *)dmW->dmFormName - (char *)dmW;
208 if(!dmW) return NULL;
209 Formname = (dmW->dmSize > off_formname);
210 size = dmW->dmSize - CCHDEVICENAME - (Formname ? CCHFORMNAME : 0);
211 dmA = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra);
212 WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, dmA->dmDeviceName,
213 CCHDEVICENAME, NULL, NULL);
215 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
216 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR));
218 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
219 off_formname - CCHDEVICENAME * sizeof(WCHAR));
220 WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, dmA->dmFormName,
221 CCHFORMNAME, NULL, NULL);
222 memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
223 (off_formname + CCHFORMNAME * sizeof(WCHAR)));
226 memcpy((char *)dmA + dmA->dmSize, (char *)dmW + dmW->dmSize,
231 /***********************************************************
233 * Creates a unicode copy of PRINTER_INFO_2A on heap
235 static LPPRINTER_INFO_2W PRINTER_INFO_2AtoW(HANDLE heap, LPPRINTER_INFO_2A piA)
237 LPPRINTER_INFO_2W piW;
238 if(!piA) return NULL;
239 piW = HeapAlloc(heap, 0, sizeof(*piW));
240 memcpy(piW, piA, sizeof(*piW)); /* copy everything first */
241 piW->pServerName = HEAP_strdupAtoW(heap, 0, piA->pServerName);
242 piW->pPrinterName = HEAP_strdupAtoW(heap, 0, piA->pPrinterName);
243 piW->pShareName = HEAP_strdupAtoW(heap, 0, piA->pShareName);
244 piW->pPortName = HEAP_strdupAtoW(heap, 0, piA->pPortName);
245 piW->pDriverName = HEAP_strdupAtoW(heap, 0, piA->pDriverName);
246 piW->pComment = HEAP_strdupAtoW(heap, 0, piA->pComment);
247 piW->pLocation = HEAP_strdupAtoW(heap, 0, piA->pLocation);
248 piW->pDevMode = DEVMODEdupAtoW(heap, piA->pDevMode);
249 piW->pSepFile = HEAP_strdupAtoW(heap, 0, piA->pSepFile);
250 piW->pPrintProcessor = HEAP_strdupAtoW(heap, 0, piA->pPrintProcessor);
251 piW->pDatatype = HEAP_strdupAtoW(heap, 0, piA->pDatatype);
252 piW->pParameters = HEAP_strdupAtoW(heap, 0, piA->pParameters);
256 /***********************************************************
257 * FREE_PRINTER_INFO_2W
258 * Free PRINTER_INFO_2W and all strings
260 static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW)
264 HeapFree(heap,0,piW->pServerName);
265 HeapFree(heap,0,piW->pPrinterName);
266 HeapFree(heap,0,piW->pShareName);
267 HeapFree(heap,0,piW->pPortName);
268 HeapFree(heap,0,piW->pDriverName);
269 HeapFree(heap,0,piW->pComment);
270 HeapFree(heap,0,piW->pLocation);
271 HeapFree(heap,0,piW->pDevMode);
272 HeapFree(heap,0,piW->pSepFile);
273 HeapFree(heap,0,piW->pPrintProcessor);
274 HeapFree(heap,0,piW->pDatatype);
275 HeapFree(heap,0,piW->pParameters);
276 HeapFree(heap,0,piW);
280 /******************************************************************
281 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
284 INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
285 LPSTR pOutput, LPDEVMODEA lpdm)
288 ret = GDI_CallDeviceCapabilities16(pDevice, pPort, cap, pOutput, lpdm);
290 /* If DC_PAPERSIZE map POINT16s to POINTs */
291 if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
292 POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
294 memcpy(tmp, pOutput, ret * sizeof(POINT16));
295 for(i = 0; i < ret; i++)
296 CONV_POINT16TO32(tmp + i, (POINT*)pOutput + i);
297 HeapFree( GetProcessHeap(), 0, tmp );
303 /*****************************************************************************
304 * DeviceCapabilitiesW [WINSPOOL.152]
306 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
309 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
310 WORD fwCapability, LPWSTR pOutput,
311 const DEVMODEW *pDevMode)
313 LPDEVMODEA dmA = DEVMODEdupWtoA(GetProcessHeap(), pDevMode);
314 LPSTR pDeviceA = HEAP_strdupWtoA(GetProcessHeap(),0,pDevice);
315 LPSTR pPortA = HEAP_strdupWtoA(GetProcessHeap(),0,pPort);
318 if(pOutput && (fwCapability == DC_BINNAMES ||
319 fwCapability == DC_FILEDEPENDENCIES ||
320 fwCapability == DC_PAPERNAMES)) {
321 /* These need A -> W translation */
324 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL,
328 switch(fwCapability) {
333 case DC_FILEDEPENDENCIES:
337 pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret);
338 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA,
340 for(i = 0; i < ret; i++)
341 MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1,
342 pOutput + (i * size), size);
343 HeapFree(GetProcessHeap(), 0, pOutputA);
345 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability,
346 (LPSTR)pOutput, dmA);
348 HeapFree(GetProcessHeap(),0,pPortA);
349 HeapFree(GetProcessHeap(),0,pDeviceA);
350 HeapFree(GetProcessHeap(),0,dmA);
354 /******************************************************************
355 * DocumentPropertiesA [WINSPOOL.155]
358 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
359 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
360 LPDEVMODEA pDevModeInput,DWORD fMode )
362 LPOPENEDPRINTER lpOpenedPrinter;
363 LPSTR lpName = pDeviceName;
366 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
367 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
372 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
373 if(!lpOpenedPrinter) {
374 SetLastError(ERROR_INVALID_HANDLE);
377 lpNameW = lpOpenedPrinter->lpsPrinterName;
378 lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
381 ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
382 pDevModeInput, NULL, fMode);
385 HeapFree(GetProcessHeap(),0,lpName);
390 /*****************************************************************************
391 * DocumentPropertiesW
393 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
395 LPDEVMODEW pDevModeOutput,
396 LPDEVMODEW pDevModeInput, DWORD fMode)
399 LPSTR pDeviceNameA = HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName);
400 LPDEVMODEA pDevModeInputA = DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput);
401 LPDEVMODEA pDevModeOutputA = NULL;
404 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
405 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
408 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, NULL, NULL, 0);
409 if(ret < 0) return ret;
410 pDevModeOutputA = HeapAlloc(GetProcessHeap(), 0, ret);
412 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, pDevModeOutputA,
413 pDevModeInputA, fMode);
415 DEVMODEcpyAtoW(pDevModeOutput, pDevModeOutputA);
416 HeapFree(GetProcessHeap(),0,pDevModeOutputA);
418 if(fMode == 0 && ret > 0)
419 ret += (CCHDEVICENAME + CCHFORMNAME);
420 HeapFree(GetProcessHeap(),0,pDevModeInputA);
421 HeapFree(GetProcessHeap(),0,pDeviceNameA);
425 /******************************************************************
426 * OpenPrinterA [WINSPOOL.196]
429 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
430 LPPRINTER_DEFAULTSA pDefault)
432 LPWSTR lpPrinterNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName);
433 PRINTER_DEFAULTSW DefaultW, *pDefaultW = NULL;
437 DefaultW.pDatatype = HEAP_strdupAtoW(GetProcessHeap(), 0,
438 pDefault->pDatatype);
439 DefaultW.pDevMode = DEVMODEdupAtoW(GetProcessHeap(),
441 DefaultW.DesiredAccess = pDefault->DesiredAccess;
442 pDefaultW = &DefaultW;
444 ret = OpenPrinterW(lpPrinterNameW, phPrinter, pDefaultW);
446 HeapFree(GetProcessHeap(), 0, DefaultW.pDatatype);
447 HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode);
449 HeapFree(GetProcessHeap(), 0, lpPrinterNameW);
453 /******************************************************************
454 * OpenPrinterW [WINSPOOL.197]
457 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
458 LPPRINTER_DEFAULTSW pDefault)
460 LPOPENEDPRINTER lpOpenedPrinter;
461 HKEY hkeyPrinters, hkeyPrinter;
463 if (!lpPrinterName) {
464 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault);
465 SetLastError(ERROR_INVALID_PARAMETER);
469 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName),
472 /* Check Printer exists */
473 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
475 ERR("Can't create Printers key\n");
476 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
480 if(RegOpenKeyW(hkeyPrinters, lpPrinterName, &hkeyPrinter)
482 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName));
483 RegCloseKey(hkeyPrinters);
484 SetLastError(ERROR_INVALID_PARAMETER);
487 RegCloseKey(hkeyPrinter);
488 RegCloseKey(hkeyPrinters);
490 if(!phPrinter) /* This seems to be what win95 does anyway */
493 /* Get a place in the opened printer buffer*/
494 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntry();
495 if(!lpOpenedPrinter) {
496 ERR("Can't allocate printer slot\n");
497 SetLastError(ERROR_OUTOFMEMORY);
501 /* Get the name of the printer */
502 lpOpenedPrinter->lpsPrinterName =
503 HEAP_strdupW( GetProcessHeap(), 0, lpPrinterName );
505 /* Get the unique handle of the printer*/
506 *phPrinter = lpOpenedPrinter->hPrinter;
508 if (pDefault != NULL)
509 FIXME("Not handling pDefault\n");
514 /******************************************************************
515 * AddMonitorA [WINSPOOL.107]
518 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
520 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
521 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
525 /******************************************************************
526 * DeletePrinterDriverA [WINSPOOL.146]
530 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
532 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
533 debugstr_a(pDriverName));
534 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
539 /******************************************************************
540 * DeleteMonitorA [WINSPOOL.135]
544 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
546 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
547 debugstr_a(pMonitorName));
548 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
553 /******************************************************************
554 * DeletePortA [WINSPOOL.137]
558 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
560 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
561 debugstr_a(pPortName));
562 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
566 /******************************************************************************
567 * SetPrinterW [WINSPOOL.214]
577 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
581 /******************************************************************************
582 * WritePrinter [WINSPOOL.223]
592 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
596 /*****************************************************************************
597 * AddFormA [WINSPOOL.103]
599 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
601 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
605 /*****************************************************************************
606 * AddFormW [WINSPOOL.104]
608 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
610 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
614 /*****************************************************************************
615 * AddJobA [WINSPOOL.105]
617 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
618 DWORD cbBuf, LPDWORD pcbNeeded)
620 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
625 /*****************************************************************************
626 * AddJobW [WINSPOOL.106]
628 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
631 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
636 /*****************************************************************************
637 * AddPrinterW [WINSPOOL.122]
639 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
641 PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
645 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
648 TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
651 FIXME("pName = %s - unsupported\n", debugstr_w(pName));
652 SetLastError(ERROR_INVALID_PARAMETER);
656 WARN("Level = %ld\n", Level);
657 SetLastError(ERROR_INVALID_LEVEL);
661 SetLastError(ERROR_INVALID_PARAMETER);
664 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
666 ERR("Can't create Printers key\n");
669 if(RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
671 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
672 RegCloseKey(hkeyPrinter);
673 RegCloseKey(hkeyPrinters);
676 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
678 ERR("Can't create Drivers key\n");
679 RegCloseKey(hkeyPrinters);
682 if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
684 WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
685 RegCloseKey(hkeyPrinters);
686 RegCloseKey(hkeyDrivers);
687 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
690 RegCloseKey(hkeyDriver);
691 RegCloseKey(hkeyDrivers);
693 if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */
694 WARN("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
695 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
696 RegCloseKey(hkeyPrinters);
700 /* See if we can load the driver. We may need the devmode structure anyway
702 size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0);
704 WARN("DocumentProperties fails\n");
705 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
711 dmW = HeapAlloc(GetProcessHeap(), 0, size);
712 DocumentPropertiesW(0, -1, pi->pPrinterName, dmW, NULL, DM_OUT_BUFFER);
715 if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
717 WARN("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
718 SetLastError(ERROR_INVALID_PRINTER_NAME);
719 RegCloseKey(hkeyPrinters);
721 HeapFree(GetProcessHeap(), 0, dmW);
724 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
725 (LPBYTE)&pi->Attributes, sizeof(DWORD));
726 RegSetValueExW(hkeyPrinter, DatatypeW, 0, REG_SZ, (LPBYTE)pi->pDatatype,
729 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
730 and we support these drivers. NT writes DEVMODEW so somehow
731 we'll need to distinguish between these when we support NT
733 dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
734 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
735 dmA->dmSize + dmA->dmDriverExtra);
736 HeapFree(GetProcessHeap(), 0, dmA);
738 HeapFree(GetProcessHeap(), 0, dmW);
739 RegSetValueExW(hkeyPrinter, DescriptionW, 0, REG_SZ, (LPBYTE)pi->pComment,
741 RegSetValueExW(hkeyPrinter, LocationW, 0, REG_SZ, (LPBYTE)pi->pLocation,
743 RegSetValueExW(hkeyPrinter, NameW, 0, REG_SZ, (LPBYTE)pi->pPrinterName, 0);
744 RegSetValueExW(hkeyPrinter, ParametersW, 0, REG_SZ,
745 (LPBYTE)pi->pParameters, 0);
746 RegSetValueExW(hkeyPrinter, PortW, 0, REG_SZ, (LPBYTE)pi->pPortName, 0);
747 RegSetValueExW(hkeyPrinter, Print_ProcessorW, 0, REG_SZ,
748 (LPBYTE)pi->pPrintProcessor, 0);
749 RegSetValueExW(hkeyPrinter, Printer_DriverW, 0, REG_SZ,
750 (LPBYTE)pi->pDriverName, 0);
751 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
752 (LPBYTE)&pi->Priority, sizeof(DWORD));
753 RegSetValueExW(hkeyPrinter, Separator_FileW, 0, REG_SZ,
754 (LPBYTE)pi->pSepFile, 0);
755 RegSetValueExW(hkeyPrinter, Share_NameW, 0, REG_SZ, (LPBYTE)pi->pShareName,
757 RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
758 (LPBYTE)&pi->StartTime, sizeof(DWORD));
759 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
760 (LPBYTE)&pi->Status, sizeof(DWORD));
761 RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
762 (LPBYTE)&pi->UntilTime, sizeof(DWORD));
764 RegCloseKey(hkeyPrinter);
765 RegCloseKey(hkeyPrinters);
766 if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
767 ERR("OpenPrinter failing\n");
773 /*****************************************************************************
774 * AddPrinterA [WINSPOOL.117]
776 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
779 PRINTER_INFO_2W *piW;
780 PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
783 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
785 WARN("Level = %ld\n", Level);
786 SetLastError(ERROR_INVALID_LEVEL);
789 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
790 piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
792 ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
794 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
795 HeapFree(GetProcessHeap(),0,pNameW);
800 /*****************************************************************************
801 * ClosePrinter [WINSPOOL.126]
803 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
805 LPOPENEDPRINTER lpOpenedPrinter;
807 TRACE("Handle %d\n", hPrinter);
809 if (!pOpenedPrinterDPA)
812 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
814 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
815 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
816 lpOpenedPrinter->lpsPrinterName = NULL;
817 lpOpenedPrinter->hPrinter = -1;
824 /*****************************************************************************
825 * DeleteFormA [WINSPOOL.133]
827 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
829 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
833 /*****************************************************************************
834 * DeleteFormW [WINSPOOL.134]
836 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
838 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
842 /*****************************************************************************
843 * DeletePrinter [WINSPOOL.143]
845 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
850 LPOPENEDPRINTER lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
851 if(!lpOpenedPrinter) {
852 SetLastError(ERROR_INVALID_HANDLE);
855 lpNameW = lpOpenedPrinter->lpsPrinterName;
856 if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
858 ERR("Can't open Printers key\n");
862 /* This should use a recursive delete see Q142491 or SHDeleteKey */
863 if(RegDeleteKeyW(hkeyPrinters, lpNameW) == ERROR_SUCCESS) {
864 SetLastError(ERROR_PRINTER_NOT_FOUND); /* ?? */
865 RegCloseKey(hkeyPrinters);
869 ClosePrinter(hPrinter);
873 /*****************************************************************************
874 * SetPrinterA [WINSPOOL.211]
876 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
879 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
883 /*****************************************************************************
884 * SetJobA [WINSPOOL.209]
886 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
887 LPBYTE pJob, DWORD Command)
889 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
894 /*****************************************************************************
895 * SetJobW [WINSPOOL.210]
897 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
898 LPBYTE pJob, DWORD Command)
900 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
905 /*****************************************************************************
906 * GetFormA [WINSPOOL.181]
908 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
909 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
911 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
912 Level,pForm,cbBuf,pcbNeeded);
916 /*****************************************************************************
917 * GetFormW [WINSPOOL.182]
919 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
920 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
922 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
923 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
927 /*****************************************************************************
928 * SetFormA [WINSPOOL.207]
930 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
933 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
937 /*****************************************************************************
938 * SetFormW [WINSPOOL.208]
940 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
943 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
947 /*****************************************************************************
948 * ReadPrinter [WINSPOOL.202]
950 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
951 LPDWORD pNoBytesRead)
953 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
957 /*****************************************************************************
958 * ResetPrinterA [WINSPOOL.203]
960 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
962 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
966 /*****************************************************************************
967 * ResetPrinterW [WINSPOOL.204]
969 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
971 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
975 /*****************************************************************************
976 * WINSPOOL_GetDWORDFromReg
978 * Return DWORD associated with ValueName from hkey.
980 static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
982 DWORD sz = sizeof(DWORD), type, value = 0;
985 ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz);
987 if(ret != ERROR_SUCCESS) {
988 WARN("Got ret = %ld on name %s\n", ret, ValueName);
991 if(type != REG_DWORD) {
992 ERR("Got type %ld\n", type);
998 /*****************************************************************************
999 * WINSPOOL_GetStringFromReg
1001 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1002 * String is stored either as unicode or ascii.
1003 * Bit of a hack here to get the ValueName if we want ascii.
1005 static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
1006 DWORD buflen, DWORD *needed,
1009 DWORD sz = buflen, type;
1013 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1015 LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
1016 ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
1017 HeapFree(GetProcessHeap(),0,ValueNameA);
1019 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1020 WARN("Got ret = %ld\n", ret);
1028 /*****************************************************************************
1029 * WINSPOOL_GetDevModeFromReg
1031 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1032 * DevMode is stored either as unicode or ascii.
1034 static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
1036 DWORD buflen, DWORD *needed,
1039 DWORD sz = buflen, type;
1042 if (ptr) memset(ptr, 0, sizeof(DEVMODEA));
1043 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1044 if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
1045 if (sz < sizeof(DEVMODEA))
1047 ERR("corrupted registry for %s\n", debugstr_w(ValueName));
1048 sz = sizeof(DEVMODEA);
1050 /* ensures that dmSize is not erratically bogus if registry is invalid */
1051 if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
1052 ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
1054 sz += (CCHDEVICENAME + CCHFORMNAME);
1056 DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
1057 memcpy(ptr, dmW, sz);
1058 HeapFree(GetProcessHeap(),0,dmW);
1065 /*********************************************************************
1066 * WINSPOOL_GetPrinter_2
1068 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1069 * The strings are either stored as unicode or ascii.
1071 static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
1072 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1075 DWORD size, left = cbBuf;
1076 BOOL space = (cbBuf > 0);
1081 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1083 if(space && size <= left) {
1084 pi2->pPrinterName = (LPWSTR)ptr;
1091 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
1093 if(space && size <= left) {
1094 pi2->pShareName = (LPWSTR)ptr;
1101 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1103 if(space && size <= left) {
1104 pi2->pPortName = (LPWSTR)ptr;
1111 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
1113 if(space && size <= left) {
1114 pi2->pDriverName = (LPWSTR)ptr;
1121 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
1123 if(space && size <= left) {
1124 pi2->pComment = (LPWSTR)ptr;
1131 if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
1133 if(space && size <= left) {
1134 pi2->pLocation = (LPWSTR)ptr;
1141 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
1143 if(space && size <= left) {
1144 pi2->pDevMode = (LPDEVMODEW)ptr;
1151 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
1153 if(space && size <= left) {
1154 pi2->pSepFile = (LPWSTR)ptr;
1161 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
1163 if(space && size <= left) {
1164 pi2->pPrintProcessor = (LPWSTR)ptr;
1171 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
1173 if(space && size <= left) {
1174 pi2->pDatatype = (LPWSTR)ptr;
1181 if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
1183 if(space && size <= left) {
1184 pi2->pParameters = (LPWSTR)ptr;
1192 pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1193 pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
1194 pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1195 "Default Priority");
1196 pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
1197 pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
1200 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1201 memset(pi2, 0, sizeof(*pi2));
1206 /*********************************************************************
1207 * WINSPOOL_GetPrinter_4
1209 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1211 static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
1212 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1215 DWORD size, left = cbBuf;
1216 BOOL space = (cbBuf > 0);
1221 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1223 if(space && size <= left) {
1224 pi4->pPrinterName = (LPWSTR)ptr;
1232 pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1235 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1236 memset(pi4, 0, sizeof(*pi4));
1241 /*********************************************************************
1242 * WINSPOOL_GetPrinter_5
1244 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1246 static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
1247 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1250 DWORD size, left = cbBuf;
1251 BOOL space = (cbBuf > 0);
1256 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1258 if(space && size <= left) {
1259 pi5->pPrinterName = (LPWSTR)ptr;
1266 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1268 if(space && size <= left) {
1269 pi5->pPortName = (LPWSTR)ptr;
1277 pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1278 pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1280 pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1284 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1285 memset(pi5, 0, sizeof(*pi5));
1290 /*****************************************************************************
1291 * WINSPOOL_GetPrinter
1293 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1294 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1295 * just a collection of pointers to strings.
1297 static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1298 DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
1300 OPENEDPRINTER *lpOpenedPrinter;
1301 DWORD size, needed = 0;
1303 HKEY hkeyPrinter, hkeyPrinters;
1306 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1308 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1309 if(!lpOpenedPrinter) {
1310 SetLastError(ERROR_INVALID_HANDLE);
1313 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1315 ERR("Can't create Printers key\n");
1318 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1320 ERR("Can't find opened printer %s in registry\n",
1321 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1322 RegCloseKey(hkeyPrinters);
1323 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1330 PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
1332 size = sizeof(PRINTER_INFO_2W);
1334 ptr = pPrinter + size;
1336 memset(pPrinter, 0, size);
1341 ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
1349 PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
1351 size = sizeof(PRINTER_INFO_4W);
1353 ptr = pPrinter + size;
1355 memset(pPrinter, 0, size);
1360 ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
1369 PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
1371 size = sizeof(PRINTER_INFO_5W);
1373 ptr = pPrinter + size;
1375 memset(pPrinter, 0, size);
1381 ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
1388 FIXME("Unimplemented level %ld\n", Level);
1389 SetLastError(ERROR_INVALID_LEVEL);
1390 RegCloseKey(hkeyPrinters);
1391 RegCloseKey(hkeyPrinter);
1395 RegCloseKey(hkeyPrinter);
1396 RegCloseKey(hkeyPrinters);
1398 TRACE("returing %d needed = %ld\n", ret, needed);
1399 if(pcbNeeded) *pcbNeeded = needed;
1401 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1405 /*****************************************************************************
1406 * GetPrinterW [WINSPOOL.194]
1408 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1409 DWORD cbBuf, LPDWORD pcbNeeded)
1411 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1415 /*****************************************************************************
1416 * GetPrinterA [WINSPOOL.187]
1418 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1419 DWORD cbBuf, LPDWORD pcbNeeded)
1421 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1425 /*****************************************************************************
1426 * WINSPOOL_EnumPrinters
1428 * Implementation of EnumPrintersA|W
1430 static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
1431 DWORD dwLevel, LPBYTE lpbPrinters,
1432 DWORD cbBuf, LPDWORD lpdwNeeded,
1433 LPDWORD lpdwReturned, BOOL unicode)
1436 HKEY hkeyPrinters, hkeyPrinter;
1437 WCHAR PrinterName[255];
1438 DWORD needed = 0, number = 0;
1439 DWORD used, i, left;
1443 memset(lpbPrinters, 0, cbBuf);
1447 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1448 FIXME("dwType = %08lx\n", dwType);
1449 SetLastError(ERROR_INVALID_FLAGS);
1453 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1455 ERR("Can't create Printers key\n");
1459 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1460 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1461 RegCloseKey(hkeyPrinters);
1462 ERR("Can't query Printers key\n");
1465 TRACE("Found %ld printers\n", number);
1469 RegCloseKey(hkeyPrinters);
1471 *lpdwReturned = number;
1475 used = number * sizeof(PRINTER_INFO_2W);
1478 used = number * sizeof(PRINTER_INFO_4W);
1481 used = number * sizeof(PRINTER_INFO_5W);
1485 SetLastError(ERROR_INVALID_LEVEL);
1486 RegCloseKey(hkeyPrinters);
1489 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1491 for(i = 0; i < number; i++) {
1492 if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1494 ERR("Can't enum key number %ld\n", i);
1495 RegCloseKey(hkeyPrinters);
1498 TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
1499 if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1501 ERR("Can't open key %s\n", debugstr_w(PrinterName));
1502 RegCloseKey(hkeyPrinters);
1507 buf = lpbPrinters + used;
1508 left = cbBuf - used;
1516 WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
1517 left, &needed, unicode);
1519 if(pi) pi += sizeof(PRINTER_INFO_2W);
1522 WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
1523 left, &needed, unicode);
1525 if(pi) pi += sizeof(PRINTER_INFO_4W);
1528 WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
1529 left, &needed, unicode);
1531 if(pi) pi += sizeof(PRINTER_INFO_5W);
1534 ERR("Shouldn't be here!\n");
1535 RegCloseKey(hkeyPrinter);
1536 RegCloseKey(hkeyPrinters);
1539 RegCloseKey(hkeyPrinter);
1541 RegCloseKey(hkeyPrinters);
1548 memset(lpbPrinters, 0, cbBuf);
1549 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1553 *lpdwReturned = number;
1554 SetLastError(ERROR_SUCCESS);
1559 /******************************************************************
1560 * EnumPrintersW [WINSPOOL.175]
1562 * Enumerates the available printers, print servers and print
1563 * providers, depending on the specified flags, name and level.
1567 * If level is set to 1:
1568 * Not implemented yet!
1569 * Returns TRUE with an empty list.
1571 * If level is set to 2:
1572 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1573 * Returns an array of PRINTER_INFO_2 data structures in the
1574 * lpbPrinters buffer. Note that according to MSDN also an
1575 * OpenPrinter should be performed on every remote printer.
1577 * If level is set to 4 (officially WinNT only):
1578 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1579 * Fast: Only the registry is queried to retrieve printer names,
1580 * no connection to the driver is made.
1581 * Returns an array of PRINTER_INFO_4 data structures in the
1582 * lpbPrinters buffer.
1584 * If level is set to 5 (officially WinNT4/Win9x only):
1585 * Fast: Only the registry is queried to retrieve printer names,
1586 * no connection to the driver is made.
1587 * Returns an array of PRINTER_INFO_5 data structures in the
1588 * lpbPrinters buffer.
1590 * If level set to 3 or 6+:
1591 * returns zero (faillure!)
1593 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1597 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1598 * - Only levels 2, 4 and 5 are implemented at the moment.
1599 * - 16-bit printer drivers are not enumerated.
1600 * - Returned amount of bytes used/needed does not match the real Windoze
1601 * implementation (as in this implementation, all strings are part
1602 * of the buffer, whereas Win32 keeps them somewhere else)
1603 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1606 * - In a regular Wine installation, no registry settings for printers
1607 * exist, which makes this function return an empty list.
1609 BOOL WINAPI EnumPrintersW(
1610 DWORD dwType, /* Types of print objects to enumerate */
1611 LPWSTR lpszName, /* name of objects to enumerate */
1612 DWORD dwLevel, /* type of printer info structure */
1613 LPBYTE lpbPrinters, /* buffer which receives info */
1614 DWORD cbBuf, /* max size of buffer in bytes */
1615 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
1616 LPDWORD lpdwReturned /* number of entries returned */
1619 return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
1620 lpdwNeeded, lpdwReturned, TRUE);
1623 /******************************************************************
1624 * EnumPrintersA [WINSPOOL.174]
1627 BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
1628 DWORD dwLevel, LPBYTE lpbPrinters,
1629 DWORD cbBuf, LPDWORD lpdwNeeded,
1630 LPDWORD lpdwReturned)
1633 LPWSTR lpszNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
1635 ret = WINSPOOL_EnumPrinters(dwType, lpszNameW, dwLevel, lpbPrinters, cbBuf,
1636 lpdwNeeded, lpdwReturned, FALSE);
1637 HeapFree(GetProcessHeap(),0,lpszNameW);
1642 /*****************************************************************************
1643 * WINSPOOL_GetPrinterDriver
1645 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
1646 DWORD Level, LPBYTE pDriverInfo,
1647 DWORD cbBuf, LPDWORD pcbNeeded,
1650 OPENEDPRINTER *lpOpenedPrinter;
1651 WCHAR DriverName[100];
1652 DWORD ret, type, size, dw, needed = 0;
1654 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
1656 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
1657 Level,pDriverInfo,cbBuf, pcbNeeded);
1659 ZeroMemory(pDriverInfo, cbBuf);
1661 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1662 if(!lpOpenedPrinter) {
1663 SetLastError(ERROR_INVALID_HANDLE);
1667 FIXME("pEnvironment = %s\n", debugstr_w(pEnvironment));
1668 SetLastError(ERROR_INVALID_ENVIRONMENT);
1671 if(Level < 1 || Level > 3) {
1672 SetLastError(ERROR_INVALID_LEVEL);
1675 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1677 ERR("Can't create Printers key\n");
1680 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1682 ERR("Can't find opened printer %s in registry\n",
1683 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1684 RegCloseKey(hkeyPrinters);
1685 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1688 size = sizeof(DriverName);
1689 ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
1690 (LPBYTE)DriverName, &size);
1691 RegCloseKey(hkeyPrinter);
1692 RegCloseKey(hkeyPrinters);
1693 if(ret != ERROR_SUCCESS) {
1694 ERR("Can't get DriverName for printer %s\n",
1695 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1698 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1700 ERR("Can't create Drivers key\n");
1703 if(RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver)
1705 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName));
1706 RegCloseKey(hkeyDrivers);
1707 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1713 size = sizeof(DRIVER_INFO_1W);
1716 size = sizeof(DRIVER_INFO_2W);
1719 size = sizeof(DRIVER_INFO_3W);
1722 ERR("Invalid level\n");
1727 ptr = pDriverInfo + size;
1734 size = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
1736 size = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0, NULL,
1742 strcpyW((LPWSTR)ptr, DriverName);
1744 WideCharToMultiByte(CP_ACP, 0, DriverName, -1, ptr, size, NULL,
1747 ((DRIVER_INFO_1W *)pDriverInfo)->pName = (LPWSTR)ptr;
1749 ((DRIVER_INFO_2W *)pDriverInfo)->pName = (LPWSTR)ptr;
1755 DRIVER_INFO_2W *di2 = (DRIVER_INFO_2W *)pDriverInfo;
1758 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw,
1761 WARN("Can't get Version\n");
1766 pEnvironment = DefaultEnvironmentW;
1768 size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
1770 size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
1775 strcpyW((LPWSTR)ptr, pEnvironment);
1777 WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, ptr, size,
1779 di2->pEnvironment = (LPWSTR)ptr;
1785 if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, ptr, cbBuf, &size,
1787 if(cbBuf && size <= cbBuf) {
1788 di2->pDriverPath = (LPWSTR)ptr;
1794 if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, ptr, cbBuf, &size,
1796 if(cbBuf && size <= cbBuf) {
1797 di2->pDataFile = (LPWSTR)ptr;
1803 if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, ptr,
1804 cbBuf, &size, unicode)) {
1805 if(cbBuf && size <= cbBuf) {
1806 di2->pConfigFile = (LPWSTR)ptr;
1814 DRIVER_INFO_3W *di3 = (DRIVER_INFO_3W *)pDriverInfo;
1816 if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, ptr, cbBuf, &size,
1818 if(cbBuf && size <= cbBuf) {
1819 di3->pHelpFile = (LPWSTR)ptr;
1825 if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, ptr, cbBuf,
1827 if(cbBuf && size <= cbBuf) {
1828 di3->pDependentFiles = (LPWSTR)ptr;
1834 if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, ptr, cbBuf, &size,
1836 if(cbBuf && size <= cbBuf) {
1837 di3->pMonitorName = (LPWSTR)ptr;
1843 if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, ptr, cbBuf, &size,
1845 if(cbBuf && size <= cbBuf) {
1846 di3->pDefaultDataType = (LPWSTR)ptr;
1853 RegCloseKey(hkeyDriver);
1854 RegCloseKey(hkeyDrivers);
1856 if(pcbNeeded) *pcbNeeded = needed;
1857 if(cbBuf) return TRUE;
1858 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1862 /*****************************************************************************
1863 * GetPrinterDriverA [WINSPOOL.190]
1865 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1866 DWORD Level, LPBYTE pDriverInfo,
1867 DWORD cbBuf, LPDWORD pcbNeeded)
1870 LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
1871 ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
1872 cbBuf, pcbNeeded, FALSE);
1873 HeapFree(GetProcessHeap(),0,pEnvW);
1876 /*****************************************************************************
1877 * GetPrinterDriverW [WINSPOOL.193]
1879 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1880 DWORD Level, LPBYTE pDriverInfo,
1881 DWORD cbBuf, LPDWORD pcbNeeded)
1883 return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level,
1884 pDriverInfo, cbBuf, pcbNeeded, TRUE);
1887 /*****************************************************************************
1888 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1890 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1891 DWORD Level, LPBYTE pDriverDirectory,
1892 DWORD cbBuf, LPDWORD pcbNeeded)
1896 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1897 pDriverDirectory, cbBuf, pcbNeeded);
1899 FIXME("pName = `%s' - unsupported\n", pName);
1900 SetLastError(ERROR_INVALID_PARAMETER);
1903 if(pEnvironment != NULL) {
1904 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
1905 SetLastError(ERROR_INVALID_ENVIRONMENT);
1908 if(Level != 1) /* win95 ignores this so we just carry on */
1909 WARN("Level = %ld - assuming 1\n", Level);
1911 /* FIXME should read from registry */
1912 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
1915 *pcbNeeded = needed;
1916 if(needed > cbBuf) {
1917 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1924 /*****************************************************************************
1925 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1927 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
1928 DWORD Level, LPBYTE pDriverDirectory,
1929 DWORD cbBuf, LPDWORD pcbNeeded)
1931 LPSTR pNameA = NULL, pEnvironmentA = NULL;
1935 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
1937 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
1938 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
1939 pDriverDirectory, cbBuf, pcbNeeded );
1941 HeapFree( GetProcessHeap(), 0, pNameA );
1943 HeapFree( GetProcessHeap(), 0, pEnvironment );
1948 /*****************************************************************************
1949 * AddPrinterDriverA [WINSPOOL.120]
1951 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
1954 HKEY hkeyDrivers, hkeyName;
1956 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
1958 if(level != 2 && level != 3) {
1959 SetLastError(ERROR_INVALID_LEVEL);
1963 FIXME("pName= `%s' - unsupported\n", pName);
1964 SetLastError(ERROR_INVALID_PARAMETER);
1968 WARN("pDriverInfo == NULL");
1969 SetLastError(ERROR_INVALID_PARAMETER);
1974 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
1976 memset(&di3, 0, sizeof(di3));
1977 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
1980 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
1982 SetLastError(ERROR_INVALID_PARAMETER);
1985 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
1986 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
1987 if(!di3.pHelpFile) di3.pHelpFile = "";
1988 if(!di3.pMonitorName) di3.pMonitorName = "";
1990 if(di3.pEnvironment) {
1991 FIXME("pEnvironment = `%s'\n", di3.pEnvironment);
1992 SetLastError(ERROR_INVALID_ENVIRONMENT);
1995 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1997 ERR("Can't create Drivers key\n");
2001 if(level == 2) { /* apparently can't overwrite with level2 */
2002 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
2003 RegCloseKey(hkeyName);
2004 RegCloseKey(hkeyDrivers);
2005 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
2006 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
2010 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
2011 RegCloseKey(hkeyDrivers);
2012 ERR("Can't create Name key\n");
2015 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
2017 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
2018 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
2019 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
2021 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
2022 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
2023 di3.pDependentFiles, 0);
2024 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
2025 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
2026 RegCloseKey(hkeyName);
2027 RegCloseKey(hkeyDrivers);
2031 /*****************************************************************************
2032 * AddPrinterDriverW [WINSPOOL.121]
2034 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
2037 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
2043 /*****************************************************************************
2044 * PrinterProperties [WINSPOOL.201]
2046 * Displays a dialog to set the properties of the printer.
2049 * nonzero on succes or zero on faillure
2052 * implemented as stub only
2054 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
2055 HANDLE hPrinter /* handle to printer object */
2057 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
2058 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2062 /*****************************************************************************
2063 * EnumJobsA [WINSPOOL.162]
2066 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2067 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2071 if(pcbNeeded) *pcbNeeded = 0;
2072 if(pcReturned) *pcReturned = 0;
2077 /*****************************************************************************
2078 * EnumJobsW [WINSPOOL.163]
2081 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2082 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2086 if(pcbNeeded) *pcbNeeded = 0;
2087 if(pcReturned) *pcReturned = 0;