Transform every ERR() to WARN() in MakeProcInstance.
[wine/gsoc_dplay.git] / dlls / winspool / info.c
blob0344592647611f8fdc44821c5ff79316d4dff6a8
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/unicode.h"
19 #include "debugtools.h"
20 #include "heap.h"
21 #include "commctrl.h"
22 #include "winnls.h"
24 DEFAULT_DEBUG_CHANNEL(winspool);
26 typedef struct _OPENEDPRINTER
28 LPWSTR lpsPrinterName;
29 HANDLE hPrinter;
30 } OPENEDPRINTER, *LPOPENEDPRINTER;
32 /* The OpenedPrinter Table dynamic array */
33 static HDPA pOpenedPrinterDPA = NULL;
35 extern HDPA (WINAPI* WINSPOOL_DPA_CreateEx) (INT, HANDLE);
36 extern LPVOID (WINAPI* WINSPOOL_DPA_GetPtr) (const HDPA, INT);
37 extern INT (WINAPI* WINSPOOL_DPA_InsertPtr) (const HDPA, INT, LPVOID);
39 static char Printers[] =
40 "System\\CurrentControlSet\\control\\Print\\Printers\\";
41 static char Drivers[] =
42 "System\\CurrentControlSet\\control\\Print\\Environments\\Windows 4.0\\Drivers\\"; /* Hmm, well */
44 static WCHAR DefaultEnvironmentW[] = {'W','i','n','e',0};
46 static WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t',
47 'i','o','n',' ','F','i','l','e',0};
48 static WCHAR DatatypeW[] = {'D','a','t','a','t','y','p','e',0};
49 static WCHAR Data_FileW[] = {'D','a','t','a',' ','F','i','l','e',0};
50 static WCHAR Default_DevModeW[] = {'D','e','f','a','u','l','t',' ','D','e','v',
51 'M','o','d','e',0};
52 static WCHAR Dependent_FilesW[] = {'D','e','p','e','n','d','e','n','t',' ','F',
53 'i','l','e','s',0};
54 static WCHAR DescriptionW[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
55 static WCHAR DriverW[] = {'D','r','i','v','e','r',0};
56 static WCHAR Help_FileW[] = {'H','e','l','p',' ','F','i','l','e',0};
57 static WCHAR LocationW[] = {'L','o','c','a','t','i','o','n',0};
58 static WCHAR MonitorW[] = {'M','o','n','i','t','o','r',0};
59 static WCHAR NameW[] = {'N','a','m','e',0};
60 static WCHAR ParametersW[] = {'P','a','r','a','m','e','t','e','r','s',0};
61 static WCHAR PortW[] = {'P','o','r','t',0};
62 static WCHAR Print_ProcessorW[] = {'P','r','i','n','t',' ','P','r','o','c','e',
63 's','s','o','r',0};
64 static WCHAR Printer_DriverW[] = {'P','r','i','n','t','e','r',' ','D','r','i',
65 'v','e','r',0};
66 static WCHAR Separator_FileW[] = {'S','e','p','a','r','a','t','o','r',' ','F',
67 'i','l','e',0};
68 static WCHAR Share_NameW[] = {'S','h','a','r','e',' ','N','a','m','e',0};
69 static WCHAR WinPrintW[] = {'W','i','n','P','r','i','n','t',0};
71 /******************************************************************
72 * WINSPOOL_GetOpenedPrinterEntry
73 * Get the first place empty in the opened printer table
75 static LPOPENEDPRINTER WINSPOOL_GetOpenedPrinterEntry()
77 int i;
78 LPOPENEDPRINTER pOpenedPrinter;
81 * Create the opened printers' handle dynamic array.
83 if (!pOpenedPrinterDPA)
85 pOpenedPrinterDPA = WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
86 for (i = 0; i < 10; i++)
88 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
89 HEAP_ZERO_MEMORY,
90 sizeof(OPENEDPRINTER));
91 pOpenedPrinter->hPrinter = -1;
92 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
97 * Search for a handle not yet allocated.
99 for (i = 0; i < pOpenedPrinterDPA->nItemCount; i++)
101 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, i);
103 if (pOpenedPrinter->hPrinter == -1)
105 pOpenedPrinter->hPrinter = i + 1;
106 return pOpenedPrinter;
111 * Didn't find one, insert new element in the array.
113 if (i == pOpenedPrinterDPA->nItemCount)
115 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
116 HEAP_ZERO_MEMORY,
117 sizeof(OPENEDPRINTER));
118 pOpenedPrinter->hPrinter = i + 1;
119 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
120 return pOpenedPrinter;
123 return NULL;
126 /******************************************************************
127 * WINSPOOL_GetOpenedPrinter
128 * Get the pointer to the opened printer referred by the handle
130 static LPOPENEDPRINTER WINSPOOL_GetOpenedPrinter(int printerHandle)
132 LPOPENEDPRINTER pOpenedPrinter;
134 if(!pOpenedPrinterDPA) return NULL;
135 if((printerHandle <=0) ||
136 (printerHandle > (pOpenedPrinterDPA->nItemCount - 1)))
137 return NULL;
139 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, printerHandle-1);
141 return pOpenedPrinter;
144 /***********************************************************
145 * DEVMODEcpyAtoW
147 static LPDEVMODEW DEVMODEcpyAtoW(DEVMODEW *dmW, const DEVMODEA *dmA)
149 BOOL Formname;
150 ptrdiff_t off_formname = (char *)dmA->dmFormName - (char *)dmA;
151 DWORD size;
153 Formname = (dmA->dmSize > off_formname);
154 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
155 MultiByteToWideChar(CP_ACP, 0, dmA->dmDeviceName, -1, dmW->dmDeviceName,
156 CCHDEVICENAME);
157 if(!Formname) {
158 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
159 dmA->dmSize - CCHDEVICENAME);
160 } else {
161 memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion,
162 off_formname - CCHDEVICENAME);
163 MultiByteToWideChar(CP_ACP, 0, dmA->dmFormName, -1, dmW->dmFormName,
164 CCHFORMNAME);
165 memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA->dmSize -
166 (off_formname + CCHFORMNAME));
168 dmW->dmSize = size;
169 memcpy((char *)dmW + dmW->dmSize, (char *)dmA + dmA->dmSize,
170 dmA->dmDriverExtra);
171 return dmW;
174 /***********************************************************
175 * DEVMODEdupAtoW
176 * Creates a unicode copy of supplied devmode on heap
178 static LPDEVMODEW DEVMODEdupAtoW(HANDLE heap, const DEVMODEA *dmA)
180 LPDEVMODEW dmW;
181 DWORD size;
182 BOOL Formname;
183 ptrdiff_t off_formname;
185 TRACE("\n");
186 if(!dmA) return NULL;
188 off_formname = (char *)dmA->dmFormName - (char *)dmA;
189 Formname = (dmA->dmSize > off_formname);
190 size = dmA->dmSize + CCHDEVICENAME + (Formname ? CCHFORMNAME : 0);
191 dmW = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmA->dmDriverExtra);
192 return DEVMODEcpyAtoW(dmW, dmA);
195 /***********************************************************
196 * DEVMODEdupWtoA
197 * Creates an ascii copy of supplied devmode on heap
199 static LPDEVMODEA DEVMODEdupWtoA(HANDLE heap, const DEVMODEW *dmW)
201 LPDEVMODEA dmA;
202 DWORD size;
203 BOOL Formname;
204 ptrdiff_t off_formname = (char *)dmW->dmFormName - (char *)dmW;
206 if(!dmW) return NULL;
207 Formname = (dmW->dmSize > off_formname);
208 size = dmW->dmSize - CCHDEVICENAME - (Formname ? CCHFORMNAME : 0);
209 dmA = HeapAlloc(heap, HEAP_ZERO_MEMORY, size + dmW->dmDriverExtra);
210 WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, dmA->dmDeviceName,
211 CCHDEVICENAME, NULL, NULL);
212 if(!Formname) {
213 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
214 dmW->dmSize - CCHDEVICENAME * sizeof(WCHAR));
215 } else {
216 memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion,
217 off_formname - CCHDEVICENAME * sizeof(WCHAR));
218 WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, dmA->dmFormName,
219 CCHFORMNAME, NULL, NULL);
220 memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW->dmSize -
221 (off_formname + CCHFORMNAME * sizeof(WCHAR)));
223 dmA->dmSize = size;
224 memcpy((char *)dmA + dmA->dmSize, (char *)dmW + dmW->dmSize,
225 dmW->dmDriverExtra);
226 return dmA;
229 /***********************************************************
230 * PRINTER_INFO_2AtoW
231 * Creates a unicode copy of PRINTER_INFO_2A on heap
233 static LPPRINTER_INFO_2W PRINTER_INFO_2AtoW(HANDLE heap, LPPRINTER_INFO_2A piA)
235 LPPRINTER_INFO_2W piW;
236 if(!piA) return NULL;
237 piW = HeapAlloc(heap, 0, sizeof(*piW));
238 memcpy(piW, piA, sizeof(*piW)); /* copy everything first */
239 piW->pServerName = HEAP_strdupAtoW(heap, 0, piA->pServerName);
240 piW->pPrinterName = HEAP_strdupAtoW(heap, 0, piA->pPrinterName);
241 piW->pShareName = HEAP_strdupAtoW(heap, 0, piA->pShareName);
242 piW->pPortName = HEAP_strdupAtoW(heap, 0, piA->pPortName);
243 piW->pDriverName = HEAP_strdupAtoW(heap, 0, piA->pDriverName);
244 piW->pComment = HEAP_strdupAtoW(heap, 0, piA->pComment);
245 piW->pLocation = HEAP_strdupAtoW(heap, 0, piA->pLocation);
246 piW->pDevMode = DEVMODEdupAtoW(heap, piA->pDevMode);
247 piW->pSepFile = HEAP_strdupAtoW(heap, 0, piA->pSepFile);
248 piW->pPrintProcessor = HEAP_strdupAtoW(heap, 0, piA->pPrintProcessor);
249 piW->pDatatype = HEAP_strdupAtoW(heap, 0, piA->pDatatype);
250 piW->pParameters = HEAP_strdupAtoW(heap, 0, piA->pParameters);
251 return piW;
254 /***********************************************************
255 * FREE_PRINTER_INFO_2W
256 * Free PRINTER_INFO_2W and all strings
258 static void FREE_PRINTER_INFO_2W(HANDLE heap, LPPRINTER_INFO_2W piW)
260 if(!piW) return;
262 HeapFree(heap,0,piW->pServerName);
263 HeapFree(heap,0,piW->pPrinterName);
264 HeapFree(heap,0,piW->pShareName);
265 HeapFree(heap,0,piW->pPortName);
266 HeapFree(heap,0,piW->pDriverName);
267 HeapFree(heap,0,piW->pComment);
268 HeapFree(heap,0,piW->pLocation);
269 HeapFree(heap,0,piW->pDevMode);
270 HeapFree(heap,0,piW->pSepFile);
271 HeapFree(heap,0,piW->pPrintProcessor);
272 HeapFree(heap,0,piW->pDatatype);
273 HeapFree(heap,0,piW->pParameters);
274 HeapFree(heap,0,piW);
275 return;
278 /******************************************************************
279 * DeviceCapabilitiesA [WINSPOOL.150 & WINSPOOL.151]
282 INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort, WORD cap,
283 LPSTR pOutput, LPDEVMODEA lpdm)
285 INT ret;
286 ret = GDI_CallDeviceCapabilities16(pDevice, pPort, cap, pOutput, lpdm);
288 /* If DC_PAPERSIZE map POINT16s to POINTs */
289 if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
290 POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
291 INT i;
292 memcpy(tmp, pOutput, ret * sizeof(POINT16));
293 for(i = 0; i < ret; i++)
294 CONV_POINT16TO32(tmp + i, (POINT*)pOutput + i);
295 HeapFree( GetProcessHeap(), 0, tmp );
297 return ret;
301 /*****************************************************************************
302 * DeviceCapabilitiesW [WINSPOOL.152]
304 * Call DeviceCapabilitiesA since we later call 16bit stuff anyway
307 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
308 WORD fwCapability, LPWSTR pOutput,
309 const DEVMODEW *pDevMode)
311 LPDEVMODEA dmA = DEVMODEdupWtoA(GetProcessHeap(), pDevMode);
312 LPSTR pDeviceA = HEAP_strdupWtoA(GetProcessHeap(),0,pDevice);
313 LPSTR pPortA = HEAP_strdupWtoA(GetProcessHeap(),0,pPort);
314 INT ret;
316 if(pOutput && (fwCapability == DC_BINNAMES ||
317 fwCapability == DC_FILEDEPENDENCIES ||
318 fwCapability == DC_PAPERNAMES)) {
319 /* These need A -> W translation */
320 INT size = 0, i;
321 LPSTR pOutputA;
322 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, NULL,
323 dmA);
324 if(ret == -1)
325 return ret;
326 switch(fwCapability) {
327 case DC_BINNAMES:
328 size = 24;
329 break;
330 case DC_PAPERNAMES:
331 case DC_FILEDEPENDENCIES:
332 size = 64;
333 break;
335 pOutputA = HeapAlloc(GetProcessHeap(), 0, size * ret);
336 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability, pOutputA,
337 dmA);
338 for(i = 0; i < ret; i++)
339 MultiByteToWideChar(CP_ACP, 0, pOutputA + (i * size), -1,
340 pOutput + (i * size), size);
341 HeapFree(GetProcessHeap(), 0, pOutputA);
342 } else {
343 ret = DeviceCapabilitiesA(pDeviceA, pPortA, fwCapability,
344 (LPSTR)pOutput, dmA);
346 HeapFree(GetProcessHeap(),0,pPortA);
347 HeapFree(GetProcessHeap(),0,pDeviceA);
348 HeapFree(GetProcessHeap(),0,dmA);
349 return ret;
352 /******************************************************************
353 * DocumentPropertiesA [WINSPOOL.155]
356 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
357 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
358 LPDEVMODEA pDevModeInput,DWORD fMode )
360 LPOPENEDPRINTER lpOpenedPrinter;
361 LPSTR lpName = pDeviceName;
362 LONG ret;
364 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
365 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
368 if(!pDeviceName) {
369 LPWSTR lpNameW;
370 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
371 if(!lpOpenedPrinter) {
372 SetLastError(ERROR_INVALID_HANDLE);
373 return -1;
375 lpNameW = lpOpenedPrinter->lpsPrinterName;
376 lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
379 ret = GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
380 pDevModeInput, NULL, fMode);
382 if(!pDeviceName)
383 HeapFree(GetProcessHeap(),0,lpName);
384 return ret;
388 /*****************************************************************************
389 * DocumentPropertiesW
391 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
392 LPWSTR pDeviceName,
393 LPDEVMODEW pDevModeOutput,
394 LPDEVMODEW pDevModeInput, DWORD fMode)
397 LPSTR pDeviceNameA = HEAP_strdupWtoA(GetProcessHeap(),0,pDeviceName);
398 LPDEVMODEA pDevModeInputA = DEVMODEdupWtoA(GetProcessHeap(),pDevModeInput);
399 LPDEVMODEA pDevModeOutputA = NULL;
400 LONG ret;
402 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
403 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
404 fMode);
405 if(pDevModeOutput) {
406 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, NULL, NULL, 0);
407 if(ret < 0) return ret;
408 pDevModeOutputA = HeapAlloc(GetProcessHeap(), 0, ret);
410 ret = DocumentPropertiesA(hWnd, hPrinter, pDeviceNameA, pDevModeOutputA,
411 pDevModeInputA, fMode);
412 if(pDevModeOutput) {
413 DEVMODEcpyAtoW(pDevModeOutput, pDevModeOutputA);
414 HeapFree(GetProcessHeap(),0,pDevModeOutputA);
416 if(fMode == 0 && ret > 0)
417 ret += (CCHDEVICENAME + CCHFORMNAME);
418 HeapFree(GetProcessHeap(),0,pDevModeInputA);
419 HeapFree(GetProcessHeap(),0,pDeviceNameA);
420 return ret;
423 /******************************************************************
424 * OpenPrinterA [WINSPOOL.196]
427 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
428 LPPRINTER_DEFAULTSA pDefault)
430 LPWSTR lpPrinterNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpPrinterName);
431 PRINTER_DEFAULTSW DefaultW, *pDefaultW = NULL;
432 BOOL ret;
434 if(pDefault) {
435 DefaultW.pDatatype = HEAP_strdupAtoW(GetProcessHeap(), 0,
436 pDefault->pDatatype);
437 DefaultW.pDevMode = DEVMODEdupAtoW(GetProcessHeap(),
438 pDefault->pDevMode);
439 DefaultW.DesiredAccess = pDefault->DesiredAccess;
440 pDefaultW = &DefaultW;
442 ret = OpenPrinterW(lpPrinterNameW, phPrinter, pDefaultW);
443 if(pDefault) {
444 HeapFree(GetProcessHeap(), 0, DefaultW.pDatatype);
445 HeapFree(GetProcessHeap(), 0, DefaultW.pDevMode);
447 HeapFree(GetProcessHeap(), 0, lpPrinterNameW);
448 return ret;
451 /******************************************************************
452 * OpenPrinterW [WINSPOOL.197]
455 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
456 LPPRINTER_DEFAULTSW pDefault)
458 LPOPENEDPRINTER lpOpenedPrinter;
459 HKEY hkeyPrinters, hkeyPrinter;
461 if (!lpPrinterName) {
462 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault);
463 SetLastError(ERROR_INVALID_PARAMETER);
464 return FALSE;
467 TRACE("(printerName: %s, pDefault %p)\n", debugstr_w(lpPrinterName),
468 pDefault);
470 /* Check Printer exists */
471 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
472 ERROR_SUCCESS) {
473 ERR("Can't create Printers key\n");
474 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
475 return FALSE;
478 if(RegOpenKeyW(hkeyPrinters, lpPrinterName, &hkeyPrinter)
479 != ERROR_SUCCESS) {
480 WARN("Can't find printer %s in registry\n", debugstr_w(lpPrinterName));
481 RegCloseKey(hkeyPrinters);
482 SetLastError(ERROR_INVALID_PARAMETER);
483 return FALSE;
485 RegCloseKey(hkeyPrinter);
486 RegCloseKey(hkeyPrinters);
488 if(!phPrinter) /* This seems to be what win95 does anyway */
489 return TRUE;
491 /* Get a place in the opened printer buffer*/
492 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntry();
493 if(!lpOpenedPrinter) {
494 ERR("Can't allocate printer slot\n");
495 SetLastError(ERROR_OUTOFMEMORY);
496 return FALSE;
499 /* Get the name of the printer */
500 lpOpenedPrinter->lpsPrinterName =
501 HEAP_strdupW( GetProcessHeap(), 0, lpPrinterName );
503 /* Get the unique handle of the printer*/
504 *phPrinter = lpOpenedPrinter->hPrinter;
506 if (pDefault != NULL)
507 FIXME("Not handling pDefault\n");
509 return TRUE;
512 /******************************************************************
513 * AddMonitorA [WINSPOOL.107]
516 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
518 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
519 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
520 return FALSE;
523 /******************************************************************
524 * DeletePrinterDriverA [WINSPOOL.146]
527 BOOL WINAPI
528 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
530 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
531 debugstr_a(pDriverName));
532 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
533 return FALSE;
537 /******************************************************************
538 * DeleteMonitorA [WINSPOOL.135]
541 BOOL WINAPI
542 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
544 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
545 debugstr_a(pMonitorName));
546 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
547 return FALSE;
551 /******************************************************************
552 * DeletePortA [WINSPOOL.137]
555 BOOL WINAPI
556 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
558 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
559 debugstr_a(pPortName));
560 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
561 return FALSE;
564 /******************************************************************************
565 * SetPrinterW [WINSPOOL.214]
567 BOOL WINAPI
568 SetPrinterW(
569 HANDLE hPrinter,
570 DWORD Level,
571 LPBYTE pPrinter,
572 DWORD Command) {
574 FIXME("():stub\n");
575 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
576 return FALSE;
579 /******************************************************************************
580 * WritePrinter [WINSPOOL.223]
582 BOOL WINAPI
583 WritePrinter(
584 HANDLE hPrinter,
585 LPVOID pBuf,
586 DWORD cbBuf,
587 LPDWORD pcWritten) {
589 FIXME("():stub\n");
590 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
591 return FALSE;
594 /*****************************************************************************
595 * AddFormA [WINSPOOL.103]
597 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
599 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
600 return 1;
603 /*****************************************************************************
604 * AddFormW [WINSPOOL.104]
606 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
608 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
609 return 1;
612 /*****************************************************************************
613 * AddJobA [WINSPOOL.105]
615 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
616 DWORD cbBuf, LPDWORD pcbNeeded)
618 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
619 pcbNeeded);
620 return 1;
623 /*****************************************************************************
624 * AddJobW [WINSPOOL.106]
626 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
627 LPDWORD pcbNeeded)
629 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
630 pcbNeeded);
631 return 1;
634 /*****************************************************************************
635 * AddPrinterW [WINSPOOL.122]
637 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
639 PRINTER_INFO_2W *pi = (PRINTER_INFO_2W *) pPrinter;
640 LPDEVMODEA dmA;
641 LPDEVMODEW dmW;
642 HANDLE retval;
643 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
644 LONG size;
646 TRACE("(%s,%ld,%p)\n", debugstr_w(pName), Level, pPrinter);
648 if(pName != NULL) {
649 FIXME("pName = %s - unsupported\n", debugstr_w(pName));
650 SetLastError(ERROR_INVALID_PARAMETER);
651 return 0;
653 if(Level != 2) {
654 WARN("Level = %ld\n", Level);
655 SetLastError(ERROR_INVALID_LEVEL);
656 return 0;
658 if(!pPrinter) {
659 SetLastError(ERROR_INVALID_PARAMETER);
660 return 0;
662 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
663 ERROR_SUCCESS) {
664 ERR("Can't create Printers key\n");
665 return 0;
667 if(RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
668 ERROR_SUCCESS) {
669 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
670 RegCloseKey(hkeyPrinter);
671 RegCloseKey(hkeyPrinters);
672 return 0;
674 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
675 ERROR_SUCCESS) {
676 ERR("Can't create Drivers key\n");
677 RegCloseKey(hkeyPrinters);
678 return 0;
680 if(RegOpenKeyW(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
681 ERROR_SUCCESS) {
682 WARN("Can't find driver %s\n", debugstr_w(pi->pDriverName));
683 RegCloseKey(hkeyPrinters);
684 RegCloseKey(hkeyDrivers);
685 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
686 return 0;
688 RegCloseKey(hkeyDriver);
689 RegCloseKey(hkeyDrivers);
691 if(lstrcmpiW(pi->pPrintProcessor, WinPrintW)) { /* FIXME */
692 WARN("Can't find processor %s\n", debugstr_w(pi->pPrintProcessor));
693 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
694 RegCloseKey(hkeyPrinters);
695 return 0;
698 /* See if we can load the driver. We may need the devmode structure anyway
700 size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0);
701 if(size < 0) {
702 WARN("DocumentProperties fails\n");
703 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
704 return 0;
706 if(pi->pDevMode) {
707 dmW = pi->pDevMode;
708 } else {
709 dmW = HeapAlloc(GetProcessHeap(), 0, size);
710 DocumentPropertiesW(0, -1, pi->pPrinterName, dmW, NULL, DM_OUT_BUFFER);
713 if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
714 ERROR_SUCCESS) {
715 WARN("Can't create printer %s\n", debugstr_w(pi->pPrinterName));
716 SetLastError(ERROR_INVALID_PRINTER_NAME);
717 RegCloseKey(hkeyPrinters);
718 if(!pi->pDevMode)
719 HeapFree(GetProcessHeap(), 0, dmW);
720 return 0;
722 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
723 (LPBYTE)&pi->Attributes, sizeof(DWORD));
724 RegSetValueExW(hkeyPrinter, DatatypeW, 0, REG_SZ, (LPBYTE)pi->pDatatype,
727 /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does
728 and we support these drivers. NT writes DEVMODEW so somehow
729 we'll need to distinguish between these when we support NT
730 drivers */
731 dmA = DEVMODEdupWtoA(GetProcessHeap(), dmW);
732 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, (LPBYTE)dmA,
733 dmA->dmSize + dmA->dmDriverExtra);
734 HeapFree(GetProcessHeap(), 0, dmA);
735 if(!pi->pDevMode)
736 HeapFree(GetProcessHeap(), 0, dmW);
737 RegSetValueExW(hkeyPrinter, DescriptionW, 0, REG_SZ, (LPBYTE)pi->pComment,
739 RegSetValueExW(hkeyPrinter, LocationW, 0, REG_SZ, (LPBYTE)pi->pLocation,
741 RegSetValueExW(hkeyPrinter, NameW, 0, REG_SZ, (LPBYTE)pi->pPrinterName, 0);
742 RegSetValueExW(hkeyPrinter, ParametersW, 0, REG_SZ,
743 (LPBYTE)pi->pParameters, 0);
744 RegSetValueExW(hkeyPrinter, PortW, 0, REG_SZ, (LPBYTE)pi->pPortName, 0);
745 RegSetValueExW(hkeyPrinter, Print_ProcessorW, 0, REG_SZ,
746 (LPBYTE)pi->pPrintProcessor, 0);
747 RegSetValueExW(hkeyPrinter, Printer_DriverW, 0, REG_SZ,
748 (LPBYTE)pi->pDriverName, 0);
749 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
750 (LPBYTE)&pi->Priority, sizeof(DWORD));
751 RegSetValueExW(hkeyPrinter, Separator_FileW, 0, REG_SZ,
752 (LPBYTE)pi->pSepFile, 0);
753 RegSetValueExW(hkeyPrinter, Share_NameW, 0, REG_SZ, (LPBYTE)pi->pShareName,
755 RegSetValueExA(hkeyPrinter, "StartTime", 0, REG_DWORD,
756 (LPBYTE)&pi->StartTime, sizeof(DWORD));
757 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
758 (LPBYTE)&pi->Status, sizeof(DWORD));
759 RegSetValueExA(hkeyPrinter, "UntilTime", 0, REG_DWORD,
760 (LPBYTE)&pi->UntilTime, sizeof(DWORD));
762 RegCloseKey(hkeyPrinter);
763 RegCloseKey(hkeyPrinters);
764 if(!OpenPrinterW(pi->pPrinterName, &retval, NULL)) {
765 ERR("OpenPrinter failing\n");
766 return 0;
768 return retval;
771 /*****************************************************************************
772 * AddPrinterA [WINSPOOL.117]
774 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
776 WCHAR *pNameW;
777 PRINTER_INFO_2W *piW;
778 PRINTER_INFO_2A *piA = (PRINTER_INFO_2A*)pPrinter;
779 HANDLE ret;
781 TRACE("(%s,%ld,%p): stub\n", debugstr_a(pName), Level, pPrinter);
782 if(Level != 2) {
783 WARN("Level = %ld\n", Level);
784 SetLastError(ERROR_INVALID_LEVEL);
785 return 0;
787 pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
788 piW = PRINTER_INFO_2AtoW(GetProcessHeap(), piA);
790 ret = AddPrinterW(pNameW, Level, (LPBYTE)piW);
792 FREE_PRINTER_INFO_2W(GetProcessHeap(), piW);
793 HeapFree(GetProcessHeap(),0,pNameW);
794 return ret;
798 /*****************************************************************************
799 * ClosePrinter [WINSPOOL.126]
801 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
803 LPOPENEDPRINTER lpOpenedPrinter;
805 TRACE("Handle %d\n", hPrinter);
807 if (!pOpenedPrinterDPA)
808 return FALSE;
810 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
812 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
813 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
814 lpOpenedPrinter->lpsPrinterName = NULL;
815 lpOpenedPrinter->hPrinter = -1;
817 return TRUE;
819 return FALSE;
822 /*****************************************************************************
823 * DeleteFormA [WINSPOOL.133]
825 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
827 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
828 return 1;
831 /*****************************************************************************
832 * DeleteFormW [WINSPOOL.134]
834 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
836 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
837 return 1;
840 /*****************************************************************************
841 * DeletePrinter [WINSPOOL.143]
843 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
845 LPWSTR lpNameW;
846 HKEY hkeyPrinters;
848 LPOPENEDPRINTER lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
849 if(!lpOpenedPrinter) {
850 SetLastError(ERROR_INVALID_HANDLE);
851 return FALSE;
853 lpNameW = lpOpenedPrinter->lpsPrinterName;
854 if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
855 ERROR_SUCCESS) {
856 ERR("Can't open Printers key\n");
857 return 0;
860 /* This should use a recursive delete see Q142491 or SHDeleteKey */
861 if(RegDeleteKeyW(hkeyPrinters, lpNameW) == ERROR_SUCCESS) {
862 SetLastError(ERROR_PRINTER_NOT_FOUND); /* ?? */
863 RegCloseKey(hkeyPrinters);
864 return 0;
867 ClosePrinter(hPrinter);
868 return TRUE;
871 /*****************************************************************************
872 * SetPrinterA [WINSPOOL.211]
874 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
875 DWORD Command)
877 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
878 return FALSE;
881 /*****************************************************************************
882 * SetJobA [WINSPOOL.209]
884 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
885 LPBYTE pJob, DWORD Command)
887 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
888 Command);
889 return FALSE;
892 /*****************************************************************************
893 * SetJobW [WINSPOOL.210]
895 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
896 LPBYTE pJob, DWORD Command)
898 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
899 Command);
900 return FALSE;
903 /*****************************************************************************
904 * GetFormA [WINSPOOL.181]
906 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
907 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
909 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
910 Level,pForm,cbBuf,pcbNeeded);
911 return FALSE;
914 /*****************************************************************************
915 * GetFormW [WINSPOOL.182]
917 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
918 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
920 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
921 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
922 return FALSE;
925 /*****************************************************************************
926 * SetFormA [WINSPOOL.207]
928 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
929 LPBYTE pForm)
931 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
932 return FALSE;
935 /*****************************************************************************
936 * SetFormW [WINSPOOL.208]
938 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
939 LPBYTE pForm)
941 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
942 return FALSE;
945 /*****************************************************************************
946 * ReadPrinter [WINSPOOL.202]
948 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
949 LPDWORD pNoBytesRead)
951 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
952 return FALSE;
955 /*****************************************************************************
956 * ResetPrinterA [WINSPOOL.203]
958 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
960 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
961 return FALSE;
964 /*****************************************************************************
965 * ResetPrinterW [WINSPOOL.204]
967 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
969 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
970 return FALSE;
973 /*****************************************************************************
974 * WINSPOOL_GetDWORDFromReg
976 * Return DWORD associated with ValueName from hkey.
978 static DWORD WINSPOOL_GetDWORDFromReg(HKEY hkey, LPCSTR ValueName)
980 DWORD sz = sizeof(DWORD), type, value = 0;
981 LONG ret;
983 ret = RegQueryValueExA(hkey, ValueName, 0, &type, (LPBYTE)&value, &sz);
985 if(ret != ERROR_SUCCESS) {
986 WARN("Got ret = %ld on name %s\n", ret, ValueName);
987 return 0;
989 if(type != REG_DWORD) {
990 ERR("Got type %ld\n", type);
991 return 0;
993 return value;
996 /*****************************************************************************
997 * WINSPOOL_GetStringFromReg
999 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1000 * String is stored either as unicode or ascii.
1001 * Bit of a hack here to get the ValueName if we want ascii.
1003 static BOOL WINSPOOL_GetStringFromReg(HKEY hkey, LPCWSTR ValueName, LPBYTE ptr,
1004 DWORD buflen, DWORD *needed,
1005 BOOL unicode)
1007 DWORD sz = buflen, type;
1008 LONG ret;
1010 if(unicode)
1011 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1012 else {
1013 LPSTR ValueNameA = HEAP_strdupWtoA(GetProcessHeap(),0,ValueName);
1014 ret = RegQueryValueExA(hkey, ValueNameA, 0, &type, ptr, &sz);
1015 HeapFree(GetProcessHeap(),0,ValueNameA);
1017 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1018 WARN("Got ret = %ld\n", ret);
1019 *needed = 0;
1020 return FALSE;
1022 *needed = sz;
1023 return TRUE;
1026 /*****************************************************************************
1027 * WINSPOOL_GetDevModeFromReg
1029 * Get ValueName from hkey storing result in ptr. buflen is space left in ptr
1030 * DevMode is stored either as unicode or ascii.
1032 static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName,
1033 LPBYTE ptr,
1034 DWORD buflen, DWORD *needed,
1035 BOOL unicode)
1037 DWORD sz = buflen, type;
1038 LONG ret;
1040 if (ptr) memset(ptr, 0, sizeof(DEVMODEA));
1041 ret = RegQueryValueExW(hkey, ValueName, 0, &type, ptr, &sz);
1042 if ((ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA)) sz = 0;
1043 if (sz < sizeof(DEVMODEA))
1045 ERR("corrupted registry for %s\n", debugstr_w(ValueName));
1046 sz = sizeof(DEVMODEA);
1048 /* ensures that dmSize is not erratically bogus if registry is invalid */
1049 if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA))
1050 ((DEVMODEA*)ptr)->dmSize = sizeof(DEVMODEA);
1051 if(unicode) {
1052 sz += (CCHDEVICENAME + CCHFORMNAME);
1053 if(buflen >= sz) {
1054 DEVMODEW *dmW = DEVMODEdupAtoW(GetProcessHeap(), (DEVMODEA*)ptr);
1055 memcpy(ptr, dmW, sz);
1056 HeapFree(GetProcessHeap(),0,dmW);
1059 *needed = sz;
1060 return TRUE;
1063 /*********************************************************************
1064 * WINSPOOL_GetPrinter_2
1066 * Fills out a PRINTER_INFO_2A|W struct storing the strings in buf.
1067 * The strings are either stored as unicode or ascii.
1069 static BOOL WINSPOOL_GetPrinter_2(HKEY hkeyPrinter, PRINTER_INFO_2W *pi2,
1070 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1071 BOOL unicode)
1073 DWORD size, left = cbBuf;
1074 BOOL space = (cbBuf > 0);
1075 LPBYTE ptr = buf;
1077 *pcbNeeded = 0;
1079 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1080 unicode)) {
1081 if(space && size <= left) {
1082 pi2->pPrinterName = (LPWSTR)ptr;
1083 ptr += size;
1084 left -= size;
1085 } else
1086 space = FALSE;
1087 *pcbNeeded += size;
1089 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Share_NameW, ptr, left, &size,
1090 unicode)) {
1091 if(space && size <= left) {
1092 pi2->pShareName = (LPWSTR)ptr;
1093 ptr += size;
1094 left -= size;
1095 } else
1096 space = FALSE;
1097 *pcbNeeded += size;
1099 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1100 unicode)) {
1101 if(space && size <= left) {
1102 pi2->pPortName = (LPWSTR)ptr;
1103 ptr += size;
1104 left -= size;
1105 } else
1106 space = FALSE;
1107 *pcbNeeded += size;
1109 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Printer_DriverW, ptr, left,
1110 &size, unicode)) {
1111 if(space && size <= left) {
1112 pi2->pDriverName = (LPWSTR)ptr;
1113 ptr += size;
1114 left -= size;
1115 } else
1116 space = FALSE;
1117 *pcbNeeded += size;
1119 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DescriptionW, ptr, left, &size,
1120 unicode)) {
1121 if(space && size <= left) {
1122 pi2->pComment = (LPWSTR)ptr;
1123 ptr += size;
1124 left -= size;
1125 } else
1126 space = FALSE;
1127 *pcbNeeded += size;
1129 if(WINSPOOL_GetStringFromReg(hkeyPrinter, LocationW, ptr, left, &size,
1130 unicode)) {
1131 if(space && size <= left) {
1132 pi2->pLocation = (LPWSTR)ptr;
1133 ptr += size;
1134 left -= size;
1135 } else
1136 space = FALSE;
1137 *pcbNeeded += size;
1139 if(WINSPOOL_GetDevModeFromReg(hkeyPrinter, Default_DevModeW, ptr, left,
1140 &size, unicode)) {
1141 if(space && size <= left) {
1142 pi2->pDevMode = (LPDEVMODEW)ptr;
1143 ptr += size;
1144 left -= size;
1145 } else
1146 space = FALSE;
1147 *pcbNeeded += size;
1149 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Separator_FileW, ptr, left,
1150 &size, unicode)) {
1151 if(space && size <= left) {
1152 pi2->pSepFile = (LPWSTR)ptr;
1153 ptr += size;
1154 left -= size;
1155 } else
1156 space = FALSE;
1157 *pcbNeeded += size;
1159 if(WINSPOOL_GetStringFromReg(hkeyPrinter, Print_ProcessorW, ptr, left,
1160 &size, unicode)) {
1161 if(space && size <= left) {
1162 pi2->pPrintProcessor = (LPWSTR)ptr;
1163 ptr += size;
1164 left -= size;
1165 } else
1166 space = FALSE;
1167 *pcbNeeded += size;
1169 if(WINSPOOL_GetStringFromReg(hkeyPrinter, DatatypeW, ptr, left,
1170 &size, unicode)) {
1171 if(space && size <= left) {
1172 pi2->pDatatype = (LPWSTR)ptr;
1173 ptr += size;
1174 left -= size;
1175 } else
1176 space = FALSE;
1177 *pcbNeeded += size;
1179 if(WINSPOOL_GetStringFromReg(hkeyPrinter, ParametersW, ptr, left,
1180 &size, unicode)) {
1181 if(space && size <= left) {
1182 pi2->pParameters = (LPWSTR)ptr;
1183 ptr += size;
1184 left -= size;
1185 } else
1186 space = FALSE;
1187 *pcbNeeded += size;
1189 if(pi2) {
1190 pi2->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1191 pi2->Priority = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Priority");
1192 pi2->DefaultPriority = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1193 "Default Priority");
1194 pi2->StartTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "StartTime");
1195 pi2->UntilTime = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "UntilTime");
1198 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1199 memset(pi2, 0, sizeof(*pi2));
1201 return space;
1204 /*********************************************************************
1205 * WINSPOOL_GetPrinter_4
1207 * Fills out a PRINTER_INFO_4 struct storing the strings in buf.
1209 static BOOL WINSPOOL_GetPrinter_4(HKEY hkeyPrinter, PRINTER_INFO_4W *pi4,
1210 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1211 BOOL unicode)
1213 DWORD size, left = cbBuf;
1214 BOOL space = (cbBuf > 0);
1215 LPBYTE ptr = buf;
1217 *pcbNeeded = 0;
1219 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1220 unicode)) {
1221 if(space && size <= left) {
1222 pi4->pPrinterName = (LPWSTR)ptr;
1223 ptr += size;
1224 left -= size;
1225 } else
1226 space = FALSE;
1227 *pcbNeeded += size;
1229 if(pi4) {
1230 pi4->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1233 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1234 memset(pi4, 0, sizeof(*pi4));
1236 return space;
1239 /*********************************************************************
1240 * WINSPOOL_GetPrinter_5
1242 * Fills out a PRINTER_INFO_5 struct storing the strings in buf.
1244 static BOOL WINSPOOL_GetPrinter_5(HKEY hkeyPrinter, PRINTER_INFO_5W *pi5,
1245 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded,
1246 BOOL unicode)
1248 DWORD size, left = cbBuf;
1249 BOOL space = (cbBuf > 0);
1250 LPBYTE ptr = buf;
1252 *pcbNeeded = 0;
1254 if(WINSPOOL_GetStringFromReg(hkeyPrinter, NameW, ptr, left, &size,
1255 unicode)) {
1256 if(space && size <= left) {
1257 pi5->pPrinterName = (LPWSTR)ptr;
1258 ptr += size;
1259 left -= size;
1260 } else
1261 space = FALSE;
1262 *pcbNeeded += size;
1264 if(WINSPOOL_GetStringFromReg(hkeyPrinter, PortW, ptr, left, &size,
1265 unicode)) {
1266 if(space && size <= left) {
1267 pi5->pPortName = (LPWSTR)ptr;
1268 ptr += size;
1269 left -= size;
1270 } else
1271 space = FALSE;
1272 *pcbNeeded += size;
1274 if(pi5) {
1275 pi5->Attributes = WINSPOOL_GetDWORDFromReg(hkeyPrinter, "Attributes");
1276 pi5->DeviceNotSelectedTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1277 "dnsTimeout");
1278 pi5->TransmissionRetryTimeout = WINSPOOL_GetDWORDFromReg(hkeyPrinter,
1279 "txTimeout");
1282 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1283 memset(pi5, 0, sizeof(*pi5));
1285 return space;
1288 /*****************************************************************************
1289 * WINSPOOL_GetPrinter
1291 * Implementation of GetPrinterA|W. Relies on PRINTER_INFO_*W being
1292 * essentially the same as PRINTER_INFO_*A. i.e. the structure itself is
1293 * just a collection of pointers to strings.
1295 static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1296 DWORD cbBuf, LPDWORD pcbNeeded, BOOL unicode)
1298 OPENEDPRINTER *lpOpenedPrinter;
1299 DWORD size, needed = 0;
1300 LPBYTE ptr = NULL;
1301 HKEY hkeyPrinter, hkeyPrinters;
1302 BOOL ret;
1304 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1306 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1307 if(!lpOpenedPrinter) {
1308 SetLastError(ERROR_INVALID_HANDLE);
1309 return FALSE;
1311 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1312 ERROR_SUCCESS) {
1313 ERR("Can't create Printers key\n");
1314 return FALSE;
1316 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1317 != ERROR_SUCCESS) {
1318 ERR("Can't find opened printer %s in registry\n",
1319 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1320 RegCloseKey(hkeyPrinters);
1321 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1322 return FALSE;
1325 switch(Level) {
1326 case 2:
1328 PRINTER_INFO_2W *pi2 = (PRINTER_INFO_2W *)pPrinter;
1330 size = sizeof(PRINTER_INFO_2W);
1331 if(size <= cbBuf) {
1332 ptr = pPrinter + size;
1333 cbBuf -= size;
1334 memset(pPrinter, 0, size);
1335 } else {
1336 pi2 = NULL;
1337 cbBuf = 0;
1339 ret = WINSPOOL_GetPrinter_2(hkeyPrinter, pi2, ptr, cbBuf, &needed,
1340 unicode);
1341 needed += size;
1342 break;
1345 case 4:
1347 PRINTER_INFO_4W *pi4 = (PRINTER_INFO_4W *)pPrinter;
1349 size = sizeof(PRINTER_INFO_4W);
1350 if(size <= cbBuf) {
1351 ptr = pPrinter + size;
1352 cbBuf -= size;
1353 memset(pPrinter, 0, size);
1354 } else {
1355 pi4 = NULL;
1356 cbBuf = 0;
1358 ret = WINSPOOL_GetPrinter_4(hkeyPrinter, pi4, ptr, cbBuf, &needed,
1359 unicode);
1360 needed += size;
1361 break;
1365 case 5:
1367 PRINTER_INFO_5W *pi5 = (PRINTER_INFO_5W *)pPrinter;
1369 size = sizeof(PRINTER_INFO_5W);
1370 if(size <= cbBuf) {
1371 ptr = pPrinter + size;
1372 cbBuf -= size;
1373 memset(pPrinter, 0, size);
1374 } else {
1375 pi5 = NULL;
1376 cbBuf = 0;
1379 ret = WINSPOOL_GetPrinter_5(hkeyPrinter, pi5, ptr, cbBuf, &needed,
1380 unicode);
1381 needed += size;
1382 break;
1385 default:
1386 FIXME("Unimplemented level %ld\n", Level);
1387 SetLastError(ERROR_INVALID_LEVEL);
1388 RegCloseKey(hkeyPrinters);
1389 RegCloseKey(hkeyPrinter);
1390 return FALSE;
1393 RegCloseKey(hkeyPrinter);
1394 RegCloseKey(hkeyPrinters);
1396 TRACE("returing %d needed = %ld\n", ret, needed);
1397 if(pcbNeeded) *pcbNeeded = needed;
1398 if(!ret)
1399 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1400 return ret;
1403 /*****************************************************************************
1404 * GetPrinterW [WINSPOOL.194]
1406 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1407 DWORD cbBuf, LPDWORD pcbNeeded)
1409 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1410 TRUE);
1413 /*****************************************************************************
1414 * GetPrinterA [WINSPOOL.187]
1416 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1417 DWORD cbBuf, LPDWORD pcbNeeded)
1419 return WINSPOOL_GetPrinter(hPrinter, Level, pPrinter, cbBuf, pcbNeeded,
1420 FALSE);
1423 /*****************************************************************************
1424 * WINSPOOL_EnumPrinters
1426 * Implementation of EnumPrintersA|W
1428 static BOOL WINSPOOL_EnumPrinters(DWORD dwType, LPWSTR lpszName,
1429 DWORD dwLevel, LPBYTE lpbPrinters,
1430 DWORD cbBuf, LPDWORD lpdwNeeded,
1431 LPDWORD lpdwReturned, BOOL unicode)
1434 HKEY hkeyPrinters, hkeyPrinter;
1435 WCHAR PrinterName[255];
1436 DWORD needed = 0, number = 0;
1437 DWORD used, i, left;
1438 PBYTE pi, buf;
1440 if(lpbPrinters)
1441 memset(lpbPrinters, 0, cbBuf);
1442 if(lpdwReturned)
1443 *lpdwReturned = 0;
1445 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1446 FIXME("dwType = %08lx\n", dwType);
1447 SetLastError(ERROR_INVALID_FLAGS);
1448 return FALSE;
1451 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1452 ERROR_SUCCESS) {
1453 ERR("Can't create Printers key\n");
1454 return FALSE;
1457 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1458 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1459 RegCloseKey(hkeyPrinters);
1460 ERR("Can't query Printers key\n");
1461 return FALSE;
1463 TRACE("Found %ld printers\n", number);
1465 switch(dwLevel) {
1466 case 1:
1467 RegCloseKey(hkeyPrinters);
1468 if (lpdwReturned)
1469 *lpdwReturned = number;
1470 return TRUE;
1472 case 2:
1473 used = number * sizeof(PRINTER_INFO_2W);
1474 break;
1475 case 4:
1476 used = number * sizeof(PRINTER_INFO_4W);
1477 break;
1478 case 5:
1479 used = number * sizeof(PRINTER_INFO_5W);
1480 break;
1482 default:
1483 SetLastError(ERROR_INVALID_LEVEL);
1484 RegCloseKey(hkeyPrinters);
1485 return FALSE;
1487 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1489 for(i = 0; i < number; i++) {
1490 if(RegEnumKeyW(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1491 ERROR_SUCCESS) {
1492 ERR("Can't enum key number %ld\n", i);
1493 RegCloseKey(hkeyPrinters);
1494 return FALSE;
1496 TRACE("Printer %ld is %s\n", i, debugstr_w(PrinterName));
1497 if(RegOpenKeyW(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1498 ERROR_SUCCESS) {
1499 ERR("Can't open key %s\n", debugstr_w(PrinterName));
1500 RegCloseKey(hkeyPrinters);
1501 return FALSE;
1504 if(cbBuf > used) {
1505 buf = lpbPrinters + used;
1506 left = cbBuf - used;
1507 } else {
1508 buf = NULL;
1509 left = 0;
1512 switch(dwLevel) {
1513 case 2:
1514 WINSPOOL_GetPrinter_2(hkeyPrinter, (PRINTER_INFO_2W *)pi, buf,
1515 left, &needed, unicode);
1516 used += needed;
1517 if(pi) pi += sizeof(PRINTER_INFO_2W);
1518 break;
1519 case 4:
1520 WINSPOOL_GetPrinter_4(hkeyPrinter, (PRINTER_INFO_4W *)pi, buf,
1521 left, &needed, unicode);
1522 used += needed;
1523 if(pi) pi += sizeof(PRINTER_INFO_4W);
1524 break;
1525 case 5:
1526 WINSPOOL_GetPrinter_5(hkeyPrinter, (PRINTER_INFO_5W *)pi, buf,
1527 left, &needed, unicode);
1528 used += needed;
1529 if(pi) pi += sizeof(PRINTER_INFO_5W);
1530 break;
1531 default:
1532 ERR("Shouldn't be here!\n");
1533 RegCloseKey(hkeyPrinter);
1534 RegCloseKey(hkeyPrinters);
1535 return FALSE;
1537 RegCloseKey(hkeyPrinter);
1539 RegCloseKey(hkeyPrinters);
1541 if(lpdwNeeded)
1542 *lpdwNeeded = used;
1544 if(used > cbBuf) {
1545 if(lpbPrinters)
1546 memset(lpbPrinters, 0, cbBuf);
1547 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1548 return FALSE;
1550 if(lpdwReturned)
1551 *lpdwReturned = number;
1552 SetLastError(ERROR_SUCCESS);
1553 return TRUE;
1557 /******************************************************************
1558 * EnumPrintersW [WINSPOOL.175]
1560 * Enumerates the available printers, print servers and print
1561 * providers, depending on the specified flags, name and level.
1563 * RETURNS:
1565 * If level is set to 1:
1566 * Not implemented yet!
1567 * Returns TRUE with an empty list.
1569 * If level is set to 2:
1570 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1571 * Returns an array of PRINTER_INFO_2 data structures in the
1572 * lpbPrinters buffer. Note that according to MSDN also an
1573 * OpenPrinter should be performed on every remote printer.
1575 * If level is set to 4 (officially WinNT only):
1576 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
1577 * Fast: Only the registry is queried to retrieve printer names,
1578 * no connection to the driver is made.
1579 * Returns an array of PRINTER_INFO_4 data structures in the
1580 * lpbPrinters buffer.
1582 * If level is set to 5 (officially WinNT4/Win9x only):
1583 * Fast: Only the registry is queried to retrieve printer names,
1584 * no connection to the driver is made.
1585 * Returns an array of PRINTER_INFO_5 data structures in the
1586 * lpbPrinters buffer.
1588 * If level set to 3 or 6+:
1589 * returns zero (faillure!)
1591 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
1592 * for information.
1594 * BUGS:
1595 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
1596 * - Only levels 2, 4 and 5 are implemented at the moment.
1597 * - 16-bit printer drivers are not enumerated.
1598 * - Returned amount of bytes used/needed does not match the real Windoze
1599 * implementation (as in this implementation, all strings are part
1600 * of the buffer, whereas Win32 keeps them somewhere else)
1601 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1603 * NOTE:
1604 * - In a regular Wine installation, no registry settings for printers
1605 * exist, which makes this function return an empty list.
1607 BOOL WINAPI EnumPrintersW(
1608 DWORD dwType, /* Types of print objects to enumerate */
1609 LPWSTR lpszName, /* name of objects to enumerate */
1610 DWORD dwLevel, /* type of printer info structure */
1611 LPBYTE lpbPrinters, /* buffer which receives info */
1612 DWORD cbBuf, /* max size of buffer in bytes */
1613 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
1614 LPDWORD lpdwReturned /* number of entries returned */
1617 return WINSPOOL_EnumPrinters(dwType, lpszName, dwLevel, lpbPrinters, cbBuf,
1618 lpdwNeeded, lpdwReturned, TRUE);
1621 /******************************************************************
1622 * EnumPrintersA [WINSPOOL.174]
1625 BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
1626 DWORD dwLevel, LPBYTE lpbPrinters,
1627 DWORD cbBuf, LPDWORD lpdwNeeded,
1628 LPDWORD lpdwReturned)
1630 BOOL ret;
1631 LPWSTR lpszNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpszName);
1633 ret = WINSPOOL_EnumPrinters(dwType, lpszNameW, dwLevel, lpbPrinters, cbBuf,
1634 lpdwNeeded, lpdwReturned, FALSE);
1635 HeapFree(GetProcessHeap(),0,lpszNameW);
1636 return ret;
1640 /*****************************************************************************
1641 * WINSPOOL_GetPrinterDriver
1643 static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
1644 DWORD Level, LPBYTE pDriverInfo,
1645 DWORD cbBuf, LPDWORD pcbNeeded,
1646 BOOL unicode)
1648 OPENEDPRINTER *lpOpenedPrinter;
1649 WCHAR DriverName[100];
1650 DWORD ret, type, size, dw, needed = 0;
1651 LPBYTE ptr = NULL;
1652 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
1654 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
1655 Level,pDriverInfo,cbBuf, pcbNeeded);
1657 ZeroMemory(pDriverInfo, cbBuf);
1659 lpOpenedPrinter = WINSPOOL_GetOpenedPrinter(hPrinter);
1660 if(!lpOpenedPrinter) {
1661 SetLastError(ERROR_INVALID_HANDLE);
1662 return FALSE;
1664 if(pEnvironment) {
1665 FIXME("pEnvironment = %s\n", debugstr_w(pEnvironment));
1666 SetLastError(ERROR_INVALID_ENVIRONMENT);
1667 return FALSE;
1669 if(Level < 1 || Level > 3) {
1670 SetLastError(ERROR_INVALID_LEVEL);
1671 return FALSE;
1673 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1674 ERROR_SUCCESS) {
1675 ERR("Can't create Printers key\n");
1676 return FALSE;
1678 if(RegOpenKeyW(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1679 != ERROR_SUCCESS) {
1680 ERR("Can't find opened printer %s in registry\n",
1681 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1682 RegCloseKey(hkeyPrinters);
1683 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1684 return FALSE;
1686 size = sizeof(DriverName);
1687 ret = RegQueryValueExW(hkeyPrinter, Printer_DriverW, 0, &type,
1688 (LPBYTE)DriverName, &size);
1689 RegCloseKey(hkeyPrinter);
1690 RegCloseKey(hkeyPrinters);
1691 if(ret != ERROR_SUCCESS) {
1692 ERR("Can't get DriverName for printer %s\n",
1693 debugstr_w(lpOpenedPrinter->lpsPrinterName));
1694 return FALSE;
1696 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1697 ERROR_SUCCESS) {
1698 ERR("Can't create Drivers key\n");
1699 return FALSE;
1701 if(RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver)
1702 != ERROR_SUCCESS) {
1703 ERR("Can't find driver %s in registry\n", debugstr_w(DriverName));
1704 RegCloseKey(hkeyDrivers);
1705 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1706 return FALSE;
1709 switch(Level) {
1710 case 1:
1711 size = sizeof(DRIVER_INFO_1W);
1712 break;
1713 case 2:
1714 size = sizeof(DRIVER_INFO_2W);
1715 break;
1716 case 3:
1717 size = sizeof(DRIVER_INFO_3W);
1718 break;
1719 default:
1720 ERR("Invalid level\n");
1721 return FALSE;
1724 if(size <= cbBuf) {
1725 ptr = pDriverInfo + size;
1726 cbBuf -= size;
1727 } else
1728 cbBuf = 0;
1729 needed = size;
1731 if(unicode)
1732 size = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
1733 else
1734 size = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0, NULL,
1735 NULL);
1737 if(size <= cbBuf) {
1738 cbBuf -= size;
1739 if(unicode)
1740 strcpyW((LPWSTR)ptr, DriverName);
1741 else
1742 WideCharToMultiByte(CP_ACP, 0, DriverName, -1, ptr, size, NULL,
1743 NULL);
1744 if(Level == 1)
1745 ((DRIVER_INFO_1W *)pDriverInfo)->pName = (LPWSTR)ptr;
1746 else
1747 ((DRIVER_INFO_2W *)pDriverInfo)->pName = (LPWSTR)ptr;
1748 ptr += size;
1750 needed += size;
1752 if(Level > 1) {
1753 DRIVER_INFO_2W *di2 = (DRIVER_INFO_2W *)pDriverInfo;
1755 size = sizeof(dw);
1756 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw,
1757 &size) !=
1758 ERROR_SUCCESS)
1759 WARN("Can't get Version\n");
1760 else if(cbBuf)
1761 di2->cVersion = dw;
1763 if(!pEnvironment)
1764 pEnvironment = DefaultEnvironmentW;
1765 if(unicode)
1766 size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
1767 else
1768 size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
1769 NULL, NULL);
1770 if(size <= cbBuf) {
1771 cbBuf -= size;
1772 if(unicode)
1773 strcpyW((LPWSTR)ptr, pEnvironment);
1774 else
1775 WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, ptr, size,
1776 NULL, NULL);
1777 di2->pEnvironment = (LPWSTR)ptr;
1778 ptr += size;
1779 } else
1780 cbBuf = 0;
1781 needed += size;
1783 if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, ptr, cbBuf, &size,
1784 unicode)) {
1785 if(cbBuf && size <= cbBuf) {
1786 di2->pDriverPath = (LPWSTR)ptr;
1787 ptr += size;
1788 } else
1789 cbBuf = 0;
1790 needed += size;
1792 if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, ptr, cbBuf, &size,
1793 unicode)) {
1794 if(cbBuf && size <= cbBuf) {
1795 di2->pDataFile = (LPWSTR)ptr;
1796 ptr += size;
1797 } else
1798 cbBuf = 0;
1799 needed += size;
1801 if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, ptr,
1802 cbBuf, &size, unicode)) {
1803 if(cbBuf && size <= cbBuf) {
1804 di2->pConfigFile = (LPWSTR)ptr;
1805 ptr += size;
1806 } else
1807 cbBuf = 0;
1808 needed += size;
1811 if(Level > 2) {
1812 DRIVER_INFO_3W *di3 = (DRIVER_INFO_3W *)pDriverInfo;
1814 if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, ptr, cbBuf, &size,
1815 unicode)) {
1816 if(cbBuf && size <= cbBuf) {
1817 di3->pHelpFile = (LPWSTR)ptr;
1818 ptr += size;
1819 } else
1820 cbBuf = 0;
1821 needed += size;
1823 if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, ptr, cbBuf,
1824 &size, unicode)) {
1825 if(cbBuf && size <= cbBuf) {
1826 di3->pDependentFiles = (LPWSTR)ptr;
1827 ptr += size;
1828 } else
1829 cbBuf = 0;
1830 needed += size;
1832 if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, ptr, cbBuf, &size,
1833 unicode)) {
1834 if(cbBuf && size <= cbBuf) {
1835 di3->pMonitorName = (LPWSTR)ptr;
1836 ptr += size;
1837 } else
1838 cbBuf = 0;
1839 needed += size;
1841 if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, ptr, cbBuf, &size,
1842 unicode)) {
1843 if(cbBuf && size <= cbBuf) {
1844 di3->pDefaultDataType = (LPWSTR)ptr;
1845 ptr += size;
1846 } else
1847 cbBuf = 0;
1848 needed += size;
1851 RegCloseKey(hkeyDriver);
1852 RegCloseKey(hkeyDrivers);
1854 if(pcbNeeded) *pcbNeeded = needed;
1855 if(cbBuf) return TRUE;
1856 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1857 return FALSE;
1860 /*****************************************************************************
1861 * GetPrinterDriverA [WINSPOOL.190]
1863 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1864 DWORD Level, LPBYTE pDriverInfo,
1865 DWORD cbBuf, LPDWORD pcbNeeded)
1867 BOOL ret;
1868 LPWSTR pEnvW = HEAP_strdupAtoW(GetProcessHeap(),0,pEnvironment);
1869 ret = WINSPOOL_GetPrinterDriver(hPrinter, pEnvW, Level, pDriverInfo,
1870 cbBuf, pcbNeeded, FALSE);
1871 HeapFree(GetProcessHeap(),0,pEnvW);
1872 return ret;
1874 /*****************************************************************************
1875 * GetPrinterDriverW [WINSPOOL.193]
1877 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1878 DWORD Level, LPBYTE pDriverInfo,
1879 DWORD cbBuf, LPDWORD pcbNeeded)
1881 return WINSPOOL_GetPrinterDriver(hPrinter, pEnvironment, Level,
1882 pDriverInfo, cbBuf, pcbNeeded, TRUE);
1885 /*****************************************************************************
1886 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1888 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1889 DWORD Level, LPBYTE pDriverDirectory,
1890 DWORD cbBuf, LPDWORD pcbNeeded)
1892 DWORD needed;
1894 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1895 pDriverDirectory, cbBuf, pcbNeeded);
1896 if(pName != NULL) {
1897 FIXME("pName = `%s' - unsupported\n", pName);
1898 SetLastError(ERROR_INVALID_PARAMETER);
1899 return FALSE;
1901 if(pEnvironment != NULL) {
1902 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
1903 SetLastError(ERROR_INVALID_ENVIRONMENT);
1904 return FALSE;
1906 if(Level != 1) /* win95 ignores this so we just carry on */
1907 WARN("Level = %ld - assuming 1\n", Level);
1909 /* FIXME should read from registry */
1910 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
1911 needed++;
1912 if(pcbNeeded)
1913 *pcbNeeded = needed;
1914 if(needed > cbBuf) {
1915 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1916 return FALSE;
1918 return TRUE;
1922 /*****************************************************************************
1923 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1925 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
1926 DWORD Level, LPBYTE pDriverDirectory,
1927 DWORD cbBuf, LPDWORD pcbNeeded)
1929 LPSTR pNameA = NULL, pEnvironmentA = NULL;
1930 BOOL ret;
1932 if(pName)
1933 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
1934 if(pEnvironment)
1935 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
1936 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
1937 pDriverDirectory, cbBuf, pcbNeeded );
1938 if(pNameA)
1939 HeapFree( GetProcessHeap(), 0, pNameA );
1940 if(pEnvironmentA)
1941 HeapFree( GetProcessHeap(), 0, pEnvironment );
1943 return ret;
1946 /*****************************************************************************
1947 * AddPrinterDriverA [WINSPOOL.120]
1949 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
1951 DRIVER_INFO_3A di3;
1952 HKEY hkeyDrivers, hkeyName;
1954 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
1956 if(level != 2 && level != 3) {
1957 SetLastError(ERROR_INVALID_LEVEL);
1958 return FALSE;
1960 if(pName != NULL) {
1961 FIXME("pName= `%s' - unsupported\n", pName);
1962 SetLastError(ERROR_INVALID_PARAMETER);
1963 return FALSE;
1965 if(!pDriverInfo) {
1966 WARN("pDriverInfo == NULL");
1967 SetLastError(ERROR_INVALID_PARAMETER);
1968 return FALSE;
1971 if(level == 3)
1972 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
1973 else {
1974 memset(&di3, 0, sizeof(di3));
1975 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
1978 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
1979 !di3.pDataFile) {
1980 SetLastError(ERROR_INVALID_PARAMETER);
1981 return FALSE;
1983 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
1984 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
1985 if(!di3.pHelpFile) di3.pHelpFile = "";
1986 if(!di3.pMonitorName) di3.pMonitorName = "";
1988 if(di3.pEnvironment) {
1989 FIXME("pEnvironment = `%s'\n", di3.pEnvironment);
1990 SetLastError(ERROR_INVALID_ENVIRONMENT);
1991 return FALSE;
1993 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1994 ERROR_SUCCESS) {
1995 ERR("Can't create Drivers key\n");
1996 return FALSE;
1999 if(level == 2) { /* apparently can't overwrite with level2 */
2000 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
2001 RegCloseKey(hkeyName);
2002 RegCloseKey(hkeyDrivers);
2003 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
2004 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
2005 return FALSE;
2008 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
2009 RegCloseKey(hkeyDrivers);
2010 ERR("Can't create Name key\n");
2011 return FALSE;
2013 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
2015 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
2016 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
2017 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
2018 sizeof(DWORD));
2019 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
2020 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
2021 di3.pDependentFiles, 0);
2022 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
2023 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
2024 RegCloseKey(hkeyName);
2025 RegCloseKey(hkeyDrivers);
2027 return TRUE;
2029 /*****************************************************************************
2030 * AddPrinterDriverW [WINSPOOL.121]
2032 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
2033 LPBYTE pDriverInfo)
2035 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
2036 level,pDriverInfo);
2037 return FALSE;
2041 /*****************************************************************************
2042 * PrinterProperties [WINSPOOL.201]
2044 * Displays a dialog to set the properties of the printer.
2046 * RETURNS
2047 * nonzero on succes or zero on faillure
2049 * BUGS
2050 * implemented as stub only
2052 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
2053 HANDLE hPrinter /* handle to printer object */
2055 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
2056 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2057 return FALSE;
2060 /*****************************************************************************
2061 * EnumJobsA [WINSPOOL.162]
2064 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2065 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2066 LPDWORD pcReturned)
2068 FIXME("stub\n");
2069 if(pcbNeeded) *pcbNeeded = 0;
2070 if(pcReturned) *pcReturned = 0;
2071 return TRUE;
2075 /*****************************************************************************
2076 * EnumJobsW [WINSPOOL.163]
2079 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
2080 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
2081 LPDWORD pcReturned)
2083 FIXME("stub\n");
2084 if(pcbNeeded) *pcbNeeded = 0;
2085 if(pcReturned) *pcReturned = 0;
2086 return TRUE;