Converted to the new debug interface, using script written by Patrik
[wine/wine64.git] / misc / printdrv.c
blob2fbafdfe41cca93c50b9ccde3adfc507d5ce52c7
1 /*
2 * Implementation of some printer driver bits
3 *
4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
7 */
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include "winspool.h"
13 #include "winbase.h"
14 #include "wine/wingdi16.h"
15 #include "ldt.h"
16 #include "winerror.h"
17 #include "winreg.h"
18 #include "debugtools.h"
20 DECLARE_DEBUG_CHANNEL(gdi)
21 DECLARE_DEBUG_CHANNEL(print)
23 CRITICAL_SECTION PRINT32_RegistryBlocker;
25 static char PrinterModel[] = "Printer Model";
26 static char DefaultDevMode[] = "Default DevMode";
27 static char PrinterDriverData[] = "PrinterDriverData";
28 static char Printers[] = "System\\CurrentControlSet\\Control\\Print\\Printers\\";
30 /******************************************************************
31 * StartDoc16 [GDI.377]
34 INT16 WINAPI StartDoc16( HDC16 hdc, const DOCINFO16 *lpdoc )
36 INT16 retVal;
37 TRACE_(print)("(%p)\n", lpdoc );
38 TRACE_(print)("%d 0x%lx:0x%p 0x%lx:0x%p\n",lpdoc->cbSize,
39 lpdoc->lpszDocName,PTR_SEG_TO_LIN(lpdoc->lpszDocName),
40 lpdoc->lpszOutput,PTR_SEG_TO_LIN(lpdoc->lpszOutput));
41 TRACE_(print)("%d %s %s\n",lpdoc->cbSize,
42 (LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszDocName),
43 (LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszOutput));
44 retVal = Escape16(hdc, STARTDOC,
45 strlen((LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszDocName)), lpdoc->lpszDocName, 0);
46 TRACE_(print)("Escape16 returned %d\n",retVal);
47 return retVal;
50 /******************************************************************
51 * EndPage16 [GDI.380]
54 INT16 WINAPI EndPage16( HDC16 hdc )
56 INT16 retVal;
57 retVal = Escape16(hdc, NEWFRAME, 0, 0, 0);
58 TRACE_(print)("Escape16 returned %d\n",retVal);
59 return retVal;
62 /******************************************************************
63 * StartDoc32A [GDI32.347]
66 INT WINAPI StartDocA(HDC hdc ,const DOCINFOA* doc)
68 FIXME_(gdi)("stub\n");
69 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
70 return 0; /* failure*/
73 /*************************************************************************
74 * StartDoc32W [GDI32.348]
77 INT WINAPI StartDocW(HDC hdc, const DOCINFOW* doc) {
78 FIXME_(gdi)("stub\n");
79 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
80 return 0; /* failure*/
83 /******************************************************************
84 * StartPage32 [GDI32.349]
87 INT WINAPI StartPage(HDC hdc)
89 FIXME_(gdi)("stub\n");
90 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
91 return 0; /* failure*/
94 /******************************************************************
95 * EndPage32 [GDI32.77]
98 INT WINAPI EndPage(HDC hdc)
100 FIXME_(gdi)("stub\n");
101 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
102 return 0; /* failure*/
105 /******************************************************************
106 * EndDoc16 [GDI.378]
109 INT16 WINAPI EndDoc16(HDC16 hdc)
111 return Escape16(hdc, ENDDOC, 0, 0, 0);
114 /******************************************************************
115 * EndDoc32 [GDI32.76]
118 INT WINAPI EndDoc(HDC hdc)
120 FIXME_(gdi)("stub\n");
121 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
122 return 0; /* failure*/
125 /******************************************************************************
126 * AbortDoc16 [GDI.382]
128 INT16 WINAPI AbortDoc16(HDC16 hdc)
130 return Escape16(hdc, ABORTDOC, 0, 0, 0);
133 /******************************************************************************
134 * AbortDoc32 [GDI32.0]
136 INT WINAPI AbortDoc(HDC hdc)
138 FIXME_(gdi)("(%d): stub\n", hdc);
139 return 1;
142 /******************************************************************
143 * DrvGetPrinterDataInternal
145 * Helper for DrvGetPrinterData
147 static DWORD DrvGetPrinterDataInternal(LPSTR RegStr_Printer,
148 LPBYTE lpPrinterData, int cbData, int what)
150 DWORD res = -1;
151 HKEY hkey;
152 DWORD dwType, cbQueryData;
154 if (!(RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey))) {
155 if (what == INT_PD_DEFAULT_DEVMODE) { /* "Default DevMode" */
156 if (!(RegQueryValueExA(hkey, DefaultDevMode, 0, &dwType, 0, &cbQueryData))) {
157 if (!lpPrinterData)
158 res = cbQueryData;
159 else if ((cbQueryData) && (cbQueryData <= cbData)) {
160 cbQueryData = cbData;
161 if (RegQueryValueExA(hkey, DefaultDevMode, 0,
162 &dwType, lpPrinterData, &cbQueryData))
163 res = cbQueryData;
166 } else { /* "Printer Driver" */
167 cbQueryData = 32;
168 RegQueryValueExA(hkey, "Printer Driver", 0,
169 &dwType, lpPrinterData, &cbQueryData);
170 res = cbQueryData;
173 if (hkey) RegCloseKey(hkey);
174 return res;
177 /******************************************************************
178 * DrvGetPrinterData [GDI.282]
181 DWORD WINAPI DrvGetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
182 LPDWORD lpType, LPBYTE lpPrinterData,
183 int cbData, LPDWORD lpNeeded)
185 LPSTR RegStr_Printer;
186 HKEY hkey = 0, hkey2 = 0;
187 DWORD res = 0;
188 DWORD dwType, PrinterAttr, cbPrinterAttr, SetData, size;
190 if (HIWORD(lpPrinter))
191 TRACE_(print)("printer %s\n",lpPrinter);
192 else
193 TRACE_(print)("printer %p\n",lpPrinter);
194 if (HIWORD(lpProfile))
195 TRACE_(print)("profile %s\n",lpProfile);
196 else
197 TRACE_(print)("profile %p\n",lpProfile);
198 TRACE_(print)("lpType %p\n",lpType);
200 if ((!lpPrinter) || (!lpProfile) || (!lpNeeded))
201 return ERROR_INVALID_PARAMETER;
203 RegStr_Printer = HeapAlloc(GetProcessHeap(), 0,
204 strlen(Printers) + strlen(lpPrinter) + 2);
205 strcpy(RegStr_Printer, Printers);
206 strcat(RegStr_Printer, lpPrinter);
208 if (((DWORD)lpProfile == INT_PD_DEFAULT_DEVMODE) || (HIWORD(lpProfile) &&
209 (!strcmp(lpProfile, DefaultDevMode)))) {
210 size = DrvGetPrinterDataInternal(RegStr_Printer, lpPrinterData, cbData,
211 INT_PD_DEFAULT_DEVMODE);
212 if (size+1) {
213 *lpNeeded = size;
214 if ((lpPrinterData) && (*lpNeeded > cbData))
215 res = ERROR_MORE_DATA;
217 else res = ERROR_INVALID_PRINTER_NAME;
219 else
220 if (((DWORD)lpProfile == INT_PD_DEFAULT_MODEL) || (HIWORD(lpProfile) &&
221 (!strcmp(lpProfile, PrinterModel)))) {
222 *lpNeeded = 32;
223 if (!lpPrinterData) goto failed;
224 if (cbData < 32) {
225 res = ERROR_MORE_DATA;
226 goto failed;
228 size = DrvGetPrinterDataInternal(RegStr_Printer, lpPrinterData, cbData,
229 INT_PD_DEFAULT_MODEL);
230 if ((size+1) && (lpType))
231 *lpType = REG_SZ;
232 else
233 res = ERROR_INVALID_PRINTER_NAME;
235 else
237 if ((res = RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)))
238 goto failed;
239 cbPrinterAttr = 4;
240 if ((res = RegQueryValueExA(hkey, "Attributes", 0,
241 &dwType, (LPBYTE)&PrinterAttr, &cbPrinterAttr)))
242 goto failed;
243 if ((res = RegOpenKeyA(hkey, PrinterDriverData, &hkey2)))
244 goto failed;
245 *lpNeeded = cbData;
246 res = RegQueryValueExA(hkey2, lpProfile, 0,
247 lpType, lpPrinterData, lpNeeded);
248 if ((res != ERROR_CANTREAD) &&
249 ((PrinterAttr &
250 (PRINTER_ATTRIBUTE_ENABLE_BIDI|PRINTER_ATTRIBUTE_NETWORK))
251 == PRINTER_ATTRIBUTE_NETWORK))
253 if (!(res) && (*lpType == REG_DWORD) && (*(LPDWORD)lpPrinterData == -1))
254 res = ERROR_INVALID_DATA;
256 else
258 SetData = -1;
259 RegSetValueExA(hkey2, lpProfile, 0, REG_DWORD, (LPBYTE)&SetData, 4); /* no result returned */
263 failed:
264 if (hkey2) RegCloseKey(hkey2);
265 if (hkey) RegCloseKey(hkey);
266 HeapFree(GetProcessHeap(), 0, RegStr_Printer);
267 return res;
271 /******************************************************************
272 * DrvSetPrinterData [GDI.281]
275 DWORD WINAPI DrvSetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
276 DWORD lpType, LPBYTE lpPrinterData,
277 DWORD dwSize)
279 LPSTR RegStr_Printer;
280 HKEY hkey = 0;
281 DWORD res = 0;
283 if (HIWORD(lpPrinter))
284 TRACE_(print)("printer %s\n",lpPrinter);
285 else
286 TRACE_(print)("printer %p\n",lpPrinter);
287 if (HIWORD(lpProfile))
288 TRACE_(print)("profile %s\n",lpProfile);
289 else
290 TRACE_(print)("profile %p\n",lpProfile);
291 TRACE_(print)("lpType %08lx\n",lpType);
293 if ((!lpPrinter) || (!lpProfile) ||
294 ((DWORD)lpProfile == INT_PD_DEFAULT_MODEL) || (HIWORD(lpProfile) &&
295 (!strcmp(lpProfile, PrinterModel))))
296 return ERROR_INVALID_PARAMETER;
298 RegStr_Printer = HeapAlloc(GetProcessHeap(), 0,
299 strlen(Printers) + strlen(lpPrinter) + 2);
300 strcpy(RegStr_Printer, Printers);
301 strcat(RegStr_Printer, lpPrinter);
303 if (((DWORD)lpProfile == INT_PD_DEFAULT_DEVMODE) || (HIWORD(lpProfile) &&
304 (!strcmp(lpProfile, DefaultDevMode)))) {
305 if ( RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)
306 != ERROR_SUCCESS ||
307 RegSetValueExA(hkey, DefaultDevMode, 0, REG_BINARY,
308 lpPrinterData, dwSize) != ERROR_SUCCESS )
309 res = ERROR_INVALID_PRINTER_NAME;
311 else
313 strcat(RegStr_Printer, "\\");
315 if( (res = RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)) ==
316 ERROR_SUCCESS ) {
318 if (!lpPrinterData)
319 res = RegDeleteValueA(hkey, lpProfile);
320 else
321 res = RegSetValueExA(hkey, lpProfile, 0, lpType,
322 lpPrinterData, dwSize);
326 if (hkey) RegCloseKey(hkey);
327 HeapFree(GetProcessHeap(), 0, RegStr_Printer);
328 return res;
332 /******************************************************************
333 * DeviceCapabilities32A [WINSPOOL.151]
336 INT WINAPI DeviceCapabilitiesA(LPCSTR printer,LPCSTR target,WORD z,
337 LPSTR a,LPDEVMODEA b)
339 FIXME_(print)("(%s,%s,%d,%p,%p):stub.\n",printer,target,z,a,b);
340 return 1;
344 /*****************************************************************************
345 * DeviceCapabilities32W
347 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
348 WORD fwCapability, LPWSTR pOutput,
349 const DEVMODEW *pDevMode)
351 FIXME_(print)("(%p,%p,%d,%p,%p): stub\n",
352 pDevice, pPort, fwCapability, pOutput, pDevMode);
353 return -1;
356 /******************************************************************
357 * DocumentProperties32A [WINSPOOL.155]
360 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
361 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
362 LPDEVMODEA pDevModeInput,DWORD fMode )
364 FIXME_(print)("(%d,%d,%s,%p,%p,%ld):stub.\n",
365 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
367 return 1;
371 /*****************************************************************************
372 * DocumentProperties32W
374 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
375 LPWSTR pDeviceName,
376 LPDEVMODEW pDevModeOutput,
377 LPDEVMODEW pDevModeInput, DWORD fMode)
379 FIXME_(print)("(%d,%d,%s,%p,%p,%ld): stub\n",
380 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
381 fMode);
382 return -1;
386 /******************************************************************
387 * OpenPrinter32A [WINSPOOL.196]
390 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
391 LPPRINTER_DEFAULTSA pDefault)
393 FIXME_(print)("(%s,%p,%p):stub\n",debugstr_a(lpPrinterName), phPrinter,
394 pDefault);
395 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
396 return FALSE;
399 /******************************************************************
400 * OpenPrinter32W [WINSPOOL.197]
403 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
404 LPPRINTER_DEFAULTSW pDefault)
406 FIXME_(print)("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
407 pDefault);
408 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
409 return FALSE;
415 /******************************************************************
416 * ENUMPRINTERS_GetDWORDFromRegistryA internal
418 * Reads a DWORD from registry KeyName
420 * RETURNS
421 * value on OK or NULL on error
423 DWORD ENUMPRINTERS_GetDWORDFromRegistryA(
424 HKEY hPrinterSettings, /* handle to registry key */
425 LPSTR KeyName /* name key to retrieve string from*/
427 DWORD DataSize=8;
428 DWORD DataType;
429 BYTE Data[8];
430 DWORD Result=684;
432 if (RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
433 Data, &DataSize)!=ERROR_SUCCESS)
434 FIXME_(print)("Query of register didn't succeed?");
435 if (DataType == REG_DWORD_LITTLE_ENDIAN)
436 Result = Data[0] + (Data[1]<<8) + (Data[2]<<16) + (Data[3]<<24);
437 if (DataType == REG_DWORD_BIG_ENDIAN)
438 Result = Data[3] + (Data[2]<<8) + (Data[1]<<16) + (Data[0]<<24);
439 return(Result);
443 /******************************************************************
444 * ENUMPRINTERS_AddStringFromRegistryA internal
446 * Reads a string from registry KeyName and writes it at
447 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
449 * RETURNS
450 * FALSE if there is still space left in the buffer.
452 BOOL ENUMPRINTERS_AddStringFromRegistryA(
453 HKEY hPrinterSettings, /* handle to registry key */
454 LPSTR KeyName, /* name key to retrieve string from*/
455 LPSTR* Dest, /* pointer to write string addres to */
456 LPBYTE lpbPrinters, /* buffer which receives info*/
457 LPDWORD dwNextStringPos, /* pos in buffer for next string */
458 DWORD dwBufSize, /* max size of buffer in bytes */
459 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
461 DWORD DataSize=34;
462 DWORD DataType;
463 LPSTR Data = (LPSTR) malloc(DataSize*sizeof(char));
465 while(RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
466 Data, &DataSize)==ERROR_MORE_DATA)
468 Data = (LPSTR) realloc(Data, DataSize+2);
471 if (DataType == REG_SZ)
473 if (bCalcSpaceOnly==FALSE)
474 *Dest = &lpbPrinters[*dwNextStringPos];
475 *dwNextStringPos += DataSize+1;
476 if (*dwNextStringPos > dwBufSize)
477 bCalcSpaceOnly=TRUE;
478 if (bCalcSpaceOnly==FALSE)
480 if (DataSize==0) /* DataSize = 0 means empty string, even though*/
481 *Dest[0]=0; /* the data itself needs not to be empty */
482 else
483 strcpy(*Dest, Data);
486 else
487 WARN_(print)("Expected string setting, got something else from registry");
489 if (Data)
490 free(Data);
491 return(bCalcSpaceOnly);
496 /******************************************************************
497 * ENUMPRINTERS_AddInfo2A internal
499 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
500 * for printer PrinterNameKey.
501 * Note that there is no check whether the information really fits!
503 * RETURNS
504 * FALSE if there is still space left in the buffer.
506 * BUGS:
507 * This function should not only read the registry but also ask the driver
508 * for information.
510 BOOL ENUMPRINTERS_AddInfo2A(
511 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
512 LPBYTE lpbPrinters, /* buffer which receives info*/
513 DWORD dwNextStructPos, /* pos in buffer for struct */
514 LPDWORD dwNextStringPos, /* pos in buffer for next string */
515 DWORD dwBufSize, /* max size of buffer in bytes */
516 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
518 HKEY hPrinterSettings;
519 DWORD DevSize=0;
520 DWORD DataType;
521 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
522 strlen(lpszPrinterName)+2);
523 LPPRINTER_INFO_2A lpPInfo2 = (LPPRINTER_INFO_2A) &lpbPrinters[dwNextStructPos];
525 /* open the registry to find the attributes, etc of the printer */
526 if (lpszPrinterSettings!=NULL)
528 strcpy(lpszPrinterSettings,Printers);
529 strcat(lpszPrinterSettings,lpszPrinterName);
531 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
532 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
534 WARN_(print)("The registry did not contain my printer anymore?\n");
536 else
538 if (bCalcSpaceOnly==FALSE)
539 lpPInfo2->pServerName = NULL;
540 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
541 "Name", &(lpPInfo2->pPrinterName),
542 lpbPrinters, dwNextStringPos,
543 dwBufSize, bCalcSpaceOnly);
544 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
545 "Share Name", &(lpPInfo2->pShareName),
546 lpbPrinters, dwNextStringPos,
547 dwBufSize, bCalcSpaceOnly);
548 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
549 "Port", &(lpPInfo2->pPortName),
550 lpbPrinters, dwNextStringPos,
551 dwBufSize, bCalcSpaceOnly);
552 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
553 "Printer Driver", &(lpPInfo2->pDriverName),
554 lpbPrinters, dwNextStringPos,
555 dwBufSize, bCalcSpaceOnly);
556 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
557 "Description", &(lpPInfo2->pComment),
558 lpbPrinters, dwNextStringPos,
559 dwBufSize, bCalcSpaceOnly);
560 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
561 "Location", &(lpPInfo2->pLocation),
562 lpbPrinters, dwNextStringPos,
563 dwBufSize, bCalcSpaceOnly);
565 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
566 "Separator File", &(lpPInfo2->pSepFile),
567 lpbPrinters, dwNextStringPos,
568 dwBufSize, bCalcSpaceOnly);
569 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
570 "Print Processor", &(lpPInfo2->pPrintProcessor),
571 lpbPrinters, dwNextStringPos,
572 dwBufSize, bCalcSpaceOnly);
573 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
574 "Datatype", &(lpPInfo2->pDatatype),
575 lpbPrinters, dwNextStringPos,
576 dwBufSize, bCalcSpaceOnly);
577 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
578 "Parameters", &(lpPInfo2->pParameters),
579 lpbPrinters, dwNextStringPos,
580 dwBufSize, bCalcSpaceOnly);
581 if (bCalcSpaceOnly == FALSE)
583 lpPInfo2->pSecurityDescriptor = NULL; /* EnumPrinters doesn't return this*/
585 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
586 lpPInfo2->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
587 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
588 lpPInfo2->Priority = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
589 "Priority");
590 lpPInfo2->DefaultPriority = ENUMPRINTERS_GetDWORDFromRegistryA(
591 hPrinterSettings, "Default Priority");
592 lpPInfo2->StartTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
593 "StartTime");
594 lpPInfo2->UntilTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
595 "UntilTime");
596 lpPInfo2->Status = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
597 "Status");
598 lpPInfo2->cJobs = 0; /* FIXME: according to MSDN, this does not
599 * reflect the TotalJobs Key ??? */
600 lpPInfo2->AveragePPM = 0; /* FIXME: according to MSDN, this does not
601 * reflect the TotalPages Key ??? */
603 /* and read the devModes structure... */
604 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
605 NULL, &DevSize); /* should return ERROR_MORE_DATA */
606 lpPInfo2->pDevMode = (LPDEVMODEA) &lpbPrinters[*dwNextStringPos];
607 *dwNextStringPos += DevSize + 1;
609 if (*dwNextStringPos > dwBufSize)
610 bCalcSpaceOnly=TRUE;
611 if (bCalcSpaceOnly==FALSE)
612 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
613 (LPBYTE)lpPInfo2->pDevMode, &DevSize);
616 if (lpszPrinterSettings)
617 free(lpszPrinterSettings);
619 return(bCalcSpaceOnly);
622 /******************************************************************
623 * ENUMPRINTERS_AddInfo4A internal
625 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
626 * for printer PrinterNameKey.
627 * Note that there is no check whether the information really fits!
629 * RETURNS
630 * FALSE if there is still space left in the buffer.
632 * BUGS:
633 * This function should not exist in Win95 mode, but does anyway.
635 BOOL ENUMPRINTERS_AddInfo4A(
636 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
637 LPBYTE lpbPrinters, /* buffer which receives info*/
638 DWORD dwNextStructPos, /* pos in buffer for struct */
639 LPDWORD dwNextStringPos, /* pos in buffer for next string */
640 DWORD dwBufSize, /* max size of buffer in bytes */
641 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
643 HKEY hPrinterSettings;
644 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
645 strlen(lpszPrinterName)+2);
646 LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos];
648 /* open the registry to find the attributes of the printer */
649 if (lpszPrinterSettings!=NULL)
651 strcpy(lpszPrinterSettings,Printers);
652 strcat(lpszPrinterSettings,lpszPrinterName);
654 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
655 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
657 WARN_(print)("The registry did not contain my printer anymore?\n");
659 else
661 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
662 "Name", &(lpPInfo4->pPrinterName),
663 lpbPrinters, dwNextStringPos,
664 dwBufSize, bCalcSpaceOnly);
665 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
666 if (bCalcSpaceOnly==FALSE)
667 lpPInfo4->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
668 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
670 if (lpszPrinterSettings)
671 free(lpszPrinterSettings);
673 return(bCalcSpaceOnly);
676 /******************************************************************
677 * ENUMPRINTERS_AddInfo5A internal
679 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
680 * for printer PrinterNameKey.
681 * Settings are read from the registry.
682 * Note that there is no check whether the information really fits!
683 * RETURNS
684 * FALSE if there is still space left in the buffer.
686 BOOL ENUMPRINTERS_AddInfo5A(
687 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
688 LPBYTE lpbPrinters, /* buffer which receives info*/
689 DWORD dwNextStructPos, /* pos in buffer for struct */
690 LPDWORD dwNextStringPos, /* pos in buffer for next string */
691 DWORD dwBufSize, /* max size of buffer in bytes */
692 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
694 HKEY hPrinterSettings;
695 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
696 strlen(lpszPrinterName)+2);
697 LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos];
699 /* open the registry to find the attributes, etc of the printer */
700 if (lpszPrinterSettings!=NULL)
702 strcpy(lpszPrinterSettings,Printers);
703 strcat(lpszPrinterSettings,lpszPrinterName);
705 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
706 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
708 WARN_(print)("The registry did not contain my printer anymore?\n");
710 else
712 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
713 "Name", &(lpPInfo5->pPrinterName),
714 lpbPrinters, dwNextStringPos,
715 dwBufSize, bCalcSpaceOnly);
716 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
717 "Port", &(lpPInfo5->pPortName), lpbPrinters,
718 dwNextStringPos, dwBufSize, bCalcSpaceOnly);
719 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
720 if (bCalcSpaceOnly == FALSE)
722 lpPInfo5->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
723 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
724 lpPInfo5->DeviceNotSelectedTimeOut
725 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
726 "txTimeout");
727 lpPInfo5->TransmissionRetryTimeout
728 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
729 "dnsTimeout");
733 if (lpszPrinterSettings)
734 free(lpszPrinterSettings);
736 return(bCalcSpaceOnly);
740 /******************************************************************
741 * EnumPrintersA [WINSPOOL.174]
743 * Enumerates the available printers, print servers and print
744 * providers, depending on the specified flags, name and level.
746 * RETURNS:
748 * If level is set to 1:
749 * Not implemented yet!
750 * Returns TRUE with an empty list.
752 * If level is set to 2:
753 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
754 * Returns an array of PRINTER_INFO_2 data structures in the
755 * lpbPrinters buffer. Note that according to MSDN also an
756 * OpenPrinter should be performed on every remote printer.
758 * If level is set to 4 (officially WinNT only):
759 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
760 * Fast: Only the registry is queried to retrieve printer names,
761 * no connection to the driver is made.
762 * Returns an array of PRINTER_INFO_4 data structures in the
763 * lpbPrinters buffer.
765 * If level is set to 5 (officially WinNT4/Win9x only):
766 * Fast: Only the registry is queried to retrieve printer names,
767 * no connection to the driver is made.
768 * Returns an array of PRINTER_INFO_5 data structures in the
769 * lpbPrinters buffer.
771 * If level set to 3 or 6+:
772 * returns zero (faillure!)
774 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
775 * for information.
777 * BUGS:
778 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
779 * - Only levels 2, 4 and 5 are implemented at the moment.
780 * - 16-bit printer drivers are not enumerated.
781 * - Returned amount of bytes used/needed does not match the real Windoze
782 * implementation (as in this implementation, all strings are part
783 * of the buffer, whereas Win32 keeps them somewhere else)
784 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
786 * NOTE:
787 * - In a regular Wine installation, no registry settings for printers
788 * exist, which makes this function return an empty list.
790 BOOL WINAPI EnumPrintersA(
791 DWORD dwType, /* Types of print objects to enumerate */
792 LPSTR lpszName, /* name of objects to enumerate */
793 DWORD dwLevel, /* type of printer info structure */
794 LPBYTE lpbPrinters,/* buffer which receives info*/
795 DWORD cbBuf, /* max size of buffer in bytes */
796 LPDWORD lpdwNeeded,/* pointer to var: # bytes used/needed */
797 LPDWORD lpdwReturned/* number of entries returned */
800 HKEY hPrinterListKey;
801 DWORD dwIndex=0;
802 char PrinterName[255];
803 DWORD PrinterNameLength=255;
804 FILETIME FileTime;
805 DWORD dwNextStringPos; /* position of next space for a string in the buffer*/
806 DWORD dwStructPrinterInfoSize; /* size of a Printer_Info_X structure */
807 BOOL bCalcSpaceOnly=FALSE;/* if TRUE: don't store data, just calculate space*/
809 TRACE_(print)("entered.\n");
811 /* test whether we're requested to really fill in. If so,
812 * zero out the data area, and initialise some returns to zero,
813 * to prevent problems
815 if (lpbPrinters==NULL || cbBuf==0)
816 bCalcSpaceOnly=TRUE;
817 else
819 int i;
820 for (i=0; i<cbBuf; i++)
821 lpbPrinters[i]=0;
823 *lpdwReturned=0;
824 *lpdwNeeded = 0;
826 /* check for valid Flags */
827 if (dwType != PRINTER_ENUM_LOCAL && dwType != PRINTER_ENUM_NAME)
829 SetLastError(ERROR_INVALID_FLAGS);
830 return(0);
832 switch(dwLevel)
834 case 1:
835 return(TRUE);
836 case 2:
837 case 4:
838 case 5:
839 break;
840 default:
841 SetLastError(ERROR_INVALID_PARAMETER);
842 return(FALSE);
845 /* Enter critical section to prevent AddPrinters() et al. to
846 * modify whilst we're reading in the registry
848 InitializeCriticalSection(&PRINT32_RegistryBlocker);
849 EnterCriticalSection(&PRINT32_RegistryBlocker);
851 /* get a pointer to a list of all printer names in the registry */
852 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Printers, 0, KEY_READ,
853 &hPrinterListKey) !=ERROR_SUCCESS)
855 /* Oh no! An empty list of printers!
856 * (which is a valid configuration anyway)
858 TRACE_(print)("No entries in the Printers part of the registry\n");
861 /* count the number of entries and check if it fits in the buffer
863 while(RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
864 NULL, NULL, NULL, &FileTime)==ERROR_SUCCESS)
866 PrinterNameLength=255;
867 dwIndex++;
869 *lpdwReturned = dwIndex;
870 switch(dwLevel)
872 case 1:
873 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_1A);
874 break;
875 case 2:
876 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_2A);
877 break;
878 case 4:
879 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_4A);
880 break;
881 case 5:
882 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_5A);
883 break;
884 default:
885 dwStructPrinterInfoSize = 0;
886 break;
888 if (dwIndex*dwStructPrinterInfoSize+1 > cbBuf)
889 bCalcSpaceOnly = TRUE;
891 /* the strings which contain e.g. PrinterName, PortName, etc,
892 * are also stored in lpbPrinters, but after the regular structs.
893 * dwNextStringPos will always point to the next free place for a
894 * string.
896 dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize;
898 /* check each entry: if OK, add to list in corresponding INFO .
900 for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++)
902 PrinterNameLength=255;
903 if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
904 NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS)
905 break; /* exit for loop*/
907 /* check whether this printer is allowed in the list
908 * by comparing name to lpszName
910 if (dwType == PRINTER_ENUM_NAME)
911 if (strcmp(PrinterName,lpszName)!=0)
912 continue;
914 switch(dwLevel)
916 case 1:
917 /* FIXME: unimplemented */
918 break;
919 case 2:
920 bCalcSpaceOnly = ENUMPRINTERS_AddInfo2A(PrinterName, lpbPrinters,
921 dwIndex*dwStructPrinterInfoSize,
922 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
923 break;
924 case 4:
925 bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters,
926 dwIndex*dwStructPrinterInfoSize,
927 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
928 break;
929 case 5:
930 bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters,
931 dwIndex*dwStructPrinterInfoSize,
932 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
933 break;
936 RegCloseKey(hPrinterListKey);
937 *lpdwNeeded = dwNextStringPos;
939 if (bCalcSpaceOnly==TRUE)
941 if (lpbPrinters!=NULL)
943 int i;
944 for (i=0; i<cbBuf; i++)
945 lpbPrinters[i]=0;
947 *lpdwReturned=0;
949 LeaveCriticalSection(&PRINT32_RegistryBlocker);
950 return(TRUE);
953 /******************************************************************
954 * EnumPrinters32W [WINSPOOL.175]
957 BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
958 DWORD dwLevel, LPBYTE lpbPrinters,
959 DWORD cbBuf, LPDWORD lpdwNeeded,
960 LPDWORD lpdwReturned)
962 FIXME_(print)("Nearly empty stub\n");
963 *lpdwReturned=0;
964 *lpdwNeeded = 0;
965 return TRUE;
968 /******************************************************************
969 * AddMonitor32A [WINSPOOL.107]
972 BOOL WINAPI AddMonitorA(LPCSTR pName, DWORD Level, LPBYTE pMonitors)
974 FIXME_(print)("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
975 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
976 return FALSE;
979 /******************************************************************
980 * DeletePrinterDriver32A [WINSPOOL.146]
983 BOOL WINAPI
984 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
986 FIXME_(print)("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
987 debugstr_a(pDriverName));
988 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
989 return FALSE;
993 /******************************************************************
994 * DeleteMonitor32A [WINSPOOL.135]
997 BOOL WINAPI
998 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
1000 FIXME_(print)("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
1001 debugstr_a(pMonitorName));
1002 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1003 return FALSE;
1007 /******************************************************************
1008 * DeletePort32A [WINSPOOL.137]
1011 BOOL WINAPI
1012 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
1014 FIXME_(print)("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
1015 debugstr_a(pPortName));
1016 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1017 return FALSE;
1020 /******************************************************************************
1021 * SetPrinter32W [WINSPOOL.214]
1023 BOOL WINAPI
1024 SetPrinterW(
1025 HANDLE hPrinter,
1026 DWORD Level,
1027 LPBYTE pPrinter,
1028 DWORD Command) {
1030 FIXME_(print)("():stub\n");
1031 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1032 return FALSE;
1035 /******************************************************************************
1036 * WritePrinter32 [WINSPOOL.223]
1038 BOOL WINAPI
1039 WritePrinter(
1040 HANDLE hPrinter,
1041 LPVOID pBuf,
1042 DWORD cbBuf,
1043 LPDWORD pcWritten) {
1045 FIXME_(print)("():stub\n");
1046 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1047 return FALSE;
1050 /*****************************************************************************
1051 * AddForm32A [WINSPOOL.103]
1053 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
1055 FIXME_(print)("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
1056 return 1;
1059 /*****************************************************************************
1060 * AddForm32W [WINSPOOL.104]
1062 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
1064 FIXME_(print)("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
1065 return 1;
1068 /*****************************************************************************
1069 * AddJob32A [WINSPOOL.105]
1071 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
1072 DWORD cbBuf, LPDWORD pcbNeeded)
1074 FIXME_(print)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
1075 pcbNeeded);
1076 return 1;
1079 /*****************************************************************************
1080 * AddJob32W [WINSPOOL.106]
1082 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
1083 LPDWORD pcbNeeded)
1085 FIXME_(print)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
1086 pcbNeeded);
1087 return 1;
1090 /*****************************************************************************
1091 * AddPrinter32A [WINSPOOL.117]
1093 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
1095 FIXME_(print)("(%s,%ld,%p): stub\n", pName, Level, pPrinter);
1096 return 0;
1099 /*****************************************************************************
1100 * AddPrinter32W [WINSPOOL.122]
1102 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
1104 FIXME_(print)("(%p,%ld,%p): stub\n", pName, Level, pPrinter);
1105 return 0;
1109 /*****************************************************************************
1110 * ClosePrinter32 [WINSPOOL.126]
1112 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
1114 FIXME_(print)("(%d): stub\n", hPrinter);
1115 return 1;
1118 /*****************************************************************************
1119 * DeleteForm32A [WINSPOOL.133]
1121 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
1123 FIXME_(print)("(%d,%s): stub\n", hPrinter, pFormName);
1124 return 1;
1127 /*****************************************************************************
1128 * DeleteForm32W [WINSPOOL.134]
1130 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
1132 FIXME_(print)("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
1133 return 1;
1136 /*****************************************************************************
1137 * DeletePrinter32 [WINSPOOL.143]
1139 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
1141 FIXME_(print)("(%d): stub\n", hPrinter);
1142 return 1;
1145 /*****************************************************************************
1146 * SetPrinter32A [WINSPOOL.211]
1148 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1149 DWORD Command)
1151 FIXME_(print)("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
1152 return FALSE;
1155 /*****************************************************************************
1156 * SetJob32A [WINSPOOL.209]
1158 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
1159 LPBYTE pJob, DWORD Command)
1161 FIXME_(print)("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1162 Command);
1163 return FALSE;
1166 /*****************************************************************************
1167 * SetJob32W [WINSPOOL.210]
1169 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
1170 LPBYTE pJob, DWORD Command)
1172 FIXME_(print)("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1173 Command);
1174 return FALSE;
1177 /*****************************************************************************
1178 * GetForm32A [WINSPOOL.181]
1180 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1181 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1183 FIXME_(print)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
1184 Level,pForm,cbBuf,pcbNeeded);
1185 return FALSE;
1188 /*****************************************************************************
1189 * GetForm32W [WINSPOOL.182]
1191 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1192 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1194 FIXME_(print)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
1195 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
1196 return FALSE;
1199 /*****************************************************************************
1200 * SetForm32A [WINSPOOL.207]
1202 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1203 LPBYTE pForm)
1205 FIXME_(print)("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1206 return FALSE;
1209 /*****************************************************************************
1210 * SetForm32W [WINSPOOL.208]
1212 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1213 LPBYTE pForm)
1215 FIXME_(print)("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1216 return FALSE;
1219 /*****************************************************************************
1220 * ReadPrinter32 [WINSPOOL.202]
1222 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1223 LPDWORD pNoBytesRead)
1225 FIXME_(print)("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1226 return FALSE;
1229 /*****************************************************************************
1230 * ResetPrinter32A [WINSPOOL.203]
1232 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1234 FIXME_(print)("(%d, %p): stub\n", hPrinter, pDefault);
1235 return FALSE;
1238 /*****************************************************************************
1239 * ResetPrinter32W [WINSPOOL.204]
1241 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1243 FIXME_(print)("(%d, %p): stub\n", hPrinter, pDefault);
1244 return FALSE;
1247 /*****************************************************************************
1248 * GetPrinter32A [WINSPOOL.187]
1250 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1251 DWORD cbBuf, LPDWORD pcbNeeded)
1253 FIXME_(print)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
1254 cbBuf, pcbNeeded);
1255 return FALSE;
1258 /*****************************************************************************
1259 * GetPrinter32W [WINSPOOL.194]
1261 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1262 DWORD cbBuf, LPDWORD pcbNeeded)
1264 FIXME_(print)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
1265 cbBuf, pcbNeeded);
1266 return FALSE;
1269 /*****************************************************************************
1270 * GetPrinterDriver32A [WINSPOOL.190]
1272 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1273 DWORD Level, LPBYTE pDriverInfo,
1274 DWORD cbBuf, LPDWORD pcbNeeded)
1276 FIXME_(print)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1277 Level,pDriverInfo,cbBuf, pcbNeeded);
1278 return FALSE;
1281 /*****************************************************************************
1282 * GetPrinterDriver32W [WINSPOOL.193]
1284 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1285 DWORD Level, LPBYTE pDriverInfo,
1286 DWORD cbBuf, LPDWORD pcbNeeded)
1288 FIXME_(print)("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1289 Level,pDriverInfo,cbBuf, pcbNeeded);
1290 return FALSE;
1292 /*****************************************************************************
1293 * AddPrinterDriver32A [WINSPOOL.120]
1295 BOOL WINAPI AddPrinterDriverA(LPSTR printerName,DWORD level,
1296 LPBYTE pDriverInfo)
1298 FIXME_(print)("(%s,%ld,%p): stub\n",printerName,level,pDriverInfo);
1299 return FALSE;
1301 /*****************************************************************************
1302 * AddPrinterDriver32W [WINSPOOL.121]
1304 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
1305 LPBYTE pDriverInfo)
1307 FIXME_(print)("(%s,%ld,%p): stub\n",debugstr_w(printerName),
1308 level,pDriverInfo);
1309 return FALSE;
1313 /*****************************************************************************
1314 * PrinterProperties [WINSPOOL.201]
1316 * Displays a dialog to set the properties of the printer.
1318 * RETURNS
1319 * nonzero on succes or zero on faillure
1321 * BUGS
1322 * implemented as stub only
1324 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
1325 HANDLE hPrinter /* handle to printer object */
1327 FIXME_(print)("(%d,%d): stub\n", hWnd, hPrinter);
1328 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1329 return FALSE;