Fixes DeviceCapabilities for DC_PAPERSIZE.
[wine/wine-kai.git] / dlls / winspool / info.c
blobc556972434d07c8af22c543cee8a79fe82429e21
1 /*
2 * WINSPOOL functions
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 "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\\Wine\\Drivers\\";
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, NULL,
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 TRACE("(printerName: %s, pDefault %p\n", lpPrinterName, pDefault);
211 /* Check Printer exists */
212 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
213 ERROR_SUCCESS) {
214 ERR("Can't create Printers key\n");
215 SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */
216 return FALSE;
219 if(RegOpenKeyA(hkeyPrinters, lpPrinterName, &hkeyPrinter)
220 != ERROR_SUCCESS) {
221 WARN("Can't find printer `%s' in registry\n", lpPrinterName);
222 RegCloseKey(hkeyPrinters);
223 SetLastError(ERROR_INVALID_PARAMETER);
224 return FALSE;
226 RegCloseKey(hkeyPrinter);
227 RegCloseKey(hkeyPrinters);
229 if(!phPrinter) /* This seems to be what win95 does anyway */
230 return TRUE;
232 /* Get a place in the opened printer buffer*/
233 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntryA();
234 if(!lpOpenedPrinter) {
235 ERR("Can't allocate printer slot\n");
236 SetLastError(ERROR_OUTOFMEMORY);
237 return FALSE;
240 /* Get the name of the printer */
241 lpOpenedPrinter->lpsPrinterName =
242 HEAP_strdupA( GetProcessHeap(), 0, lpPrinterName );
244 /* Get the unique handle of the printer*/
245 *phPrinter = lpOpenedPrinter->hPrinter;
247 if (pDefault != NULL) {
248 lpOpenedPrinter->lpDefault =
249 HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA));
250 lpOpenedPrinter->lpDefault->pDevMode =
251 HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA));
252 memcpy(lpOpenedPrinter->lpDefault->pDevMode, pDefault->pDevMode,
253 sizeof(DEVMODEA));
254 lpOpenedPrinter->lpDefault->pDatatype =
255 HEAP_strdupA( GetProcessHeap(), 0, pDefault->pDatatype );
256 lpOpenedPrinter->lpDefault->DesiredAccess =
257 pDefault->DesiredAccess;
260 return TRUE;
264 /******************************************************************
265 * OpenPrinter32W [WINSPOOL.197]
268 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
269 LPPRINTER_DEFAULTSW pDefault)
271 FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
272 pDefault);
273 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
274 return FALSE;
280 /******************************************************************
281 * ENUMPRINTERS_GetDWORDFromRegistryA internal
283 * Reads a DWORD from registry KeyName
285 * RETURNS
286 * value on OK or NULL on error
288 DWORD ENUMPRINTERS_GetDWORDFromRegistryA(
289 HKEY hPrinterSettings, /* handle to registry key */
290 LPSTR KeyName /* name key to retrieve string from*/
292 DWORD DataSize=8;
293 DWORD DataType;
294 BYTE Data[8];
295 DWORD Result=684;
297 if (RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
298 Data, &DataSize)!=ERROR_SUCCESS)
299 FIXME("Query of register '%s' didn't succeed?\n", KeyName);
300 if (DataType == REG_DWORD_LITTLE_ENDIAN)
301 Result = Data[0] + (Data[1]<<8) + (Data[2]<<16) + (Data[3]<<24);
302 if (DataType == REG_DWORD_BIG_ENDIAN)
303 Result = Data[3] + (Data[2]<<8) + (Data[1]<<16) + (Data[0]<<24);
304 return(Result);
308 /******************************************************************
309 * ENUMPRINTERS_AddStringFromRegistryA internal
311 * Reads a string from registry KeyName and writes it at
312 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
314 * RETURNS
315 * FALSE if there is still space left in the buffer.
317 BOOL ENUMPRINTERS_AddStringFromRegistryA(
318 HKEY hPrinterSettings, /* handle to registry key */
319 LPSTR KeyName, /* name key to retrieve string from*/
320 LPSTR* Dest, /* pointer to write string addres to */
321 LPBYTE lpbPrinters, /* buffer which receives info*/
322 LPDWORD dwNextStringPos,/* pos in buffer for next string */
323 DWORD dwBufSize, /* max size of buffer in bytes */
324 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
326 DWORD DataSize=34;
327 DWORD DataType, ret;
328 LPSTR Data = (LPSTR) malloc(DataSize*sizeof(char));
330 TRACE("Reading '%s'\n", KeyName);
331 while((ret = RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
332 Data, &DataSize))==ERROR_MORE_DATA)
334 Data = (LPSTR) realloc(Data, DataSize+2);
336 if (ret != ERROR_SUCCESS) {
337 if(!bCalcSpaceOnly)
338 *Dest = NULL;
340 else if (DataType == REG_SZ)
342 if (bCalcSpaceOnly==FALSE)
343 *Dest = &lpbPrinters[*dwNextStringPos];
344 *dwNextStringPos += DataSize+1;
345 if (*dwNextStringPos > dwBufSize)
346 bCalcSpaceOnly=TRUE;
347 if (bCalcSpaceOnly==FALSE)
349 if (DataSize==0) /* DataSize = 0 means empty string, even though*/
350 *Dest[0]=0; /* the data itself needs not to be empty */
351 else
352 strcpy(*Dest, Data);
355 else
356 WARN("Expected string setting, got %lx\n", DataType);
358 if (Data)
359 free(Data);
360 return(bCalcSpaceOnly);
365 /******************************************************************
366 * ENUMPRINTERS_AddInfo2A internal
368 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
369 * for printer PrinterNameKey.
370 * Note that there is no check whether the information really fits!
372 * RETURNS
373 * FALSE if there is still space left in the buffer.
375 * BUGS:
376 * This function should not only read the registry but also ask the driver
377 * for information.
379 BOOL ENUMPRINTERS_AddInfo2A(
380 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
381 LPBYTE lpbPrinters, /* buffer which receives info*/
382 DWORD dwNextStructPos, /* pos in buffer for struct */
383 LPDWORD dwNextStringPos, /* pos in buffer for next string */
384 DWORD dwBufSize, /* max size of buffer in bytes */
385 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
387 HKEY hPrinterSettings;
388 DWORD DevSize=0;
389 DWORD DataType;
390 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
391 strlen(lpszPrinterName)+2);
392 LPPRINTER_INFO_2A lpPInfo2 = (LPPRINTER_INFO_2A) &lpbPrinters[dwNextStructPos];
394 /* open the registry to find the attributes, etc of the printer */
395 if (lpszPrinterSettings!=NULL)
397 strcpy(lpszPrinterSettings,Printers);
398 strcat(lpszPrinterSettings,lpszPrinterName);
400 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
401 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
403 WARN("The registry did not contain my printer anymore?\n");
405 else
407 if (bCalcSpaceOnly==FALSE)
408 lpPInfo2->pServerName = NULL;
409 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
410 "Name", &(lpPInfo2->pPrinterName),
411 lpbPrinters, dwNextStringPos,
412 dwBufSize, bCalcSpaceOnly);
413 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
414 "Share Name", &(lpPInfo2->pShareName),
415 lpbPrinters, dwNextStringPos,
416 dwBufSize, bCalcSpaceOnly);
417 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
418 "Port", &(lpPInfo2->pPortName),
419 lpbPrinters, dwNextStringPos,
420 dwBufSize, bCalcSpaceOnly);
421 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
422 "Printer Driver", &(lpPInfo2->pDriverName),
423 lpbPrinters, dwNextStringPos,
424 dwBufSize, bCalcSpaceOnly);
425 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
426 "Description", &(lpPInfo2->pComment),
427 lpbPrinters, dwNextStringPos,
428 dwBufSize, bCalcSpaceOnly);
429 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
430 "Location", &(lpPInfo2->pLocation),
431 lpbPrinters, dwNextStringPos,
432 dwBufSize, bCalcSpaceOnly);
434 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
435 "Separator File", &(lpPInfo2->pSepFile),
436 lpbPrinters, dwNextStringPos,
437 dwBufSize, bCalcSpaceOnly);
438 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
439 "Print Processor", &(lpPInfo2->pPrintProcessor),
440 lpbPrinters, dwNextStringPos,
441 dwBufSize, bCalcSpaceOnly);
442 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
443 "Datatype", &(lpPInfo2->pDatatype),
444 lpbPrinters, dwNextStringPos,
445 dwBufSize, bCalcSpaceOnly);
446 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
447 "Parameters", &(lpPInfo2->pParameters),
448 lpbPrinters, dwNextStringPos,
449 dwBufSize, bCalcSpaceOnly);
450 if (bCalcSpaceOnly == FALSE)
452 lpPInfo2->pSecurityDescriptor = NULL; /* EnumPrinters doesn't return this*/
454 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
455 lpPInfo2->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
456 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
457 lpPInfo2->Priority = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
458 "Priority");
459 lpPInfo2->DefaultPriority = ENUMPRINTERS_GetDWORDFromRegistryA(
460 hPrinterSettings, "Default Priority");
461 lpPInfo2->StartTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
462 "StartTime");
463 lpPInfo2->UntilTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
464 "UntilTime");
465 lpPInfo2->Status = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
466 "Status");
467 lpPInfo2->cJobs = 0; /* FIXME: according to MSDN, this does not
468 * reflect the TotalJobs Key ??? */
469 lpPInfo2->AveragePPM = 0; /* FIXME: according to MSDN, this does not
470 * reflect the TotalPages Key ??? */
472 /* and read the devModes structure... */
473 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
474 NULL, &DevSize); /* should return ERROR_MORE_DATA */
475 lpPInfo2->pDevMode = (LPDEVMODEA) &lpbPrinters[*dwNextStringPos];
476 *dwNextStringPos += DevSize + 1;
478 if (*dwNextStringPos > dwBufSize)
479 bCalcSpaceOnly=TRUE;
480 if (bCalcSpaceOnly==FALSE)
481 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
482 (LPBYTE)lpPInfo2->pDevMode, &DevSize);
485 if (lpszPrinterSettings)
486 free(lpszPrinterSettings);
488 return(bCalcSpaceOnly);
491 /******************************************************************
492 * ENUMPRINTERS_AddInfo4A internal
494 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
495 * for printer PrinterNameKey.
496 * Note that there is no check whether the information really fits!
498 * RETURNS
499 * FALSE if there is still space left in the buffer.
501 * BUGS:
502 * This function should not exist in Win95 mode, but does anyway.
504 BOOL ENUMPRINTERS_AddInfo4A(
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 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
514 strlen(lpszPrinterName)+2);
515 LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos];
517 /* open the registry to find the attributes of the printer */
518 if (lpszPrinterSettings!=NULL)
520 strcpy(lpszPrinterSettings,Printers);
521 strcat(lpszPrinterSettings,lpszPrinterName);
523 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
524 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
526 WARN("The registry did not contain my printer anymore?\n");
528 else
530 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
531 "Name", &(lpPInfo4->pPrinterName),
532 lpbPrinters, dwNextStringPos,
533 dwBufSize, bCalcSpaceOnly);
534 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
535 if (bCalcSpaceOnly==FALSE)
536 lpPInfo4->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
537 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
539 if (lpszPrinterSettings)
540 free(lpszPrinterSettings);
542 return(bCalcSpaceOnly);
545 /******************************************************************
546 * ENUMPRINTERS_AddInfo5A internal
548 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
549 * for printer PrinterNameKey.
550 * Settings are read from the registry.
551 * Note that there is no check whether the information really fits!
552 * RETURNS
553 * FALSE if there is still space left in the buffer.
555 BOOL ENUMPRINTERS_AddInfo5A(
556 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
557 LPBYTE lpbPrinters, /* buffer which receives info*/
558 DWORD dwNextStructPos, /* pos in buffer for struct */
559 LPDWORD dwNextStringPos, /* pos in buffer for next string */
560 DWORD dwBufSize, /* max size of buffer in bytes */
561 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
563 HKEY hPrinterSettings;
564 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
565 strlen(lpszPrinterName)+2);
566 LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos];
568 /* open the registry to find the attributes, etc of the printer */
569 if (lpszPrinterSettings!=NULL)
571 strcpy(lpszPrinterSettings,Printers);
572 strcat(lpszPrinterSettings,lpszPrinterName);
574 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
575 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
577 WARN("The registry did not contain my printer anymore?\n");
579 else
581 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
582 "Name", &(lpPInfo5->pPrinterName),
583 lpbPrinters, dwNextStringPos,
584 dwBufSize, bCalcSpaceOnly);
585 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
586 "Port", &(lpPInfo5->pPortName), lpbPrinters,
587 dwNextStringPos, dwBufSize, bCalcSpaceOnly);
588 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
589 if (bCalcSpaceOnly == FALSE)
591 lpPInfo5->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
592 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
593 lpPInfo5->DeviceNotSelectedTimeOut
594 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
595 "txTimeout");
596 lpPInfo5->TransmissionRetryTimeout
597 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
598 "dnsTimeout");
602 if (lpszPrinterSettings)
603 free(lpszPrinterSettings);
605 return(bCalcSpaceOnly);
609 /******************************************************************
610 * EnumPrintersA [WINSPOOL.174]
612 * Enumerates the available printers, print servers and print
613 * providers, depending on the specified flags, name and level.
615 * RETURNS:
617 * If level is set to 1:
618 * Not implemented yet!
619 * Returns TRUE with an empty list.
621 * If level is set to 2:
622 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
623 * Returns an array of PRINTER_INFO_2 data structures in the
624 * lpbPrinters buffer. Note that according to MSDN also an
625 * OpenPrinter should be performed on every remote printer.
627 * If level is set to 4 (officially WinNT only):
628 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
629 * Fast: Only the registry is queried to retrieve printer names,
630 * no connection to the driver is made.
631 * Returns an array of PRINTER_INFO_4 data structures in the
632 * lpbPrinters buffer.
634 * If level is set to 5 (officially WinNT4/Win9x only):
635 * Fast: Only the registry is queried to retrieve printer names,
636 * no connection to the driver is made.
637 * Returns an array of PRINTER_INFO_5 data structures in the
638 * lpbPrinters buffer.
640 * If level set to 3 or 6+:
641 * returns zero (faillure!)
643 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
644 * for information.
646 * BUGS:
647 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
648 * - Only levels 2, 4 and 5 are implemented at the moment.
649 * - 16-bit printer drivers are not enumerated.
650 * - Returned amount of bytes used/needed does not match the real Windoze
651 * implementation (as in this implementation, all strings are part
652 * of the buffer, whereas Win32 keeps them somewhere else)
653 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
655 * NOTE:
656 * - In a regular Wine installation, no registry settings for printers
657 * exist, which makes this function return an empty list.
659 BOOL WINAPI EnumPrintersA(
660 DWORD dwType, /* Types of print objects to enumerate */
661 LPSTR lpszName, /* name of objects to enumerate */
662 DWORD dwLevel, /* type of printer info structure */
663 LPBYTE lpbPrinters, /* buffer which receives info */
664 DWORD cbBuf, /* max size of buffer in bytes */
665 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
666 LPDWORD lpdwReturned /* number of entries returned */
669 HKEY hPrinterListKey;
670 DWORD dwIndex=0;
671 char PrinterName[255];
672 DWORD PrinterNameLength=255;
673 FILETIME FileTime;
674 DWORD dwNextStringPos; /* position of next space for a string in the buffer*/
675 DWORD dwStructPrinterInfoSize; /* size of a Printer_Info_X structure */
676 BOOL bCalcSpaceOnly=FALSE;/*if TRUE: don't store data, just calculate space*/
678 TRACE("entered.\n");
680 /* test whether we're requested to really fill in. If so,
681 * zero out the data area, and initialise some returns to zero,
682 * to prevent problems
684 if (lpbPrinters==NULL || cbBuf==0)
685 bCalcSpaceOnly=TRUE;
686 else
688 int i;
689 for (i=0; i<cbBuf; i++)
690 lpbPrinters[i]=0;
692 *lpdwReturned=0;
693 *lpdwNeeded = 0;
695 /* check for valid Flags */
696 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME)))
698 FIXME("dwType = %08lx\n", dwType);
699 SetLastError(ERROR_INVALID_FLAGS);
700 return(0);
702 switch(dwLevel)
704 case 1:
705 return(TRUE);
706 case 2:
707 case 4:
708 case 5:
709 break;
710 default:
711 SetLastError(ERROR_INVALID_LEVEL);
712 return(FALSE);
715 /* Enter critical section to prevent AddPrinters() et al. to
716 * modify whilst we're reading in the registry
718 InitializeCriticalSection(&PRINT32_RegistryBlocker);
719 EnterCriticalSection(&PRINT32_RegistryBlocker);
721 /* get a pointer to a list of all printer names in the registry */
722 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Printers, 0, KEY_READ,
723 &hPrinterListKey) !=ERROR_SUCCESS)
725 /* Oh no! An empty list of printers!
726 * (which is a valid configuration anyway)
728 TRACE("No entries in the Printers part of the registry\n");
731 /* count the number of entries and check if it fits in the buffer
733 while(RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
734 NULL, NULL, NULL, &FileTime)==ERROR_SUCCESS)
736 PrinterNameLength=255;
737 dwIndex++;
739 *lpdwReturned = dwIndex;
740 switch(dwLevel)
742 case 1:
743 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_1A);
744 break;
745 case 2:
746 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_2A);
747 break;
748 case 4:
749 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_4A);
750 break;
751 case 5:
752 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_5A);
753 break;
754 default:
755 dwStructPrinterInfoSize = 0;
756 break;
758 if (dwIndex*dwStructPrinterInfoSize+1 > cbBuf)
759 bCalcSpaceOnly = TRUE;
761 /* the strings which contain e.g. PrinterName, PortName, etc,
762 * are also stored in lpbPrinters, but after the regular structs.
763 * dwNextStringPos will always point to the next free place for a
764 * string.
766 dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize;
768 /* check each entry: if OK, add to list in corresponding INFO .
770 for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++)
772 PrinterNameLength=255;
773 if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
774 NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS)
775 break; /* exit for loop*/
776 TRACE("Got printer '%s'\n", PrinterName);
778 /* check whether this printer is allowed in the list
779 * by comparing name to lpszName
781 if (dwType & PRINTER_ENUM_NAME)
782 if (strcmp(PrinterName,lpszName)!=0)
783 continue;
785 switch(dwLevel)
787 case 1:
788 /* FIXME: unimplemented */
789 break;
790 case 2:
791 bCalcSpaceOnly = ENUMPRINTERS_AddInfo2A(PrinterName, lpbPrinters,
792 dwIndex*dwStructPrinterInfoSize,
793 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
794 break;
795 case 4:
796 bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters,
797 dwIndex*dwStructPrinterInfoSize,
798 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
799 break;
800 case 5:
801 bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters,
802 dwIndex*dwStructPrinterInfoSize,
803 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
804 break;
807 RegCloseKey(hPrinterListKey);
808 LeaveCriticalSection(&PRINT32_RegistryBlocker);
809 *lpdwNeeded = dwNextStringPos + 10; /*Hack*/
811 if (bCalcSpaceOnly==TRUE)
813 if (lpbPrinters!=NULL)
815 int i;
816 for (i=0; i<cbBuf; i++)
817 lpbPrinters[i]=0;
819 *lpdwReturned=0;
820 SetLastError(ERROR_INSUFFICIENT_BUFFER);
821 return FALSE;
823 return(TRUE);
826 /******************************************************************
827 * EnumPrinters32W [WINSPOOL.175]
830 BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
831 DWORD dwLevel, LPBYTE lpbPrinters,
832 DWORD cbBuf, LPDWORD lpdwNeeded,
833 LPDWORD lpdwReturned)
835 FIXME("Nearly empty stub\n");
836 *lpdwReturned=0;
837 *lpdwNeeded = 0;
838 return TRUE;
841 /******************************************************************
842 * AddMonitor32A [WINSPOOL.107]
845 BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors)
847 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
848 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
849 return FALSE;
852 /******************************************************************
853 * DeletePrinterDriver32A [WINSPOOL.146]
856 BOOL WINAPI
857 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
859 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
860 debugstr_a(pDriverName));
861 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
862 return FALSE;
866 /******************************************************************
867 * DeleteMonitor32A [WINSPOOL.135]
870 BOOL WINAPI
871 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
873 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
874 debugstr_a(pMonitorName));
875 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
876 return FALSE;
880 /******************************************************************
881 * DeletePort32A [WINSPOOL.137]
884 BOOL WINAPI
885 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
887 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
888 debugstr_a(pPortName));
889 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
890 return FALSE;
893 /******************************************************************************
894 * SetPrinter32W [WINSPOOL.214]
896 BOOL WINAPI
897 SetPrinterW(
898 HANDLE hPrinter,
899 DWORD Level,
900 LPBYTE pPrinter,
901 DWORD Command) {
903 FIXME("():stub\n");
904 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
905 return FALSE;
908 /******************************************************************************
909 * WritePrinter32 [WINSPOOL.223]
911 BOOL WINAPI
912 WritePrinter(
913 HANDLE hPrinter,
914 LPVOID pBuf,
915 DWORD cbBuf,
916 LPDWORD pcWritten) {
918 FIXME("():stub\n");
919 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
920 return FALSE;
923 /*****************************************************************************
924 * AddForm32A [WINSPOOL.103]
926 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
928 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
929 return 1;
932 /*****************************************************************************
933 * AddForm32W [WINSPOOL.104]
935 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
937 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
938 return 1;
941 /*****************************************************************************
942 * AddJob32A [WINSPOOL.105]
944 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
945 DWORD cbBuf, LPDWORD pcbNeeded)
947 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
948 pcbNeeded);
949 return 1;
952 /*****************************************************************************
953 * AddJob32W [WINSPOOL.106]
955 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
956 LPDWORD pcbNeeded)
958 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
959 pcbNeeded);
960 return 1;
963 /*****************************************************************************
964 * AddPrinter32A [WINSPOOL.117]
966 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
968 PRINTER_INFO_2A *pi = (PRINTER_INFO_2A *) pPrinter;
970 HANDLE retval;
971 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
973 TRACE("(%s,%ld,%p)\n", pName, Level, pPrinter);
975 if(pName != NULL) {
976 FIXME("pName = `%s' - unsupported\n", pName);
977 SetLastError(ERROR_INVALID_PARAMETER);
978 return 0;
980 if(Level != 2) {
981 WARN("Level = %ld\n", Level);
982 SetLastError(ERROR_INVALID_LEVEL);
983 return 0;
985 if(!pPrinter) {
986 SetLastError(ERROR_INVALID_PARAMETER);
987 return 0;
989 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
990 ERROR_SUCCESS) {
991 ERR("Can't create Printers key\n");
992 return 0;
994 if(RegOpenKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
995 ERROR_SUCCESS) {
996 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
997 RegCloseKey(hkeyPrinter);
998 RegCloseKey(hkeyPrinters);
999 return 0;
1001 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1002 ERROR_SUCCESS) {
1003 ERR("Can't create Drivers key\n");
1004 RegCloseKey(hkeyPrinters);
1005 return 0;
1007 if(RegOpenKeyA(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
1008 ERROR_SUCCESS) {
1009 WARN("Can't find driver `%s'\n", pi->pDriverName);
1010 RegCloseKey(hkeyPrinters);
1011 RegCloseKey(hkeyDrivers);
1012 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
1013 return 0;
1015 RegCloseKey(hkeyDriver);
1016 RegCloseKey(hkeyDrivers);
1017 if(strcasecmp(pi->pPrintProcessor, "WinPrint")) { /* FIXME */
1018 WARN("Can't find processor `%s'\n", pi->pPrintProcessor);
1019 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
1020 RegCloseKey(hkeyPrinters);
1021 return 0;
1023 if(RegCreateKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
1024 ERROR_SUCCESS) {
1025 WARN("Can't create printer `%s'\n", pi->pPrinterName);
1026 SetLastError(ERROR_INVALID_PRINTER_NAME);
1027 RegCloseKey(hkeyPrinters);
1028 return 0;
1030 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
1031 (LPSTR)&pi->Attributes, sizeof(DWORD));
1032 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY,
1033 (LPSTR)&pi->pDevMode,
1034 pi->pDevMode ? pi->pDevMode->dmSize : 0);
1035 RegSetValueExA(hkeyPrinter, "Description", 0, REG_SZ, pi->pComment, 0);
1036 RegSetValueExA(hkeyPrinter, "Location", 0, REG_SZ, pi->pLocation, 0);
1037 RegSetValueExA(hkeyPrinter, "Name", 0, REG_SZ, pi->pPrinterName, 0);
1038 RegSetValueExA(hkeyPrinter, "Parameters", 0, REG_SZ, pi->pParameters, 0);
1039 RegSetValueExA(hkeyPrinter, "Port", 0, REG_SZ, pi->pPortName, 0);
1040 RegSetValueExA(hkeyPrinter, "Print Processor", 0, REG_SZ,
1041 pi->pPrintProcessor, 0);
1042 RegSetValueExA(hkeyPrinter, "Printer Driver", 0, REG_SZ, pi->pDriverName,
1044 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
1045 (LPSTR)&pi->Priority, sizeof(DWORD));
1046 RegSetValueExA(hkeyPrinter, "Separator File", 0, REG_SZ, pi->pSepFile, 0);
1047 RegSetValueExA(hkeyPrinter, "Share Name", 0, REG_SZ, pi->pShareName, 0);
1048 RegSetValueExA(hkeyPrinter, "Start Time", 0, REG_DWORD,
1049 (LPSTR)&pi->StartTime, sizeof(DWORD));
1050 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
1051 (LPSTR)&pi->Status, sizeof(DWORD));
1052 RegSetValueExA(hkeyPrinter, "Until Time", 0, REG_DWORD,
1053 (LPSTR)&pi->UntilTime, sizeof(DWORD));
1055 RegCloseKey(hkeyPrinter);
1056 RegCloseKey(hkeyPrinters);
1057 if(!OpenPrinterA(pi->pPrinterName, &retval, NULL)) {
1058 ERR("OpenPrinter failing\n");
1059 return 0;
1061 return retval;
1064 /*****************************************************************************
1065 * AddPrinter32W [WINSPOOL.122]
1067 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
1069 FIXME("(%p,%ld,%p): stub\n", pName, Level, pPrinter);
1070 return 0;
1074 /*****************************************************************************
1075 * ClosePrinter32 [WINSPOOL.126]
1077 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
1079 LPOPENEDPRINTERA lpOpenedPrinter;
1081 TRACE("Handle %d\n", hPrinter);
1083 if (!pOpenedPrinterDPA)
1084 return FALSE;
1086 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
1088 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
1089 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
1090 lpOpenedPrinter->lpsPrinterName = NULL;
1092 /* Free the memory of lpDefault if it has been initialized*/
1093 if(lpOpenedPrinter->lpDefault != NULL)
1095 HeapFree(GetProcessHeap(), 0,
1096 lpOpenedPrinter->lpDefault->pDevMode);
1097 HeapFree(GetProcessHeap(), 0,
1098 lpOpenedPrinter->lpDefault->pDatatype);
1099 HeapFree(GetProcessHeap(), 0,
1100 lpOpenedPrinter->lpDefault);
1101 lpOpenedPrinter->lpDefault = NULL;
1104 lpOpenedPrinter->hPrinter = -1;
1106 return TRUE;
1108 return FALSE;
1111 /*****************************************************************************
1112 * DeleteForm32A [WINSPOOL.133]
1114 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
1116 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
1117 return 1;
1120 /*****************************************************************************
1121 * DeleteForm32W [WINSPOOL.134]
1123 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
1125 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
1126 return 1;
1129 /*****************************************************************************
1130 * DeletePrinter32 [WINSPOOL.143]
1132 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
1134 FIXME("(%d): stub\n", hPrinter);
1135 return 1;
1138 /*****************************************************************************
1139 * SetPrinter32A [WINSPOOL.211]
1141 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1142 DWORD Command)
1144 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
1145 return FALSE;
1148 /*****************************************************************************
1149 * SetJob32A [WINSPOOL.209]
1151 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
1152 LPBYTE pJob, DWORD Command)
1154 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1155 Command);
1156 return FALSE;
1159 /*****************************************************************************
1160 * SetJob32W [WINSPOOL.210]
1162 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
1163 LPBYTE pJob, DWORD Command)
1165 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1166 Command);
1167 return FALSE;
1170 /*****************************************************************************
1171 * GetForm32A [WINSPOOL.181]
1173 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1174 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1176 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
1177 Level,pForm,cbBuf,pcbNeeded);
1178 return FALSE;
1181 /*****************************************************************************
1182 * GetForm32W [WINSPOOL.182]
1184 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1185 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1187 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
1188 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
1189 return FALSE;
1192 /*****************************************************************************
1193 * SetForm32A [WINSPOOL.207]
1195 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1196 LPBYTE pForm)
1198 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1199 return FALSE;
1202 /*****************************************************************************
1203 * SetForm32W [WINSPOOL.208]
1205 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1206 LPBYTE pForm)
1208 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1209 return FALSE;
1212 /*****************************************************************************
1213 * ReadPrinter32 [WINSPOOL.202]
1215 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1216 LPDWORD pNoBytesRead)
1218 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1219 return FALSE;
1222 /*****************************************************************************
1223 * ResetPrinter32A [WINSPOOL.203]
1225 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1227 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1228 return FALSE;
1231 /*****************************************************************************
1232 * ResetPrinter32W [WINSPOOL.204]
1234 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1236 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1237 return FALSE;
1241 /*****************************************************************************
1242 * WINSPOOL_GetStringFromRegA
1244 * Get ValueName from hkey storing result in str. buflen is space left in str
1246 static BOOL WINSPOOL_GetStringFromRegA(HKEY hkey, LPCSTR ValueName, LPSTR ptr,
1247 DWORD buflen, DWORD *needed)
1249 DWORD sz = buflen, type;
1250 LONG ret;
1252 ret = RegQueryValueExA(hkey, ValueName, 0, &type, ptr, &sz);
1254 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1255 ERR("Got ret = %ld\n", ret);
1256 return FALSE;
1258 *needed = sz;
1259 return TRUE;
1262 /*********************************************************************
1263 * WINSPOOL_GetPrinter_2A
1265 * Fills out a PRINTER_INFO_2A struct storing the strings in buf.
1267 static BOOL WINSPOOL_GetPrinter_2A(HKEY hkeyPrinter, PRINTER_INFO_2A *pi2,
1268 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
1270 DWORD size, left = cbBuf;
1271 BOOL space = (cbBuf > 0);
1272 LPBYTE ptr = buf;
1274 *pcbNeeded = 0;
1276 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
1277 if(space && size <= left) {
1278 pi2->pPrinterName = ptr;
1279 ptr += size;
1280 left -= size;
1281 } else
1282 space = FALSE;
1283 *pcbNeeded += size;
1285 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, left, &size);
1286 if(space && size <= left) {
1287 pi2->pPortName = ptr;
1288 ptr += size;
1289 left -= size;
1290 } else
1291 space = FALSE;
1292 *pcbNeeded += size;
1294 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Printer Driver", ptr, left,
1295 &size);
1296 if(space && size <= left) {
1297 pi2->pDriverName = ptr;
1298 ptr += size;
1299 left -= size;
1300 } else
1301 space = FALSE;
1302 *pcbNeeded += size;
1304 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Default DevMode", ptr, left,
1305 &size);
1306 if(space && size <= left) {
1307 pi2->pDevMode = (LPDEVMODEA)ptr;
1308 ptr += size;
1309 left -= size;
1310 } else
1311 space = FALSE;
1312 *pcbNeeded += size;
1314 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Print Processor", ptr, left,
1315 &size);
1316 if(space && size <= left) {
1317 pi2->pPrintProcessor = ptr;
1318 ptr += size;
1319 left -= size;
1320 } else
1321 space = FALSE;
1322 *pcbNeeded += size;
1324 if(!space && pi2) /* zero out pi2 if we can't completely fill buf */
1325 memset(pi2, 0, sizeof(*pi2));
1327 return space;
1330 /*********************************************************************
1331 * WINSPOOL_GetPrinter_4A
1333 * Fills out a PRINTER_INFO_4A struct storing the strings in buf.
1335 static BOOL WINSPOOL_GetPrinter_4A(HKEY hkeyPrinter, PRINTER_INFO_4A *pi4,
1336 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
1338 DWORD size, left = cbBuf;
1339 BOOL space = (cbBuf > 0);
1340 LPBYTE ptr = buf;
1342 *pcbNeeded = 0;
1344 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
1345 if(space && size <= left) {
1346 pi4->pPrinterName = ptr;
1347 ptr += size;
1348 left -= size;
1349 } else
1350 space = FALSE;
1352 *pcbNeeded += size;
1354 if(!space && pi4) /* zero out pi4 if we can't completely fill buf */
1355 memset(pi4, 0, sizeof(*pi4));
1357 return space;
1360 /*********************************************************************
1361 * WINSPOOL_GetPrinter_5A
1363 * Fills out a PRINTER_INFO_5A struct storing the strings in buf.
1365 static BOOL WINSPOOL_GetPrinter_5A(HKEY hkeyPrinter, PRINTER_INFO_5A *pi5,
1366 LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded)
1368 DWORD size, left = cbBuf;
1369 BOOL space = (cbBuf > 0);
1370 LPBYTE ptr = buf;
1372 *pcbNeeded = 0;
1374 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size);
1375 if(space && size <= left) {
1376 pi5->pPrinterName = ptr;
1377 ptr += size;
1378 left -= size;
1379 } else
1380 space = FALSE;
1381 *pcbNeeded += size;
1383 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, left, &size);
1384 if(space && size <= left) {
1385 pi5->pPortName = ptr;
1386 ptr += size;
1387 left -= size;
1388 } else
1389 space = FALSE;
1390 *pcbNeeded += size;
1392 if(!space && pi5) /* zero out pi5 if we can't completely fill buf */
1393 memset(pi5, 0, sizeof(*pi5));
1395 return space;
1398 /*****************************************************************************
1399 * GetPrinterA [WINSPOOL.187]
1401 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1402 DWORD cbBuf, LPDWORD pcbNeeded)
1404 OPENEDPRINTERA *lpOpenedPrinter;
1405 DWORD size, needed = 0;
1406 LPBYTE ptr = NULL;
1407 HKEY hkeyPrinter, hkeyPrinters;
1408 BOOL ret;
1410 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1412 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
1413 if(!lpOpenedPrinter) {
1414 SetLastError(ERROR_INVALID_HANDLE);
1415 return FALSE;
1417 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1418 ERROR_SUCCESS) {
1419 ERR("Can't create Printers key\n");
1420 return FALSE;
1422 if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1423 != ERROR_SUCCESS) {
1424 ERR("Can't find opened printer `%s' in registry\n",
1425 lpOpenedPrinter->lpsPrinterName);
1426 RegCloseKey(hkeyPrinters);
1427 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1428 return FALSE;
1431 switch(Level) {
1432 case 2:
1434 PRINTER_INFO_2A *pi2 = (PRINTER_INFO_2A *)pPrinter;
1436 size = sizeof(PRINTER_INFO_2A);
1437 if(size <= cbBuf) {
1438 ptr = pPrinter + size;
1439 cbBuf -= size;
1440 memset(pPrinter, 0, size);
1441 } else {
1442 pi2 = NULL;
1443 cbBuf = 0;
1445 ret = WINSPOOL_GetPrinter_2A(hkeyPrinter, pi2, ptr, cbBuf, &needed);
1446 needed += size;
1447 break;
1450 case 4:
1452 PRINTER_INFO_4A *pi4 = (PRINTER_INFO_4A *)pPrinter;
1454 size = sizeof(PRINTER_INFO_4A);
1455 if(size <= cbBuf) {
1456 ptr = pPrinter + size;
1457 cbBuf -= size;
1458 memset(pPrinter, 0, size);
1459 } else {
1460 pi4 = NULL;
1461 cbBuf = 0;
1463 ret = WINSPOOL_GetPrinter_4A(hkeyPrinter, pi4, ptr, cbBuf, &needed);
1464 needed += size;
1465 break;
1469 case 5:
1471 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A *)pPrinter;
1473 size = sizeof(PRINTER_INFO_5A);
1474 if(size <= cbBuf) {
1475 ptr = pPrinter + size;
1476 cbBuf -= size;
1477 memset(pPrinter, 0, size);
1478 } else {
1479 pi5 = NULL;
1480 cbBuf = 0;
1483 ret = WINSPOOL_GetPrinter_5A(hkeyPrinter, pi5, ptr, cbBuf, &needed);
1484 needed += size;
1485 break;
1488 default:
1489 FIXME("Unimplemented level %ld\n", Level);
1490 SetLastError(ERROR_INVALID_LEVEL);
1491 RegCloseKey(hkeyPrinters);
1492 RegCloseKey(hkeyPrinter);
1493 return FALSE;
1496 RegCloseKey(hkeyPrinter);
1497 RegCloseKey(hkeyPrinters);
1499 if(pcbNeeded) *pcbNeeded = needed;
1500 if(!ret)
1501 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1502 return ret;
1506 /*****************************************************************************
1507 * GetPrinterW [WINSPOOL.194]
1509 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1510 DWORD cbBuf, LPDWORD pcbNeeded)
1512 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
1513 cbBuf, pcbNeeded);
1514 return FALSE;
1518 /*****************************************************************************
1519 * GetPrinterDriver32A [WINSPOOL.190]
1521 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1522 DWORD Level, LPBYTE pDriverInfo,
1523 DWORD cbBuf, LPDWORD pcbNeeded)
1525 OPENEDPRINTERA *lpOpenedPrinter;
1526 char DriverName[100];
1527 DWORD ret, type, size, dw, needed = 0;
1528 LPBYTE ptr = NULL;
1529 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
1531 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,pEnvironment,
1532 Level,pDriverInfo,cbBuf, pcbNeeded);
1534 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
1535 if(!lpOpenedPrinter) {
1536 SetLastError(ERROR_INVALID_HANDLE);
1537 return FALSE;
1539 if(pEnvironment) {
1540 FIXME("pEnvironment = `%s'\n", pEnvironment);
1541 SetLastError(ERROR_INVALID_ENVIRONMENT);
1542 return FALSE;
1544 if(Level < 1 || Level > 3) {
1545 SetLastError(ERROR_INVALID_LEVEL);
1546 return FALSE;
1548 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1549 ERROR_SUCCESS) {
1550 ERR("Can't create Printers key\n");
1551 return FALSE;
1553 if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1554 != ERROR_SUCCESS) {
1555 ERR("Can't find opened printer `%s' in registry\n",
1556 lpOpenedPrinter->lpsPrinterName);
1557 RegCloseKey(hkeyPrinters);
1558 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1559 return FALSE;
1561 size = sizeof(DriverName);
1562 ret = RegQueryValueExA(hkeyPrinter, "Printer Driver", 0, &type, DriverName,
1563 &size);
1564 RegCloseKey(hkeyPrinter);
1565 RegCloseKey(hkeyPrinters);
1566 if(ret != ERROR_SUCCESS) {
1567 ERR("Can't get DriverName for printer `%s'\n",
1568 lpOpenedPrinter->lpsPrinterName);
1569 return FALSE;
1571 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1572 ERROR_SUCCESS) {
1573 ERR("Can't create Drivers key\n");
1574 return FALSE;
1576 if(RegOpenKeyA(hkeyDrivers, DriverName, &hkeyDriver)
1577 != ERROR_SUCCESS) {
1578 ERR("Can't find driver `%s' in registry\n", DriverName);
1579 RegCloseKey(hkeyDrivers);
1580 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1581 return FALSE;
1584 switch(Level) {
1585 case 1:
1586 size = sizeof(DRIVER_INFO_1A);
1587 break;
1588 case 2:
1589 size = sizeof(DRIVER_INFO_2A);
1590 break;
1591 case 3:
1592 size = sizeof(DRIVER_INFO_3A);
1593 break;
1594 default:
1595 ERR("Invalid level\n");
1596 return FALSE;
1599 if(size <= cbBuf) {
1600 ptr = pDriverInfo + size;
1601 cbBuf -= size;
1602 } else
1603 cbBuf = 0;
1604 needed = size;
1606 size = strlen(DriverName) + 1;
1607 if(size <= cbBuf) {
1608 cbBuf -= size;
1609 strcpy(ptr, DriverName);
1610 if(Level == 1)
1611 ((DRIVER_INFO_1A *)pDriverInfo)->pName = ptr;
1612 else
1613 ((DRIVER_INFO_2A *)pDriverInfo)->pName = ptr;
1614 ptr += size;
1616 needed += size;
1618 if(Level > 1) {
1619 DRIVER_INFO_2A *di2 = (DRIVER_INFO_2A *)pDriverInfo;
1621 size = sizeof(dw);
1622 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw,
1623 &size) !=
1624 ERROR_SUCCESS)
1625 WARN("Can't get Version\n");
1626 else if(cbBuf)
1627 di2->cVersion = dw;
1629 size = strlen("Wine") + 1; /* FIXME */
1630 if(size <= cbBuf) {
1631 cbBuf -= size;
1632 strcpy(ptr, "Wine");
1633 di2->pEnvironment = ptr;
1634 ptr += size;
1635 } else
1636 cbBuf = 0;
1637 needed += size;
1639 WINSPOOL_GetStringFromRegA(hkeyDriver, "Driver", ptr, cbBuf, &size);
1640 if(cbBuf && size <= cbBuf) {
1641 di2->pDriverPath = ptr;
1642 ptr += size;
1643 } else
1644 cbBuf = 0;
1645 needed += size;
1647 WINSPOOL_GetStringFromRegA(hkeyDriver, "Data File", ptr, cbBuf, &size);
1648 if(cbBuf && size <= cbBuf) {
1649 di2->pDataFile = ptr;
1650 ptr += size;
1651 } else
1652 cbBuf = 0;
1653 needed += size;
1655 WINSPOOL_GetStringFromRegA(hkeyDriver, "Configuration File", ptr,
1656 cbBuf, &size);
1657 if(cbBuf && size <= cbBuf) {
1658 di2->pConfigFile = ptr;
1659 ptr += size;
1660 } else
1661 cbBuf = 0;
1662 needed += size;
1665 if(Level > 2) {
1666 DRIVER_INFO_3A *di3 = (DRIVER_INFO_3A *)pDriverInfo;
1668 WINSPOOL_GetStringFromRegA(hkeyDriver, "Help File", ptr, cbBuf, &size);
1669 if(cbBuf && size <= cbBuf) {
1670 di3->pHelpFile = ptr;
1671 ptr += size;
1672 } else
1673 cbBuf = 0;
1674 needed += size;
1676 WINSPOOL_GetStringFromRegA(hkeyDriver, "Dependent Files", ptr, cbBuf,
1677 &size);
1678 if(cbBuf && size <= cbBuf) {
1679 di3->pDependentFiles = ptr;
1680 ptr += size;
1681 } else
1682 cbBuf = 0;
1683 needed += size;
1685 WINSPOOL_GetStringFromRegA(hkeyDriver, "Monitor", ptr, cbBuf, &size);
1686 if(cbBuf && size <= cbBuf) {
1687 di3->pMonitorName = ptr;
1688 ptr += size;
1689 } else
1690 cbBuf = 0;
1691 needed += size;
1693 WINSPOOL_GetStringFromRegA(hkeyDriver, "DataType", ptr, cbBuf, &size);
1694 if(cbBuf && size <= cbBuf) {
1695 di3->pDefaultDataType = ptr;
1696 ptr += size;
1697 } else
1698 cbBuf = 0;
1699 needed += size;
1701 RegCloseKey(hkeyDriver);
1702 RegCloseKey(hkeyDrivers);
1704 if(pcbNeeded) *pcbNeeded = needed;
1705 if(cbBuf) return TRUE;
1706 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1707 return FALSE;
1710 /*****************************************************************************
1711 * GetPrinterDriver32W [WINSPOOL.193]
1713 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1714 DWORD Level, LPBYTE pDriverInfo,
1715 DWORD cbBuf, LPDWORD pcbNeeded)
1717 FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1718 Level,pDriverInfo,cbBuf, pcbNeeded);
1719 return FALSE;
1722 /*****************************************************************************
1723 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1725 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1726 DWORD Level, LPBYTE pDriverDirectory,
1727 DWORD cbBuf, LPDWORD pcbNeeded)
1729 DWORD needed;
1731 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1732 pDriverDirectory, cbBuf, pcbNeeded);
1733 if(pName != NULL) {
1734 FIXME("pName = `%s' - unsupported\n", pName);
1735 SetLastError(ERROR_INVALID_PARAMETER);
1736 return FALSE;
1738 if(pEnvironment != NULL) {
1739 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
1740 SetLastError(ERROR_INVALID_ENVIRONMENT);
1741 return FALSE;
1743 if(Level != 1) /* win95 ignores this so we just carry on */
1744 WARN("Level = %ld - assuming 1\n", Level);
1746 /* FIXME should read from registry */
1747 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
1748 needed++;
1749 if(pcbNeeded)
1750 *pcbNeeded = needed;
1751 if(needed > cbBuf) {
1752 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1753 return FALSE;
1755 return TRUE;
1759 /*****************************************************************************
1760 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1762 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
1763 DWORD Level, LPBYTE pDriverDirectory,
1764 DWORD cbBuf, LPDWORD pcbNeeded)
1766 LPSTR pNameA = NULL, pEnvironmentA = NULL;
1767 BOOL ret;
1769 if(pName)
1770 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
1771 if(pEnvironment)
1772 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
1773 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
1774 pDriverDirectory, cbBuf, pcbNeeded );
1775 if(pNameA)
1776 HeapFree( GetProcessHeap(), 0, pNameA );
1777 if(pEnvironmentA)
1778 HeapFree( GetProcessHeap(), 0, pEnvironment );
1780 return ret;
1783 /*****************************************************************************
1784 * AddPrinterDriver32A [WINSPOOL.120]
1786 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
1788 DRIVER_INFO_3A di3;
1789 HKEY hkeyDrivers, hkeyName;
1791 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
1793 if(level != 2 && level != 3) {
1794 SetLastError(ERROR_INVALID_LEVEL);
1795 return FALSE;
1797 if(pName != NULL) {
1798 FIXME("pName= `%s' - unsupported\n", pName);
1799 SetLastError(ERROR_INVALID_PARAMETER);
1800 return FALSE;
1802 if(!pDriverInfo) {
1803 WARN("pDriverInfo == NULL");
1804 SetLastError(ERROR_INVALID_PARAMETER);
1805 return FALSE;
1808 if(level == 3)
1809 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
1810 else {
1811 memset(&di3, 0, sizeof(di3));
1812 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
1815 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
1816 !di3.pDataFile) {
1817 SetLastError(ERROR_INVALID_PARAMETER);
1818 return FALSE;
1820 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
1821 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
1822 if(!di3.pHelpFile) di3.pHelpFile = "";
1823 if(!di3.pMonitorName) di3.pMonitorName = "";
1825 if(di3.pEnvironment) {
1826 FIXME("pEnvironment = `%s'\n", di3.pEnvironment);
1827 SetLastError(ERROR_INVALID_ENVIRONMENT);
1828 return FALSE;
1830 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1831 ERROR_SUCCESS) {
1832 ERR("Can't create Drivers key\n");
1833 return FALSE;
1836 if(level == 2) { /* apparently can't overwrite with level2 */
1837 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
1838 RegCloseKey(hkeyName);
1839 RegCloseKey(hkeyDrivers);
1840 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
1841 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
1842 return FALSE;
1845 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
1846 RegCloseKey(hkeyDrivers);
1847 ERR("Can't create Name key\n");
1848 return FALSE;
1850 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
1852 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
1853 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
1854 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
1855 sizeof(DWORD));
1856 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
1857 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
1858 di3.pDependentFiles, 0);
1859 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
1860 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
1861 RegCloseKey(hkeyName);
1862 RegCloseKey(hkeyDrivers);
1864 return TRUE;
1866 /*****************************************************************************
1867 * AddPrinterDriver32W [WINSPOOL.121]
1869 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
1870 LPBYTE pDriverInfo)
1872 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
1873 level,pDriverInfo);
1874 return FALSE;
1878 /*****************************************************************************
1879 * PrinterProperties [WINSPOOL.201]
1881 * Displays a dialog to set the properties of the printer.
1883 * RETURNS
1884 * nonzero on succes or zero on faillure
1886 * BUGS
1887 * implemented as stub only
1889 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
1890 HANDLE hPrinter /* handle to printer object */
1892 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
1893 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1894 return FALSE;
1897 /*****************************************************************************
1898 * EnumJobsA [WINSPOOL.162]
1901 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
1902 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
1903 LPDWORD pcReturned)
1905 FIXME("stub\n");
1906 if(pcbNeeded) *pcbNeeded = 0;
1907 if(pcReturned) *pcReturned = 0;
1908 return TRUE;
1912 /*****************************************************************************
1913 * EnumJobsW [WINSPOOL.163]
1916 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
1917 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
1918 LPDWORD pcReturned)
1920 FIXME("stub\n");
1921 if(pcbNeeded) *pcbNeeded = 0;
1922 if(pcReturned) *pcReturned = 0;
1923 return TRUE;