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 = HeapAlloc( GetProcessHeap(), 0,
502 (strlenW(lpPrinterName)+1)*sizeof(WCHAR) );
503 strcpyW( lpOpenedPrinter->lpsPrinterName, 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 * WINSPOOL_OpenDriverReg [internal]
639 * opens the registry for the printer drivers depending on the given input
640 * variable pEnvironment
643 * the opened hkey on success
646 static HKEY WINSPOOL_OpenDriverReg( LPVOID pEnvironment, BOOL unicode)
648 LPSTR lpKey, p = NULL;
651 (unicode) ? debugstr_w(pEnvironment) : debugstr_a(pEnvironment));
654 p = (unicode) ? HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment) :
658 ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
660 if(!GetVersionExA( &ver))
663 switch (ver.dwPlatformId) {
664 case VER_PLATFORM_WIN32s:
666 case VER_PLATFORM_WIN32_NT:
667 p = "Windows NT x86";
673 TRACE("set environment to %s\n", p);
676 lpKey = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
677 strlen(p) + strlen(Drivers));
678 (void) wsprintfA( lpKey, Drivers, p);
680 TRACE("%s\n", lpKey);
682 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, lpKey, &retval) !=
686 if(pEnvironment && unicode)
687 HeapFree( GetProcessHeap(), 0, p);
688 HeapFree( GetProcessHeap(), 0, lpKey);
693 /*****************************************************************************
694 * AddPrinterW [WINSPOOL.122]
696 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
698 PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
702 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
705 TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
708 FIXME("pName = %s - unsupported\n", debugstr_w(pName));
709 SetLastError(ERROR_INVALID_PARAMETER);
713 WARN("Level = %ld\n", Level);
714 SetLastError(ERROR_INVALID_LEVEL);
718 SetLastError(ERROR_INVALID_PARAMETER);
721 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
723 ERR("Can't create Printers key\n");
726 if(RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
728 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
729 RegCloseKey(hkeyPrinter);
730 RegCloseKey(hkeyPrinters);
733 hkeyDrivers = WINSPOOL_OpenDriverReg( NULL, TRUE);
735 ERR("Can't create Drivers key\n");
736 RegCloseKey(hkeyPrinters);
739 if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
741 WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
742 RegCloseKey(hkeyPrinters);
743 RegCloseKey(hkeyDrivers);
744 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
747 RegCloseKey(hkeyDriver);
748 RegCloseKey(hkeyDrivers);
750 if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */
751 WARN("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
752 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
753 RegCloseKey(hkeyPrinters);
757 /* See if we can load the driver. We may need the devmode structure anyway
759 size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0);
761 WARN("DocumentProperties fails\n");
762 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
768 dmW = HeapAlloc(GetProcessHeap(), 0, size);
769 DocumentPropertiesW(0, -1, pi->pPrinterName, dmW, NULL, DM_OUT_BUFFER);
772 if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
774 WARN("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
775 SetLastError(ERROR_INVALID_PRINTER_NAME);
776 RegCloseKey(hkeyPrinters);
778 HeapFree(GetProcessHeap(), 0, dmW);
781 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
782 (LPBYTE)&pi->Attributes, sizeof(DWORD));
783 RegSetValueExW(hkeyPrinter, DatatypeW, 0, REG_SZ, (LPBYTE)pi->pDatatype,
786 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
787 and we support these drivers. NT writes DEVMODEW so somehow
788 we'll need to distinguish between these when we support NT
790 dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
791 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
792 dmA->dmSize + dmA->dmDriverExtra);
793 HeapFree(GetProcessHeap(), 0, dmA);
795 HeapFree(GetProcessHeap(), 0, dmW);
796 RegSetValueExW(hkeyPrinter, DescriptionW, 0, REG_SZ, (LPBYTE)pi->pComment,
798 RegSetValueExW(hkeyPrinter, LocationW, 0, REG_SZ, (LPBYTE)pi->pLocation,
800 RegSetValueExW(hkeyPrinter, NameW, 0, REG_SZ, (LPBYTE)pi->pPrinterName, 0);
801 RegSetValueExW(hkeyPrinter, ParametersW, 0, REG_SZ,
802 (LPBYTE)pi->pParameters, 0);
803 RegSetValueExW(hkeyPrinter, PortW, 0, REG_SZ, (LPBYTE)pi->pPortName, 0);
804 RegSetValueExW(hkeyPrinter, Print_ProcessorW, 0, REG_SZ,
805 (LPBYTE)pi->pPrintProcessor, 0);
806 RegSetValueExW(hkeyPrinter, Printer_DriverW, 0, REG_SZ,
807 (LPBYTE)pi->pDriverName, 0);
808 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
809 (LPBYTE)&pi->Priority, sizeof(DWORD));
810 RegSetValueExW(hkeyPrinter, Separator_FileW, 0, REG_SZ,
811 (LPBYTE)pi->pSepFile, 0);
812 RegSetValueExW(hkeyPrinter, Share_NameW, 0, REG_SZ, (LPBYTE)pi->pShareName,
814 RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
815 (LPBYTE)&pi->StartTime, sizeof(DWORD));
816 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
817 (LPBYTE)&pi->Status, sizeof(DWORD));
818 RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
819 (LPBYTE)&pi->UntilTime, sizeof(DWORD));
821 RegCloseKey(hkeyPrinter);
822 RegCloseKey(hkeyPrinters);
823 if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
824 ERR("OpenPrinter failing\n");
830 /*****************************************************************************
831 * AddPrinterA [WINSPOOL.117]
833 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
836 PRINTER_INFO_2W *piW;
837 PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
840 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
842 WARN("Level = %ld\n", Level);
843 SetLastError(ERROR_INVALID_LEVEL);
846 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
847 piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
849 ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
851 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
852 HeapFree(GetProcessHeap(),0,pNameW);
857 /*****************************************************************************
858 * ClosePrinter [WINSPOOL.126]
860 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
862 LPOPENEDPRINTER lpOpenedPrinter;
864 TRACE("Handle %d\n", hPrinter);
866 if (!pOpenedPrinterDPA)
869 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
871 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
872 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
873 lpOpenedPrinter->lpsPrinterName = NULL;
874 lpOpenedPrinter->hPrinter = -1;
881 /*****************************************************************************
882 * DeleteFormA [WINSPOOL.133]
884 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
886 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
890 /*****************************************************************************
891 * DeleteFormW [WINSPOOL.134]
893 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
895 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
899 /*****************************************************************************
900 * DeletePrinter [WINSPOOL.143]
902 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
907 LPOPENEDPRINTER lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
908 if(!lpOpenedPrinter) {
909 SetLastError(ERROR_INVALID_HANDLE);
912 lpNameW = lpOpenedPrinter->lpsPrinterName;
913 if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
915 ERR("Can't open Printers key\n");
919 /* This should use a recursive delete see Q142491 or SHDeleteKey */
920 if(RegDeleteKeyW(hkeyPrinters, lpNameW) == ERROR_SUCCESS) {
921 SetLastError(ERROR_PRINTER_NOT_FOUND); /* ?? */
922 RegCloseKey(hkeyPrinters);
926 ClosePrinter(hPrinter);
930 /*****************************************************************************
931 * SetPrinterA [WINSPOOL.211]
933 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
936 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
940 /*****************************************************************************
941 * SetJobA [WINSPOOL.209]
943 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
944 LPBYTE pJob, DWORD Command)
946 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
951 /*****************************************************************************
952 * SetJobW [WINSPOOL.210]
954 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
955 LPBYTE pJob, DWORD Command)
957 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
962 /*****************************************************************************
963 * GetFormA [WINSPOOL.181]
965 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
966 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
968 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
969 Level,pForm,cbBuf,pcbNeeded);
973 /*****************************************************************************
974 * GetFormW [WINSPOOL.182]
976 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
977 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
979 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
980 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
984 /*****************************************************************************
985 * SetFormA [WINSPOOL.207]
987 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
990 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
994 /*****************************************************************************
995 * SetFormW [WINSPOOL.208]
997 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1000 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1004 /*****************************************************************************
1005 * ReadPrinter [WINSPOOL.202]
1007 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1008 LPDWORD pNoBytesRead)
1010 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1014 /*****************************************************************************
1015 * ResetPrinterA [WINSPOOL.203]
1017 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1019 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1023 /*****************************************************************************
1024 * ResetPrinterW [WINSPOOL.204]
1026 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1028 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1032 /*****************************************************************************
1033 * WINSPOOL_GetDWORDFromReg
1035 * Return DWORD associated with ValueName from hkey.
1037 static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
1039 DWORD sz = sizeof(DWORD), type, value = 0;
1042 ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz);
1044 if(ret != ERROR_SUCCESS) {
1045 WARN("Got ret = %ld on name %s\n", ret, ValueName);
1048 if(type != REG_DWORD) {
1049 ERR("Got type %ld\n", type);
1055 /*****************************************************************************
1056 * WINSPOOL_GetStringFromReg
1058 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1059 * String is stored either as unicode or ascii.
1060 * Bit of a hack here to get the ValueName if we want ascii.
1062 static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
1063 DWORD buflen, DWORD *needed,
1066 DWORD sz = buflen, type;
1070 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1072 LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
1073 ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
1074 HeapFree(GetProcessHeap(),0,ValueNameA);
1076 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1077 WARN("Got ret = %ld\n", ret);
1085 /*****************************************************************************
1086 * WINSPOOL_GetDevModeFromReg
1088 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1089 * DevMode is stored either as unicode or ascii.
1091 static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
1093 DWORD buflen, DWORD *needed,
1096 DWORD sz = buflen, type;
1099 if (ptr) memset(ptr, 0, sizeof(DEVMODEA));
1100 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1101 if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
1102 if (sz < sizeof(DEVMODEA))
1104 ERR("corrupted registry for %s\n", debugstr_w(ValueName));
1105 sz = sizeof(DEVMODEA);
1107 /* ensures that dmSize is not erratically bogus if registry is invalid */
1108 if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
1109 ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
1111 sz += (CCHDEVICENAME + CCHFORMNAME);
1113 DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
1114 memcpy(ptr, dmW, sz);
1115 HeapFree(GetProcessHeap(),0,dmW);
1122 /*********************************************************************
1123 * WINSPOOL_GetPrinter_2
1125 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1126 * The strings are either stored as unicode or ascii.
1128 static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
1129 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1132 DWORD size, left = cbBuf;
1133 BOOL space = (cbBuf > 0);
1138 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1140 if(space && size <= left) {
1141 pi2->pPrinterName = (LPWSTR)ptr;
1148 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
1150 if(space && size <= left) {
1151 pi2->pShareName = (LPWSTR)ptr;
1158 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1160 if(space && size <= left) {
1161 pi2->pPortName = (LPWSTR)ptr;
1168 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
1170 if(space && size <= left) {
1171 pi2->pDriverName = (LPWSTR)ptr;
1178 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
1180 if(space && size <= left) {
1181 pi2->pComment = (LPWSTR)ptr;
1188 if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
1190 if(space && size <= left) {
1191 pi2->pLocation = (LPWSTR)ptr;
1198 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
1200 if(space && size <= left) {
1201 pi2->pDevMode = (LPDEVMODEW)ptr;
1208 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
1210 if(space && size <= left) {
1211 pi2->pSepFile = (LPWSTR)ptr;
1218 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
1220 if(space && size <= left) {
1221 pi2->pPrintProcessor = (LPWSTR)ptr;
1228 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
1230 if(space && size <= left) {
1231 pi2->pDatatype = (LPWSTR)ptr;
1238 if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
1240 if(space && size <= left) {
1241 pi2->pParameters = (LPWSTR)ptr;
1249 pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1250 pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
1251 pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1252 "Default Priority");
1253 pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
1254 pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
1257 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1258 memset(pi2, 0, sizeof(*pi2));
1263 /*********************************************************************
1264 * WINSPOOL_GetPrinter_4
1266 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1268 static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
1269 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1272 DWORD size, left = cbBuf;
1273 BOOL space = (cbBuf > 0);
1278 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1280 if(space && size <= left) {
1281 pi4->pPrinterName = (LPWSTR)ptr;
1289 pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1292 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1293 memset(pi4, 0, sizeof(*pi4));
1298 /*********************************************************************
1299 * WINSPOOL_GetPrinter_5
1301 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1303 static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
1304 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1307 DWORD size, left = cbBuf;
1308 BOOL space = (cbBuf > 0);
1313 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1315 if(space && size <= left) {
1316 pi5->pPrinterName = (LPWSTR)ptr;
1323 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1325 if(space && size <= left) {
1326 pi5->pPortName = (LPWSTR)ptr;
1334 pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1335 pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1337 pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1341 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1342 memset(pi5, 0, sizeof(*pi5));
1347 /*****************************************************************************
1348 * WINSPOOL_GetPrinter
1350 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1351 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1352 * just a collection of pointers to strings.
1354 static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1355 DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
1357 OPENEDPRINTER *lpOpenedPrinter;
1358 DWORD size, needed = 0;
1360 HKEY hkeyPrinter, hkeyPrinters;
1363 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1365 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1366 if(!lpOpenedPrinter) {
1367 SetLastError(ERROR_INVALID_HANDLE);
1370 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1372 ERR("Can't create Printers key\n");
1375 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1377 ERR("Can't find opened printer %s in registry\n",
1378 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1379 RegCloseKey(hkeyPrinters);
1380 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1387 PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
1389 size = sizeof(PRINTER_INFO_2W);
1391 ptr = pPrinter + size;
1393 memset(pPrinter, 0, size);
1398 ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
1406 PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
1408 size = sizeof(PRINTER_INFO_4W);
1410 ptr = pPrinter + size;
1412 memset(pPrinter, 0, size);
1417 ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
1426 PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
1428 size = sizeof(PRINTER_INFO_5W);
1430 ptr = pPrinter + size;
1432 memset(pPrinter, 0, size);
1438 ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
1445 FIXME("Unimplemented level %ld\n", Level);
1446 SetLastError(ERROR_INVALID_LEVEL);
1447 RegCloseKey(hkeyPrinters);
1448 RegCloseKey(hkeyPrinter);
1452 RegCloseKey(hkeyPrinter);
1453 RegCloseKey(hkeyPrinters);
1455 TRACE("returing %d needed = %ld\n", ret, needed);
1456 if(pcbNeeded) *pcbNeeded = needed;
1458 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1462 /*****************************************************************************
1463 * GetPrinterW [WINSPOOL.194]
1465 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1466 DWORD cbBuf, LPDWORD pcbNeeded)
1468 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1472 /*****************************************************************************
1473 * GetPrinterA [WINSPOOL.187]
1475 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1476 DWORD cbBuf, LPDWORD pcbNeeded)
1478 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1482 /*****************************************************************************
1483 * WINSPOOL_EnumPrinters
1485 * Implementation of EnumPrintersA|W
1487 static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
1488 DWORD dwLevel, LPBYTE lpbPrinters,
1489 DWORD cbBuf, LPDWORD lpdwNeeded,
1490 LPDWORD lpdwReturned, BOOL unicode)
1493 HKEY hkeyPrinters, hkeyPrinter;
1494 WCHAR PrinterName[255];
1495 DWORD needed = 0, number = 0;
1496 DWORD used, i, left;
1500 memset(lpbPrinters, 0, cbBuf);
1504 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1505 FIXME("dwType = %08lx\n", dwType);
1506 SetLastError(ERROR_INVALID_FLAGS);
1510 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1512 ERR("Can't create Printers key\n");
1516 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1517 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1518 RegCloseKey(hkeyPrinters);
1519 ERR("Can't query Printers key\n");
1522 TRACE("Found %ld printers\n", number);
1526 RegCloseKey(hkeyPrinters);
1528 *lpdwReturned = number;
1532 used = number * sizeof(PRINTER_INFO_2W);
1535 used = number * sizeof(PRINTER_INFO_4W);
1538 used = number * sizeof(PRINTER_INFO_5W);
1542 SetLastError(ERROR_INVALID_LEVEL);
1543 RegCloseKey(hkeyPrinters);
1546 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1548 for(i = 0; i < number; i++) {
1549 if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1551 ERR("Can't enum key number %ld\n", i);
1552 RegCloseKey(hkeyPrinters);
1555 TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
1556 if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1558 ERR("Can't open key %s\n", debugstr_w(PrinterName));
1559 RegCloseKey(hkeyPrinters);
1564 buf = lpbPrinters + used;
1565 left = cbBuf - used;
1573 WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
1574 left, &needed, unicode);
1576 if(pi) pi += sizeof(PRINTER_INFO_2W);
1579 WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
1580 left, &needed, unicode);
1582 if(pi) pi += sizeof(PRINTER_INFO_4W);
1585 WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
1586 left, &needed, unicode);
1588 if(pi) pi += sizeof(PRINTER_INFO_5W);
1591 ERR("Shouldn't be here!\n");
1592 RegCloseKey(hkeyPrinter);
1593 RegCloseKey(hkeyPrinters);
1596 RegCloseKey(hkeyPrinter);
1598 RegCloseKey(hkeyPrinters);
1605 memset(lpbPrinters, 0, cbBuf);
1606 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1610 *lpdwReturned = number;
1611 SetLastError(ERROR_SUCCESS);
1616 /******************************************************************
1617 * EnumPrintersW [WINSPOOL.175]
1619 * Enumerates the available printers, print servers and print
1620 * providers, depending on the specified flags, name and level.
1624 * If level is set to 1:
1625 * Not implemented yet!
1626 * Returns TRUE with an empty list.
1628 * If level is set to 2:
1629 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1630 * Returns an array of PRINTER_INFO_2 data structures in the
1631 * lpbPrinters buffer. Note that according to MSDN also an
1632 * OpenPrinter should be performed on every remote printer.
1634 * If level is set to 4 (officially WinNT only):
1635 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1636 * Fast: Only the registry is queried to retrieve printer names,
1637 * no connection to the driver is made.
1638 * Returns an array of PRINTER_INFO_4 data structures in the
1639 * lpbPrinters buffer.
1641 * If level is set to 5 (officially WinNT4/Win9x only):
1642 * Fast: Only the registry is queried to retrieve printer names,
1643 * no connection to the driver is made.
1644 * Returns an array of PRINTER_INFO_5 data structures in the
1645 * lpbPrinters buffer.
1647 * If level set to 3 or 6+:
1648 * returns zero (faillure!)
1650 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1654 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1655 * - Only levels 2, 4 and 5 are implemented at the moment.
1656 * - 16-bit printer drivers are not enumerated.
1657 * - Returned amount of bytes used/needed does not match the real Windoze
1658 * implementation (as in this implementation, all strings are part
1659 * of the buffer, whereas Win32 keeps them somewhere else)
1660 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1663 * - In a regular Wine installation, no registry settings for printers
1664 * exist, which makes this function return an empty list.
1666 BOOL WINAPI EnumPrintersW(
1667 DWORD dwType, /* Types of print objects to enumerate */
1668 LPWSTR lpszName, /* name of objects to enumerate */
1669 DWORD dwLevel, /* type of printer info structure */
1670 LPBYTE lpbPrinters, /* buffer which receives info */
1671 DWORD cbBuf, /* max size of buffer in bytes */
1672 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
1673 LPDWORD lpdwReturned /* number of entries returned */
1676 return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
1677 lpdwNeeded, lpdwReturned, TRUE);
1680 /******************************************************************
1681 * EnumPrintersA [WINSPOOL.174]
1684 BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
1685 DWORD dwLevel, LPBYTE lpbPrinters,
1686 DWORD cbBuf, LPDWORD lpdwNeeded,
1687 LPDWORD lpdwReturned)
1690 LPWSTR lpszNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
1692 ret = WINSPOOL_EnumPrinters(dwType, lpszNameW, dwLevel, lpbPrinters, cbBuf,
1693 lpdwNeeded, lpdwReturned, FALSE);
1694 HeapFree(GetProcessHeap(),0,lpszNameW);
1698 /*****************************************************************************
1699 * WINSPOOL_GetDriverInfoFromReg [internal]
1701 * Enters the information from the registry into the DRIVER_INFO struct
1704 * zero if the printer driver does not exist in the registry
1705 * (only if Level > 1) otherwise nonzero
1707 static BOOL WINSPOOL_GetDriverInfoFromReg(
1710 LPWSTR pEnvironment,
1712 LPBYTE ptr, /* DRIVER_INFO */
1713 LPBYTE pDriverStrings, /* strings buffer */
1714 DWORD cbBuf, /* size of string buffer */
1715 LPDWORD pcbNeeded, /* space needed for str. */
1716 BOOL unicode) /* type of strings */
1717 { DWORD dw, size, tmp, type;
1719 LPBYTE strPtr = pDriverStrings;
1721 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
1722 debugstr_w(DriverName), debugstr_w(pEnvironment),
1723 Level, ptr, pDriverStrings, cbBuf, unicode);
1726 *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
1727 if (*pcbNeeded <= cbBuf)
1728 strcpyW((LPWSTR)strPtr, DriverName);
1730 *pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0,
1732 if(*pcbNeeded <= cbBuf)
1733 WideCharToMultiByte(CP_ACP, 0, DriverName, -1, strPtr, *pcbNeeded,
1738 ((PDRIVER_INFO_1W) ptr)->pName = (LPWSTR) strPtr;
1742 ((PDRIVER_INFO_3W) ptr)->pName = (LPWSTR) strPtr;
1743 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1746 if(RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) {
1747 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName));
1748 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1753 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw, &size) !=
1755 WARN("Can't get Version\n");
1757 ((PDRIVER_INFO_3A) ptr)->cVersion = dw;
1760 pEnvironment = DefaultEnvironmentW;
1762 size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
1764 size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
1767 if(*pcbNeeded <= cbBuf) {
1769 strcpyW((LPWSTR)strPtr, pEnvironment);
1771 WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, strPtr, size,
1774 ((PDRIVER_INFO_3W) ptr)->pEnvironment = (LPWSTR)strPtr;
1775 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1778 if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size,
1781 if(*pcbNeeded <= cbBuf)
1782 WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, size, &tmp,
1785 ((PDRIVER_INFO_3W) ptr)->pDriverPath = (LPWSTR)strPtr;
1786 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1789 if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size,
1792 if(*pcbNeeded <= cbBuf)
1793 WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, size,
1796 ((PDRIVER_INFO_3W) ptr)->pDataFile = (LPWSTR)strPtr;
1797 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1800 if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
1801 0, &size, unicode)) {
1803 if(*pcbNeeded <= cbBuf)
1804 WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
1805 size, &tmp, unicode);
1807 ((PDRIVER_INFO_3W) ptr)->pConfigFile = (LPWSTR)strPtr;
1808 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1812 RegCloseKey(hkeyDriver);
1813 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
1817 if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size,
1820 if(*pcbNeeded <= cbBuf)
1821 WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr,
1822 size, &tmp, unicode);
1824 ((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr;
1825 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1828 if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0,
1831 if(*pcbNeeded <= cbBuf)
1832 WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr,
1833 size, &tmp, unicode);
1835 ((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr;
1836 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1839 if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size,
1842 if(*pcbNeeded <= cbBuf)
1843 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
1844 size, &tmp, unicode);
1846 ((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr;
1847 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1850 if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size,
1853 if(*pcbNeeded <= cbBuf)
1854 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
1855 size, &tmp, unicode);
1857 ((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr;
1858 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1861 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
1862 RegCloseKey(hkeyDriver);
1866 /*****************************************************************************
1867 * WINSPOOL_GetPrinterDriver
1869 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
1870 DWORD Level, LPBYTE pDriverInfo,
1871 DWORD cbBuf, LPDWORD pcbNeeded,
1874 OPENEDPRINTER *lpOpenedPrinter;
1875 WCHAR DriverName[100];
1876 DWORD ret, type, size, needed = 0;
1878 HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers;
1880 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
1881 Level,pDriverInfo,cbBuf, pcbNeeded);
1883 ZeroMemory(pDriverInfo, cbBuf);
1885 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1886 if(!lpOpenedPrinter) {
1887 SetLastError(ERROR_INVALID_HANDLE);
1890 if(Level < 1 || Level > 3) {
1891 SetLastError(ERROR_INVALID_LEVEL);
1894 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1896 ERR("Can't create Printers key\n");
1899 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1901 ERR("Can't find opened printer %s in registry\n",
1902 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1903 RegCloseKey(hkeyPrinters);
1904 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1907 size = sizeof(DriverName);
1908 ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
1909 (LPBYTE)DriverName, &size);
1910 RegCloseKey(hkeyPrinter);
1911 RegCloseKey(hkeyPrinters);
1912 if(ret != ERROR_SUCCESS) {
1913 ERR("Can't get DriverName for printer %s\n",
1914 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1918 hkeyDrivers = WINSPOOL_OpenDriverReg( pEnvironment, TRUE);
1920 ERR("Can't create Drivers key\n");
1926 size = sizeof(DRIVER_INFO_1W);
1929 size = sizeof(DRIVER_INFO_2W);
1932 size = sizeof(DRIVER_INFO_3W);
1935 ERR("Invalid level\n");
1940 ptr = pDriverInfo + size;
1942 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName,
1943 pEnvironment, Level, pDriverInfo,
1944 (cbBuf < size) ? NULL : ptr,
1945 (cbBuf < size) ? 0 : cbBuf - size,
1946 &needed, unicode)) {
1947 RegCloseKey(hkeyDrivers);
1951 RegCloseKey(hkeyDrivers);
1953 if(pcbNeeded) *pcbNeeded = size + needed;
1954 TRACE("buffer space %ld required %ld\n", cbBuf, *pcbNeeded);
1955 if(cbBuf >= needed) return TRUE;
1956 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1960 /*****************************************************************************
1961 * GetPrinterDriverA [WINSPOOL.190]
1963 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1964 DWORD Level, LPBYTE pDriverInfo,
1965 DWORD cbBuf, LPDWORD pcbNeeded)
1968 LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
1969 ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
1970 cbBuf, pcbNeeded, FALSE);
1971 HeapFree(GetProcessHeap(),0,pEnvW);
1974 /*****************************************************************************
1975 * GetPrinterDriverW [WINSPOOL.193]
1977 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1978 DWORD Level, LPBYTE pDriverInfo,
1979 DWORD cbBuf, LPDWORD pcbNeeded)
1981 return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level,
1982 pDriverInfo, cbBuf, pcbNeeded, TRUE);
1985 /*****************************************************************************
1986 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1988 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1989 DWORD Level, LPBYTE pDriverDirectory,
1990 DWORD cbBuf, LPDWORD pcbNeeded)
1994 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1995 pDriverDirectory, cbBuf, pcbNeeded);
1997 FIXME("pName = `%s' - unsupported\n", pName);
1998 SetLastError(ERROR_INVALID_PARAMETER);
2001 if(pEnvironment != NULL) {
2002 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
2003 SetLastError(ERROR_INVALID_ENVIRONMENT);
2006 if(Level != 1) /* win95 ignores this so we just carry on */
2007 WARN("Level = %ld - assuming 1\n", Level);
2009 /* FIXME should read from registry */
2010 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
2013 *pcbNeeded = needed;
2014 if(needed > cbBuf) {
2015 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2022 /*****************************************************************************
2023 * GetPrinterDriverDirectoryW [WINSPOOL.192]
2025 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
2026 DWORD Level, LPBYTE pDriverDirectory,
2027 DWORD cbBuf, LPDWORD pcbNeeded)
2029 LPSTR pNameA = NULL, pEnvironmentA = NULL;
2033 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
2035 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
2036 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
2037 pDriverDirectory, cbBuf, pcbNeeded );
2039 HeapFree( GetProcessHeap(), 0, pNameA );
2041 HeapFree( GetProcessHeap(), 0, pEnvironmentA );
2046 /*****************************************************************************
2047 * AddPrinterDriverA [WINSPOOL.120]
2049 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
2052 HKEY hkeyDrivers, hkeyName;
2054 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
2056 if(level != 2 && level != 3) {
2057 SetLastError(ERROR_INVALID_LEVEL);
2061 FIXME("pName= `%s' - unsupported\n", pName);
2062 SetLastError(ERROR_INVALID_PARAMETER);
2066 WARN("pDriverInfo == NULL");
2067 SetLastError(ERROR_INVALID_PARAMETER);
2072 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
2074 memset(&di3, 0, sizeof(di3));
2075 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
2078 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
2080 SetLastError(ERROR_INVALID_PARAMETER);
2083 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
2084 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
2085 if(!di3.pHelpFile) di3.pHelpFile = "";
2086 if(!di3.pMonitorName) di3.pMonitorName = "";
2088 hkeyDrivers = WINSPOOL_OpenDriverReg(di3.pEnvironment, FALSE);
2091 ERR("Can't create Drivers key\n");
2095 if(level == 2) { /* apparently can't overwrite with level2 */
2096 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
2097 RegCloseKey(hkeyName);
2098 RegCloseKey(hkeyDrivers);
2099 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
2100 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
2104 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
2105 RegCloseKey(hkeyDrivers);
2106 ERR("Can't create Name key\n");
2109 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
2111 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
2112 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
2113 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
2115 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
2116 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
2117 di3.pDependentFiles, 0);
2118 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
2119 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
2120 RegCloseKey(hkeyName);
2121 RegCloseKey(hkeyDrivers);
2125 /*****************************************************************************
2126 * AddPrinterDriverW [WINSPOOL.121]
2128 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
2131 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
2137 /*****************************************************************************
2138 * PrinterProperties [WINSPOOL.201]
2140 * Displays a dialog to set the properties of the printer.
2143 * nonzero on succes or zero on faillure
2146 * implemented as stub only
2148 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
2149 HANDLE hPrinter /* handle to printer object */
2151 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
2152 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2156 /*****************************************************************************
2157 * EnumJobsA [WINSPOOL.162]
2160 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2161 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2165 if(pcbNeeded) *pcbNeeded = 0;
2166 if(pcReturned) *pcReturned = 0;
2171 /*****************************************************************************
2172 * EnumJobsW [WINSPOOL.163]
2175 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2176 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2180 if(pcbNeeded) *pcbNeeded = 0;
2181 if(pcReturned) *pcReturned = 0;
2185 /*****************************************************************************
2186 * WINSPOOL_EnumPrinterDrivers [internal]
2188 * Delivers information about all installed printer drivers installed on
2189 * localhost or a given server
2192 * nonzero on succes or zero on failure, if the buffer for the returned
2193 * information is too small the function will return an error
2196 * - only implemented for localhost, foreign hosts will return an error
2198 static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPWSTR pEnvironment,
2199 DWORD Level, LPBYTE pDriverInfo,
2200 DWORD cbBuf, LPDWORD pcbNeeded,
2201 LPDWORD pcReturned, BOOL unicode)
2204 DWORD i, needed, number = 0, size = 0;
2205 WCHAR DriverNameW[255];
2208 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2209 debugstr_w(pName), debugstr_w(pEnvironment),
2210 Level, pDriverInfo, cbBuf, unicode);
2212 /* check for local drivers */
2214 ERR("remote drivers unsupported! Current remote host is %s\n",
2219 /* check input parameter */
2220 if((Level < 1) || (Level > 3)) {
2221 ERR("unsupported level %ld \n", Level);
2225 /* initialize return values */
2227 memset( pDriverInfo, 0, cbBuf);
2231 hkeyDrivers = WINSPOOL_OpenDriverReg(pEnvironment, TRUE);
2233 ERR("Can't open Drivers key\n");
2237 if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL,
2238 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
2239 RegCloseKey(hkeyDrivers);
2240 ERR("Can't query Drivers key\n");
2243 TRACE("Found %ld Drivers\n", number);
2245 /* get size of single struct
2246 * unicode and ascii structure have the same size
2250 size = sizeof(DRIVER_INFO_1A);
2253 size = sizeof(DRIVER_INFO_2A);
2256 size = sizeof(DRIVER_INFO_3A);
2260 /* calculate required buffer size */
2261 *pcbNeeded = size * number;
2263 for( i = 0, ptr = (pDriverInfo && (cbBuf >= size)) ? pDriverInfo : NULL ;
2265 i++, ptr = (ptr && (cbBuf >= size * i)) ? ptr + size : NULL) {
2266 if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW))
2268 ERR("Can't enum key number %ld\n", i);
2269 RegCloseKey(hkeyDrivers);
2272 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
2273 pEnvironment, Level, ptr,
2274 (cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded,
2275 (cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
2276 &needed, unicode)) {
2277 RegCloseKey(hkeyDrivers);
2280 (*pcbNeeded) += needed;
2283 RegCloseKey(hkeyDrivers);
2285 if(cbBuf < *pcbNeeded){
2286 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2293 /*****************************************************************************
2294 * EnumPrinterDriversW [WINSPOOL.173]
2296 * see function EnumPrinterDrivers for RETURNS, BUGS
2298 BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
2299 LPBYTE pDriverInfo, DWORD cbBuf,
2300 LPDWORD pcbNeeded, LPDWORD pcReturned)
2302 return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
2303 cbBuf, pcbNeeded, pcReturned, TRUE);
2306 /*****************************************************************************
2307 * EnumPrinterDriversA [WINSPOOL.172]
2309 * see function EnumPrinterDrivers for RETURNS, BUGS
2311 BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level,
2312 LPBYTE pDriverInfo, DWORD cbBuf,
2313 LPDWORD pcbNeeded, LPDWORD pcReturned)
2315 WCHAR *pNameW = NULL, *pEnvironmentW = NULL;
2318 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
2320 pEnvironmentW = HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment);
2322 ret = WINSPOOL_EnumPrinterDrivers(pNameW, pEnvironmentW, Level, pDriverInfo,
2323 cbBuf, pcbNeeded, pcReturned, FALSE);
2325 HeapFree(GetProcessHeap(), 0, pNameW);
2327 HeapFree(GetProcessHeap(), 0, pEnvironmentW);
2333 /******************************************************************************
2334 * EnumPortsA (WINSPOOL.166)
2336 BOOL WINAPI EnumPortsA(LPSTR name,DWORD level,LPBYTE ports,DWORD bufsize,
2337 LPDWORD bufneeded,LPDWORD bufreturned)
2339 FIXME("(%s,%ld,%p,%ld,%p,%p), stub!\n",name,level,ports,bufsize,bufneeded,bufreturned);