This patch initializes the return buffer used in GetPrinterDriverA to
[wine.git] / dlls / winspool / info.c
blobfac76bccf702e383ef2cfb2579c288cb4892e227
1 /*
2 * WINSPOOL functions
3 *
4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend, Huw D M Davies
7 */
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include "winspool.h"
13 #include "winbase.h"
14 #include "winerror.h"
15 #include "winreg.h"
16 #include "debugtools.h"
17 #include "heap.h"
18 #include "commctrl.h"
20 DEFAULT_DEBUG_CHANNEL(winspool)
22 CRITICAL_SECTION PRINT32_RegistryBlocker;
24 typedef struct _OPENEDPRINTERA
26 LPSTR lpsPrinterName;
27 HANDLE hPrinter;
28 LPPRINTER_DEFAULTSA lpDefault;
29 } OPENEDPRINTERA, *LPOPENEDPRINTERA;
31 /* The OpenedPrinter Table dynamic array */
32 static HDPA pOpenedPrinterDPA = NULL;
34 extern HDPA (WINAPI* WINSPOOL_DPA_CreateEx) (INT, HANDLE);
35 extern LPVOID (WINAPI* WINSPOOL_DPA_GetPtr) (const HDPA, INT);
36 extern INT (WINAPI* WINSPOOL_DPA_InsertPtr) (const HDPA, INT, LPVOID);
38 static char Printers[] =
39 "System\\CurrentControlSet\\control\\Print\\Printers\\";
40 static char Drivers[] =
41 "System\\CurrentControlSet\\control\\Print\\Environments\\Windows 4.0\\Drivers\\"; /* Hmm, well */
43 /******************************************************************
44 * WINSPOOL_GetOpenedPrinterEntryA
45 * Get the first place empty in the opened printer table
47 static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterEntryA()
49 int i;
50 LPOPENEDPRINTERA pOpenedPrinter;
53 * Create the opened printers' handle dynamic array.
55 if (!pOpenedPrinterDPA)
57 pOpenedPrinterDPA = WINSPOOL_DPA_CreateEx(10, GetProcessHeap());
58 for (i = 0; i < 10; i++)
60 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
61 HEAP_ZERO_MEMORY,
62 sizeof(OPENEDPRINTERA));
63 pOpenedPrinter->hPrinter = -1;
64 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
69 * Search for a handle not yet allocated.
71 for (i = 0; i < pOpenedPrinterDPA->nItemCount; i++)
73 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, i);
75 if (pOpenedPrinter->hPrinter == -1)
77 pOpenedPrinter->hPrinter = i + 1;
78 return pOpenedPrinter;
83 * Didn't find one, insert new element in the array.
85 if (i == pOpenedPrinterDPA->nItemCount)
87 pOpenedPrinter = HeapAlloc(GetProcessHeap(),
88 HEAP_ZERO_MEMORY,
89 sizeof(OPENEDPRINTERA));
90 pOpenedPrinter->hPrinter = i + 1;
91 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
92 return pOpenedPrinter;
95 return NULL;
98 /******************************************************************
99 * WINSPOOL_GetOpenedPrinterA
100 * Get the pointer to the opened printer referred by the handle
102 static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterA(int printerHandle)
104 LPOPENEDPRINTERA pOpenedPrinter;
106 if(!pOpenedPrinterDPA) return NULL;
107 if((printerHandle <=0) ||
108 (printerHandle > (pOpenedPrinterDPA->nItemCount - 1)))
109 return NULL;
111 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, printerHandle-1);
113 return pOpenedPrinter;
116 /******************************************************************
117 * DeviceCapabilities32A [WINSPOOL.151]
120 INT WINAPI DeviceCapabilitiesA(LPCSTR pDeivce,LPCSTR pPort, WORD cap,
121 LPSTR pOutput, LPDEVMODEA lpdm)
123 INT ret;
124 ret = GDI_CallDeviceCapabilities16(pDeivce, pPort, cap, pOutput, lpdm);
126 /* If DC_PAPERSIZE map POINT16s to POINTs */
127 if(ret != -1 && cap == DC_PAPERSIZE && pOutput) {
128 POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) );
129 INT i;
130 memcpy(tmp, pOutput, ret * sizeof(POINT16));
131 for(i = 0; i < ret; i++)
132 CONV_POINT16TO32(tmp + i, (POINT*)pOutput + i);
133 HeapFree( GetProcessHeap(), 0, tmp );
135 return ret;
139 /*****************************************************************************
140 * DeviceCapabilities32W
142 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
143 WORD fwCapability, LPWSTR pOutput,
144 const DEVMODEW *pDevMode)
146 FIXME("(%p,%p,%d,%p,%p): stub\n",
147 pDevice, pPort, fwCapability, pOutput, pDevMode);
148 return -1;
151 /******************************************************************
152 * DocumentProperties32A [WINSPOOL.155]
155 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
156 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
157 LPDEVMODEA pDevModeInput,DWORD fMode )
159 LPOPENEDPRINTERA lpOpenedPrinter;
160 LPSTR lpName = pDeviceName;
162 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
163 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
166 if(!pDeviceName) {
167 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
168 if(!lpOpenedPrinter) {
169 SetLastError(ERROR_INVALID_HANDLE);
170 return -1;
172 lpName = lpOpenedPrinter->lpsPrinterName;
175 return GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, "LPT1:",
176 pDevModeInput, NULL, fMode);
181 /*****************************************************************************
182 * DocumentProperties32W
184 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
185 LPWSTR pDeviceName,
186 LPDEVMODEW pDevModeOutput,
187 LPDEVMODEW pDevModeInput, DWORD fMode)
189 FIXME("(%d,%d,%s,%p,%p,%ld): stub\n",
190 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
191 fMode);
192 return -1;
196 /******************************************************************
197 * OpenPrinter32A [WINSPOOL.196]
200 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
201 LPPRINTER_DEFAULTSA pDefault)
203 /* Not implemented: use the DesiredAccess of pDefault to set
204 the access rights to the printer */
206 LPOPENEDPRINTERA lpOpenedPrinter;
207 HKEY hkeyPrinters, hkeyPrinter;
209 if (!lpPrinterName) {
210 WARN("(printerName: NULL, pDefault %p Ret: False\n", pDefault);
211 SetLastError(ERROR_INVALID_PARAMETER);
212 return FALSE;
215 TRACE("(printerName: %s, pDefault %p\n", lpPrinterName, pDefault);
217 /* Check Printer exists */
218 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
219 ERROR_SUCCESS) {
220 ERR("Can't create Printers key\n");
221 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
222 return FALSE;
225 if(RegOpenKeyA(hkeyPrinters, lpPrinterName, &hkeyPrinter)
226 != ERROR_SUCCESS) {
227 WARN("Can't find printer `%s' in registry\n", lpPrinterName);
228 RegCloseKey(hkeyPrinters);
229 SetLastError(ERROR_INVALID_PARAMETER);
230 return FALSE;
232 RegCloseKey(hkeyPrinter);
233 RegCloseKey(hkeyPrinters);
235 if(!phPrinter) /* This seems to be what win95 does anyway */
236 return TRUE;
238 /* Get a place in the opened printer buffer*/
239 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntryA();
240 if(!lpOpenedPrinter) {
241 ERR("Can't allocate printer slot\n");
242 SetLastError(ERROR_OUTOFMEMORY);
243 return FALSE;
246 /* Get the name of the printer */
247 lpOpenedPrinter->lpsPrinterName =
248 HEAP_strdupA( GetProcessHeap(), 0, lpPrinterName );
250 /* Get the unique handle of the printer*/
251 *phPrinter = lpOpenedPrinter->hPrinter;
253 if (pDefault != NULL) {
254 lpOpenedPrinter->lpDefault =
255 HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA));
256 lpOpenedPrinter->lpDefault->pDevMode =
257 HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA));
258 memcpy(lpOpenedPrinter->lpDefault->pDevMode, pDefault->pDevMode,
259 sizeof(DEVMODEA));
260 lpOpenedPrinter->lpDefault->pDatatype =
261 HEAP_strdupA( GetProcessHeap(), 0, pDefault->pDatatype );
262 lpOpenedPrinter->lpDefault->DesiredAccess =
263 pDefault->DesiredAccess;
266 return TRUE;
270 /******************************************************************
271 * OpenPrinter32W [WINSPOOL.197]
274 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
275 LPPRINTER_DEFAULTSW pDefault)
277 FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
278 pDefault);
279 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
280 return FALSE;
283 /******************************************************************
284 * AddMonitor32A [WINSPOOL.107]
287 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
289 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
290 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
291 return FALSE;
294 /******************************************************************
295 * DeletePrinterDriver32A [WINSPOOL.146]
298 BOOL WINAPI
299 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
301 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
302 debugstr_a(pDriverName));
303 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
304 return FALSE;
308 /******************************************************************
309 * DeleteMonitor32A [WINSPOOL.135]
312 BOOL WINAPI
313 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
315 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
316 debugstr_a(pMonitorName));
317 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
318 return FALSE;
322 /******************************************************************
323 * DeletePort32A [WINSPOOL.137]
326 BOOL WINAPI
327 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
329 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
330 debugstr_a(pPortName));
331 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
332 return FALSE;
335 /******************************************************************************
336 * SetPrinter32W [WINSPOOL.214]
338 BOOL WINAPI
339 SetPrinterW(
340 HANDLE hPrinter,
341 DWORD Level,
342 LPBYTE pPrinter,
343 DWORD Command) {
345 FIXME("():stub\n");
346 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
347 return FALSE;
350 /******************************************************************************
351 * WritePrinter32 [WINSPOOL.223]
353 BOOL WINAPI
354 WritePrinter(
355 HANDLE hPrinter,
356 LPVOID pBuf,
357 DWORD cbBuf,
358 LPDWORD pcWritten) {
360 FIXME("():stub\n");
361 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
362 return FALSE;
365 /*****************************************************************************
366 * AddForm32A [WINSPOOL.103]
368 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
370 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
371 return 1;
374 /*****************************************************************************
375 * AddForm32W [WINSPOOL.104]
377 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
379 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
380 return 1;
383 /*****************************************************************************
384 * AddJob32A [WINSPOOL.105]
386 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
387 DWORD cbBuf, LPDWORD pcbNeeded)
389 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
390 pcbNeeded);
391 return 1;
394 /*****************************************************************************
395 * AddJob32W [WINSPOOL.106]
397 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
398 LPDWORD pcbNeeded)
400 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
401 pcbNeeded);
402 return 1;
405 /*****************************************************************************
406 * AddPrinter32A [WINSPOOL.117]
408 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
410 PRINTER_INFO_2A *pi = (PRINTER_INFO_2A *) pPrinter;
412 HANDLE retval;
413 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
415 TRACE("(%s,%ld,%p)\n", pName, Level, pPrinter);
417 if(pName != NULL) {
418 FIXME("pName = `%s' - unsupported\n", pName);
419 SetLastError(ERROR_INVALID_PARAMETER);
420 return 0;
422 if(Level != 2) {
423 WARN("Level = %ld\n", Level);
424 SetLastError(ERROR_INVALID_LEVEL);
425 return 0;
427 if(!pPrinter) {
428 SetLastError(ERROR_INVALID_PARAMETER);
429 return 0;
431 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
432 ERROR_SUCCESS) {
433 ERR("Can't create Printers key\n");
434 return 0;
436 if(RegOpenKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
437 ERROR_SUCCESS) {
438 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
439 RegCloseKey(hkeyPrinter);
440 RegCloseKey(hkeyPrinters);
441 return 0;
443 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
444 ERROR_SUCCESS) {
445 ERR("Can't create Drivers key\n");
446 RegCloseKey(hkeyPrinters);
447 return 0;
449 if(RegOpenKeyA(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
450 ERROR_SUCCESS) {
451 WARN("Can't find driver `%s'\n", pi->pDriverName);
452 RegCloseKey(hkeyPrinters);
453 RegCloseKey(hkeyDrivers);
454 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
455 return 0;
457 RegCloseKey(hkeyDriver);
458 RegCloseKey(hkeyDrivers);
459 if(strcasecmp(pi->pPrintProcessor, "WinPrint")) { /* FIXME */
460 WARN("Can't find processor `%s'\n", pi->pPrintProcessor);
461 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
462 RegCloseKey(hkeyPrinters);
463 return 0;
465 if(RegCreateKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
466 ERROR_SUCCESS) {
467 WARN("Can't create printer `%s'\n", pi->pPrinterName);
468 SetLastError(ERROR_INVALID_PRINTER_NAME);
469 RegCloseKey(hkeyPrinters);
470 return 0;
472 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
473 (LPSTR)&pi->Attributes, sizeof(DWORD));
474 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY,
475 (LPSTR)&pi->pDevMode,
476 pi->pDevMode ? pi->pDevMode->dmSize : 0);
477 RegSetValueExA(hkeyPrinter, "Description", 0, REG_SZ, pi->pComment, 0);
478 RegSetValueExA(hkeyPrinter, "Location", 0, REG_SZ, pi->pLocation, 0);
479 RegSetValueExA(hkeyPrinter, "Name", 0, REG_SZ, pi->pPrinterName, 0);
480 RegSetValueExA(hkeyPrinter, "Parameters", 0, REG_SZ, pi->pParameters, 0);
481 RegSetValueExA(hkeyPrinter, "Port", 0, REG_SZ, pi->pPortName, 0);
482 RegSetValueExA(hkeyPrinter, "Print Processor", 0, REG_SZ,
483 pi->pPrintProcessor, 0);
484 RegSetValueExA(hkeyPrinter, "Printer Driver", 0, REG_SZ, pi->pDriverName,
486 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
487 (LPSTR)&pi->Priority, sizeof(DWORD));
488 RegSetValueExA(hkeyPrinter, "Separator File", 0, REG_SZ, pi->pSepFile, 0);
489 RegSetValueExA(hkeyPrinter, "Share Name", 0, REG_SZ, pi->pShareName, 0);
490 RegSetValueExA(hkeyPrinter, "Start Time", 0, REG_DWORD,
491 (LPSTR)&pi->StartTime, sizeof(DWORD));
492 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
493 (LPSTR)&pi->Status, sizeof(DWORD));
494 RegSetValueExA(hkeyPrinter, "Until Time", 0, REG_DWORD,
495 (LPSTR)&pi->UntilTime, sizeof(DWORD));
497 RegCloseKey(hkeyPrinter);
498 RegCloseKey(hkeyPrinters);
499 if(!OpenPrinterA(pi->pPrinterName, &retval, NULL)) {
500 ERR("OpenPrinter failing\n");
501 return 0;
503 return retval;
506 /*****************************************************************************
507 * AddPrinter32W [WINSPOOL.122]
509 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
511 FIXME("(%p,%ld,%p): stub\n", pName, Level, pPrinter);
512 return 0;
516 /*****************************************************************************
517 * ClosePrinter32 [WINSPOOL.126]
519 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
521 LPOPENEDPRINTERA lpOpenedPrinter;
523 TRACE("Handle %d\n", hPrinter);
525 if (!pOpenedPrinterDPA)
526 return FALSE;
528 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
530 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
531 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
532 lpOpenedPrinter->lpsPrinterName = NULL;
534 /* Free the memory of lpDefault if it has been initialized*/
535 if(lpOpenedPrinter->lpDefault != NULL)
537 HeapFree(GetProcessHeap(), 0,
538 lpOpenedPrinter->lpDefault->pDevMode);
539 HeapFree(GetProcessHeap(), 0,
540 lpOpenedPrinter->lpDefault->pDatatype);
541 HeapFree(GetProcessHeap(), 0,
542 lpOpenedPrinter->lpDefault);
543 lpOpenedPrinter->lpDefault = NULL;
546 lpOpenedPrinter->hPrinter = -1;
548 return TRUE;
550 return FALSE;
553 /*****************************************************************************
554 * DeleteForm32A [WINSPOOL.133]
556 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
558 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
559 return 1;
562 /*****************************************************************************
563 * DeleteForm32W [WINSPOOL.134]
565 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
567 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
568 return 1;
571 /*****************************************************************************
572 * DeletePrinter32 [WINSPOOL.143]
574 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
576 FIXME("(%d): stub\n", hPrinter);
577 return 1;
580 /*****************************************************************************
581 * SetPrinter32A [WINSPOOL.211]
583 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
584 DWORD Command)
586 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
587 return FALSE;
590 /*****************************************************************************
591 * SetJob32A [WINSPOOL.209]
593 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
594 LPBYTE pJob, DWORD Command)
596 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
597 Command);
598 return FALSE;
601 /*****************************************************************************
602 * SetJob32W [WINSPOOL.210]
604 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
605 LPBYTE pJob, DWORD Command)
607 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
608 Command);
609 return FALSE;
612 /*****************************************************************************
613 * GetForm32A [WINSPOOL.181]
615 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
616 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
618 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
619 Level,pForm,cbBuf,pcbNeeded);
620 return FALSE;
623 /*****************************************************************************
624 * GetForm32W [WINSPOOL.182]
626 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
627 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
629 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
630 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
631 return FALSE;
634 /*****************************************************************************
635 * SetForm32A [WINSPOOL.207]
637 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
638 LPBYTE pForm)
640 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
641 return FALSE;
644 /*****************************************************************************
645 * SetForm32W [WINSPOOL.208]
647 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
648 LPBYTE pForm)
650 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
651 return FALSE;
654 /*****************************************************************************
655 * ReadPrinter32 [WINSPOOL.202]
657 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
658 LPDWORD pNoBytesRead)
660 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
661 return FALSE;
664 /*****************************************************************************
665 * ResetPrinter32A [WINSPOOL.203]
667 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
669 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
670 return FALSE;
673 /*****************************************************************************
674 * ResetPrinter32W [WINSPOOL.204]
676 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
678 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
679 return FALSE;
683 /*****************************************************************************
684 * WINSPOOL_GetStringFromRegA
686 * Get ValueName from hkey storing result in str. buflen is space left in str
688 static BOOL WINSPOOL_GetStringFromRegA(HKEY hkey, LPCSTR ValueName, LPSTR ptr,
689 DWORD buflen, DWORD *needed)
691 DWORD sz = buflen, type;
692 LONG ret;
694 ret = RegQueryValueExA(hkey, ValueName, 0, &type, ptr, &sz);
696 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
697 ERR("Got ret = %ld\n", ret);
698 return FALSE;
700 *needed = sz;
701 return TRUE;
704 /*********************************************************************
705 * WINSPOOL_GetPrinter_2A
707 * Fills out a PRINTER_INFO_2A struct storing the strings in buf.
709 static BOOL WINSPOOL_GetPrinter_2A(HKEY hkeyPrinter, PRINTER_INFO_2A *pi2,
710 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
712 DWORD size, left = cbBuf;
713 BOOL space = (cbBuf > 0);
714 LPBYTE ptr = buf;
716 *pcbNeeded = 0;
718 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
719 if(space && size <= left) {
720 pi2->pPrinterName = ptr;
721 ptr += size;
722 left -= size;
723 } else
724 space = FALSE;
725 *pcbNeeded += size;
727 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, left, &size);
728 if(space && size <= left) {
729 pi2->pPortName = ptr;
730 ptr += size;
731 left -= size;
732 } else
733 space = FALSE;
734 *pcbNeeded += size;
736 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Printer Driver", ptr, left,
737 &size);
738 if(space && size <= left) {
739 pi2->pDriverName = ptr;
740 ptr += size;
741 left -= size;
742 } else
743 space = FALSE;
744 *pcbNeeded += size;
746 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Default DevMode", ptr, left,
747 &size);
748 if(space && size <= left) {
749 pi2->pDevMode = (LPDEVMODEA)ptr;
750 ptr += size;
751 left -= size;
752 } else
753 space = FALSE;
754 *pcbNeeded += size;
756 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Print Processor", ptr, left,
757 &size);
758 if(space && size <= left) {
759 pi2->pPrintProcessor = ptr;
760 ptr += size;
761 left -= size;
762 } else
763 space = FALSE;
764 *pcbNeeded += size;
766 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
767 memset(pi2, 0, sizeof(*pi2));
769 return space;
772 /*********************************************************************
773 * WINSPOOL_GetPrinter_4A
775 * Fills out a PRINTER_INFO_4A struct storing the strings in buf.
777 static BOOL WINSPOOL_GetPrinter_4A(HKEY hkeyPrinter, PRINTER_INFO_4A *pi4,
778 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
780 DWORD size, left = cbBuf;
781 BOOL space = (cbBuf > 0);
782 LPBYTE ptr = buf;
784 *pcbNeeded = 0;
786 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
787 if(space && size <= left) {
788 pi4->pPrinterName = ptr;
789 ptr += size;
790 left -= size;
791 } else
792 space = FALSE;
794 *pcbNeeded += size;
796 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
797 memset(pi4, 0, sizeof(*pi4));
799 return space;
802 /*********************************************************************
803 * WINSPOOL_GetPrinter_5A
805 * Fills out a PRINTER_INFO_5A struct storing the strings in buf.
807 static BOOL WINSPOOL_GetPrinter_5A(HKEY hkeyPrinter, PRINTER_INFO_5A *pi5,
808 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
810 DWORD size, left = cbBuf;
811 BOOL space = (cbBuf > 0);
812 LPBYTE ptr = buf;
814 *pcbNeeded = 0;
816 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
817 if(space && size <= left) {
818 pi5->pPrinterName = ptr;
819 ptr += size;
820 left -= size;
821 } else
822 space = FALSE;
823 *pcbNeeded += size;
825 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, left, &size);
826 if(space && size <= left) {
827 pi5->pPortName = ptr;
828 ptr += size;
829 left -= size;
830 } else
831 space = FALSE;
832 *pcbNeeded += size;
834 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
835 memset(pi5, 0, sizeof(*pi5));
837 return space;
840 /*****************************************************************************
841 * GetPrinterA [WINSPOOL.187]
843 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
844 DWORD cbBuf, LPDWORD pcbNeeded)
846 OPENEDPRINTERA *lpOpenedPrinter;
847 DWORD size, needed = 0;
848 LPBYTE ptr = NULL;
849 HKEY hkeyPrinter, hkeyPrinters;
850 BOOL ret;
852 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
854 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
855 if(!lpOpenedPrinter) {
856 SetLastError(ERROR_INVALID_HANDLE);
857 return FALSE;
859 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
860 ERROR_SUCCESS) {
861 ERR("Can't create Printers key\n");
862 return FALSE;
864 if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
865 != ERROR_SUCCESS) {
866 ERR("Can't find opened printer `%s' in registry\n",
867 lpOpenedPrinter->lpsPrinterName);
868 RegCloseKey(hkeyPrinters);
869 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
870 return FALSE;
873 switch(Level) {
874 case 2:
876 PRINTER_INFO_2A *pi2 = (PRINTER_INFO_2A *)pPrinter;
878 size = sizeof(PRINTER_INFO_2A);
879 if(size <= cbBuf) {
880 ptr = pPrinter + size;
881 cbBuf -= size;
882 memset(pPrinter, 0, size);
883 } else {
884 pi2 = NULL;
885 cbBuf = 0;
887 ret = WINSPOOL_GetPrinter_2A(hkeyPrinter, pi2, ptr, cbBuf, &needed);
888 needed += size;
889 break;
892 case 4:
894 PRINTER_INFO_4A *pi4 = (PRINTER_INFO_4A *)pPrinter;
896 size = sizeof(PRINTER_INFO_4A);
897 if(size <= cbBuf) {
898 ptr = pPrinter + size;
899 cbBuf -= size;
900 memset(pPrinter, 0, size);
901 } else {
902 pi4 = NULL;
903 cbBuf = 0;
905 ret = WINSPOOL_GetPrinter_4A(hkeyPrinter, pi4, ptr, cbBuf, &needed);
906 needed += size;
907 break;
911 case 5:
913 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A *)pPrinter;
915 size = sizeof(PRINTER_INFO_5A);
916 if(size <= cbBuf) {
917 ptr = pPrinter + size;
918 cbBuf -= size;
919 memset(pPrinter, 0, size);
920 } else {
921 pi5 = NULL;
922 cbBuf = 0;
925 ret = WINSPOOL_GetPrinter_5A(hkeyPrinter, pi5, ptr, cbBuf, &needed);
926 needed += size;
927 break;
930 default:
931 FIXME("Unimplemented level %ld\n", Level);
932 SetLastError(ERROR_INVALID_LEVEL);
933 RegCloseKey(hkeyPrinters);
934 RegCloseKey(hkeyPrinter);
935 return FALSE;
938 RegCloseKey(hkeyPrinter);
939 RegCloseKey(hkeyPrinters);
941 if(pcbNeeded) *pcbNeeded = needed;
942 if(!ret)
943 SetLastError(ERROR_INSUFFICIENT_BUFFER);
944 return ret;
948 /*****************************************************************************
949 * GetPrinterW [WINSPOOL.194]
951 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
952 DWORD cbBuf, LPDWORD pcbNeeded)
954 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
955 cbBuf, pcbNeeded);
956 return FALSE;
959 /******************************************************************
960 * EnumPrintersA [WINSPOOL.174]
962 * Enumerates the available printers, print servers and print
963 * providers, depending on the specified flags, name and level.
965 * RETURNS:
967 * If level is set to 1:
968 * Not implemented yet!
969 * Returns TRUE with an empty list.
971 * If level is set to 2:
972 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
973 * Returns an array of PRINTER_INFO_2 data structures in the
974 * lpbPrinters buffer. Note that according to MSDN also an
975 * OpenPrinter should be performed on every remote printer.
977 * If level is set to 4 (officially WinNT only):
978 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
979 * Fast: Only the registry is queried to retrieve printer names,
980 * no connection to the driver is made.
981 * Returns an array of PRINTER_INFO_4 data structures in the
982 * lpbPrinters buffer.
984 * If level is set to 5 (officially WinNT4/Win9x only):
985 * Fast: Only the registry is queried to retrieve printer names,
986 * no connection to the driver is made.
987 * Returns an array of PRINTER_INFO_5 data structures in the
988 * lpbPrinters buffer.
990 * If level set to 3 or 6+:
991 * returns zero (faillure!)
993 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
994 * for information.
996 * BUGS:
997 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
998 * - Only levels 2, 4 and 5 are implemented at the moment.
999 * - 16-bit printer drivers are not enumerated.
1000 * - Returned amount of bytes used/needed does not match the real Windoze
1001 * implementation (as in this implementation, all strings are part
1002 * of the buffer, whereas Win32 keeps them somewhere else)
1003 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
1005 * NOTE:
1006 * - In a regular Wine installation, no registry settings for printers
1007 * exist, which makes this function return an empty list.
1009 BOOL WINAPI EnumPrintersA(
1010 DWORD dwType, /* Types of print objects to enumerate */
1011 LPSTR lpszName, /* name of objects to enumerate */
1012 DWORD dwLevel, /* type of printer info structure */
1013 LPBYTE lpbPrinters, /* buffer which receives info */
1014 DWORD cbBuf, /* max size of buffer in bytes */
1015 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
1016 LPDWORD lpdwReturned /* number of entries returned */
1020 HKEY hkeyPrinters, hkeyPrinter;
1021 char PrinterName[255];
1022 DWORD needed = 0, number = 0;
1023 DWORD used, i, left;
1024 PBYTE pi, buf;
1026 if(lpbPrinters)
1027 memset(lpbPrinters, 0, cbBuf);
1028 if(lpdwReturned)
1029 *lpdwReturned = 0;
1031 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) {
1032 FIXME("dwType = %08lx\n", dwType);
1033 SetLastError(ERROR_INVALID_FLAGS);
1034 return FALSE;
1037 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1038 ERROR_SUCCESS) {
1039 ERR("Can't create Printers key\n");
1040 return FALSE;
1043 if(RegQueryInfoKeyA(hkeyPrinters, NULL, NULL, NULL, &number, NULL, NULL,
1044 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
1045 RegCloseKey(hkeyPrinters);
1046 ERR("Can't query Printers key\n");
1047 return FALSE;
1049 TRACE("Found %ld printers\n", number);
1051 switch(dwLevel) {
1052 case 1:
1053 RegCloseKey(hkeyPrinters);
1054 if (lpdwReturned)
1055 *lpdwReturned = number;
1056 return TRUE;
1058 case 2:
1059 used = number * sizeof(PRINTER_INFO_2A);
1060 break;
1061 case 4:
1062 used = number * sizeof(PRINTER_INFO_4A);
1063 break;
1064 case 5:
1065 used = number * sizeof(PRINTER_INFO_5A);
1066 break;
1068 default:
1069 SetLastError(ERROR_INVALID_LEVEL);
1070 RegCloseKey(hkeyPrinters);
1071 return FALSE;
1073 pi = (used <= cbBuf) ? lpbPrinters : NULL;
1075 for(i = 0; i < number; i++) {
1076 if(RegEnumKeyA(hkeyPrinters, i, PrinterName, sizeof(PrinterName)) !=
1077 ERROR_SUCCESS) {
1078 ERR("Can't enum key number %ld\n", i);
1079 RegCloseKey(hkeyPrinters);
1080 return FALSE;
1082 if(RegOpenKeyA(hkeyPrinters, PrinterName, &hkeyPrinter) !=
1083 ERROR_SUCCESS) {
1084 ERR("Can't open key '%s'\n", PrinterName);
1085 RegCloseKey(hkeyPrinters);
1086 return FALSE;
1089 if(cbBuf > used) {
1090 buf = lpbPrinters + used;
1091 left = cbBuf - used;
1092 } else {
1093 buf = NULL;
1094 left = 0;
1097 switch(dwLevel) {
1098 case 2:
1099 WINSPOOL_GetPrinter_2A(hkeyPrinter, (PRINTER_INFO_2A *)pi, buf,
1100 left, &needed);
1101 used += needed;
1102 if(pi) pi += sizeof(PRINTER_INFO_2A);
1103 break;
1104 case 4:
1105 WINSPOOL_GetPrinter_4A(hkeyPrinter, (PRINTER_INFO_4A *)pi, buf,
1106 left, &needed);
1107 used += needed;
1108 if(pi) pi += sizeof(PRINTER_INFO_4A);
1109 break;
1110 case 5:
1111 WINSPOOL_GetPrinter_5A(hkeyPrinter, (PRINTER_INFO_5A *)pi, buf,
1112 left, &needed);
1113 used += needed;
1114 if(pi) pi += sizeof(PRINTER_INFO_5A);
1115 break;
1116 default:
1117 ERR("Shouldn't be here!\n");
1118 RegCloseKey(hkeyPrinter);
1119 RegCloseKey(hkeyPrinters);
1120 return FALSE;
1122 RegCloseKey(hkeyPrinter);
1124 RegCloseKey(hkeyPrinters);
1126 if(lpdwNeeded)
1127 *lpdwNeeded = used;
1128 if(used > cbBuf) {
1129 if(lpbPrinters)
1130 memset(lpbPrinters, 0, cbBuf);
1131 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1132 return FALSE;
1134 if(lpdwReturned)
1135 *lpdwReturned = number;
1136 SetLastError(ERROR_SUCCESS);
1137 return TRUE;
1140 /******************************************************************
1141 * EnumPrintersW [WINSPOOL.175]
1144 BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
1145 DWORD dwLevel, LPBYTE lpbPrinters,
1146 DWORD cbBuf, LPDWORD lpdwNeeded,
1147 LPDWORD lpdwReturned)
1149 FIXME("Nearly empty stub\n");
1150 *lpdwReturned=0;
1151 *lpdwNeeded = 0;
1152 return TRUE;
1156 /*****************************************************************************
1157 * GetPrinterDriver32A [WINSPOOL.190]
1159 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1160 DWORD Level, LPBYTE pDriverInfo,
1161 DWORD cbBuf, LPDWORD pcbNeeded)
1163 OPENEDPRINTERA *lpOpenedPrinter;
1164 char DriverName[100];
1165 DWORD ret, type, size, dw, needed = 0;
1166 LPBYTE ptr = NULL;
1167 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
1169 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,pEnvironment,
1170 Level,pDriverInfo,cbBuf, pcbNeeded);
1172 ZeroMemory(pDriverInfo, cbBuf);
1174 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
1175 if(!lpOpenedPrinter) {
1176 SetLastError(ERROR_INVALID_HANDLE);
1177 return FALSE;
1179 if(pEnvironment) {
1180 FIXME("pEnvironment = `%s'\n", pEnvironment);
1181 SetLastError(ERROR_INVALID_ENVIRONMENT);
1182 return FALSE;
1184 if(Level < 1 || Level > 3) {
1185 SetLastError(ERROR_INVALID_LEVEL);
1186 return FALSE;
1188 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1189 ERROR_SUCCESS) {
1190 ERR("Can't create Printers key\n");
1191 return FALSE;
1193 if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1194 != ERROR_SUCCESS) {
1195 ERR("Can't find opened printer `%s' in registry\n",
1196 lpOpenedPrinter->lpsPrinterName);
1197 RegCloseKey(hkeyPrinters);
1198 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1199 return FALSE;
1201 size = sizeof(DriverName);
1202 ret = RegQueryValueExA(hkeyPrinter, "Printer Driver", 0, &type, DriverName,
1203 &size);
1204 RegCloseKey(hkeyPrinter);
1205 RegCloseKey(hkeyPrinters);
1206 if(ret != ERROR_SUCCESS) {
1207 ERR("Can't get DriverName for printer `%s'\n",
1208 lpOpenedPrinter->lpsPrinterName);
1209 return FALSE;
1211 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1212 ERROR_SUCCESS) {
1213 ERR("Can't create Drivers key\n");
1214 return FALSE;
1216 if(RegOpenKeyA(hkeyDrivers, DriverName, &hkeyDriver)
1217 != ERROR_SUCCESS) {
1218 ERR("Can't find driver `%s' in registry\n", DriverName);
1219 RegCloseKey(hkeyDrivers);
1220 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1221 return FALSE;
1224 switch(Level) {
1225 case 1:
1226 size = sizeof(DRIVER_INFO_1A);
1227 break;
1228 case 2:
1229 size = sizeof(DRIVER_INFO_2A);
1230 break;
1231 case 3:
1232 size = sizeof(DRIVER_INFO_3A);
1233 break;
1234 default:
1235 ERR("Invalid level\n");
1236 return FALSE;
1239 if(size <= cbBuf) {
1240 ptr = pDriverInfo + size;
1241 cbBuf -= size;
1242 } else
1243 cbBuf = 0;
1244 needed = size;
1246 size = strlen(DriverName) + 1;
1247 if(size <= cbBuf) {
1248 cbBuf -= size;
1249 strcpy(ptr, DriverName);
1250 if(Level == 1)
1251 ((DRIVER_INFO_1A *)pDriverInfo)->pName = ptr;
1252 else
1253 ((DRIVER_INFO_2A *)pDriverInfo)->pName = ptr;
1254 ptr += size;
1256 needed += size;
1258 if(Level > 1) {
1259 DRIVER_INFO_2A *di2 = (DRIVER_INFO_2A *)pDriverInfo;
1261 size = sizeof(dw);
1262 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw,
1263 &size) !=
1264 ERROR_SUCCESS)
1265 WARN("Can't get Version\n");
1266 else if(cbBuf)
1267 di2->cVersion = dw;
1269 size = strlen("Wine") + 1; /* FIXME */
1270 if(size <= cbBuf) {
1271 cbBuf -= size;
1272 strcpy(ptr, "Wine");
1273 di2->pEnvironment = ptr;
1274 ptr += size;
1275 } else
1276 cbBuf = 0;
1277 needed += size;
1279 WINSPOOL_GetStringFromRegA(hkeyDriver, "Driver", ptr, cbBuf, &size);
1280 if(cbBuf && size <= cbBuf) {
1281 di2->pDriverPath = ptr;
1282 ptr += size;
1283 } else
1284 cbBuf = 0;
1285 needed += size;
1287 WINSPOOL_GetStringFromRegA(hkeyDriver, "Data File", ptr, cbBuf, &size);
1288 if(cbBuf && size <= cbBuf) {
1289 di2->pDataFile = ptr;
1290 ptr += size;
1291 } else
1292 cbBuf = 0;
1293 needed += size;
1295 WINSPOOL_GetStringFromRegA(hkeyDriver, "Configuration File", ptr,
1296 cbBuf, &size);
1297 if(cbBuf && size <= cbBuf) {
1298 di2->pConfigFile = ptr;
1299 ptr += size;
1300 } else
1301 cbBuf = 0;
1302 needed += size;
1305 if(Level > 2) {
1306 DRIVER_INFO_3A *di3 = (DRIVER_INFO_3A *)pDriverInfo;
1308 WINSPOOL_GetStringFromRegA(hkeyDriver, "Help File", ptr, cbBuf, &size);
1309 if(cbBuf && size <= cbBuf) {
1310 di3->pHelpFile = ptr;
1311 ptr += size;
1312 } else
1313 cbBuf = 0;
1314 needed += size;
1316 WINSPOOL_GetStringFromRegA(hkeyDriver, "Dependent Files", ptr, cbBuf,
1317 &size);
1318 if(cbBuf && size <= cbBuf) {
1319 di3->pDependentFiles = ptr;
1320 ptr += size;
1321 } else
1322 cbBuf = 0;
1323 needed += size;
1325 WINSPOOL_GetStringFromRegA(hkeyDriver, "Monitor", ptr, cbBuf, &size);
1326 if(cbBuf && size <= cbBuf) {
1327 di3->pMonitorName = ptr;
1328 ptr += size;
1329 } else
1330 cbBuf = 0;
1331 needed += size;
1333 WINSPOOL_GetStringFromRegA(hkeyDriver, "DataType", ptr, cbBuf, &size);
1334 if(cbBuf && size <= cbBuf) {
1335 di3->pDefaultDataType = ptr;
1336 ptr += size;
1337 } else
1338 cbBuf = 0;
1339 needed += size;
1341 RegCloseKey(hkeyDriver);
1342 RegCloseKey(hkeyDrivers);
1344 if(pcbNeeded) *pcbNeeded = needed;
1345 if(cbBuf) return TRUE;
1346 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1347 return FALSE;
1350 /*****************************************************************************
1351 * GetPrinterDriver32W [WINSPOOL.193]
1353 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1354 DWORD Level, LPBYTE pDriverInfo,
1355 DWORD cbBuf, LPDWORD pcbNeeded)
1357 FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1358 Level,pDriverInfo,cbBuf, pcbNeeded);
1359 return FALSE;
1362 /*****************************************************************************
1363 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1365 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1366 DWORD Level, LPBYTE pDriverDirectory,
1367 DWORD cbBuf, LPDWORD pcbNeeded)
1369 DWORD needed;
1371 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1372 pDriverDirectory, cbBuf, pcbNeeded);
1373 if(pName != NULL) {
1374 FIXME("pName = `%s' - unsupported\n", pName);
1375 SetLastError(ERROR_INVALID_PARAMETER);
1376 return FALSE;
1378 if(pEnvironment != NULL) {
1379 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
1380 SetLastError(ERROR_INVALID_ENVIRONMENT);
1381 return FALSE;
1383 if(Level != 1) /* win95 ignores this so we just carry on */
1384 WARN("Level = %ld - assuming 1\n", Level);
1386 /* FIXME should read from registry */
1387 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
1388 needed++;
1389 if(pcbNeeded)
1390 *pcbNeeded = needed;
1391 if(needed > cbBuf) {
1392 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1393 return FALSE;
1395 return TRUE;
1399 /*****************************************************************************
1400 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1402 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
1403 DWORD Level, LPBYTE pDriverDirectory,
1404 DWORD cbBuf, LPDWORD pcbNeeded)
1406 LPSTR pNameA = NULL, pEnvironmentA = NULL;
1407 BOOL ret;
1409 if(pName)
1410 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
1411 if(pEnvironment)
1412 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
1413 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
1414 pDriverDirectory, cbBuf, pcbNeeded );
1415 if(pNameA)
1416 HeapFree( GetProcessHeap(), 0, pNameA );
1417 if(pEnvironmentA)
1418 HeapFree( GetProcessHeap(), 0, pEnvironment );
1420 return ret;
1423 /*****************************************************************************
1424 * AddPrinterDriver32A [WINSPOOL.120]
1426 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
1428 DRIVER_INFO_3A di3;
1429 HKEY hkeyDrivers, hkeyName;
1431 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
1433 if(level != 2 && level != 3) {
1434 SetLastError(ERROR_INVALID_LEVEL);
1435 return FALSE;
1437 if(pName != NULL) {
1438 FIXME("pName= `%s' - unsupported\n", pName);
1439 SetLastError(ERROR_INVALID_PARAMETER);
1440 return FALSE;
1442 if(!pDriverInfo) {
1443 WARN("pDriverInfo == NULL");
1444 SetLastError(ERROR_INVALID_PARAMETER);
1445 return FALSE;
1448 if(level == 3)
1449 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
1450 else {
1451 memset(&di3, 0, sizeof(di3));
1452 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
1455 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
1456 !di3.pDataFile) {
1457 SetLastError(ERROR_INVALID_PARAMETER);
1458 return FALSE;
1460 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
1461 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
1462 if(!di3.pHelpFile) di3.pHelpFile = "";
1463 if(!di3.pMonitorName) di3.pMonitorName = "";
1465 if(di3.pEnvironment) {
1466 FIXME("pEnvironment = `%s'\n", di3.pEnvironment);
1467 SetLastError(ERROR_INVALID_ENVIRONMENT);
1468 return FALSE;
1470 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1471 ERROR_SUCCESS) {
1472 ERR("Can't create Drivers key\n");
1473 return FALSE;
1476 if(level == 2) { /* apparently can't overwrite with level2 */
1477 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
1478 RegCloseKey(hkeyName);
1479 RegCloseKey(hkeyDrivers);
1480 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
1481 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
1482 return FALSE;
1485 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
1486 RegCloseKey(hkeyDrivers);
1487 ERR("Can't create Name key\n");
1488 return FALSE;
1490 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
1492 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
1493 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
1494 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
1495 sizeof(DWORD));
1496 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
1497 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
1498 di3.pDependentFiles, 0);
1499 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
1500 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
1501 RegCloseKey(hkeyName);
1502 RegCloseKey(hkeyDrivers);
1504 return TRUE;
1506 /*****************************************************************************
1507 * AddPrinterDriver32W [WINSPOOL.121]
1509 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
1510 LPBYTE pDriverInfo)
1512 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
1513 level,pDriverInfo);
1514 return FALSE;
1518 /*****************************************************************************
1519 * PrinterProperties [WINSPOOL.201]
1521 * Displays a dialog to set the properties of the printer.
1523 * RETURNS
1524 * nonzero on succes or zero on faillure
1526 * BUGS
1527 * implemented as stub only
1529 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
1530 HANDLE hPrinter /* handle to printer object */
1532 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
1533 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1534 return FALSE;
1537 /*****************************************************************************
1538 * EnumJobsA [WINSPOOL.162]
1541 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
1542 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
1543 LPDWORD pcReturned)
1545 FIXME("stub\n");
1546 if(pcbNeeded) *pcbNeeded = 0;
1547 if(pcReturned) *pcReturned = 0;
1548 return TRUE;
1552 /*****************************************************************************
1553 * EnumJobsW [WINSPOOL.163]
1556 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
1557 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
1558 LPDWORD pcReturned)
1560 FIXME("stub\n");
1561 if(pcbNeeded) *pcbNeeded = 0;
1562 if(pcReturned) *pcReturned = 0;
1563 return TRUE;