- moved some code from WINSPOOL_GetPrinterDriver into new function
[wine/gsoc_dplay.git] / dlls / winspool / info.c
blobcee70417beb1246aedbfec5a3396507da33da1cb
1 /*
2 * WINSPOOL functions
3 *
4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
7 * Copyright 1999, 2000 Huw D M Davies
8 */
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <stddef.h>
14 #include "winspool.h"
15 #include "winbase.h"
16 #include "winerror.h"
17 #include "winreg.h"
18 #include "wine/windef16.h"
19 #include "wine/unicode.h"
20 #include "debugtools.h"
21 #include "heap.h"
22 #include "commctrl.h"
23 #include "winnls.h"
25 DEFAULT_DEBUG_CHANNEL(winspool);
27 typedef struct _OPENEDPRINTER
29 LPWSTR lpsPrinterName;
30 HANDLE hPrinter;
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\\Windows 4.0\\Drivers\\"; /* Hmm, well */
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',
52 'M','o','d','e',0};
53 static WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F',
54 'i','l','e','s',0};
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',
64 's','s','o','r',0};
65 static WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i',
66 'v','e','r',0};
67 static WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F',
68 'i','l','e',0};
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()
78 int i;
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(),
90 HEAP_ZERO_MEMORY,
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(),
117 HEAP_ZERO_MEMORY,
118 sizeof(OPENEDPRINTER));
119 pOpenedPrinter->hPrinter = i + 1;
120 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
121 return pOpenedPrinter;
124 return NULL;
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)))
138 return NULL;
140 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, printerHandle-1);
142 return pOpenedPrinter;
145 /***********************************************************
146 * DEVMODEcpyAtoW
148 static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA)
150 BOOL Formname;
151 ptrdiff_t off_formname = (char *)dmA->dmFormName - (char *)dmA;
152 DWORD size;
154 Formname = (dmA->dmSize > off_formname);
155 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
156 MultiByteToWideChar(CP_ACP, 0, dmA->dmDeviceName, -1, dmW->dmDeviceName,
157 CCHDEVICENAME);
158 if(!Formname) {
159 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
160 dmA->dmSize - CCHDEVICENAME);
161 } else {
162 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
163 off_formname - CCHDEVICENAME);
164 MultiByteToWideChar(CP_ACP, 0, dmA->dmFormName, -1, dmW->dmFormName,
165 CCHFORMNAME);
166 memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize -
167 (off_formname + CCHFORMNAME));
169 dmW->dmSize = size;
170 memcpy((char *)dmW + dmW->dmSize, (char *)dmA + dmA->dmSize,
171 dmA->dmDriverExtra);
172 return dmW;
175 /***********************************************************
176 * DEVMODEdupAtoW
177 * Creates a unicode copy of supplied devmode on heap
179 static LPDEVMODEW DEVMODEdupAtoW(HANDLE heap, const DEVMODEA *dmA)
181 LPDEVMODEW dmW;
182 DWORD size;
183 BOOL Formname;
184 ptrdiff_t off_formname;
186 TRACE("\n");
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 /***********************************************************
197 * DEVMODEdupWtoA
198 * Creates an ascii copy of supplied devmode on heap
200 static LPDEVMODEA DEVMODEdupWtoA(HANDLE heap, const DEVMODEW *dmW)
202 LPDEVMODEA dmA;
203 DWORD size;
204 BOOL Formname;
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);
213 if(!Formname) {
214 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
215 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR));
216 } else {
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)));
224 dmA->dmSize = size;
225 memcpy((char *)dmA + dmA->dmSize, (char *)dmW + dmW->dmSize,
226 dmW->dmDriverExtra);
227 return dmA;
230 /***********************************************************
231 * PRINTER_INFO_2AtoW
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);
252 return piW;
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)
261 if(!piW) return;
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);
276 return;
279 /******************************************************************
280 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
283 INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
284 LPSTR pOutput, LPDEVMODEA lpdm)
286 INT ret;
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) );
292 INT i;
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 );
298 return ret;
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);
315 INT ret;
317 if(pOutput && (fwCapability == DC_BINNAMES ||
318 fwCapability == DC_FILEDEPENDENCIES ||
319 fwCapability == DC_PAPERNAMES)) {
320 /* These need A -> W translation */
321 INT size = 0, i;
322 LPSTR pOutputA;
323 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL,
324 dmA);
325 if(ret == -1)
326 return ret;
327 switch(fwCapability) {
328 case DC_BINNAMES:
329 size = 24;
330 break;
331 case DC_PAPERNAMES:
332 case DC_FILEDEPENDENCIES:
333 size = 64;
334 break;
336 pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret);
337 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA,
338 dmA);
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);
343 } else {
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);
350 return ret;
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;
363 LONG ret;
365 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
366 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
369 if(!pDeviceName) {
370 LPWSTR lpNameW;
371 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
372 if(!lpOpenedPrinter) {
373 SetLastError(ERROR_INVALID_HANDLE);
374 return -1;
376 lpNameW = lpOpenedPrinter->lpsPrinterName;
377 lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
380 ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
381 pDevModeInput, NULL, fMode);
383 if(!pDeviceName)
384 HeapFree(GetProcessHeap(),0,lpName);
385 return ret;
389 /*****************************************************************************
390 * DocumentPropertiesW
392 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
393 LPWSTR pDeviceName,
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;
401 LONG ret;
403 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
404 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
405 fMode);
406 if(pDevModeOutput) {
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);
413 if(pDevModeOutput) {
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);
421 return ret;
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;
433 BOOL ret;
435 if(pDefault) {
436 DefaultW.pDatatype = HEAP_strdupAtoW(GetProcessHeap(), 0,
437 pDefault->pDatatype);
438 DefaultW.pDevMode = DEVMODEdupAtoW(GetProcessHeap(),
439 pDefault->pDevMode);
440 DefaultW.DesiredAccess = pDefault->DesiredAccess;
441 pDefaultW = &DefaultW;
443 ret = OpenPrinterW(lpPrinterNameW, phPrinter, pDefaultW);
444 if(pDefault) {
445 HeapFree(GetProcessHeap(), 0, DefaultW.pDatatype);
446 HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode);
448 HeapFree(GetProcessHeap(), 0, lpPrinterNameW);
449 return ret;
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);
465 return FALSE;
468 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName),
469 pDefault);
471 /* Check Printer exists */
472 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
473 ERROR_SUCCESS) {
474 ERR("Can't create Printers key\n");
475 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
476 return FALSE;
479 if(RegOpenKeyW(hkeyPrinters, lpPrinterName, &hkeyPrinter)
480 != ERROR_SUCCESS) {
481 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName));
482 RegCloseKey(hkeyPrinters);
483 SetLastError(ERROR_INVALID_PARAMETER);
484 return FALSE;
486 RegCloseKey(hkeyPrinter);
487 RegCloseKey(hkeyPrinters);
489 if(!phPrinter) /* This seems to be what win95 does anyway */
490 return TRUE;
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);
497 return FALSE;
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");
510 return TRUE;
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);
521 return FALSE;
524 /******************************************************************
525 * DeletePrinterDriverA [WINSPOOL.146]
528 BOOL WINAPI
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);
534 return FALSE;
538 /******************************************************************
539 * DeleteMonitorA [WINSPOOL.135]
542 BOOL WINAPI
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);
548 return FALSE;
552 /******************************************************************
553 * DeletePortA [WINSPOOL.137]
556 BOOL WINAPI
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);
562 return FALSE;
565 /******************************************************************************
566 * SetPrinterW [WINSPOOL.214]
568 BOOL WINAPI
569 SetPrinterW(
570 HANDLE hPrinter,
571 DWORD Level,
572 LPBYTE pPrinter,
573 DWORD Command) {
575 FIXME("():stub\n");
576 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
577 return FALSE;
580 /******************************************************************************
581 * WritePrinter [WINSPOOL.223]
583 BOOL WINAPI
584 WritePrinter(
585 HANDLE hPrinter,
586 LPVOID pBuf,
587 DWORD cbBuf,
588 LPDWORD pcWritten) {
590 FIXME("():stub\n");
591 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
592 return FALSE;
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);
601 return 1;
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);
610 return 1;
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,
620 pcbNeeded);
621 return 1;
624 /*****************************************************************************
625 * AddJobW [WINSPOOL.106]
627 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
628 LPDWORD pcbNeeded)
630 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
631 pcbNeeded);
632 return 1;
635 /*****************************************************************************
636 * AddPrinterW [WINSPOOL.122]
638 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
640 PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
641 LPDEVMODEA dmA;
642 LPDEVMODEW dmW;
643 HANDLE retval;
644 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
645 LONG size;
647 TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
649 if(pName != NULL) {
650 FIXME("pName = %s - unsupported\n", debugstr_w(pName));
651 SetLastError(ERROR_INVALID_PARAMETER);
652 return 0;
654 if(Level != 2) {
655 WARN("Level = %ld\n", Level);
656 SetLastError(ERROR_INVALID_LEVEL);
657 return 0;
659 if(!pPrinter) {
660 SetLastError(ERROR_INVALID_PARAMETER);
661 return 0;
663 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
664 ERROR_SUCCESS) {
665 ERR("Can't create Printers key\n");
666 return 0;
668 if(RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
669 ERROR_SUCCESS) {
670 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
671 RegCloseKey(hkeyPrinter);
672 RegCloseKey(hkeyPrinters);
673 return 0;
675 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
676 ERROR_SUCCESS) {
677 ERR("Can't create Drivers key\n");
678 RegCloseKey(hkeyPrinters);
679 return 0;
681 if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
682 ERROR_SUCCESS) {
683 WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
684 RegCloseKey(hkeyPrinters);
685 RegCloseKey(hkeyDrivers);
686 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
687 return 0;
689 RegCloseKey(hkeyDriver);
690 RegCloseKey(hkeyDrivers);
692 if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */
693 WARN("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
694 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
695 RegCloseKey(hkeyPrinters);
696 return 0;
699 /* See if we can load the driver. We may need the devmode structure anyway
701 size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0);
702 if(size < 0) {
703 WARN("DocumentProperties fails\n");
704 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
705 return 0;
707 if(pi->pDevMode) {
708 dmW = pi->pDevMode;
709 } else {
710 dmW = HeapAlloc(GetProcessHeap(), 0, size);
711 DocumentPropertiesW(0, -1, pi->pPrinterName, dmW, NULL, DM_OUT_BUFFER);
714 if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
715 ERROR_SUCCESS) {
716 WARN("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
717 SetLastError(ERROR_INVALID_PRINTER_NAME);
718 RegCloseKey(hkeyPrinters);
719 if(!pi->pDevMode)
720 HeapFree(GetProcessHeap(), 0, dmW);
721 return 0;
723 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
724 (LPBYTE)&pi->Attributes, sizeof(DWORD));
725 RegSetValueExW(hkeyPrinter, DatatypeW, 0, REG_SZ, (LPBYTE)pi->pDatatype,
728 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
729 and we support these drivers. NT writes DEVMODEW so somehow
730 we'll need to distinguish between these when we support NT
731 drivers */
732 dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
733 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
734 dmA->dmSize + dmA->dmDriverExtra);
735 HeapFree(GetProcessHeap(), 0, dmA);
736 if(!pi->pDevMode)
737 HeapFree(GetProcessHeap(), 0, dmW);
738 RegSetValueExW(hkeyPrinter, DescriptionW, 0, REG_SZ, (LPBYTE)pi->pComment,
740 RegSetValueExW(hkeyPrinter, LocationW, 0, REG_SZ, (LPBYTE)pi->pLocation,
742 RegSetValueExW(hkeyPrinter, NameW, 0, REG_SZ, (LPBYTE)pi->pPrinterName, 0);
743 RegSetValueExW(hkeyPrinter, ParametersW, 0, REG_SZ,
744 (LPBYTE)pi->pParameters, 0);
745 RegSetValueExW(hkeyPrinter, PortW, 0, REG_SZ, (LPBYTE)pi->pPortName, 0);
746 RegSetValueExW(hkeyPrinter, Print_ProcessorW, 0, REG_SZ,
747 (LPBYTE)pi->pPrintProcessor, 0);
748 RegSetValueExW(hkeyPrinter, Printer_DriverW, 0, REG_SZ,
749 (LPBYTE)pi->pDriverName, 0);
750 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
751 (LPBYTE)&pi->Priority, sizeof(DWORD));
752 RegSetValueExW(hkeyPrinter, Separator_FileW, 0, REG_SZ,
753 (LPBYTE)pi->pSepFile, 0);
754 RegSetValueExW(hkeyPrinter, Share_NameW, 0, REG_SZ, (LPBYTE)pi->pShareName,
756 RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
757 (LPBYTE)&pi->StartTime, sizeof(DWORD));
758 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
759 (LPBYTE)&pi->Status, sizeof(DWORD));
760 RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
761 (LPBYTE)&pi->UntilTime, sizeof(DWORD));
763 RegCloseKey(hkeyPrinter);
764 RegCloseKey(hkeyPrinters);
765 if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
766 ERR("OpenPrinter failing\n");
767 return 0;
769 return retval;
772 /*****************************************************************************
773 * AddPrinterA [WINSPOOL.117]
775 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
777 WCHAR *pNameW;
778 PRINTER_INFO_2W *piW;
779 PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
780 HANDLE ret;
782 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
783 if(Level != 2) {
784 WARN("Level = %ld\n", Level);
785 SetLastError(ERROR_INVALID_LEVEL);
786 return 0;
788 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
789 piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
791 ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
793 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
794 HeapFree(GetProcessHeap(),0,pNameW);
795 return ret;
799 /*****************************************************************************
800 * ClosePrinter [WINSPOOL.126]
802 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
804 LPOPENEDPRINTER lpOpenedPrinter;
806 TRACE("Handle %d\n", hPrinter);
808 if (!pOpenedPrinterDPA)
809 return FALSE;
811 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
813 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
814 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
815 lpOpenedPrinter->lpsPrinterName = NULL;
816 lpOpenedPrinter->hPrinter = -1;
818 return TRUE;
820 return FALSE;
823 /*****************************************************************************
824 * DeleteFormA [WINSPOOL.133]
826 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
828 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
829 return 1;
832 /*****************************************************************************
833 * DeleteFormW [WINSPOOL.134]
835 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
837 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
838 return 1;
841 /*****************************************************************************
842 * DeletePrinter [WINSPOOL.143]
844 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
846 LPWSTR lpNameW;
847 HKEY hkeyPrinters;
849 LPOPENEDPRINTER lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
850 if(!lpOpenedPrinter) {
851 SetLastError(ERROR_INVALID_HANDLE);
852 return FALSE;
854 lpNameW = lpOpenedPrinter->lpsPrinterName;
855 if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
856 ERROR_SUCCESS) {
857 ERR("Can't open Printers key\n");
858 return 0;
861 /* This should use a recursive delete see Q142491 or SHDeleteKey */
862 if(RegDeleteKeyW(hkeyPrinters, lpNameW) == ERROR_SUCCESS) {
863 SetLastError(ERROR_PRINTER_NOT_FOUND); /* ?? */
864 RegCloseKey(hkeyPrinters);
865 return 0;
868 ClosePrinter(hPrinter);
869 return TRUE;
872 /*****************************************************************************
873 * SetPrinterA [WINSPOOL.211]
875 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
876 DWORD Command)
878 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
879 return FALSE;
882 /*****************************************************************************
883 * SetJobA [WINSPOOL.209]
885 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
886 LPBYTE pJob, DWORD Command)
888 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
889 Command);
890 return FALSE;
893 /*****************************************************************************
894 * SetJobW [WINSPOOL.210]
896 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
897 LPBYTE pJob, DWORD Command)
899 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
900 Command);
901 return FALSE;
904 /*****************************************************************************
905 * GetFormA [WINSPOOL.181]
907 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
908 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
910 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
911 Level,pForm,cbBuf,pcbNeeded);
912 return FALSE;
915 /*****************************************************************************
916 * GetFormW [WINSPOOL.182]
918 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
919 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
921 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
922 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
923 return FALSE;
926 /*****************************************************************************
927 * SetFormA [WINSPOOL.207]
929 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
930 LPBYTE pForm)
932 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
933 return FALSE;
936 /*****************************************************************************
937 * SetFormW [WINSPOOL.208]
939 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
940 LPBYTE pForm)
942 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
943 return FALSE;
946 /*****************************************************************************
947 * ReadPrinter [WINSPOOL.202]
949 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
950 LPDWORD pNoBytesRead)
952 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
953 return FALSE;
956 /*****************************************************************************
957 * ResetPrinterA [WINSPOOL.203]
959 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
961 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
962 return FALSE;
965 /*****************************************************************************
966 * ResetPrinterW [WINSPOOL.204]
968 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
970 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
971 return FALSE;
974 /*****************************************************************************
975 * WINSPOOL_GetDWORDFromReg
977 * Return DWORD associated with ValueName from hkey.
979 static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
981 DWORD sz = sizeof(DWORD), type, value = 0;
982 LONG ret;
984 ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz);
986 if(ret != ERROR_SUCCESS) {
987 WARN("Got ret = %ld on name %s\n", ret, ValueName);
988 return 0;
990 if(type != REG_DWORD) {
991 ERR("Got type %ld\n", type);
992 return 0;
994 return value;
997 /*****************************************************************************
998 * WINSPOOL_GetStringFromReg
1000 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1001 * String is stored either as unicode or ascii.
1002 * Bit of a hack here to get the ValueName if we want ascii.
1004 static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
1005 DWORD buflen, DWORD *needed,
1006 BOOL unicode)
1008 DWORD sz = buflen, type;
1009 LONG ret;
1011 if(unicode)
1012 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1013 else {
1014 LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
1015 ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
1016 HeapFree(GetProcessHeap(),0,ValueNameA);
1018 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1019 WARN("Got ret = %ld\n", ret);
1020 *needed = 0;
1021 return FALSE;
1023 *needed = sz;
1024 return TRUE;
1027 /*****************************************************************************
1028 * WINSPOOL_GetDevModeFromReg
1030 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1031 * DevMode is stored either as unicode or ascii.
1033 static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
1034 LPBYTE ptr,
1035 DWORD buflen, DWORD *needed,
1036 BOOL unicode)
1038 DWORD sz = buflen, type;
1039 LONG ret;
1041 if (ptr) memset(ptr, 0, sizeof(DEVMODEA));
1042 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1043 if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
1044 if (sz < sizeof(DEVMODEA))
1046 ERR("corrupted registry for %s\n", debugstr_w(ValueName));
1047 sz = sizeof(DEVMODEA);
1049 /* ensures that dmSize is not erratically bogus if registry is invalid */
1050 if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
1051 ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
1052 if(unicode) {
1053 sz += (CCHDEVICENAME + CCHFORMNAME);
1054 if(buflen >= sz) {
1055 DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
1056 memcpy(ptr, dmW, sz);
1057 HeapFree(GetProcessHeap(),0,dmW);
1060 *needed = sz;
1061 return TRUE;
1064 /*********************************************************************
1065 * WINSPOOL_GetPrinter_2
1067 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1068 * The strings are either stored as unicode or ascii.
1070 static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
1071 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1072 BOOL unicode)
1074 DWORD size, left = cbBuf;
1075 BOOL space = (cbBuf > 0);
1076 LPBYTE ptr = buf;
1078 *pcbNeeded = 0;
1080 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1081 unicode)) {
1082 if(space && size <= left) {
1083 pi2->pPrinterName = (LPWSTR)ptr;
1084 ptr += size;
1085 left -= size;
1086 } else
1087 space = FALSE;
1088 *pcbNeeded += size;
1090 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
1091 unicode)) {
1092 if(space && size <= left) {
1093 pi2->pShareName = (LPWSTR)ptr;
1094 ptr += size;
1095 left -= size;
1096 } else
1097 space = FALSE;
1098 *pcbNeeded += size;
1100 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1101 unicode)) {
1102 if(space && size <= left) {
1103 pi2->pPortName = (LPWSTR)ptr;
1104 ptr += size;
1105 left -= size;
1106 } else
1107 space = FALSE;
1108 *pcbNeeded += size;
1110 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
1111 &size, unicode)) {
1112 if(space && size <= left) {
1113 pi2->pDriverName = (LPWSTR)ptr;
1114 ptr += size;
1115 left -= size;
1116 } else
1117 space = FALSE;
1118 *pcbNeeded += size;
1120 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
1121 unicode)) {
1122 if(space && size <= left) {
1123 pi2->pComment = (LPWSTR)ptr;
1124 ptr += size;
1125 left -= size;
1126 } else
1127 space = FALSE;
1128 *pcbNeeded += size;
1130 if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
1131 unicode)) {
1132 if(space && size <= left) {
1133 pi2->pLocation = (LPWSTR)ptr;
1134 ptr += size;
1135 left -= size;
1136 } else
1137 space = FALSE;
1138 *pcbNeeded += size;
1140 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
1141 &size, unicode)) {
1142 if(space && size <= left) {
1143 pi2->pDevMode = (LPDEVMODEW)ptr;
1144 ptr += size;
1145 left -= size;
1146 } else
1147 space = FALSE;
1148 *pcbNeeded += size;
1150 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
1151 &size, unicode)) {
1152 if(space && size <= left) {
1153 pi2->pSepFile = (LPWSTR)ptr;
1154 ptr += size;
1155 left -= size;
1156 } else
1157 space = FALSE;
1158 *pcbNeeded += size;
1160 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
1161 &size, unicode)) {
1162 if(space && size <= left) {
1163 pi2->pPrintProcessor = (LPWSTR)ptr;
1164 ptr += size;
1165 left -= size;
1166 } else
1167 space = FALSE;
1168 *pcbNeeded += size;
1170 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
1171 &size, unicode)) {
1172 if(space && size <= left) {
1173 pi2->pDatatype = (LPWSTR)ptr;
1174 ptr += size;
1175 left -= size;
1176 } else
1177 space = FALSE;
1178 *pcbNeeded += size;
1180 if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
1181 &size, unicode)) {
1182 if(space && size <= left) {
1183 pi2->pParameters = (LPWSTR)ptr;
1184 ptr += size;
1185 left -= size;
1186 } else
1187 space = FALSE;
1188 *pcbNeeded += size;
1190 if(pi2) {
1191 pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1192 pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
1193 pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1194 "Default Priority");
1195 pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
1196 pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
1199 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1200 memset(pi2, 0, sizeof(*pi2));
1202 return space;
1205 /*********************************************************************
1206 * WINSPOOL_GetPrinter_4
1208 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1210 static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
1211 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1212 BOOL unicode)
1214 DWORD size, left = cbBuf;
1215 BOOL space = (cbBuf > 0);
1216 LPBYTE ptr = buf;
1218 *pcbNeeded = 0;
1220 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1221 unicode)) {
1222 if(space && size <= left) {
1223 pi4->pPrinterName = (LPWSTR)ptr;
1224 ptr += size;
1225 left -= size;
1226 } else
1227 space = FALSE;
1228 *pcbNeeded += size;
1230 if(pi4) {
1231 pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1234 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1235 memset(pi4, 0, sizeof(*pi4));
1237 return space;
1240 /*********************************************************************
1241 * WINSPOOL_GetPrinter_5
1243 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1245 static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
1246 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1247 BOOL unicode)
1249 DWORD size, left = cbBuf;
1250 BOOL space = (cbBuf > 0);
1251 LPBYTE ptr = buf;
1253 *pcbNeeded = 0;
1255 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1256 unicode)) {
1257 if(space && size <= left) {
1258 pi5->pPrinterName = (LPWSTR)ptr;
1259 ptr += size;
1260 left -= size;
1261 } else
1262 space = FALSE;
1263 *pcbNeeded += size;
1265 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1266 unicode)) {
1267 if(space && size <= left) {
1268 pi5->pPortName = (LPWSTR)ptr;
1269 ptr += size;
1270 left -= size;
1271 } else
1272 space = FALSE;
1273 *pcbNeeded += size;
1275 if(pi5) {
1276 pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1277 pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1278 "dnsTimeout");
1279 pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1280 "txTimeout");
1283 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1284 memset(pi5, 0, sizeof(*pi5));
1286 return space;
1289 /*****************************************************************************
1290 * WINSPOOL_GetPrinter
1292 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1293 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1294 * just a collection of pointers to strings.
1296 static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1297 DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
1299 OPENEDPRINTER *lpOpenedPrinter;
1300 DWORD size, needed = 0;
1301 LPBYTE ptr = NULL;
1302 HKEY hkeyPrinter, hkeyPrinters;
1303 BOOL ret;
1305 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1307 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1308 if(!lpOpenedPrinter) {
1309 SetLastError(ERROR_INVALID_HANDLE);
1310 return FALSE;
1312 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1313 ERROR_SUCCESS) {
1314 ERR("Can't create Printers key\n");
1315 return FALSE;
1317 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1318 != ERROR_SUCCESS) {
1319 ERR("Can't find opened printer %s in registry\n",
1320 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1321 RegCloseKey(hkeyPrinters);
1322 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1323 return FALSE;
1326 switch(Level) {
1327 case 2:
1329 PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
1331 size = sizeof(PRINTER_INFO_2W);
1332 if(size <= cbBuf) {
1333 ptr = pPrinter + size;
1334 cbBuf -= size;
1335 memset(pPrinter, 0, size);
1336 } else {
1337 pi2 = NULL;
1338 cbBuf = 0;
1340 ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
1341 unicode);
1342 needed += size;
1343 break;
1346 case 4:
1348 PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
1350 size = sizeof(PRINTER_INFO_4W);
1351 if(size <= cbBuf) {
1352 ptr = pPrinter + size;
1353 cbBuf -= size;
1354 memset(pPrinter, 0, size);
1355 } else {
1356 pi4 = NULL;
1357 cbBuf = 0;
1359 ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
1360 unicode);
1361 needed += size;
1362 break;
1366 case 5:
1368 PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
1370 size = sizeof(PRINTER_INFO_5W);
1371 if(size <= cbBuf) {
1372 ptr = pPrinter + size;
1373 cbBuf -= size;
1374 memset(pPrinter, 0, size);
1375 } else {
1376 pi5 = NULL;
1377 cbBuf = 0;
1380 ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
1381 unicode);
1382 needed += size;
1383 break;
1386 default:
1387 FIXME("Unimplemented level %ld\n", Level);
1388 SetLastError(ERROR_INVALID_LEVEL);
1389 RegCloseKey(hkeyPrinters);
1390 RegCloseKey(hkeyPrinter);
1391 return FALSE;
1394 RegCloseKey(hkeyPrinter);
1395 RegCloseKey(hkeyPrinters);
1397 TRACE("returing %d needed = %ld\n", ret, needed);
1398 if(pcbNeeded) *pcbNeeded = needed;
1399 if(!ret)
1400 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1401 return ret;
1404 /*****************************************************************************
1405 * GetPrinterW [WINSPOOL.194]
1407 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1408 DWORD cbBuf, LPDWORD pcbNeeded)
1410 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1411 TRUE);
1414 /*****************************************************************************
1415 * GetPrinterA [WINSPOOL.187]
1417 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1418 DWORD cbBuf, LPDWORD pcbNeeded)
1420 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1421 FALSE);
1424 /*****************************************************************************
1425 * WINSPOOL_EnumPrinters
1427 * Implementation of EnumPrintersA|W
1429 static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
1430 DWORD dwLevel, LPBYTE lpbPrinters,
1431 DWORD cbBuf, LPDWORD lpdwNeeded,
1432 LPDWORD lpdwReturned, BOOL unicode)
1435 HKEY hkeyPrinters, hkeyPrinter;
1436 WCHAR PrinterName[255];
1437 DWORD needed = 0, number = 0;
1438 DWORD used, i, left;
1439 PBYTE pi, buf;
1441 if(lpbPrinters)
1442 memset(lpbPrinters, 0, cbBuf);
1443 if(lpdwReturned)
1444 *lpdwReturned = 0;
1446 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1447 FIXME("dwType = %08lx\n", dwType);
1448 SetLastError(ERROR_INVALID_FLAGS);
1449 return FALSE;
1452 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1453 ERROR_SUCCESS) {
1454 ERR("Can't create Printers key\n");
1455 return FALSE;
1458 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1459 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1460 RegCloseKey(hkeyPrinters);
1461 ERR("Can't query Printers key\n");
1462 return FALSE;
1464 TRACE("Found %ld printers\n", number);
1466 switch(dwLevel) {
1467 case 1:
1468 RegCloseKey(hkeyPrinters);
1469 if (lpdwReturned)
1470 *lpdwReturned = number;
1471 return TRUE;
1473 case 2:
1474 used = number * sizeof(PRINTER_INFO_2W);
1475 break;
1476 case 4:
1477 used = number * sizeof(PRINTER_INFO_4W);
1478 break;
1479 case 5:
1480 used = number * sizeof(PRINTER_INFO_5W);
1481 break;
1483 default:
1484 SetLastError(ERROR_INVALID_LEVEL);
1485 RegCloseKey(hkeyPrinters);
1486 return FALSE;
1488 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1490 for(i = 0; i < number; i++) {
1491 if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1492 ERROR_SUCCESS) {
1493 ERR("Can't enum key number %ld\n", i);
1494 RegCloseKey(hkeyPrinters);
1495 return FALSE;
1497 TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
1498 if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1499 ERROR_SUCCESS) {
1500 ERR("Can't open key %s\n", debugstr_w(PrinterName));
1501 RegCloseKey(hkeyPrinters);
1502 return FALSE;
1505 if(cbBuf > used) {
1506 buf = lpbPrinters + used;
1507 left = cbBuf - used;
1508 } else {
1509 buf = NULL;
1510 left = 0;
1513 switch(dwLevel) {
1514 case 2:
1515 WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
1516 left, &needed, unicode);
1517 used += needed;
1518 if(pi) pi += sizeof(PRINTER_INFO_2W);
1519 break;
1520 case 4:
1521 WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
1522 left, &needed, unicode);
1523 used += needed;
1524 if(pi) pi += sizeof(PRINTER_INFO_4W);
1525 break;
1526 case 5:
1527 WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
1528 left, &needed, unicode);
1529 used += needed;
1530 if(pi) pi += sizeof(PRINTER_INFO_5W);
1531 break;
1532 default:
1533 ERR("Shouldn't be here!\n");
1534 RegCloseKey(hkeyPrinter);
1535 RegCloseKey(hkeyPrinters);
1536 return FALSE;
1538 RegCloseKey(hkeyPrinter);
1540 RegCloseKey(hkeyPrinters);
1542 if(lpdwNeeded)
1543 *lpdwNeeded = used;
1545 if(used > cbBuf) {
1546 if(lpbPrinters)
1547 memset(lpbPrinters, 0, cbBuf);
1548 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1549 return FALSE;
1551 if(lpdwReturned)
1552 *lpdwReturned = number;
1553 SetLastError(ERROR_SUCCESS);
1554 return TRUE;
1558 /******************************************************************
1559 * EnumPrintersW [WINSPOOL.175]
1561 * Enumerates the available printers, print servers and print
1562 * providers, depending on the specified flags, name and level.
1564 * RETURNS:
1566 * If level is set to 1:
1567 * Not implemented yet!
1568 * Returns TRUE with an empty list.
1570 * If level is set to 2:
1571 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1572 * Returns an array of PRINTER_INFO_2 data structures in the
1573 * lpbPrinters buffer. Note that according to MSDN also an
1574 * OpenPrinter should be performed on every remote printer.
1576 * If level is set to 4 (officially WinNT only):
1577 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1578 * Fast: Only the registry is queried to retrieve printer names,
1579 * no connection to the driver is made.
1580 * Returns an array of PRINTER_INFO_4 data structures in the
1581 * lpbPrinters buffer.
1583 * If level is set to 5 (officially WinNT4/Win9x only):
1584 * Fast: Only the registry is queried to retrieve printer names,
1585 * no connection to the driver is made.
1586 * Returns an array of PRINTER_INFO_5 data structures in the
1587 * lpbPrinters buffer.
1589 * If level set to 3 or 6+:
1590 * returns zero (faillure!)
1592 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1593 * for information.
1595 * BUGS:
1596 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1597 * - Only levels 2, 4 and 5 are implemented at the moment.
1598 * - 16-bit printer drivers are not enumerated.
1599 * - Returned amount of bytes used/needed does not match the real Windoze
1600 * implementation (as in this implementation, all strings are part
1601 * of the buffer, whereas Win32 keeps them somewhere else)
1602 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1604 * NOTE:
1605 * - In a regular Wine installation, no registry settings for printers
1606 * exist, which makes this function return an empty list.
1608 BOOL WINAPI EnumPrintersW(
1609 DWORD dwType, /* Types of print objects to enumerate */
1610 LPWSTR lpszName, /* name of objects to enumerate */
1611 DWORD dwLevel, /* type of printer info structure */
1612 LPBYTE lpbPrinters, /* buffer which receives info */
1613 DWORD cbBuf, /* max size of buffer in bytes */
1614 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
1615 LPDWORD lpdwReturned /* number of entries returned */
1618 return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
1619 lpdwNeeded, lpdwReturned, TRUE);
1622 /******************************************************************
1623 * EnumPrintersA [WINSPOOL.174]
1626 BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
1627 DWORD dwLevel, LPBYTE lpbPrinters,
1628 DWORD cbBuf, LPDWORD lpdwNeeded,
1629 LPDWORD lpdwReturned)
1631 BOOL ret;
1632 LPWSTR lpszNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
1634 ret = WINSPOOL_EnumPrinters(dwType, lpszNameW, dwLevel, lpbPrinters, cbBuf,
1635 lpdwNeeded, lpdwReturned, FALSE);
1636 HeapFree(GetProcessHeap(),0,lpszNameW);
1637 return ret;
1640 /*****************************************************************************
1641 * WINSPOOL_GetDriverInfoFromReg [internal]
1643 * Enters the information from the registry into the DRIVER_INFO struct
1645 * RETURNS
1646 * zero if the printer driver does not exist in the registry
1647 * (only if Level > 1) otherwise nonzero
1649 static BOOL WINSPOOL_GetDriverInfoFromReg(
1650 HKEY hkeyDrivers,
1651 LPWSTR DriverName,
1652 LPWSTR pEnvironment,
1653 DWORD Level,
1654 LPBYTE ptr, /* DRIVER_INFO */
1655 LPBYTE pDriverStrings, /* strings buffer */
1656 DWORD cbBuf, /* size of string buffer */
1657 LPDWORD pcbNeeded, /* space needed for str. */
1658 BOOL unicode) /* type of strings */
1659 { DWORD dw, size, type;
1660 HKEY hkeyDriver;
1661 LPBYTE strPtr = pDriverStrings;
1663 TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
1664 debugstr_w(DriverName), debugstr_w(pEnvironment),
1665 Level, ptr, pDriverStrings, cbBuf, unicode);
1667 if(unicode) {
1668 *pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
1669 if (*pcbNeeded <= cbBuf)
1670 strcpyW((LPWSTR)strPtr, DriverName);
1671 } else {
1672 *pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0,
1673 NULL, NULL);
1674 if(*pcbNeeded <= cbBuf)
1675 WideCharToMultiByte(CP_ACP, 0, DriverName, -1, strPtr, *pcbNeeded,
1676 NULL, NULL);
1678 if(Level == 1) {
1679 if(ptr)
1680 ((PDRIVER_INFO_1W) ptr)->pName = (LPWSTR) strPtr;
1681 return TRUE;
1682 } else {
1683 if(ptr)
1684 ((PDRIVER_INFO_3W) ptr)->pName = (LPWSTR) strPtr;
1685 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1688 if(RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) {
1689 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName));
1690 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1691 return FALSE;
1694 size = sizeof(dw);
1695 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw, &size) !=
1696 ERROR_SUCCESS)
1697 WARN("Can't get Version\n");
1698 else if(ptr)
1699 ((PDRIVER_INFO_3A) ptr)->cVersion = dw;
1701 if(!pEnvironment)
1702 pEnvironment = DefaultEnvironmentW;
1703 if(unicode)
1704 size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
1705 else
1706 size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
1707 NULL, NULL);
1708 *pcbNeeded += size;
1709 if(*pcbNeeded <= cbBuf) {
1710 if(unicode)
1711 strcpyW((LPWSTR)strPtr, pEnvironment);
1712 else
1713 WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, strPtr, size,
1714 NULL, NULL);
1715 if(ptr)
1716 ((PDRIVER_INFO_3W) ptr)->pEnvironment = (LPWSTR)strPtr;
1717 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1720 if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size,
1721 unicode)) {
1722 *pcbNeeded += size;
1723 if(*pcbNeeded <= cbBuf)
1724 WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, cbBuf, &size,
1725 unicode);
1726 if(ptr)
1727 ((PDRIVER_INFO_3W) ptr)->pDriverPath = (LPWSTR)strPtr;
1728 strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
1731 if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size,
1732 unicode)) {
1733 *pcbNeeded += size;
1734 if(*pcbNeeded <= cbBuf)
1735 WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, cbBuf,
1736 &size, unicode);
1737 if(ptr)
1738 ((PDRIVER_INFO_3W) ptr)->pDataFile = (LPWSTR)strPtr;
1739 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1742 if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
1743 cbBuf, &size, unicode)) {
1744 *pcbNeeded += size;
1745 if(*pcbNeeded <= cbBuf)
1746 WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
1747 cbBuf, &size, unicode);
1748 if(ptr)
1749 ((PDRIVER_INFO_3W) ptr)->pConfigFile = (LPWSTR)strPtr;
1750 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1753 if(Level == 2 ) {
1754 RegCloseKey(hkeyDriver);
1755 return TRUE;
1758 if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size,
1759 unicode)) {
1760 *pcbNeeded += size;
1761 if(*pcbNeeded <= cbBuf)
1762 WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr,
1763 cbBuf, &size, unicode);
1764 if(ptr)
1765 ((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr;
1766 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1769 if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0,
1770 &size, unicode)) {
1771 *pcbNeeded += size;
1772 if(*pcbNeeded <= cbBuf)
1773 WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr,
1774 cbBuf, &size, unicode);
1775 if(ptr)
1776 ((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr;
1777 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1780 if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size,
1781 unicode)) {
1782 *pcbNeeded += size;
1783 if(*pcbNeeded <= cbBuf)
1784 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
1785 cbBuf, &size, unicode);
1786 if(ptr)
1787 ((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr;
1788 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1791 if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size,
1792 unicode)) {
1793 *pcbNeeded += size;
1794 if(*pcbNeeded <= cbBuf)
1795 WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
1796 cbBuf, &size, unicode);
1797 if(ptr)
1798 ((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr;
1799 strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
1802 RegCloseKey(hkeyDriver);
1803 return TRUE;
1806 /*****************************************************************************
1807 * WINSPOOL_GetPrinterDriver
1809 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
1810 DWORD Level, LPBYTE pDriverInfo,
1811 DWORD cbBuf, LPDWORD pcbNeeded,
1812 BOOL unicode)
1814 OPENEDPRINTER *lpOpenedPrinter;
1815 WCHAR DriverName[100];
1816 DWORD ret, type, size, needed = 0;
1817 LPBYTE ptr = NULL;
1818 HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers;
1820 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
1821 Level,pDriverInfo,cbBuf, pcbNeeded);
1823 ZeroMemory(pDriverInfo, cbBuf);
1825 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1826 if(!lpOpenedPrinter) {
1827 SetLastError(ERROR_INVALID_HANDLE);
1828 return FALSE;
1830 if(pEnvironment) {
1831 FIXME("pEnvironment = %s\n", debugstr_w(pEnvironment));
1832 SetLastError(ERROR_INVALID_ENVIRONMENT);
1833 return FALSE;
1835 if(Level < 1 || Level > 3) {
1836 SetLastError(ERROR_INVALID_LEVEL);
1837 return FALSE;
1839 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1840 ERROR_SUCCESS) {
1841 ERR("Can't create Printers key\n");
1842 return FALSE;
1844 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1845 != ERROR_SUCCESS) {
1846 ERR("Can't find opened printer %s in registry\n",
1847 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1848 RegCloseKey(hkeyPrinters);
1849 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1850 return FALSE;
1852 size = sizeof(DriverName);
1853 ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
1854 (LPBYTE)DriverName, &size);
1855 RegCloseKey(hkeyPrinter);
1856 RegCloseKey(hkeyPrinters);
1857 if(ret != ERROR_SUCCESS) {
1858 ERR("Can't get DriverName for printer %s\n",
1859 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1860 return FALSE;
1862 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1863 ERROR_SUCCESS) {
1864 ERR("Can't create Drivers key\n");
1865 return FALSE;
1868 switch(Level) {
1869 case 1:
1870 size = sizeof(DRIVER_INFO_1W);
1871 break;
1872 case 2:
1873 size = sizeof(DRIVER_INFO_2W);
1874 break;
1875 case 3:
1876 size = sizeof(DRIVER_INFO_3W);
1877 break;
1878 default:
1879 ERR("Invalid level\n");
1880 return FALSE;
1883 if(size <= cbBuf)
1884 ptr = pDriverInfo + size;
1886 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName,
1887 pEnvironment, Level, pDriverInfo,
1888 (cbBuf < size) ? NULL : ptr,
1889 (cbBuf < size) ? 0 : cbBuf - size,
1890 &needed, unicode)) {
1891 RegCloseKey(hkeyDrivers);
1892 return FALSE;
1895 RegCloseKey(hkeyDrivers);
1897 if(pcbNeeded) *pcbNeeded = needed;
1898 if(cbBuf >= needed) return TRUE;
1899 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1900 return FALSE;
1903 /*****************************************************************************
1904 * GetPrinterDriverA [WINSPOOL.190]
1906 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1907 DWORD Level, LPBYTE pDriverInfo,
1908 DWORD cbBuf, LPDWORD pcbNeeded)
1910 BOOL ret;
1911 LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
1912 ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
1913 cbBuf, pcbNeeded, FALSE);
1914 HeapFree(GetProcessHeap(),0,pEnvW);
1915 return ret;
1917 /*****************************************************************************
1918 * GetPrinterDriverW [WINSPOOL.193]
1920 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1921 DWORD Level, LPBYTE pDriverInfo,
1922 DWORD cbBuf, LPDWORD pcbNeeded)
1924 return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level,
1925 pDriverInfo, cbBuf, pcbNeeded, TRUE);
1928 /*****************************************************************************
1929 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1931 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1932 DWORD Level, LPBYTE pDriverDirectory,
1933 DWORD cbBuf, LPDWORD pcbNeeded)
1935 DWORD needed;
1937 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1938 pDriverDirectory, cbBuf, pcbNeeded);
1939 if(pName != NULL) {
1940 FIXME("pName = `%s' - unsupported\n", pName);
1941 SetLastError(ERROR_INVALID_PARAMETER);
1942 return FALSE;
1944 if(pEnvironment != NULL) {
1945 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
1946 SetLastError(ERROR_INVALID_ENVIRONMENT);
1947 return FALSE;
1949 if(Level != 1) /* win95 ignores this so we just carry on */
1950 WARN("Level = %ld - assuming 1\n", Level);
1952 /* FIXME should read from registry */
1953 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
1954 needed++;
1955 if(pcbNeeded)
1956 *pcbNeeded = needed;
1957 if(needed > cbBuf) {
1958 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1959 return FALSE;
1961 return TRUE;
1965 /*****************************************************************************
1966 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1968 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
1969 DWORD Level, LPBYTE pDriverDirectory,
1970 DWORD cbBuf, LPDWORD pcbNeeded)
1972 LPSTR pNameA = NULL, pEnvironmentA = NULL;
1973 BOOL ret;
1975 if(pName)
1976 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
1977 if(pEnvironment)
1978 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
1979 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
1980 pDriverDirectory, cbBuf, pcbNeeded );
1981 if(pNameA)
1982 HeapFree( GetProcessHeap(), 0, pNameA );
1983 if(pEnvironmentA)
1984 HeapFree( GetProcessHeap(), 0, pEnvironmentA );
1986 return ret;
1989 /*****************************************************************************
1990 * AddPrinterDriverA [WINSPOOL.120]
1992 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
1994 DRIVER_INFO_3A di3;
1995 HKEY hkeyDrivers, hkeyName;
1997 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
1999 if(level != 2 && level != 3) {
2000 SetLastError(ERROR_INVALID_LEVEL);
2001 return FALSE;
2003 if(pName != NULL) {
2004 FIXME("pName= `%s' - unsupported\n", pName);
2005 SetLastError(ERROR_INVALID_PARAMETER);
2006 return FALSE;
2008 if(!pDriverInfo) {
2009 WARN("pDriverInfo == NULL");
2010 SetLastError(ERROR_INVALID_PARAMETER);
2011 return FALSE;
2014 if(level == 3)
2015 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
2016 else {
2017 memset(&di3, 0, sizeof(di3));
2018 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
2021 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
2022 !di3.pDataFile) {
2023 SetLastError(ERROR_INVALID_PARAMETER);
2024 return FALSE;
2026 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
2027 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
2028 if(!di3.pHelpFile) di3.pHelpFile = "";
2029 if(!di3.pMonitorName) di3.pMonitorName = "";
2031 if(di3.pEnvironment) {
2032 FIXME("pEnvironment = `%s'\n", di3.pEnvironment);
2033 SetLastError(ERROR_INVALID_ENVIRONMENT);
2034 return FALSE;
2036 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
2037 ERROR_SUCCESS) {
2038 ERR("Can't create Drivers key\n");
2039 return FALSE;
2042 if(level == 2) { /* apparently can't overwrite with level2 */
2043 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
2044 RegCloseKey(hkeyName);
2045 RegCloseKey(hkeyDrivers);
2046 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
2047 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
2048 return FALSE;
2051 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
2052 RegCloseKey(hkeyDrivers);
2053 ERR("Can't create Name key\n");
2054 return FALSE;
2056 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
2058 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
2059 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
2060 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
2061 sizeof(DWORD));
2062 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
2063 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
2064 di3.pDependentFiles, 0);
2065 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
2066 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
2067 RegCloseKey(hkeyName);
2068 RegCloseKey(hkeyDrivers);
2070 return TRUE;
2072 /*****************************************************************************
2073 * AddPrinterDriverW [WINSPOOL.121]
2075 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
2076 LPBYTE pDriverInfo)
2078 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
2079 level,pDriverInfo);
2080 return FALSE;
2084 /*****************************************************************************
2085 * PrinterProperties [WINSPOOL.201]
2087 * Displays a dialog to set the properties of the printer.
2089 * RETURNS
2090 * nonzero on succes or zero on faillure
2092 * BUGS
2093 * implemented as stub only
2095 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
2096 HANDLE hPrinter /* handle to printer object */
2098 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
2099 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2100 return FALSE;
2103 /*****************************************************************************
2104 * EnumJobsA [WINSPOOL.162]
2107 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2108 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2109 LPDWORD pcReturned)
2111 FIXME("stub\n");
2112 if(pcbNeeded) *pcbNeeded = 0;
2113 if(pcReturned) *pcReturned = 0;
2114 return TRUE;
2118 /*****************************************************************************
2119 * EnumJobsW [WINSPOOL.163]
2122 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2123 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2124 LPDWORD pcReturned)
2126 FIXME("stub\n");
2127 if(pcbNeeded) *pcbNeeded = 0;
2128 if(pcReturned) *pcReturned = 0;
2129 return TRUE;
2132 /*****************************************************************************
2133 * WINSPOOL_EnumPrinterDrivers [internal]
2135 * Delivers information about all installed printer drivers installed on
2136 * localhost or a given server
2138 * RETURNS
2139 * nonzero on succes or zero on failure, if the buffer for the returned
2140 * information is too small the function will return an error
2142 * BUGS
2143 * - only implemented for localhost, foreign hosts will return an error
2144 * - the parameter pEnvironment is ignored
2146 static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPWSTR pEnvironment,
2147 DWORD Level, LPBYTE pDriverInfo,
2148 DWORD cbBuf, LPDWORD pcbNeeded,
2149 LPDWORD pcReturned, BOOL unicode)
2151 { HKEY hkeyDrivers;
2152 DWORD i, needed, number = 0, size = 0;
2153 WCHAR DriverNameW[255];
2154 PBYTE ptr;
2156 TRACE("%s,%s,%ld,%p,%ld,%d\n",
2157 debugstr_w(pName), debugstr_w(pEnvironment),
2158 Level, pDriverInfo, cbBuf, unicode);
2160 /* check for local drivers */
2161 if(pName) {
2162 ERR("remote drivers unsupported! Current remote host is %s\n",
2163 debugstr_w(pName));
2164 return FALSE;
2167 /* check input parameter */
2168 if((Level < 1) || (Level > 3)) {
2169 ERR("unsupported level %ld \n", Level);
2170 return FALSE;
2173 /* initialize return values */
2174 if(pDriverInfo)
2175 memset( pDriverInfo, 0, cbBuf);
2176 *pcbNeeded = 0;
2177 *pcReturned = 0;
2179 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
2180 ERROR_SUCCESS) {
2181 ERR("Can't open Drivers key\n");
2182 return FALSE;
2185 if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL,
2186 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
2187 RegCloseKey(hkeyDrivers);
2188 ERR("Can't query Drivers key\n");
2189 return FALSE;
2191 TRACE("Found %ld Drivers\n", number);
2193 /* get size of single struct
2194 * unicode and ascii structure have the same size
2196 switch (Level) {
2197 case 1:
2198 size = sizeof(DRIVER_INFO_1A);
2199 break;
2200 case 2:
2201 size = sizeof(DRIVER_INFO_2A);
2202 break;
2203 case 3:
2204 size = sizeof(DRIVER_INFO_3A);
2205 break;
2208 /* calculate required buffer size */
2209 *pcbNeeded = size * number;
2211 for( i = 0, ptr = (pDriverInfo && (cbBuf >= size)) ? pDriverInfo : NULL ;
2212 i < number;
2213 i++, ptr = (ptr && (cbBuf >= size * i)) ? ptr + size : NULL) {
2214 if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW))
2215 != ERROR_SUCCESS) {
2216 ERR("Can't enum key number %ld\n", i);
2217 RegCloseKey(hkeyDrivers);
2218 return FALSE;
2220 if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
2221 pEnvironment, Level, ptr,
2222 (cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded,
2223 (cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
2224 &needed, unicode)) {
2225 RegCloseKey(hkeyDrivers);
2226 return FALSE;
2228 (*pcbNeeded) += needed;
2231 RegCloseKey(hkeyDrivers);
2233 if(cbBuf < *pcbNeeded){
2234 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2235 return FALSE;
2238 return TRUE;
2241 /*****************************************************************************
2242 * EnumPrinterDriversW [WINSPOOL.173]
2244 * see function EnumPrinterDrivers for RETURNS, BUGS
2246 BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
2247 LPBYTE pDriverInfo, DWORD cbBuf,
2248 LPDWORD pcbNeeded, LPDWORD pcReturned)
2250 return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
2251 cbBuf, pcbNeeded, pcReturned, TRUE);
2254 /*****************************************************************************
2255 * EnumPrinterDriversA [WINSPOOL.172]
2257 * see function EnumPrinterDrivers for RETURNS, BUGS
2259 BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level,
2260 LPBYTE pDriverInfo, DWORD cbBuf,
2261 LPDWORD pcbNeeded, LPDWORD pcReturned)
2262 { BOOL ret;
2263 WCHAR *pNameW = NULL, *pEnvironmentW = NULL;
2265 if(pName)
2266 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
2267 if(pEnvironment)
2268 pEnvironmentW = HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment);
2270 ret = WINSPOOL_EnumPrinterDrivers(pNameW, pEnvironmentW, Level, pDriverInfo,
2271 cbBuf, pcbNeeded, pcReturned, FALSE);
2272 if(pNameW)
2273 HeapFree(GetProcessHeap(), 0, pNameW);
2274 if(pEnvironmentW)
2275 HeapFree(GetProcessHeap(), 0, pEnvironmentW);
2277 return ret;