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/windef16.h"
19 #include "wine/unicode.h"
20 #include "debugtools.h"
25 DEFAULT_DEBUG_CHANNEL(winspool);
27 typedef struct _OPENEDPRINTER
29 LPWSTR lpsPrinterName;
31 } OPENEDPRINTER, *LPOPENEDPRINTER;
33 /* The OpenedPrinter Table dynamic array */
34 static HDPA pOpenedPrinterDPA = NULL;
36 extern HDPA (WINAPI* WINSPOOL_DPA_CreateEx) (INT, HANDLE);
37 extern LPVOID (WINAPI* WINSPOOL_DPA_GetPtr) (const HDPA, INT);
38 extern INT (WINAPI* WINSPOOL_DPA_InsertPtr) (const HDPA, INT, LPVOID);
40 static char Printers[] =
41 "System\\CurrentControlSet\\control\\Print\\Printers\\";
42 static char Drivers[] =
43 "System\\CurrentControlSet\\control\\Print\\Environments\\%s\\Drivers\\";
45 static WCHAR DefaultEnvironmentW[] = {'W','i','n','e',0};
47 static WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t',
48 'i','o','n',' ','F','i','l','e',0};
49 static WCHAR DatatypeW[] = {'D','a','t','a','t','y','p','e',0};
50 static WCHAR Data_FileW[] = {'D','a','t','a',' ','F','i','l','e',0};
51 static WCHAR Default_DevModeW[] = {'D','e','f','a','u','l','t',' ','D','e','v',
53 static WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F',
55 static WCHAR DescriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
56 static WCHAR DriverW[] = {'D','r','i','v','e','r',0};
57 static WCHAR Help_FileW[] = {'H','e','l','p',' ','F','i','l','e',0};
58 static WCHAR LocationW[] = {'L','o','c','a','t','i','o','n',0};
59 static WCHAR MonitorW[] = {'M','o','n','i','t','o','r',0};
60 static WCHAR NameW[] = {'N','a','m','e',0};
61 static WCHAR ParametersW[] = {'P','a','r','a','m','e','t','e','r','s',0};
62 static WCHAR PortW[] = {'P','o','r','t',0};
63 static WCHAR Print_ProcessorW[] = {'P','r','i','n','t',' ','P','r','o','c','e',
65 static WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i',
67 static WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F',
69 static WCHAR Share_NameW[] = {'S','h','a','r','e',' ','N','a','m','e',0};
70 static WCHAR WinPrintW[] = {'W','i','n','P','r','i','n','t',0};
72 /******************************************************************
73 * WINSPOOL_GetOpenedPrinterEntry
74 * Get the first place empty in the opened printer table
76 static LPOPENEDPRINTER WINSPOOL_GetOpenedPrinterEntry()
79 LPOPENEDPRINTER pOpenedPrinter;
82 * Create the opened printers' handle dynamic array.
84 if (!pOpenedPrinterDPA)
86 pOpenedPrinterDPA = WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
87 for (i = 0; i < 10; i++)
89 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
91 sizeof(OPENEDPRINTER));
92 pOpenedPrinter->hPrinter = -1;
93 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
98 * Search for a handle not yet allocated.
100 for (i = 0; i < pOpenedPrinterDPA->nItemCount; i++)
102 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, i);
104 if (pOpenedPrinter->hPrinter == -1)
106 pOpenedPrinter->hPrinter = i + 1;
107 return pOpenedPrinter;
112 * Didn't find one, insert new element in the array.
114 if (i == pOpenedPrinterDPA->nItemCount)
116 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
118 sizeof(OPENEDPRINTER));
119 pOpenedPrinter->hPrinter = i + 1;
120 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
121 return pOpenedPrinter;
127 /******************************************************************
128 * WINSPOOL_GetOpenedPrinter
129 * Get the pointer to the opened printer referred by the handle
131 static LPOPENEDPRINTER WINSPOOL_GetOpenedPrinter(int printerHandle)
133 LPOPENEDPRINTER pOpenedPrinter;
135 if(!pOpenedPrinterDPA) return NULL;
136 if((printerHandle <=0) ||
137 (printerHandle > (pOpenedPrinterDPA->nItemCount - 1)))
140 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, printerHandle-1);
142 return pOpenedPrinter;
145 /***********************************************************
148 static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA)
151 ptrdiff_t off_formname = (char *)dmA->dmFormName - (char *)dmA;
154 Formname = (dmA->dmSize > off_formname);
155 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
156 MultiByteToWideChar(CP_ACP, 0, dmA->dmDeviceName, -1, dmW->dmDeviceName,
159 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
160 dmA->dmSize - CCHDEVICENAME);
162 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
163 off_formname - CCHDEVICENAME);
164 MultiByteToWideChar(CP_ACP, 0, dmA->dmFormName, -1, dmW->dmFormName,
166 memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize -
167 (off_formname + CCHFORMNAME));
170 memcpy((char *)dmW + dmW->dmSize, (char *)dmA + dmA->dmSize,
175 /***********************************************************
177 * Creates a unicode copy of supplied devmode on heap
179 static LPDEVMODEW DEVMODEdupAtoW(HANDLE heap, const DEVMODEA *dmA)
184 ptrdiff_t off_formname;
187 if(!dmA) return NULL;
189 off_formname = (char *)dmA->dmFormName - (char *)dmA;
190 Formname = (dmA->dmSize > off_formname);
191 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
192 dmW = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmA->dmDriverExtra);
193 return DEVMODEcpyAtoW(dmW, dmA);
196 /***********************************************************
198 * Creates an ascii copy of supplied devmode on heap
200 static LPDEVMODEA DEVMODEdupWtoA(HANDLE heap, const DEVMODEW *dmW)
205 ptrdiff_t off_formname = (char *)dmW->dmFormName - (char *)dmW;
207 if(!dmW) return NULL;
208 Formname = (dmW->dmSize > off_formname);
209 size = dmW->dmSize - CCHDEVICENAME - (Formname ? CCHFORMNAME : 0);
210 dmA = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra);
211 WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, dmA->dmDeviceName,
212 CCHDEVICENAME, NULL, NULL);
214 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
215 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR));
217 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
218 off_formname - CCHDEVICENAME * sizeof(WCHAR));
219 WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, dmA->dmFormName,
220 CCHFORMNAME, NULL, NULL);
221 memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
222 (off_formname + CCHFORMNAME * sizeof(WCHAR)));
225 memcpy((char *)dmA + dmA->dmSize, (char *)dmW + dmW->dmSize,
230 /***********************************************************
232 * Creates a unicode copy of PRINTER_INFO_2A on heap
234 static LPPRINTER_INFO_2W PRINTER_INFO_2AtoW(HANDLE heap, LPPRINTER_INFO_2A piA)
236 LPPRINTER_INFO_2W piW;
237 if(!piA) return NULL;
238 piW = HeapAlloc(heap, 0, sizeof(*piW));
239 memcpy(piW, piA, sizeof(*piW)); /* copy everything first */
240 piW->pServerName = HEAP_strdupAtoW(heap, 0, piA->pServerName);
241 piW->pPrinterName = HEAP_strdupAtoW(heap, 0, piA->pPrinterName);
242 piW->pShareName = HEAP_strdupAtoW(heap, 0, piA->pShareName);
243 piW->pPortName = HEAP_strdupAtoW(heap, 0, piA->pPortName);
244 piW->pDriverName = HEAP_strdupAtoW(heap, 0, piA->pDriverName);
245 piW->pComment = HEAP_strdupAtoW(heap, 0, piA->pComment);
246 piW->pLocation = HEAP_strdupAtoW(heap, 0, piA->pLocation);
247 piW->pDevMode = DEVMODEdupAtoW(heap, piA->pDevMode);
248 piW->pSepFile = HEAP_strdupAtoW(heap, 0, piA->pSepFile);
249 piW->pPrintProcessor = HEAP_strdupAtoW(heap, 0, piA->pPrintProcessor);
250 piW->pDatatype = HEAP_strdupAtoW(heap, 0, piA->pDatatype);
251 piW->pParameters = HEAP_strdupAtoW(heap, 0, piA->pParameters);
255 /***********************************************************
256 * FREE_PRINTER_INFO_2W
257 * Free PRINTER_INFO_2W and all strings
259 static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW)
263 HeapFree(heap,0,piW->pServerName);
264 HeapFree(heap,0,piW->pPrinterName);
265 HeapFree(heap,0,piW->pShareName);
266 HeapFree(heap,0,piW->pPortName);
267 HeapFree(heap,0,piW->pDriverName);
268 HeapFree(heap,0,piW->pComment);
269 HeapFree(heap,0,piW->pLocation);
270 HeapFree(heap,0,piW->pDevMode);
271 HeapFree(heap,0,piW->pSepFile);
272 HeapFree(heap,0,piW->pPrintProcessor);
273 HeapFree(heap,0,piW->pDatatype);
274 HeapFree(heap,0,piW->pParameters);
275 HeapFree(heap,0,piW);
279 /******************************************************************
280 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
283 INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
284 LPSTR pOutput, LPDEVMODEA lpdm)
287 ret = GDI_CallDeviceCapabilities16(pDevice, pPort, cap, pOutput, lpdm);
289 /* If DC_PAPERSIZE map POINT16s to POINTs */
290 if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
291 POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
293 memcpy(tmp, pOutput, ret * sizeof(POINT16));
294 for(i = 0; i < ret; i++)
295 CONV_POINT16TO32(tmp + i, (POINT*)pOutput + i);
296 HeapFree( GetProcessHeap(), 0, tmp );
302 /*****************************************************************************
303 * DeviceCapabilitiesW [WINSPOOL.152]
305 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
308 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
309 WORD fwCapability, LPWSTR pOutput,
310 const DEVMODEW *pDevMode)
312 LPDEVMODEA dmA = DEVMODEdupWtoA(GetProcessHeap(), pDevMode);
313 LPSTR pDeviceA = HEAP_strdupWtoA(GetProcessHeap(),0,pDevice);
314 LPSTR pPortA = HEAP_strdupWtoA(GetProcessHeap(),0,pPort);
317 if(pOutput && (fwCapability == DC_BINNAMES ||
318 fwCapability == DC_FILEDEPENDENCIES ||
319 fwCapability == DC_PAPERNAMES)) {
320 /* These need A -> W translation */
323 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL,
327 switch(fwCapability) {
332 case DC_FILEDEPENDENCIES:
336 pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret);
337 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA,
339 for(i = 0; i < ret; i++)
340 MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1,
341 pOutput + (i * size), size);
342 HeapFree(GetProcessHeap(), 0, pOutputA);
344 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability,
345 (LPSTR)pOutput, dmA);
347 HeapFree(GetProcessHeap(),0,pPortA);
348 HeapFree(GetProcessHeap(),0,pDeviceA);
349 HeapFree(GetProcessHeap(),0,dmA);
353 /******************************************************************
354 * DocumentPropertiesA [WINSPOOL.155]
357 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
358 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
359 LPDEVMODEA pDevModeInput,DWORD fMode )
361 LPOPENEDPRINTER lpOpenedPrinter;
362 LPSTR lpName = pDeviceName;
365 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
366 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
371 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
372 if(!lpOpenedPrinter) {
373 SetLastError(ERROR_INVALID_HANDLE);
376 lpNameW = lpOpenedPrinter->lpsPrinterName;
377 lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
380 ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
381 pDevModeInput, NULL, fMode);
384 HeapFree(GetProcessHeap(),0,lpName);
389 /*****************************************************************************
390 * DocumentPropertiesW
392 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
394 LPDEVMODEW pDevModeOutput,
395 LPDEVMODEW pDevModeInput, DWORD fMode)
398 LPSTR pDeviceNameA = HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName);
399 LPDEVMODEA pDevModeInputA = DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput);
400 LPDEVMODEA pDevModeOutputA = NULL;
403 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
404 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
407 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, NULL, NULL, 0);
408 if(ret < 0) return ret;
409 pDevModeOutputA = HeapAlloc(GetProcessHeap(), 0, ret);
411 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, pDevModeOutputA,
412 pDevModeInputA, fMode);
414 DEVMODEcpyAtoW(pDevModeOutput, pDevModeOutputA);
415 HeapFree(GetProcessHeap(),0,pDevModeOutputA);
417 if(fMode == 0 && ret > 0)
418 ret += (CCHDEVICENAME + CCHFORMNAME);
419 HeapFree(GetProcessHeap(),0,pDevModeInputA);
420 HeapFree(GetProcessHeap(),0,pDeviceNameA);
424 /******************************************************************
425 * OpenPrinterA [WINSPOOL.196]
428 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
429 LPPRINTER_DEFAULTSA pDefault)
431 LPWSTR lpPrinterNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName);
432 PRINTER_DEFAULTSW DefaultW, *pDefaultW = NULL;
436 DefaultW.pDatatype = HEAP_strdupAtoW(GetProcessHeap(), 0,
437 pDefault->pDatatype);
438 DefaultW.pDevMode = DEVMODEdupAtoW(GetProcessHeap(),
440 DefaultW.DesiredAccess = pDefault->DesiredAccess;
441 pDefaultW = &DefaultW;
443 ret = OpenPrinterW(lpPrinterNameW, phPrinter, pDefaultW);
445 HeapFree(GetProcessHeap(), 0, DefaultW.pDatatype);
446 HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode);
448 HeapFree(GetProcessHeap(), 0, lpPrinterNameW);
452 /******************************************************************
453 * OpenPrinterW [WINSPOOL.197]
456 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
457 LPPRINTER_DEFAULTSW pDefault)
459 LPOPENEDPRINTER lpOpenedPrinter;
460 HKEY hkeyPrinters, hkeyPrinter;
462 if (!lpPrinterName) {
463 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault);
464 SetLastError(ERROR_INVALID_PARAMETER);
468 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName),
471 /* Check Printer exists */
472 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
474 ERR("Can't create Printers key\n");
475 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
479 if(RegOpenKeyW(hkeyPrinters, lpPrinterName, &hkeyPrinter)
481 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName));
482 RegCloseKey(hkeyPrinters);
483 SetLastError(ERROR_INVALID_PARAMETER);
486 RegCloseKey(hkeyPrinter);
487 RegCloseKey(hkeyPrinters);
489 if(!phPrinter) /* This seems to be what win95 does anyway */
492 /* Get a place in the opened printer buffer*/
493 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntry();
494 if(!lpOpenedPrinter) {
495 ERR("Can't allocate printer slot\n");
496 SetLastError(ERROR_OUTOFMEMORY);
500 /* Get the name of the printer */
501 lpOpenedPrinter->lpsPrinterName =
502 HEAP_strdupW( GetProcessHeap(), 0, lpPrinterName );
504 /* Get the unique handle of the printer*/
505 *phPrinter = lpOpenedPrinter->hPrinter;
507 if (pDefault != NULL)
508 FIXME("Not handling pDefault\n");
513 /******************************************************************
514 * AddMonitorA [WINSPOOL.107]
517 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
519 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
520 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
524 /******************************************************************
525 * DeletePrinterDriverA [WINSPOOL.146]
529 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
531 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
532 debugstr_a(pDriverName));
533 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
538 /******************************************************************
539 * DeleteMonitorA [WINSPOOL.135]
543 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
545 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
546 debugstr_a(pMonitorName));
547 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
552 /******************************************************************
553 * DeletePortA [WINSPOOL.137]
557 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
559 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
560 debugstr_a(pPortName));
561 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
565 /******************************************************************************
566 * SetPrinterW [WINSPOOL.214]
576 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
580 /******************************************************************************
581 * WritePrinter [WINSPOOL.223]
591 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
595 /*****************************************************************************
596 * AddFormA [WINSPOOL.103]
598 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
600 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
604 /*****************************************************************************
605 * AddFormW [WINSPOOL.104]
607 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
609 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
613 /*****************************************************************************
614 * AddJobA [WINSPOOL.105]
616 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
617 DWORD cbBuf, LPDWORD pcbNeeded)
619 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
624 /*****************************************************************************
625 * AddJobW [WINSPOOL.106]
627 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
630 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
635 /*****************************************************************************
636 * WINSPOOL_OpenDriverReg [internal]
638 * opens the registry for the printer drivers depending on the given input
639 * variable pEnvironment
642 * the opened hkey on success
645 static HKEY WINSPOOL_OpenDriverReg( LPVOID pEnvironment, BOOL unicode)
647 LPSTR lpKey, p = NULL;
650 (unicode) ? debugstr_w(pEnvironment) : debugstr_a(pEnvironment));
653 p = (unicode) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment) :
657 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
659 if(!GetVersionExA( &ver))
662 switch (ver.dwPlatformId) {
663 case VER_PLATFORM_WIN32s:
665 case VER_PLATFORM_WIN32_NT:
666 p = "Windows NT x86";
672 TRACE("set environment to %s\n", p);
675 lpKey = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
676 strlen(p) + strlen(Drivers));
677 (void) wsprintfA( lpKey, Drivers, p);
679 TRACE("%s\n", lpKey);
681 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &retval) !=
685 if(pEnvironment && unicode)
686 HeapFree( GetProcessHeap(), 0, p);
687 HeapFree( GetProcessHeap(), 0, lpKey);
692 /*****************************************************************************
693 * AddPrinterW [WINSPOOL.122]
695 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
697 PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
701 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
704 TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
707 FIXME("pName = %s - unsupported\n", debugstr_w(pName));
708 SetLastError(ERROR_INVALID_PARAMETER);
712 WARN("Level = %ld\n", Level);
713 SetLastError(ERROR_INVALID_LEVEL);
717 SetLastError(ERROR_INVALID_PARAMETER);
720 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
722 ERR("Can't create Printers key\n");
725 if(RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
727 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
728 RegCloseKey(hkeyPrinter);
729 RegCloseKey(hkeyPrinters);
732 hkeyDrivers = WINSPOOL_OpenDriverReg( NULL, TRUE);
734 ERR("Can't create Drivers key\n");
735 RegCloseKey(hkeyPrinters);
738 if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
740 WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
741 RegCloseKey(hkeyPrinters);
742 RegCloseKey(hkeyDrivers);
743 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
746 RegCloseKey(hkeyDriver);
747 RegCloseKey(hkeyDrivers);
749 if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */
750 WARN("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
751 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
752 RegCloseKey(hkeyPrinters);
756 /* See if we can load the driver. We may need the devmode structure anyway
758 size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0);
760 WARN("DocumentProperties fails\n");
761 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
767 dmW = HeapAlloc(GetProcessHeap(), 0, size);
768 DocumentPropertiesW(0, -1, pi->pPrinterName, dmW, NULL, DM_OUT_BUFFER);
771 if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
773 WARN("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
774 SetLastError(ERROR_INVALID_PRINTER_NAME);
775 RegCloseKey(hkeyPrinters);
777 HeapFree(GetProcessHeap(), 0, dmW);
780 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
781 (LPBYTE)&pi->Attributes, sizeof(DWORD));
782 RegSetValueExW(hkeyPrinter, DatatypeW, 0, REG_SZ, (LPBYTE)pi->pDatatype,
785 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
786 and we support these drivers. NT writes DEVMODEW so somehow
787 we'll need to distinguish between these when we support NT
789 dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
790 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
791 dmA->dmSize + dmA->dmDriverExtra);
792 HeapFree(GetProcessHeap(), 0, dmA);
794 HeapFree(GetProcessHeap(), 0, dmW);
795 RegSetValueExW(hkeyPrinter, DescriptionW, 0, REG_SZ, (LPBYTE)pi->pComment,
797 RegSetValueExW(hkeyPrinter, LocationW, 0, REG_SZ, (LPBYTE)pi->pLocation,
799 RegSetValueExW(hkeyPrinter, NameW, 0, REG_SZ, (LPBYTE)pi->pPrinterName, 0);
800 RegSetValueExW(hkeyPrinter, ParametersW, 0, REG_SZ,
801 (LPBYTE)pi->pParameters, 0);
802 RegSetValueExW(hkeyPrinter, PortW, 0, REG_SZ, (LPBYTE)pi->pPortName, 0);
803 RegSetValueExW(hkeyPrinter, Print_ProcessorW, 0, REG_SZ,
804 (LPBYTE)pi->pPrintProcessor, 0);
805 RegSetValueExW(hkeyPrinter, Printer_DriverW, 0, REG_SZ,
806 (LPBYTE)pi->pDriverName, 0);
807 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
808 (LPBYTE)&pi->Priority, sizeof(DWORD));
809 RegSetValueExW(hkeyPrinter, Separator_FileW, 0, REG_SZ,
810 (LPBYTE)pi->pSepFile, 0);
811 RegSetValueExW(hkeyPrinter, Share_NameW, 0, REG_SZ, (LPBYTE)pi->pShareName,
813 RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
814 (LPBYTE)&pi->StartTime, sizeof(DWORD));
815 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
816 (LPBYTE)&pi->Status, sizeof(DWORD));
817 RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
818 (LPBYTE)&pi->UntilTime, sizeof(DWORD));
820 RegCloseKey(hkeyPrinter);
821 RegCloseKey(hkeyPrinters);
822 if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
823 ERR("OpenPrinter failing\n");
829 /*****************************************************************************
830 * AddPrinterA [WINSPOOL.117]
832 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
835 PRINTER_INFO_2W *piW;
836 PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
839 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
841 WARN("Level = %ld\n", Level);
842 SetLastError(ERROR_INVALID_LEVEL);
845 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
846 piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
848 ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
850 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
851 HeapFree(GetProcessHeap(),0,pNameW);
856 /*****************************************************************************
857 * ClosePrinter [WINSPOOL.126]
859 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
861 LPOPENEDPRINTER lpOpenedPrinter;
863 TRACE("Handle %d\n", hPrinter);
865 if (!pOpenedPrinterDPA)
868 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
870 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
871 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
872 lpOpenedPrinter->lpsPrinterName = NULL;
873 lpOpenedPrinter->hPrinter = -1;
880 /*****************************************************************************
881 * DeleteFormA [WINSPOOL.133]
883 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
885 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
889 /*****************************************************************************
890 * DeleteFormW [WINSPOOL.134]
892 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
894 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
898 /*****************************************************************************
899 * DeletePrinter [WINSPOOL.143]
901 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
906 LPOPENEDPRINTER lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
907 if(!lpOpenedPrinter) {
908 SetLastError(ERROR_INVALID_HANDLE);
911 lpNameW = lpOpenedPrinter->lpsPrinterName;
912 if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
914 ERR("Can't open Printers key\n");
918 /* This should use a recursive delete see Q142491 or SHDeleteKey */
919 if(RegDeleteKeyW(hkeyPrinters, lpNameW) == ERROR_SUCCESS) {
920 SetLastError(ERROR_PRINTER_NOT_FOUND); /* ?? */
921 RegCloseKey(hkeyPrinters);
925 ClosePrinter(hPrinter);
929 /*****************************************************************************
930 * SetPrinterA [WINSPOOL.211]
932 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
935 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
939 /*****************************************************************************
940 * SetJobA [WINSPOOL.209]
942 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
943 LPBYTE pJob, DWORD Command)
945 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
950 /*****************************************************************************
951 * SetJobW [WINSPOOL.210]
953 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
954 LPBYTE pJob, DWORD Command)
956 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
961 /*****************************************************************************
962 * GetFormA [WINSPOOL.181]
964 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
965 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
967 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
968 Level,pForm,cbBuf,pcbNeeded);
972 /*****************************************************************************
973 * GetFormW [WINSPOOL.182]
975 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
976 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
978 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
979 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
983 /*****************************************************************************
984 * SetFormA [WINSPOOL.207]
986 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
989 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
993 /*****************************************************************************
994 * SetFormW [WINSPOOL.208]
996 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
999 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1003 /*****************************************************************************
1004 * ReadPrinter [WINSPOOL.202]
1006 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1007 LPDWORD pNoBytesRead)
1009 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1013 /*****************************************************************************
1014 * ResetPrinterA [WINSPOOL.203]
1016 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1018 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1022 /*****************************************************************************
1023 * ResetPrinterW [WINSPOOL.204]
1025 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1027 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1031 /*****************************************************************************
1032 * WINSPOOL_GetDWORDFromReg
1034 * Return DWORD associated with ValueName from hkey.
1036 static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
1038 DWORD sz = sizeof(DWORD), type, value = 0;
1041 ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz);
1043 if(ret != ERROR_SUCCESS) {
1044 WARN("Got ret = %ld on name %s\n", ret, ValueName);
1047 if(type != REG_DWORD) {
1048 ERR("Got type %ld\n", type);
1054 /*****************************************************************************
1055 * WINSPOOL_GetStringFromReg
1057 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1058 * String is stored either as unicode or ascii.
1059 * Bit of a hack here to get the ValueName if we want ascii.
1061 static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
1062 DWORD buflen, DWORD *needed,
1065 DWORD sz = buflen, type;
1069 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1071 LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
1072 ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
1073 HeapFree(GetProcessHeap(),0,ValueNameA);
1075 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1076 WARN("Got ret = %ld\n", ret);
1084 /*****************************************************************************
1085 * WINSPOOL_GetDevModeFromReg
1087 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1088 * DevMode is stored either as unicode or ascii.
1090 static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
1092 DWORD buflen, DWORD *needed,
1095 DWORD sz = buflen, type;
1098 if (ptr) memset(ptr, 0, sizeof(DEVMODEA));
1099 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1100 if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
1101 if (sz < sizeof(DEVMODEA))
1103 ERR("corrupted registry for %s\n", debugstr_w(ValueName));
1104 sz = sizeof(DEVMODEA);
1106 /* ensures that dmSize is not erratically bogus if registry is invalid */
1107 if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
1108 ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
1110 sz += (CCHDEVICENAME + CCHFORMNAME);
1112 DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
1113 memcpy(ptr, dmW, sz);
1114 HeapFree(GetProcessHeap(),0,dmW);
1121 /*********************************************************************
1122 * WINSPOOL_GetPrinter_2
1124 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1125 * The strings are either stored as unicode or ascii.
1127 static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
1128 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1131 DWORD size, left = cbBuf;
1132 BOOL space = (cbBuf > 0);
1137 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1139 if(space && size <= left) {
1140 pi2->pPrinterName = (LPWSTR)ptr;
1147 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
1149 if(space && size <= left) {
1150 pi2->pShareName = (LPWSTR)ptr;
1157 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1159 if(space && size <= left) {
1160 pi2->pPortName = (LPWSTR)ptr;
1167 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
1169 if(space && size <= left) {
1170 pi2->pDriverName = (LPWSTR)ptr;
1177 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
1179 if(space && size <= left) {
1180 pi2->pComment = (LPWSTR)ptr;
1187 if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
1189 if(space && size <= left) {
1190 pi2->pLocation = (LPWSTR)ptr;
1197 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
1199 if(space && size <= left) {
1200 pi2->pDevMode = (LPDEVMODEW)ptr;
1207 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
1209 if(space && size <= left) {
1210 pi2->pSepFile = (LPWSTR)ptr;
1217 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
1219 if(space && size <= left) {
1220 pi2->pPrintProcessor = (LPWSTR)ptr;
1227 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
1229 if(space && size <= left) {
1230 pi2->pDatatype = (LPWSTR)ptr;
1237 if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
1239 if(space && size <= left) {
1240 pi2->pParameters = (LPWSTR)ptr;
1248 pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1249 pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
1250 pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1251 "Default Priority");
1252 pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
1253 pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
1256 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1257 memset(pi2, 0, sizeof(*pi2));
1262 /*********************************************************************
1263 * WINSPOOL_GetPrinter_4
1265 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1267 static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
1268 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1271 DWORD size, left = cbBuf;
1272 BOOL space = (cbBuf > 0);
1277 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1279 if(space && size <= left) {
1280 pi4->pPrinterName = (LPWSTR)ptr;
1288 pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1291 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1292 memset(pi4, 0, sizeof(*pi4));
1297 /*********************************************************************
1298 * WINSPOOL_GetPrinter_5
1300 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1302 static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
1303 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1306 DWORD size, left = cbBuf;
1307 BOOL space = (cbBuf > 0);
1312 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1314 if(space && size <= left) {
1315 pi5->pPrinterName = (LPWSTR)ptr;
1322 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1324 if(space && size <= left) {
1325 pi5->pPortName = (LPWSTR)ptr;
1333 pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1334 pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1336 pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1340 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1341 memset(pi5, 0, sizeof(*pi5));
1346 /*****************************************************************************
1347 * WINSPOOL_GetPrinter
1349 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1350 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1351 * just a collection of pointers to strings.
1353 static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1354 DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
1356 OPENEDPRINTER *lpOpenedPrinter;
1357 DWORD size, needed = 0;
1359 HKEY hkeyPrinter, hkeyPrinters;
1362 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1364 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1365 if(!lpOpenedPrinter) {
1366 SetLastError(ERROR_INVALID_HANDLE);
1369 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1371 ERR("Can't create Printers key\n");
1374 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1376 ERR("Can't find opened printer %s in registry\n",
1377 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1378 RegCloseKey(hkeyPrinters);
1379 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1386 PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
1388 size = sizeof(PRINTER_INFO_2W);
1390 ptr = pPrinter + size;
1392 memset(pPrinter, 0, size);
1397 ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
1405 PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
1407 size = sizeof(PRINTER_INFO_4W);
1409 ptr = pPrinter + size;
1411 memset(pPrinter, 0, size);
1416 ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
1425 PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
1427 size = sizeof(PRINTER_INFO_5W);
1429 ptr = pPrinter + size;
1431 memset(pPrinter, 0, size);
1437 ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
1444 FIXME("Unimplemented level %ld\n", Level);
1445 SetLastError(ERROR_INVALID_LEVEL);
1446 RegCloseKey(hkeyPrinters);
1447 RegCloseKey(hkeyPrinter);
1451 RegCloseKey(hkeyPrinter);
1452 RegCloseKey(hkeyPrinters);
1454 TRACE("returing %d needed = %ld\n", ret, needed);
1455 if(pcbNeeded) *pcbNeeded = needed;
1457 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1461 /*****************************************************************************
1462 * GetPrinterW [WINSPOOL.194]
1464 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1465 DWORD cbBuf, LPDWORD pcbNeeded)
1467 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1471 /*****************************************************************************
1472 * GetPrinterA [WINSPOOL.187]
1474 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1475 DWORD cbBuf, LPDWORD pcbNeeded)
1477 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1481 /*****************************************************************************
1482 * WINSPOOL_EnumPrinters
1484 * Implementation of EnumPrintersA|W
1486 static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
1487 DWORD dwLevel, LPBYTE lpbPrinters,
1488 DWORD cbBuf, LPDWORD lpdwNeeded,
1489 LPDWORD lpdwReturned, BOOL unicode)
1492 HKEY hkeyPrinters, hkeyPrinter;
1493 WCHAR PrinterName[255];
1494 DWORD needed = 0, number = 0;
1495 DWORD used, i, left;
1499 memset(lpbPrinters, 0, cbBuf);
1503 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1504 FIXME("dwType = %08lx\n", dwType);
1505 SetLastError(ERROR_INVALID_FLAGS);
1509 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1511 ERR("Can't create Printers key\n");
1515 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1516 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1517 RegCloseKey(hkeyPrinters);
1518 ERR("Can't query Printers key\n");
1521 TRACE("Found %ld printers\n", number);
1525 RegCloseKey(hkeyPrinters);
1527 *lpdwReturned = number;
1531 used = number * sizeof(PRINTER_INFO_2W);
1534 used = number * sizeof(PRINTER_INFO_4W);
1537 used = number * sizeof(PRINTER_INFO_5W);
1541 SetLastError(ERROR_INVALID_LEVEL);
1542 RegCloseKey(hkeyPrinters);
1545 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1547 for(i = 0; i < number; i++) {
1548 if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1550 ERR("Can't enum key number %ld\n", i);
1551 RegCloseKey(hkeyPrinters);
1554 TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
1555 if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1557 ERR("Can't open key %s\n", debugstr_w(PrinterName));
1558 RegCloseKey(hkeyPrinters);
1563 buf = lpbPrinters + used;
1564 left = cbBuf - used;
1572 WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
1573 left, &needed, unicode);
1575 if(pi) pi += sizeof(PRINTER_INFO_2W);
1578 WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
1579 left, &needed, unicode);
1581 if(pi) pi += sizeof(PRINTER_INFO_4W);
1584 WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
1585 left, &needed, unicode);
1587 if(pi) pi += sizeof(PRINTER_INFO_5W);
1590 ERR("Shouldn't be here!\n");
1591 RegCloseKey(hkeyPrinter);
1592 RegCloseKey(hkeyPrinters);
1595 RegCloseKey(hkeyPrinter);
1597 RegCloseKey(hkeyPrinters);
1604 memset(lpbPrinters, 0, cbBuf);
1605 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1609 *lpdwReturned = number;
1610 SetLastError(ERROR_SUCCESS);
1615 /******************************************************************
1616 * EnumPrintersW [WINSPOOL.175]
1618 * Enumerates the available printers, print servers and print
1619 * providers, depending on the specified flags, name and level.
1623 * If level is set to 1:
1624 * Not implemented yet!
1625 * Returns TRUE with an empty list.
1627 * If level is set to 2:
1628 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1629 * Returns an array of PRINTER_INFO_2 data structures in the
1630 * lpbPrinters buffer. Note that according to MSDN also an
1631 * OpenPrinter should be performed on every remote printer.
1633 * If level is set to 4 (officially WinNT only):
1634 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1635 * Fast: Only the registry is queried to retrieve printer names,
1636 * no connection to the driver is made.
1637 * Returns an array of PRINTER_INFO_4 data structures in the
1638 * lpbPrinters buffer.
1640 * If level is set to 5 (officially WinNT4/Win9x only):
1641 * Fast: Only the registry is queried to retrieve printer names,
1642 * no connection to the driver is made.
1643 * Returns an array of PRINTER_INFO_5 data structures in the
1644 * lpbPrinters buffer.
1646 * If level set to 3 or 6+:
1647 * returns zero (faillure!)
1649 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1653 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1654 * - Only levels 2, 4 and 5 are implemented at the moment.
1655 * - 16-bit printer drivers are not enumerated.
1656 * - Returned amount of bytes used/needed does not match the real Windoze
1657 * implementation (as in this implementation, all strings are part
1658 * of the buffer, whereas Win32 keeps them somewhere else)
1659 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1662 * - In a regular Wine installation, no registry settings for printers
1663 * exist, which makes this function return an empty list.
1665 BOOL WINAPI EnumPrintersW(
1666 DWORD dwType, /* Types of print objects to enumerate */
1667 LPWSTR lpszName, /* name of objects to enumerate */
1668 DWORD dwLevel, /* type of printer info structure */
1669 LPBYTE lpbPrinters, /* buffer which receives info */
1670 DWORD cbBuf, /* max size of buffer in bytes */
1671 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
1672 LPDWORD lpdwReturned /* number of entries returned */
1675 return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
1676 lpdwNeeded, lpdwReturned, TRUE);
1679 /******************************************************************
1680 * EnumPrintersA [WINSPOOL.174]
1683 BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
1684 DWORD dwLevel, LPBYTE lpbPrinters,
1685 DWORD cbBuf, LPDWORD lpdwNeeded,
1686 LPDWORD lpdwReturned)
1689 LPWSTR lpszNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
1691 ret = WINSPOOL_EnumPrinters(dwType, lpszNameW, dwLevel, lpbPrinters, cbBuf,
1692 lpdwNeeded, lpdwReturned, FALSE);
1693 HeapFree(GetProcessHeap(),0,lpszNameW);
1697 /*****************************************************************************
1698 * WINSPOOL_GetDriverInfoFromReg [internal]
1700 * Enters the information from the registry into the DRIVER_INFO struct
1703 * zero if the printer driver does not exist in the registry
1704 * (only if Level > 1) otherwise nonzero
1706 static BOOL WINSPOOL_GetDriverInfoFromReg(
1709 LPWSTR pEnvironment,
1711 LPBYTE ptr, /* DRIVER_INFO */
1712 LPBYTE pDriverStrings, /* strings buffer */
1713 DWORD cbBuf, /* size of string buffer */
1714 LPDWORD pcbNeeded, /* space needed for str. */
1715 BOOL unicode) /* type of strings */
1716 { DWORD dw, size, type;
1718 LPBYTE strPtr = pDriverStrings;
1720 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
1721 debugstr_w(DriverName), debugstr_w(pEnvironment),
1722 Level, ptr, pDriverStrings, cbBuf, unicode);
1725 *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
1726 if (*pcbNeeded <= cbBuf)
1727 strcpyW((LPWSTR)strPtr, DriverName);
1729 *pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0,
1731 if(*pcbNeeded <= cbBuf)
1732 WideCharToMultiByte(CP_ACP, 0, DriverName, -1, strPtr, *pcbNeeded,
1737 ((PDRIVER_INFO_1W) ptr)->pName = (LPWSTR) strPtr;
1741 ((PDRIVER_INFO_3W) ptr)->pName = (LPWSTR) strPtr;
1742 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1745 if(RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) {
1746 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName));
1747 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1752 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw, &size) !=
1754 WARN("Can't get Version\n");
1756 ((PDRIVER_INFO_3A) ptr)->cVersion = dw;
1759 pEnvironment = DefaultEnvironmentW;
1761 size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
1763 size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
1766 if(*pcbNeeded <= cbBuf) {
1768 strcpyW((LPWSTR)strPtr, pEnvironment);
1770 WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, strPtr, size,
1773 ((PDRIVER_INFO_3W) ptr)->pEnvironment = (LPWSTR)strPtr;
1774 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1777 if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size,
1780 if(*pcbNeeded <= cbBuf)
1781 WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, cbBuf, &size,
1784 ((PDRIVER_INFO_3W) ptr)->pDriverPath = (LPWSTR)strPtr;
1785 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1788 if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size,
1791 if(*pcbNeeded <= cbBuf)
1792 WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, cbBuf,
1795 ((PDRIVER_INFO_3W) ptr)->pDataFile = (LPWSTR)strPtr;
1796 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1799 if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
1800 cbBuf, &size, unicode)) {
1802 if(*pcbNeeded <= cbBuf)
1803 WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
1804 cbBuf, &size, unicode);
1806 ((PDRIVER_INFO_3W) ptr)->pConfigFile = (LPWSTR)strPtr;
1807 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1811 RegCloseKey(hkeyDriver);
1815 if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size,
1818 if(*pcbNeeded <= cbBuf)
1819 WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr,
1820 cbBuf, &size, unicode);
1822 ((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr;
1823 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1826 if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0,
1829 if(*pcbNeeded <= cbBuf)
1830 WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr,
1831 cbBuf, &size, unicode);
1833 ((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr;
1834 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1837 if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size,
1840 if(*pcbNeeded <= cbBuf)
1841 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
1842 cbBuf, &size, unicode);
1844 ((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr;
1845 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1848 if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size,
1851 if(*pcbNeeded <= cbBuf)
1852 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
1853 cbBuf, &size, unicode);
1855 ((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr;
1856 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1859 RegCloseKey(hkeyDriver);
1863 /*****************************************************************************
1864 * WINSPOOL_GetPrinterDriver
1866 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
1867 DWORD Level, LPBYTE pDriverInfo,
1868 DWORD cbBuf, LPDWORD pcbNeeded,
1871 OPENEDPRINTER *lpOpenedPrinter;
1872 WCHAR DriverName[100];
1873 DWORD ret, type, size, needed = 0;
1875 HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers;
1877 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
1878 Level,pDriverInfo,cbBuf, pcbNeeded);
1880 ZeroMemory(pDriverInfo, cbBuf);
1882 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1883 if(!lpOpenedPrinter) {
1884 SetLastError(ERROR_INVALID_HANDLE);
1887 if(Level < 1 || Level > 3) {
1888 SetLastError(ERROR_INVALID_LEVEL);
1891 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1893 ERR("Can't create Printers key\n");
1896 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1898 ERR("Can't find opened printer %s in registry\n",
1899 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1900 RegCloseKey(hkeyPrinters);
1901 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1904 size = sizeof(DriverName);
1905 ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
1906 (LPBYTE)DriverName, &size);
1907 RegCloseKey(hkeyPrinter);
1908 RegCloseKey(hkeyPrinters);
1909 if(ret != ERROR_SUCCESS) {
1910 ERR("Can't get DriverName for printer %s\n",
1911 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1915 hkeyDrivers = WINSPOOL_OpenDriverReg( pEnvironment, TRUE);
1917 ERR("Can't create Drivers key\n");
1923 size = sizeof(DRIVER_INFO_1W);
1926 size = sizeof(DRIVER_INFO_2W);
1929 size = sizeof(DRIVER_INFO_3W);
1932 ERR("Invalid level\n");
1937 ptr = pDriverInfo + size;
1939 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName,
1940 pEnvironment, Level, pDriverInfo,
1941 (cbBuf < size) ? NULL : ptr,
1942 (cbBuf < size) ? 0 : cbBuf - size,
1943 &needed, unicode)) {
1944 RegCloseKey(hkeyDrivers);
1948 RegCloseKey(hkeyDrivers);
1950 if(pcbNeeded) *pcbNeeded = needed;
1951 if(cbBuf >= needed) return TRUE;
1952 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1956 /*****************************************************************************
1957 * GetPrinterDriverA [WINSPOOL.190]
1959 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1960 DWORD Level, LPBYTE pDriverInfo,
1961 DWORD cbBuf, LPDWORD pcbNeeded)
1964 LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
1965 ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
1966 cbBuf, pcbNeeded, FALSE);
1967 HeapFree(GetProcessHeap(),0,pEnvW);
1970 /*****************************************************************************
1971 * GetPrinterDriverW [WINSPOOL.193]
1973 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1974 DWORD Level, LPBYTE pDriverInfo,
1975 DWORD cbBuf, LPDWORD pcbNeeded)
1977 return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level,
1978 pDriverInfo, cbBuf, pcbNeeded, TRUE);
1981 /*****************************************************************************
1982 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1984 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1985 DWORD Level, LPBYTE pDriverDirectory,
1986 DWORD cbBuf, LPDWORD pcbNeeded)
1990 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1991 pDriverDirectory, cbBuf, pcbNeeded);
1993 FIXME("pName = `%s' - unsupported\n", pName);
1994 SetLastError(ERROR_INVALID_PARAMETER);
1997 if(pEnvironment != NULL) {
1998 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
1999 SetLastError(ERROR_INVALID_ENVIRONMENT);
2002 if(Level != 1) /* win95 ignores this so we just carry on */
2003 WARN("Level = %ld - assuming 1\n", Level);
2005 /* FIXME should read from registry */
2006 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
2009 *pcbNeeded = needed;
2010 if(needed > cbBuf) {
2011 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2018 /*****************************************************************************
2019 * GetPrinterDriverDirectoryW [WINSPOOL.192]
2021 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
2022 DWORD Level, LPBYTE pDriverDirectory,
2023 DWORD cbBuf, LPDWORD pcbNeeded)
2025 LPSTR pNameA = NULL, pEnvironmentA = NULL;
2029 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
2031 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
2032 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
2033 pDriverDirectory, cbBuf, pcbNeeded );
2035 HeapFree( GetProcessHeap(), 0, pNameA );
2037 HeapFree( GetProcessHeap(), 0, pEnvironmentA );
2042 /*****************************************************************************
2043 * AddPrinterDriverA [WINSPOOL.120]
2045 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
2048 HKEY hkeyDrivers, hkeyName;
2050 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
2052 if(level != 2 && level != 3) {
2053 SetLastError(ERROR_INVALID_LEVEL);
2057 FIXME("pName= `%s' - unsupported\n", pName);
2058 SetLastError(ERROR_INVALID_PARAMETER);
2062 WARN("pDriverInfo == NULL");
2063 SetLastError(ERROR_INVALID_PARAMETER);
2068 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
2070 memset(&di3, 0, sizeof(di3));
2071 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
2074 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
2076 SetLastError(ERROR_INVALID_PARAMETER);
2079 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
2080 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
2081 if(!di3.pHelpFile) di3.pHelpFile = "";
2082 if(!di3.pMonitorName) di3.pMonitorName = "";
2084 hkeyDrivers = WINSPOOL_OpenDriverReg(di3.pEnvironment, FALSE);
2087 ERR("Can't create Drivers key\n");
2091 if(level == 2) { /* apparently can't overwrite with level2 */
2092 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
2093 RegCloseKey(hkeyName);
2094 RegCloseKey(hkeyDrivers);
2095 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
2096 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
2100 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
2101 RegCloseKey(hkeyDrivers);
2102 ERR("Can't create Name key\n");
2105 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
2107 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
2108 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
2109 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
2111 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
2112 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
2113 di3.pDependentFiles, 0);
2114 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
2115 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
2116 RegCloseKey(hkeyName);
2117 RegCloseKey(hkeyDrivers);
2121 /*****************************************************************************
2122 * AddPrinterDriverW [WINSPOOL.121]
2124 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
2127 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
2133 /*****************************************************************************
2134 * PrinterProperties [WINSPOOL.201]
2136 * Displays a dialog to set the properties of the printer.
2139 * nonzero on succes or zero on faillure
2142 * implemented as stub only
2144 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
2145 HANDLE hPrinter /* handle to printer object */
2147 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
2148 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2152 /*****************************************************************************
2153 * EnumJobsA [WINSPOOL.162]
2156 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2157 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2161 if(pcbNeeded) *pcbNeeded = 0;
2162 if(pcReturned) *pcReturned = 0;
2167 /*****************************************************************************
2168 * EnumJobsW [WINSPOOL.163]
2171 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2172 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2176 if(pcbNeeded) *pcbNeeded = 0;
2177 if(pcReturned) *pcReturned = 0;
2181 /*****************************************************************************
2182 * WINSPOOL_EnumPrinterDrivers [internal]
2184 * Delivers information about all installed printer drivers installed on
2185 * localhost or a given server
2188 * nonzero on succes or zero on failure, if the buffer for the returned
2189 * information is too small the function will return an error
2192 * - only implemented for localhost, foreign hosts will return an error
2194 static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPWSTR pEnvironment,
2195 DWORD Level, LPBYTE pDriverInfo,
2196 DWORD cbBuf, LPDWORD pcbNeeded,
2197 LPDWORD pcReturned, BOOL unicode)
2200 DWORD i, needed, number = 0, size = 0;
2201 WCHAR DriverNameW[255];
2204 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2205 debugstr_w(pName), debugstr_w(pEnvironment),
2206 Level, pDriverInfo, cbBuf, unicode);
2208 /* check for local drivers */
2210 ERR("remote drivers unsupported! Current remote host is %s\n",
2215 /* check input parameter */
2216 if((Level < 1) || (Level > 3)) {
2217 ERR("unsupported level %ld \n", Level);
2221 /* initialize return values */
2223 memset( pDriverInfo, 0, cbBuf);
2227 hkeyDrivers = WINSPOOL_OpenDriverReg(pEnvironment, TRUE);
2229 ERR("Can't open Drivers key\n");
2233 if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL,
2234 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
2235 RegCloseKey(hkeyDrivers);
2236 ERR("Can't query Drivers key\n");
2239 TRACE("Found %ld Drivers\n", number);
2241 /* get size of single struct
2242 * unicode and ascii structure have the same size
2246 size = sizeof(DRIVER_INFO_1A);
2249 size = sizeof(DRIVER_INFO_2A);
2252 size = sizeof(DRIVER_INFO_3A);
2256 /* calculate required buffer size */
2257 *pcbNeeded = size * number;
2259 for( i = 0, ptr = (pDriverInfo && (cbBuf >= size)) ? pDriverInfo : NULL ;
2261 i++, ptr = (ptr && (cbBuf >= size * i)) ? ptr + size : NULL) {
2262 if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW))
2264 ERR("Can't enum key number %ld\n", i);
2265 RegCloseKey(hkeyDrivers);
2268 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
2269 pEnvironment, Level, ptr,
2270 (cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded,
2271 (cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
2272 &needed, unicode)) {
2273 RegCloseKey(hkeyDrivers);
2276 (*pcbNeeded) += needed;
2279 RegCloseKey(hkeyDrivers);
2281 if(cbBuf < *pcbNeeded){
2282 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2289 /*****************************************************************************
2290 * EnumPrinterDriversW [WINSPOOL.173]
2292 * see function EnumPrinterDrivers for RETURNS, BUGS
2294 BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
2295 LPBYTE pDriverInfo, DWORD cbBuf,
2296 LPDWORD pcbNeeded, LPDWORD pcReturned)
2298 return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
2299 cbBuf, pcbNeeded, pcReturned, TRUE);
2302 /*****************************************************************************
2303 * EnumPrinterDriversA [WINSPOOL.172]
2305 * see function EnumPrinterDrivers for RETURNS, BUGS
2307 BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level,
2308 LPBYTE pDriverInfo, DWORD cbBuf,
2309 LPDWORD pcbNeeded, LPDWORD pcReturned)
2311 WCHAR *pNameW = NULL, *pEnvironmentW = NULL;
2314 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
2316 pEnvironmentW = HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment);
2318 ret = WINSPOOL_EnumPrinterDrivers(pNameW, pEnvironmentW, Level, pDriverInfo,
2319 cbBuf, pcbNeeded, pcReturned, FALSE);
2321 HeapFree(GetProcessHeap(), 0, pNameW);
2323 HeapFree(GetProcessHeap(), 0, pEnvironmentW);