Implemented makepath, rand() returns correct range, fixed fputc.
[wine/testsucceed.git] / misc / printdrv.c
blob611a032f9d7ba9ac9a27c3a1f2737676ecd47841
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 "ldt.h"
14 #include "winerror.h"
15 #include "winreg.h"
16 #include "debug.h"
18 CRITICAL_SECTION PRINT32_RegistryBlocker;
20 static char PrinterModel[] = "Printer Model";
21 static char DefaultDevMode[] = "Default DevMode";
22 static char PrinterDriverData[] = "PrinterDriverData";
23 static char Printers[] = "System\\CurrentControlSet\\Control\\Print\\Printers\\";
25 /******************************************************************
26 * StartDoc16 [GDI.377]
29 INT16 WINAPI StartDoc16( HDC16 hdc, const DOCINFO16 *lpdoc )
31 INT16 retVal;
32 TRACE(print,"(%p)\n", lpdoc );
33 TRACE(print,"%d 0x%lx:0x%p 0x%lx:0x%p\n",lpdoc->cbSize,
34 lpdoc->lpszDocName,PTR_SEG_TO_LIN(lpdoc->lpszDocName),
35 lpdoc->lpszOutput,PTR_SEG_TO_LIN(lpdoc->lpszOutput));
36 TRACE(print, "%d %s %s\n",lpdoc->cbSize,
37 (LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszDocName),
38 (LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszOutput));
39 retVal = Escape16(hdc, STARTDOC,
40 strlen((LPSTR)PTR_SEG_TO_LIN(lpdoc->lpszDocName)), lpdoc->lpszDocName, 0);
41 TRACE(print,"Escape16 returned %d\n",retVal);
42 return retVal;
45 /******************************************************************
46 * EndPage16 [GDI.380]
49 INT16 WINAPI EndPage16( HDC16 hdc )
51 INT16 retVal;
52 retVal = Escape16(hdc, NEWFRAME, 0, 0, 0);
53 TRACE(print,"Escape16 returned %d\n",retVal);
54 return retVal;
57 /******************************************************************
58 * StartDoc32A [GDI32.347]
61 INT WINAPI StartDocA(HDC hdc ,const DOCINFOA* doc)
63 FIXME(gdi,"stub\n");
64 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
65 return 0; /* failure*/
68 /*************************************************************************
69 * StartDoc32W [GDI32.348]
72 INT WINAPI StartDocW(HDC hdc, const DOCINFOW* doc) {
73 FIXME(gdi,"stub\n");
74 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
75 return 0; /* failure*/
78 /******************************************************************
79 * StartPage32 [GDI32.349]
82 INT WINAPI StartPage(HDC hdc)
84 FIXME(gdi,"stub\n");
85 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
86 return 0; /* failure*/
89 /******************************************************************
90 * EndPage32 [GDI32.77]
93 INT WINAPI EndPage(HDC hdc)
95 FIXME(gdi,"stub\n");
96 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
97 return 0; /* failure*/
100 /******************************************************************
101 * EndDoc16 [GDI.378]
104 INT16 WINAPI EndDoc16(HDC16 hdc)
106 return Escape16(hdc, ENDDOC, 0, 0, 0);
109 /******************************************************************
110 * EndDoc32 [GDI32.76]
113 INT WINAPI EndDoc(HDC hdc)
115 FIXME(gdi,"stub\n");
116 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
117 return 0; /* failure*/
120 /******************************************************************************
121 * AbortDoc16 [GDI.382]
123 INT16 WINAPI AbortDoc16(HDC16 hdc)
125 return Escape16(hdc, ABORTDOC, 0, 0, 0);
128 /******************************************************************************
129 * AbortDoc32 [GDI32.0]
131 INT WINAPI AbortDoc(HDC hdc)
133 FIXME(gdi, "(%d): stub\n", hdc);
134 return 1;
137 /******************************************************************
138 * DrvGetPrinterDataInternal
140 * Helper for DrvGetPrinterData
142 static DWORD DrvGetPrinterDataInternal(LPSTR RegStr_Printer,
143 LPBYTE lpPrinterData, int cbData, int what)
145 DWORD res = -1;
146 HKEY hkey;
147 DWORD dwType, cbQueryData;
149 if (!(RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey))) {
150 if (what == INT_PD_DEFAULT_DEVMODE) { /* "Default DevMode" */
151 if (!(RegQueryValueExA(hkey, DefaultDevMode, 0, &dwType, 0, &cbQueryData))) {
152 if (!lpPrinterData)
153 res = cbQueryData;
154 else if ((cbQueryData) && (cbQueryData <= cbData)) {
155 cbQueryData = cbData;
156 if (RegQueryValueExA(hkey, DefaultDevMode, 0,
157 &dwType, lpPrinterData, &cbQueryData))
158 res = cbQueryData;
161 } else { /* "Printer Driver" */
162 cbQueryData = 32;
163 RegQueryValueExA(hkey, "Printer Driver", 0,
164 &dwType, lpPrinterData, &cbQueryData);
165 res = cbQueryData;
168 if (hkey) RegCloseKey(hkey);
169 return res;
172 /******************************************************************
173 * DrvGetPrinterData [GDI.282]
176 DWORD WINAPI DrvGetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
177 LPDWORD lpType, LPBYTE lpPrinterData,
178 int cbData, LPDWORD lpNeeded)
180 LPSTR RegStr_Printer;
181 HKEY hkey = 0, hkey2 = 0;
182 DWORD res = 0;
183 DWORD dwType, PrinterAttr, cbPrinterAttr, SetData, size;
185 if (HIWORD(lpPrinter))
186 TRACE(print,"printer %s\n",lpPrinter);
187 else
188 TRACE(print,"printer %p\n",lpPrinter);
189 if (HIWORD(lpProfile))
190 TRACE(print,"profile %s\n",lpProfile);
191 else
192 TRACE(print,"profile %p\n",lpProfile);
193 TRACE(print,"lpType %p\n",lpType);
195 if ((!lpPrinter) || (!lpProfile) || (!lpNeeded))
196 return ERROR_INVALID_PARAMETER;
198 RegStr_Printer = HeapAlloc(GetProcessHeap(), 0,
199 strlen(Printers) + strlen(lpPrinter) + 2);
200 strcpy(RegStr_Printer, Printers);
201 strcat(RegStr_Printer, lpPrinter);
203 if (((DWORD)lpProfile == INT_PD_DEFAULT_DEVMODE) || (HIWORD(lpProfile) &&
204 (!strcmp(lpProfile, DefaultDevMode)))) {
205 size = DrvGetPrinterDataInternal(RegStr_Printer, lpPrinterData, cbData,
206 INT_PD_DEFAULT_DEVMODE);
207 if (size+1) {
208 *lpNeeded = size;
209 if ((lpPrinterData) && (*lpNeeded > cbData))
210 res = ERROR_MORE_DATA;
212 else res = ERROR_INVALID_PRINTER_NAME;
214 else
215 if (((DWORD)lpProfile == INT_PD_DEFAULT_MODEL) || (HIWORD(lpProfile) &&
216 (!strcmp(lpProfile, PrinterModel)))) {
217 *lpNeeded = 32;
218 if (!lpPrinterData) goto failed;
219 if (cbData < 32) {
220 res = ERROR_MORE_DATA;
221 goto failed;
223 size = DrvGetPrinterDataInternal(RegStr_Printer, lpPrinterData, cbData,
224 INT_PD_DEFAULT_MODEL);
225 if ((size+1) && (lpType))
226 *lpType = REG_SZ;
227 else
228 res = ERROR_INVALID_PRINTER_NAME;
230 else
232 if ((res = RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)))
233 goto failed;
234 cbPrinterAttr = 4;
235 if ((res = RegQueryValueExA(hkey, "Attributes", 0,
236 &dwType, (LPBYTE)&PrinterAttr, &cbPrinterAttr)))
237 goto failed;
238 if ((res = RegOpenKeyA(hkey, PrinterDriverData, &hkey2)))
239 goto failed;
240 *lpNeeded = cbData;
241 res = RegQueryValueExA(hkey2, lpProfile, 0,
242 lpType, lpPrinterData, lpNeeded);
243 if ((res != ERROR_CANTREAD) &&
244 ((PrinterAttr &
245 (PRINTER_ATTRIBUTE_ENABLE_BIDI|PRINTER_ATTRIBUTE_NETWORK))
246 == PRINTER_ATTRIBUTE_NETWORK))
248 if (!(res) && (*lpType == REG_DWORD) && (*(LPDWORD)lpPrinterData == -1))
249 res = ERROR_INVALID_DATA;
251 else
253 SetData = -1;
254 RegSetValueExA(hkey2, lpProfile, 0, REG_DWORD, (LPBYTE)&SetData, 4); /* no result returned */
258 failed:
259 if (hkey2) RegCloseKey(hkey2);
260 if (hkey) RegCloseKey(hkey);
261 HeapFree(GetProcessHeap(), 0, RegStr_Printer);
262 return res;
266 /******************************************************************
267 * DrvSetPrinterData [GDI.281]
270 DWORD WINAPI DrvSetPrinterData16(LPSTR lpPrinter, LPSTR lpProfile,
271 DWORD lpType, LPBYTE lpPrinterData,
272 DWORD dwSize)
274 LPSTR RegStr_Printer;
275 HKEY hkey = 0;
276 DWORD res = 0;
278 if (HIWORD(lpPrinter))
279 TRACE(print,"printer %s\n",lpPrinter);
280 else
281 TRACE(print,"printer %p\n",lpPrinter);
282 if (HIWORD(lpProfile))
283 TRACE(print,"profile %s\n",lpProfile);
284 else
285 TRACE(print,"profile %p\n",lpProfile);
286 TRACE(print,"lpType %08lx\n",lpType);
288 if ((!lpPrinter) || (!lpProfile) ||
289 ((DWORD)lpProfile == INT_PD_DEFAULT_MODEL) || (HIWORD(lpProfile) &&
290 (!strcmp(lpProfile, PrinterModel))))
291 return ERROR_INVALID_PARAMETER;
293 RegStr_Printer = HeapAlloc(GetProcessHeap(), 0,
294 strlen(Printers) + strlen(lpPrinter) + 2);
295 strcpy(RegStr_Printer, Printers);
296 strcat(RegStr_Printer, lpPrinter);
298 if (((DWORD)lpProfile == INT_PD_DEFAULT_DEVMODE) || (HIWORD(lpProfile) &&
299 (!strcmp(lpProfile, DefaultDevMode)))) {
300 if ( RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)
301 != ERROR_SUCCESS ||
302 RegSetValueExA(hkey, DefaultDevMode, 0, REG_BINARY,
303 lpPrinterData, dwSize) != ERROR_SUCCESS )
304 res = ERROR_INVALID_PRINTER_NAME;
306 else
308 strcat(RegStr_Printer, "\\");
310 if( (res = RegOpenKeyA(HKEY_LOCAL_MACHINE, RegStr_Printer, &hkey)) ==
311 ERROR_SUCCESS ) {
313 if (!lpPrinterData)
314 res = RegDeleteValueA(hkey, lpProfile);
315 else
316 res = RegSetValueExA(hkey, lpProfile, 0, lpType,
317 lpPrinterData, dwSize);
321 if (hkey) RegCloseKey(hkey);
322 HeapFree(GetProcessHeap(), 0, RegStr_Printer);
323 return res;
327 /******************************************************************
328 * DeviceCapabilities32A [WINSPOOL.151]
331 INT WINAPI DeviceCapabilitiesA(LPCSTR printer,LPCSTR target,WORD z,
332 LPSTR a,LPDEVMODEA b)
334 FIXME(print,"(%s,%s,%d,%p,%p):stub.\n",printer,target,z,a,b);
335 return 1;
339 /*****************************************************************************
340 * DeviceCapabilities32W
342 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
343 WORD fwCapability, LPWSTR pOutput,
344 const DEVMODEW *pDevMode)
346 FIXME(print,"(%p,%p,%d,%p,%p): stub\n",
347 pDevice, pPort, fwCapability, pOutput, pDevMode);
348 return -1;
351 /******************************************************************
352 * DocumentProperties32A [WINSPOOL.155]
355 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
356 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
357 LPDEVMODEA pDevModeInput,DWORD fMode )
359 FIXME(print,"(%d,%d,%s,%p,%p,%ld):stub.\n",
360 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
362 return 1;
366 /*****************************************************************************
367 * DocumentProperties32W
369 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
370 LPWSTR pDeviceName,
371 LPDEVMODEW pDevModeOutput,
372 LPDEVMODEW pDevModeInput, DWORD fMode)
374 FIXME(print,"(%d,%d,%s,%p,%p,%ld): stub\n",
375 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
376 fMode);
377 return -1;
381 /******************************************************************
382 * OpenPrinter32A [WINSPOOL.196]
385 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
386 LPPRINTER_DEFAULTSA pDefault)
388 FIXME(print,"(%s,%p,%p):stub\n",debugstr_a(lpPrinterName), phPrinter,
389 pDefault);
390 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
391 return FALSE;
394 /******************************************************************
395 * OpenPrinter32W [WINSPOOL.197]
398 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
399 LPPRINTER_DEFAULTSW pDefault)
401 FIXME(print,"(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
402 pDefault);
403 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
404 return FALSE;
410 /******************************************************************
411 * ENUMPRINTERS_GetDWORDFromRegistryA internal
413 * Reads a DWORD from registry KeyName
415 * RETURNS
416 * value on OK or NULL on error
418 DWORD ENUMPRINTERS_GetDWORDFromRegistryA(
419 HKEY hPrinterSettings, /* handle to registry key */
420 LPSTR KeyName /* name key to retrieve string from*/
422 DWORD DataSize=8;
423 DWORD DataType;
424 BYTE Data[8];
425 DWORD Result=684;
427 if (RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
428 Data, &DataSize)!=ERROR_SUCCESS)
429 FIXME(print, "Query of register didn't succeed?");
430 if (DataType == REG_DWORD_LITTLE_ENDIAN)
431 Result = Data[0] + (Data[1]<<8) + (Data[2]<<16) + (Data[3]<<24);
432 if (DataType == REG_DWORD_BIG_ENDIAN)
433 Result = Data[3] + (Data[2]<<8) + (Data[1]<<16) + (Data[0]<<24);
434 return(Result);
438 /******************************************************************
439 * ENUMPRINTERS_AddStringFromRegistryA internal
441 * Reads a string from registry KeyName and writes it at
442 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
444 * RETURNS
445 * FALSE if there is still space left in the buffer.
447 BOOL ENUMPRINTERS_AddStringFromRegistryA(
448 HKEY hPrinterSettings, /* handle to registry key */
449 LPSTR KeyName, /* name key to retrieve string from*/
450 LPSTR* Dest, /* pointer to write string addres to */
451 LPBYTE lpbPrinters, /* buffer which receives info*/
452 LPDWORD dwNextStringPos, /* pos in buffer for next string */
453 DWORD dwBufSize, /* max size of buffer in bytes */
454 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
456 DWORD DataSize=34;
457 DWORD DataType;
458 LPSTR Data = (LPSTR) malloc(DataSize*sizeof(char));
460 while(RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
461 Data, &DataSize)==ERROR_MORE_DATA)
463 Data = (LPSTR) realloc(Data, DataSize+2);
466 if (DataType == REG_SZ)
468 *Dest = &lpbPrinters[*dwNextStringPos];
469 *dwNextStringPos += DataSize+1;
470 if (*dwNextStringPos > dwBufSize)
471 bCalcSpaceOnly=TRUE;
472 if (bCalcSpaceOnly==FALSE)
474 if (DataSize==0) /* DataSize = 0 means empty string, even though*/
475 *Dest[0]=0; /* the data itself needs not to be empty */
476 else
477 strcpy(*Dest, Data);
480 else
481 WARN(print,"Expected string setting, got something else from registry");
483 if (Data)
484 free(Data);
485 return(bCalcSpaceOnly);
490 /******************************************************************
491 * ENUMPRINTERS_AddInfo2A internal
493 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
494 * for printer PrinterNameKey.
495 * Note that there is no check whether the information really fits!
497 * RETURNS
498 * FALSE if there is still space left in the buffer.
500 * BUGS:
501 * This function should not only read the registry but also ask the driver
502 * for information.
504 BOOL ENUMPRINTERS_AddInfo2A(
505 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
506 LPBYTE lpbPrinters, /* buffer which receives info*/
507 DWORD dwNextStructPos, /* pos in buffer for struct */
508 LPDWORD dwNextStringPos, /* pos in buffer for next string */
509 DWORD dwBufSize, /* max size of buffer in bytes */
510 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
512 HKEY hPrinterSettings;
513 DWORD DevSize=0;
514 DWORD DataType;
515 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
516 strlen(lpszPrinterName)+2);
517 LPPRINTER_INFO_2A lpPInfo2 = (LPPRINTER_INFO_2A) &lpbPrinters[dwNextStructPos];
519 /* open the registry to find the attributes, etc of the printer */
520 if (lpszPrinterSettings!=NULL)
522 strcpy(lpszPrinterSettings,Printers);
523 strcat(lpszPrinterSettings,lpszPrinterName);
525 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
526 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
528 WARN(print, "The registry did not contain my printer anymore?\n");
530 else
532 lpPInfo2->pServerName = NULL;
533 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
534 "Name", &(lpPInfo2->pPrinterName),
535 lpbPrinters, dwNextStringPos,
536 dwBufSize, bCalcSpaceOnly);
537 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
538 "Share Name", &(lpPInfo2->pShareName),
539 lpbPrinters, dwNextStringPos,
540 dwBufSize, bCalcSpaceOnly);
541 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
542 "Port", &(lpPInfo2->pPortName),
543 lpbPrinters, dwNextStringPos,
544 dwBufSize, bCalcSpaceOnly);
545 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
546 "Printer Driver", &(lpPInfo2->pDriverName),
547 lpbPrinters, dwNextStringPos,
548 dwBufSize, bCalcSpaceOnly);
549 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
550 "Description", &(lpPInfo2->pComment),
551 lpbPrinters, dwNextStringPos,
552 dwBufSize, bCalcSpaceOnly);
553 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
554 "Location", &(lpPInfo2->pLocation),
555 lpbPrinters, dwNextStringPos,
556 dwBufSize, bCalcSpaceOnly);
558 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
559 "Separator File", &(lpPInfo2->pSepFile),
560 lpbPrinters, dwNextStringPos,
561 dwBufSize, bCalcSpaceOnly);
562 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
563 "Print Processor", &(lpPInfo2->pPrintProcessor),
564 lpbPrinters, dwNextStringPos,
565 dwBufSize, bCalcSpaceOnly);
566 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
567 "Datatype", &(lpPInfo2->pDatatype),
568 lpbPrinters, dwNextStringPos,
569 dwBufSize, bCalcSpaceOnly);
570 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
571 "Parameters", &(lpPInfo2->pParameters),
572 lpbPrinters, dwNextStringPos,
573 dwBufSize, bCalcSpaceOnly);
574 lpPInfo2->pSecurityDescriptor = NULL; /* EnumPrinters doesn't return this*/
576 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
577 lpPInfo2->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
578 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
579 lpPInfo2->Priority = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
580 "Priority");
581 lpPInfo2->DefaultPriority = ENUMPRINTERS_GetDWORDFromRegistryA(
582 hPrinterSettings, "Default Priority");
583 lpPInfo2->StartTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
584 "StartTime");
585 lpPInfo2->UntilTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
586 "UntilTime");
587 lpPInfo2->Status = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
588 "Status");
589 lpPInfo2->cJobs = 0; /* FIXME: according to MSDN, this does not
590 * reflect the TotalJobs Key ??? */
591 lpPInfo2->AveragePPM = 0; /* FIXME: according to MSDN, this does not
592 * reflect the TotalPages Key ??? */
594 /* and read the devModes structure... */
595 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
596 NULL, &DevSize); /* should return ERROR_MORE_DATA */
597 lpPInfo2->pDevMode = &lpbPrinters[*dwNextStringPos];
598 *dwNextStringPos += DevSize + 1;
599 if (*dwNextStringPos > dwBufSize)
600 bCalcSpaceOnly=TRUE;
601 if (bCalcSpaceOnly==FALSE)
602 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
603 (LPBYTE)lpPInfo2->pDevMode, &DevSize);
606 if (lpszPrinterSettings)
607 free(lpszPrinterSettings);
609 return(bCalcSpaceOnly);
612 /******************************************************************
613 * ENUMPRINTERS_AddInfo4A internal
615 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
616 * for printer PrinterNameKey.
617 * Note that there is no check whether the information really fits!
619 * RETURNS
620 * FALSE if there is still space left in the buffer.
622 * BUGS:
623 * This function should not exist in Win95 mode, but does anyway.
625 BOOL ENUMPRINTERS_AddInfo4A(
626 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
627 LPBYTE lpbPrinters, /* buffer which receives info*/
628 DWORD dwNextStructPos, /* pos in buffer for struct */
629 LPDWORD dwNextStringPos, /* pos in buffer for next string */
630 DWORD dwBufSize, /* max size of buffer in bytes */
631 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
633 HKEY hPrinterSettings;
634 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
635 strlen(lpszPrinterName)+2);
636 LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos];
638 /* open the registry to find the attributes of the printer */
639 if (lpszPrinterSettings!=NULL)
641 strcpy(lpszPrinterSettings,Printers);
642 strcat(lpszPrinterSettings,lpszPrinterName);
644 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
645 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
647 WARN(print, "The registry did not contain my printer anymore?\n");
649 else
651 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
652 "Name", &(lpPInfo4->pPrinterName),
653 lpbPrinters, dwNextStringPos,
654 dwBufSize, bCalcSpaceOnly);
655 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
656 lpPInfo4->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
657 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
659 if (lpszPrinterSettings)
660 free(lpszPrinterSettings);
662 return(bCalcSpaceOnly);
665 /******************************************************************
666 * ENUMPRINTERS_AddInfo5A internal
668 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
669 * for printer PrinterNameKey.
670 * Settings are read from the registry.
671 * Note that there is no check whether the information really fits!
672 * RETURNS
673 * FALSE if there is still space left in the buffer.
675 BOOL ENUMPRINTERS_AddInfo5A(
676 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
677 LPBYTE lpbPrinters, /* buffer which receives info*/
678 DWORD dwNextStructPos, /* pos in buffer for struct */
679 LPDWORD dwNextStringPos, /* pos in buffer for next string */
680 DWORD dwBufSize, /* max size of buffer in bytes */
681 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
683 HKEY hPrinterSettings;
684 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
685 strlen(lpszPrinterName)+2);
686 LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos];
688 /* open the registry to find the attributes, etc of the printer */
689 if (lpszPrinterSettings!=NULL)
691 strcpy(lpszPrinterSettings,Printers);
692 strcat(lpszPrinterSettings,lpszPrinterName);
694 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
695 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
697 WARN(print, "The registry did not contain my printer anymore?\n");
699 else
701 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
702 "Name", &(lpPInfo5->pPrinterName),
703 lpbPrinters, dwNextStringPos,
704 dwBufSize, bCalcSpaceOnly);
705 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
706 "Port", &(lpPInfo5->pPortName), lpbPrinters,
707 dwNextStringPos, dwBufSize, bCalcSpaceOnly);
708 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
709 lpPInfo5->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
710 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
711 lpPInfo5->DeviceNotSelectedTimeOut
712 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
713 "txTimeout");
714 lpPInfo5->TransmissionRetryTimeout
715 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
716 "dnsTimeout");
719 if (lpszPrinterSettings)
720 free(lpszPrinterSettings);
722 return(bCalcSpaceOnly);
726 /******************************************************************
727 * EnumPrintersA [WINSPOOL.174]
729 * Enumerates the available printers, print servers and print
730 * providers, depending on the specified flags, name and level.
732 * RETURNS:
734 * If level is set to 1:
735 * Not implemented yet!
736 * Returns TRUE with an empty list.
738 * If level is set to 2:
739 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
740 * Returns an array of PRINTER_INFO_2 data structures in the
741 * lpbPrinters buffer. Note that according to MSDN also an
742 * OpenPrinter should be performed on every remote printer.
744 * If level is set to 4 (officially WinNT only):
745 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
746 * Fast: Only the registry is queried to retrieve printer names,
747 * no connection to the driver is made.
748 * Returns an array of PRINTER_INFO_4 data structures in the
749 * lpbPrinters buffer.
751 * If level is set to 5 (officially WinNT4/Win9x only):
752 * Fast: Only the registry is queried to retrieve printer names,
753 * no connection to the driver is made.
754 * Returns an array of PRINTER_INFO_5 data structures in the
755 * lpbPrinters buffer.
757 * If level set to 3 or 6+:
758 * returns zero (faillure!)
760 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
761 * for information.
763 * BUGS:
764 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
765 * - Only levels 2, 4 and 5 are implemented at the moment.
766 * - 16-bit printer drivers are not enumerated.
767 * - Returned amount of bytes used/needed does not match the real Windoze
768 * implementation (as in this implementation, all strings are part
769 * of the buffer, whereas Win32 keeps them somewhere else)
770 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
772 * NOTE:
773 * - In a regular Wine installation, no registry settings for printers
774 * exist, which makes this function return an empty list.
776 BOOL WINAPI EnumPrintersA(
777 DWORD dwType, /* Types of print objects to enumerate */
778 LPSTR lpszName, /* name of objects to enumerate */
779 DWORD dwLevel, /* type of printer info structure */
780 LPBYTE lpbPrinters,/* buffer which receives info*/
781 DWORD cbBuf, /* max size of buffer in bytes */
782 LPDWORD lpdwNeeded,/* pointer to var: # bytes used/needed */
783 LPDWORD lpdwReturned/* number of entries returned */
786 HKEY hPrinterListKey;
787 DWORD dwIndex=0;
788 char PrinterName[255];
789 DWORD PrinterNameLength=255;
790 FILETIME FileTime;
791 DWORD dwNextStringPos; /* position of next space for a string in the buffer*/
792 DWORD dwStructPrinterInfoSize; /* size of a Printer_Info_X structure */
793 BOOL bCalcSpaceOnly=FALSE;/* if TRUE: don't store data, just calculate space*/
795 TRACE(print, "EnumPrintersA\n");
797 /* zero out the data area, and initialise some returns to zero,
798 * to prevent problems
801 int i;
802 for (i=0; i<cbBuf; i++)
803 lpbPrinters[i]=0;
805 *lpdwReturned=0;
806 *lpdwNeeded = 0;
808 /* check for valid Flags */
809 if (dwType != PRINTER_ENUM_LOCAL && dwType != PRINTER_ENUM_NAME)
811 SetLastError(ERROR_INVALID_FLAGS);
812 return(0);
814 switch(dwLevel)
816 case 1:
817 return(TRUE);
818 case 2:
819 case 4:
820 case 5:
821 break;
822 default:
823 SetLastError(ERROR_INVALID_PARAMETER);
824 return(FALSE);
827 /* Enter critical section to prevent AddPrinters() et al. to
828 * modify whilst we're reading in the registry
830 InitializeCriticalSection(&PRINT32_RegistryBlocker);
831 EnterCriticalSection(&PRINT32_RegistryBlocker);
833 /* get a pointer to a list of all printer names in the registry */
834 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Printers, 0, KEY_READ,
835 &hPrinterListKey) !=ERROR_SUCCESS)
837 /* Oh no! An empty list of printers!
838 * (which is a valid configuration anyway)
840 TRACE(print, "No entries in the Printers part of the registry\n");
843 /* count the number of entries and check if it fits in the buffer
845 while(RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
846 NULL, NULL, NULL, &FileTime)==ERROR_SUCCESS)
848 PrinterNameLength=255;
849 dwIndex++;
851 *lpdwReturned = dwIndex;
852 switch(dwLevel)
854 case 1:
855 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_1A);
856 break;
857 case 2:
858 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_2A);
859 break;
860 case 4:
861 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_4A);
862 break;
863 case 5:
864 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_5A);
865 break;
866 default:
867 dwStructPrinterInfoSize = 0;
868 break;
870 if (dwIndex*dwStructPrinterInfoSize+1 > cbBuf)
871 bCalcSpaceOnly = TRUE;
873 /* the strings which contain e.g. PrinterName, PortName, etc,
874 * are also stored in lpbPrinters, but after the regular structs.
875 * dwNextStringPos will always point to the next free place for a
876 * string.
878 dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize;
880 /* check each entry: if OK, add to list in corresponding INFO .
882 for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++)
884 PrinterNameLength=255;
885 if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
886 NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS)
887 break; /* exit for loop*/
889 /* check whether this printer is allowed in the list
890 * by comparing name to lpszName
892 if (dwType == PRINTER_ENUM_NAME)
893 if (strcmp(PrinterName,lpszName)!=0)
894 continue;
896 switch(dwLevel)
898 case 1:
899 /* FIXME: unimplemented */
900 break;
901 case 2:
902 bCalcSpaceOnly = ENUMPRINTERS_AddInfo2A(PrinterName, lpbPrinters,
903 dwIndex*dwStructPrinterInfoSize,
904 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
905 break;
906 case 4:
907 bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters,
908 dwIndex*dwStructPrinterInfoSize,
909 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
910 break;
911 case 5:
912 bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters,
913 dwIndex*dwStructPrinterInfoSize,
914 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
915 break;
918 RegCloseKey(hPrinterListKey);
919 *lpdwNeeded = dwNextStringPos;
921 if (bCalcSpaceOnly==TRUE)
923 int i;
924 for (i=0; i<cbBuf; i++)
925 lpbPrinters[i]=0;
926 *lpdwReturned=0;
928 LeaveCriticalSection(&PRINT32_RegistryBlocker);
929 return(TRUE);
932 /******************************************************************
933 * EnumPrinters32W [WINSPOOL.175]
936 BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
937 DWORD dwLevel, LPBYTE lpbPrinters,
938 DWORD cbBuf, LPDWORD lpdwNeeded,
939 LPDWORD lpdwReturned)
941 FIXME(print,"Nearly empty stub\n");
942 *lpdwReturned=0;
943 *lpdwNeeded = 0;
944 return TRUE;
947 /******************************************************************
948 * AddMonitor32A [WINSPOOL.107]
951 BOOL WINAPI AddMonitorA(LPCSTR pName, DWORD Level, LPBYTE pMonitors)
953 FIXME(print, "(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
954 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
955 return FALSE;
958 /******************************************************************
959 * DeletePrinterDriver32A [WINSPOOL.146]
962 BOOL WINAPI
963 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
965 FIXME(print,"(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
966 debugstr_a(pDriverName));
967 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
968 return FALSE;
972 /******************************************************************
973 * DeleteMonitor32A [WINSPOOL.135]
976 BOOL WINAPI
977 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
979 FIXME(print,"(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
980 debugstr_a(pMonitorName));
981 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
982 return FALSE;
986 /******************************************************************
987 * DeletePort32A [WINSPOOL.137]
990 BOOL WINAPI
991 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
993 FIXME(print,"(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
994 debugstr_a(pPortName));
995 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
996 return FALSE;
999 /******************************************************************************
1000 * SetPrinter32W [WINSPOOL.214]
1002 BOOL WINAPI
1003 SetPrinterW(
1004 HANDLE hPrinter,
1005 DWORD Level,
1006 LPBYTE pPrinter,
1007 DWORD Command) {
1009 FIXME(print,"():stub\n");
1010 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1011 return FALSE;
1014 /******************************************************************************
1015 * WritePrinter32 [WINSPOOL.223]
1017 BOOL WINAPI
1018 WritePrinter(
1019 HANDLE hPrinter,
1020 LPVOID pBuf,
1021 DWORD cbBuf,
1022 LPDWORD pcWritten) {
1024 FIXME(print,"():stub\n");
1025 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1026 return FALSE;
1029 /*****************************************************************************
1030 * AddForm32A [WINSPOOL.103]
1032 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
1034 FIXME(print, "(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
1035 return 1;
1038 /*****************************************************************************
1039 * AddForm32W [WINSPOOL.104]
1041 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
1043 FIXME(print, "(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
1044 return 1;
1047 /*****************************************************************************
1048 * AddJob32A [WINSPOOL.105]
1050 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
1051 DWORD cbBuf, LPDWORD pcbNeeded)
1053 FIXME(print, "(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
1054 pcbNeeded);
1055 return 1;
1058 /*****************************************************************************
1059 * AddJob32W [WINSPOOL.106]
1061 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
1062 LPDWORD pcbNeeded)
1064 FIXME(print, "(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
1065 pcbNeeded);
1066 return 1;
1069 /*****************************************************************************
1070 * AddPrinter32A [WINSPOOL.117]
1072 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
1074 FIXME(print, "(%s,%ld,%p): stub\n", pName, Level, pPrinter);
1075 return 0;
1078 /*****************************************************************************
1079 * AddPrinter32W [WINSPOOL.122]
1081 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
1083 FIXME(print, "(%p,%ld,%p): stub\n", pName, Level, pPrinter);
1084 return 0;
1088 /*****************************************************************************
1089 * ClosePrinter32 [WINSPOOL.126]
1091 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
1093 FIXME(print, "(%d): stub\n", hPrinter);
1094 return 1;
1097 /*****************************************************************************
1098 * DeleteForm32A [WINSPOOL.133]
1100 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
1102 FIXME(print, "(%d,%s): stub\n", hPrinter, pFormName);
1103 return 1;
1106 /*****************************************************************************
1107 * DeleteForm32W [WINSPOOL.134]
1109 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
1111 FIXME(print, "(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
1112 return 1;
1115 /*****************************************************************************
1116 * DeletePrinter32 [WINSPOOL.143]
1118 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
1120 FIXME(print, "(%d): stub\n", hPrinter);
1121 return 1;
1124 /*****************************************************************************
1125 * SetPrinter32A [WINSPOOL.211]
1127 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1128 DWORD Command)
1130 FIXME(print, "(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
1131 return FALSE;
1134 /*****************************************************************************
1135 * SetJob32A [WINSPOOL.209]
1137 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
1138 LPBYTE pJob, DWORD Command)
1140 FIXME(print, "(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1141 Command);
1142 return FALSE;
1145 /*****************************************************************************
1146 * SetJob32W [WINSPOOL.210]
1148 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
1149 LPBYTE pJob, DWORD Command)
1151 FIXME(print, "(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1152 Command);
1153 return FALSE;
1156 /*****************************************************************************
1157 * GetForm32A [WINSPOOL.181]
1159 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1160 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1162 FIXME(print, "(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
1163 Level,pForm,cbBuf,pcbNeeded);
1164 return FALSE;
1167 /*****************************************************************************
1168 * GetForm32W [WINSPOOL.182]
1170 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1171 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1173 FIXME(print, "(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
1174 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
1175 return FALSE;
1178 /*****************************************************************************
1179 * SetForm32A [WINSPOOL.207]
1181 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1182 LPBYTE pForm)
1184 FIXME(print, "(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1185 return FALSE;
1188 /*****************************************************************************
1189 * SetForm32W [WINSPOOL.208]
1191 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1192 LPBYTE pForm)
1194 FIXME(print, "(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1195 return FALSE;
1198 /*****************************************************************************
1199 * ReadPrinter32 [WINSPOOL.202]
1201 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1202 LPDWORD pNoBytesRead)
1204 FIXME(print, "(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1205 return FALSE;
1208 /*****************************************************************************
1209 * ResetPrinter32A [WINSPOOL.203]
1211 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1213 FIXME(print, "(%d, %p): stub\n", hPrinter, pDefault);
1214 return FALSE;
1217 /*****************************************************************************
1218 * ResetPrinter32W [WINSPOOL.204]
1220 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1222 FIXME(print, "(%d, %p): stub\n", hPrinter, pDefault);
1223 return FALSE;
1226 /*****************************************************************************
1227 * GetPrinter32A [WINSPOOL.187]
1229 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1230 DWORD cbBuf, LPDWORD pcbNeeded)
1232 FIXME(print, "(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
1233 cbBuf, pcbNeeded);
1234 return FALSE;
1237 /*****************************************************************************
1238 * GetPrinter32W [WINSPOOL.194]
1240 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1241 DWORD cbBuf, LPDWORD pcbNeeded)
1243 FIXME(print, "(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
1244 cbBuf, pcbNeeded);
1245 return FALSE;
1248 /*****************************************************************************
1249 * GetPrinterDriver32A [WINSPOOL.190]
1251 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1252 DWORD Level, LPBYTE pDriverInfo,
1253 DWORD cbBuf, LPDWORD pcbNeeded)
1255 FIXME(print, "(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1256 Level,pDriverInfo,cbBuf, pcbNeeded);
1257 return FALSE;
1260 /*****************************************************************************
1261 * GetPrinterDriver32W [WINSPOOL.193]
1263 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1264 DWORD Level, LPBYTE pDriverInfo,
1265 DWORD cbBuf, LPDWORD pcbNeeded)
1267 FIXME(print, "(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1268 Level,pDriverInfo,cbBuf, pcbNeeded);
1269 return FALSE;
1271 /*****************************************************************************
1272 * AddPrinterDriver32A [WINSPOOL.120]
1274 BOOL WINAPI AddPrinterDriverA(LPSTR printerName,DWORD level,
1275 LPBYTE pDriverInfo)
1277 FIXME(print, "(%s,%ld,%p): stub\n",printerName,level,pDriverInfo);
1278 return FALSE;
1280 /*****************************************************************************
1281 * AddPrinterDriver32W [WINSPOOL.121]
1283 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
1284 LPBYTE pDriverInfo)
1286 FIXME(print, "(%s,%ld,%p): stub\n",debugstr_w(printerName),
1287 level,pDriverInfo);
1288 return FALSE;