Implement DocumentProperties, DeviceCapabilities, beginnings of
[wine/wine64.git] / dlls / winspool / info.c
blob6ff0162427535a436ff0a940f8ee204d2142db5e
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"
18 DEFAULT_DEBUG_CHANNEL(winspool)
20 CRITICAL_SECTION PRINT32_RegistryBlocker;
22 #define NUM_PRINTER_MAX 10
24 typedef struct _OPENEDPRINTERA
26 LPSTR lpsPrinterName;
27 HANDLE hPrinter;
28 LPPRINTER_DEFAULTSA lpDefault;
29 } OPENEDPRINTERA, *LPOPENEDPRINTERA;
32 /* Initialize the structure OpenedPrinter Table */
33 static OPENEDPRINTERA OpenedPrinterTableA[NUM_PRINTER_MAX] =
35 {NULL, -1, NULL},
36 {NULL, -1, NULL},
37 {NULL, -1, NULL},
38 {NULL, -1, NULL},
39 {NULL, -1, NULL},
40 {NULL, -1, NULL},
41 {NULL, -1, NULL},
42 {NULL, -1, NULL},
43 {NULL, -1, NULL},
44 {NULL, -1, NULL}
47 static char Printers[] = "System\\CurrentControlSet\\Control\\Print\\Printers\\";
50 /******************************************************************
51 * WINSPOOL_GetOpenedPrinterEntryA
52 * Get the first place empty in the opened printer table
54 static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterEntryA()
56 int i;
57 for( i=0; i< NUM_PRINTER_MAX; i++)
58 if (OpenedPrinterTableA[i].hPrinter == -1)
60 OpenedPrinterTableA[i].hPrinter = i + 1;
61 return &OpenedPrinterTableA[i];
63 return NULL;
66 /******************************************************************
67 * WINSPOOL_GetOpenedPrinterA
68 * Get the pointer to the opened printer referred by the handle
70 static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterA(int printerHandle)
72 if((printerHandle <=0) || (printerHandle > (NUM_PRINTER_MAX + 1)))
73 return NULL;
74 return &OpenedPrinterTableA[printerHandle -1];
77 /******************************************************************
78 * DeviceCapabilities32A [WINSPOOL.151]
81 INT WINAPI DeviceCapabilitiesA(LPCSTR pDeivce,LPCSTR pPort, WORD cap,
82 LPSTR pOutput, LPDEVMODEA lpdm)
84 return GDI_CallDeviceCapabilities16(pDeivce, pPort, cap, pOutput, lpdm);
89 /*****************************************************************************
90 * DeviceCapabilities32W
92 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
93 WORD fwCapability, LPWSTR pOutput,
94 const DEVMODEW *pDevMode)
96 FIXME("(%p,%p,%d,%p,%p): stub\n",
97 pDevice, pPort, fwCapability, pOutput, pDevMode);
98 return -1;
101 /******************************************************************
102 * DocumentProperties32A [WINSPOOL.155]
105 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
106 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
107 LPDEVMODEA pDevModeInput,DWORD fMode )
109 LPOPENEDPRINTERA lpOpenedPrinter;
110 LPSTR lpName = pDeviceName;
112 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
113 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
116 if(!pDeviceName) {
117 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
118 if(!lpOpenedPrinter) {
119 SetLastError(ERROR_INVALID_HANDLE);
120 return -1;
122 lpName = lpOpenedPrinter->lpsPrinterName;
125 return GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, NULL,
126 pDevModeInput, NULL, fMode);
131 /*****************************************************************************
132 * DocumentProperties32W
134 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
135 LPWSTR pDeviceName,
136 LPDEVMODEW pDevModeOutput,
137 LPDEVMODEW pDevModeInput, DWORD fMode)
139 FIXME("(%d,%d,%s,%p,%p,%ld): stub\n",
140 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
141 fMode);
142 return -1;
146 /******************************************************************
147 * OpenPrinter32A [WINSPOOL.196]
150 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
151 LPPRINTER_DEFAULTSA pDefault)
153 /* Not implemented: use the DesiredAccess of pDefault to set
154 the access rights to the printer */
156 LPOPENEDPRINTERA lpOpenedPrinter;
158 TRACE("(printerName: %s, pDefault %p\n", lpPrinterName, pDefault);
160 /* Get a place in the opened printer buffer*/
161 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntryA();
163 if((lpOpenedPrinter != NULL) && (lpPrinterName !=NULL) &&
164 (phPrinter != NULL))
166 /* Get the name of the printer */
167 lpOpenedPrinter->lpsPrinterName =
168 HeapAlloc(GetProcessHeap(), 0, lstrlenA(lpPrinterName));
169 lstrcpyA(lpOpenedPrinter->lpsPrinterName, lpPrinterName);
171 /* Get the unique handle of the printer*/
172 *phPrinter = lpOpenedPrinter->hPrinter;
174 if (pDefault != NULL)
176 /* Allocate enough memory for the lpDefault structure */
177 lpOpenedPrinter->lpDefault =
178 HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA));
179 lpOpenedPrinter->lpDefault->pDevMode =
180 HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA));
181 lpOpenedPrinter->lpDefault->pDatatype =
182 HeapAlloc(GetProcessHeap(), 0, lstrlenA(pDefault->pDatatype));
184 /*Copy the information from incoming parameter*/
185 memcpy(lpOpenedPrinter->lpDefault->pDevMode, pDefault->pDevMode,
186 sizeof(DEVMODEA));
187 lstrcpyA(lpOpenedPrinter->lpDefault->pDatatype,
188 pDefault->pDatatype);
189 lpOpenedPrinter->lpDefault->DesiredAccess =
190 pDefault->DesiredAccess;
193 return TRUE;
196 if(lpOpenedPrinter == NULL)
197 FIXME("Reach the OpenedPrinterTable maximum, augment this max.\n");
198 return FALSE;
201 /******************************************************************
202 * OpenPrinter32W [WINSPOOL.197]
205 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
206 LPPRINTER_DEFAULTSW pDefault)
208 FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
209 pDefault);
210 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
211 return FALSE;
217 /******************************************************************
218 * ENUMPRINTERS_GetDWORDFromRegistryA internal
220 * Reads a DWORD from registry KeyName
222 * RETURNS
223 * value on OK or NULL on error
225 DWORD ENUMPRINTERS_GetDWORDFromRegistryA(
226 HKEY hPrinterSettings, /* handle to registry key */
227 LPSTR KeyName /* name key to retrieve string from*/
229 DWORD DataSize=8;
230 DWORD DataType;
231 BYTE Data[8];
232 DWORD Result=684;
234 if (RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
235 Data, &DataSize)!=ERROR_SUCCESS)
236 FIXME("Query of register didn't succeed?\n");
237 if (DataType == REG_DWORD_LITTLE_ENDIAN)
238 Result = Data[0] + (Data[1]<<8) + (Data[2]<<16) + (Data[3]<<24);
239 if (DataType == REG_DWORD_BIG_ENDIAN)
240 Result = Data[3] + (Data[2]<<8) + (Data[1]<<16) + (Data[0]<<24);
241 return(Result);
245 /******************************************************************
246 * ENUMPRINTERS_AddStringFromRegistryA internal
248 * Reads a string from registry KeyName and writes it at
249 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
251 * RETURNS
252 * FALSE if there is still space left in the buffer.
254 BOOL ENUMPRINTERS_AddStringFromRegistryA(
255 HKEY hPrinterSettings, /* handle to registry key */
256 LPSTR KeyName, /* name key to retrieve string from*/
257 LPSTR* Dest, /* pointer to write string addres to */
258 LPBYTE lpbPrinters, /* buffer which receives info*/
259 LPDWORD dwNextStringPos, /* pos in buffer for next string */
260 DWORD dwBufSize, /* max size of buffer in bytes */
261 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
263 DWORD DataSize=34;
264 DWORD DataType;
265 LPSTR Data = (LPSTR) malloc(DataSize*sizeof(char));
267 while(RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
268 Data, &DataSize)==ERROR_MORE_DATA)
270 Data = (LPSTR) realloc(Data, DataSize+2);
273 if (DataType == REG_SZ)
275 if (bCalcSpaceOnly==FALSE)
276 *Dest = &lpbPrinters[*dwNextStringPos];
277 *dwNextStringPos += DataSize+1;
278 if (*dwNextStringPos > dwBufSize)
279 bCalcSpaceOnly=TRUE;
280 if (bCalcSpaceOnly==FALSE)
282 if (DataSize==0) /* DataSize = 0 means empty string, even though*/
283 *Dest[0]=0; /* the data itself needs not to be empty */
284 else
285 strcpy(*Dest, Data);
288 else
289 WARN("Expected string setting, got something else from registry");
291 if (Data)
292 free(Data);
293 return(bCalcSpaceOnly);
298 /******************************************************************
299 * ENUMPRINTERS_AddInfo2A internal
301 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
302 * for printer PrinterNameKey.
303 * Note that there is no check whether the information really fits!
305 * RETURNS
306 * FALSE if there is still space left in the buffer.
308 * BUGS:
309 * This function should not only read the registry but also ask the driver
310 * for information.
312 BOOL ENUMPRINTERS_AddInfo2A(
313 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
314 LPBYTE lpbPrinters, /* buffer which receives info*/
315 DWORD dwNextStructPos, /* pos in buffer for struct */
316 LPDWORD dwNextStringPos, /* pos in buffer for next string */
317 DWORD dwBufSize, /* max size of buffer in bytes */
318 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
320 HKEY hPrinterSettings;
321 DWORD DevSize=0;
322 DWORD DataType;
323 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
324 strlen(lpszPrinterName)+2);
325 LPPRINTER_INFO_2A lpPInfo2 = (LPPRINTER_INFO_2A) &lpbPrinters[dwNextStructPos];
327 /* open the registry to find the attributes, etc of the printer */
328 if (lpszPrinterSettings!=NULL)
330 strcpy(lpszPrinterSettings,Printers);
331 strcat(lpszPrinterSettings,lpszPrinterName);
333 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
334 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
336 WARN("The registry did not contain my printer anymore?\n");
338 else
340 if (bCalcSpaceOnly==FALSE)
341 lpPInfo2->pServerName = NULL;
342 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
343 "Name", &(lpPInfo2->pPrinterName),
344 lpbPrinters, dwNextStringPos,
345 dwBufSize, bCalcSpaceOnly);
346 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
347 "Share Name", &(lpPInfo2->pShareName),
348 lpbPrinters, dwNextStringPos,
349 dwBufSize, bCalcSpaceOnly);
350 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
351 "Port", &(lpPInfo2->pPortName),
352 lpbPrinters, dwNextStringPos,
353 dwBufSize, bCalcSpaceOnly);
354 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
355 "Printer Driver", &(lpPInfo2->pDriverName),
356 lpbPrinters, dwNextStringPos,
357 dwBufSize, bCalcSpaceOnly);
358 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
359 "Description", &(lpPInfo2->pComment),
360 lpbPrinters, dwNextStringPos,
361 dwBufSize, bCalcSpaceOnly);
362 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
363 "Location", &(lpPInfo2->pLocation),
364 lpbPrinters, dwNextStringPos,
365 dwBufSize, bCalcSpaceOnly);
367 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
368 "Separator File", &(lpPInfo2->pSepFile),
369 lpbPrinters, dwNextStringPos,
370 dwBufSize, bCalcSpaceOnly);
371 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
372 "Print Processor", &(lpPInfo2->pPrintProcessor),
373 lpbPrinters, dwNextStringPos,
374 dwBufSize, bCalcSpaceOnly);
375 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
376 "Datatype", &(lpPInfo2->pDatatype),
377 lpbPrinters, dwNextStringPos,
378 dwBufSize, bCalcSpaceOnly);
379 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
380 "Parameters", &(lpPInfo2->pParameters),
381 lpbPrinters, dwNextStringPos,
382 dwBufSize, bCalcSpaceOnly);
383 if (bCalcSpaceOnly == FALSE)
385 lpPInfo2->pSecurityDescriptor = NULL; /* EnumPrinters doesn't return this*/
387 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
388 lpPInfo2->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
389 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
390 lpPInfo2->Priority = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
391 "Priority");
392 lpPInfo2->DefaultPriority = ENUMPRINTERS_GetDWORDFromRegistryA(
393 hPrinterSettings, "Default Priority");
394 lpPInfo2->StartTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
395 "StartTime");
396 lpPInfo2->UntilTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
397 "UntilTime");
398 lpPInfo2->Status = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
399 "Status");
400 lpPInfo2->cJobs = 0; /* FIXME: according to MSDN, this does not
401 * reflect the TotalJobs Key ??? */
402 lpPInfo2->AveragePPM = 0; /* FIXME: according to MSDN, this does not
403 * reflect the TotalPages Key ??? */
405 /* and read the devModes structure... */
406 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
407 NULL, &DevSize); /* should return ERROR_MORE_DATA */
408 lpPInfo2->pDevMode = (LPDEVMODEA) &lpbPrinters[*dwNextStringPos];
409 *dwNextStringPos += DevSize + 1;
411 if (*dwNextStringPos > dwBufSize)
412 bCalcSpaceOnly=TRUE;
413 if (bCalcSpaceOnly==FALSE)
414 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
415 (LPBYTE)lpPInfo2->pDevMode, &DevSize);
418 if (lpszPrinterSettings)
419 free(lpszPrinterSettings);
421 return(bCalcSpaceOnly);
424 /******************************************************************
425 * ENUMPRINTERS_AddInfo4A internal
427 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
428 * for printer PrinterNameKey.
429 * Note that there is no check whether the information really fits!
431 * RETURNS
432 * FALSE if there is still space left in the buffer.
434 * BUGS:
435 * This function should not exist in Win95 mode, but does anyway.
437 BOOL ENUMPRINTERS_AddInfo4A(
438 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
439 LPBYTE lpbPrinters, /* buffer which receives info*/
440 DWORD dwNextStructPos, /* pos in buffer for struct */
441 LPDWORD dwNextStringPos, /* pos in buffer for next string */
442 DWORD dwBufSize, /* max size of buffer in bytes */
443 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
445 HKEY hPrinterSettings;
446 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
447 strlen(lpszPrinterName)+2);
448 LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos];
450 /* open the registry to find the attributes of the printer */
451 if (lpszPrinterSettings!=NULL)
453 strcpy(lpszPrinterSettings,Printers);
454 strcat(lpszPrinterSettings,lpszPrinterName);
456 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
457 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
459 WARN("The registry did not contain my printer anymore?\n");
461 else
463 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
464 "Name", &(lpPInfo4->pPrinterName),
465 lpbPrinters, dwNextStringPos,
466 dwBufSize, bCalcSpaceOnly);
467 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
468 if (bCalcSpaceOnly==FALSE)
469 lpPInfo4->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
470 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
472 if (lpszPrinterSettings)
473 free(lpszPrinterSettings);
475 return(bCalcSpaceOnly);
478 /******************************************************************
479 * ENUMPRINTERS_AddInfo5A internal
481 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
482 * for printer PrinterNameKey.
483 * Settings are read from the registry.
484 * Note that there is no check whether the information really fits!
485 * RETURNS
486 * FALSE if there is still space left in the buffer.
488 BOOL ENUMPRINTERS_AddInfo5A(
489 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
490 LPBYTE lpbPrinters, /* buffer which receives info*/
491 DWORD dwNextStructPos, /* pos in buffer for struct */
492 LPDWORD dwNextStringPos, /* pos in buffer for next string */
493 DWORD dwBufSize, /* max size of buffer in bytes */
494 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
496 HKEY hPrinterSettings;
497 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
498 strlen(lpszPrinterName)+2);
499 LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos];
501 /* open the registry to find the attributes, etc of the printer */
502 if (lpszPrinterSettings!=NULL)
504 strcpy(lpszPrinterSettings,Printers);
505 strcat(lpszPrinterSettings,lpszPrinterName);
507 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
508 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
510 WARN("The registry did not contain my printer anymore?\n");
512 else
514 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
515 "Name", &(lpPInfo5->pPrinterName),
516 lpbPrinters, dwNextStringPos,
517 dwBufSize, bCalcSpaceOnly);
518 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
519 "Port", &(lpPInfo5->pPortName), lpbPrinters,
520 dwNextStringPos, dwBufSize, bCalcSpaceOnly);
521 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
522 if (bCalcSpaceOnly == FALSE)
524 lpPInfo5->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
525 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
526 lpPInfo5->DeviceNotSelectedTimeOut
527 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
528 "txTimeout");
529 lpPInfo5->TransmissionRetryTimeout
530 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
531 "dnsTimeout");
535 if (lpszPrinterSettings)
536 free(lpszPrinterSettings);
538 return(bCalcSpaceOnly);
542 /******************************************************************
543 * EnumPrintersA [WINSPOOL.174]
545 * Enumerates the available printers, print servers and print
546 * providers, depending on the specified flags, name and level.
548 * RETURNS:
550 * If level is set to 1:
551 * Not implemented yet!
552 * Returns TRUE with an empty list.
554 * If level is set to 2:
555 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
556 * Returns an array of PRINTER_INFO_2 data structures in the
557 * lpbPrinters buffer. Note that according to MSDN also an
558 * OpenPrinter should be performed on every remote printer.
560 * If level is set to 4 (officially WinNT only):
561 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
562 * Fast: Only the registry is queried to retrieve printer names,
563 * no connection to the driver is made.
564 * Returns an array of PRINTER_INFO_4 data structures in the
565 * lpbPrinters buffer.
567 * If level is set to 5 (officially WinNT4/Win9x only):
568 * Fast: Only the registry is queried to retrieve printer names,
569 * no connection to the driver is made.
570 * Returns an array of PRINTER_INFO_5 data structures in the
571 * lpbPrinters buffer.
573 * If level set to 3 or 6+:
574 * returns zero (faillure!)
576 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
577 * for information.
579 * BUGS:
580 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
581 * - Only levels 2, 4 and 5 are implemented at the moment.
582 * - 16-bit printer drivers are not enumerated.
583 * - Returned amount of bytes used/needed does not match the real Windoze
584 * implementation (as in this implementation, all strings are part
585 * of the buffer, whereas Win32 keeps them somewhere else)
586 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
588 * NOTE:
589 * - In a regular Wine installation, no registry settings for printers
590 * exist, which makes this function return an empty list.
592 BOOL WINAPI EnumPrintersA(
593 DWORD dwType, /* Types of print objects to enumerate */
594 LPSTR lpszName, /* name of objects to enumerate */
595 DWORD dwLevel, /* type of printer info structure */
596 LPBYTE lpbPrinters,/* buffer which receives info*/
597 DWORD cbBuf, /* max size of buffer in bytes */
598 LPDWORD lpdwNeeded,/* pointer to var: # bytes used/needed */
599 LPDWORD lpdwReturned/* number of entries returned */
602 HKEY hPrinterListKey;
603 DWORD dwIndex=0;
604 char PrinterName[255];
605 DWORD PrinterNameLength=255;
606 FILETIME FileTime;
607 DWORD dwNextStringPos; /* position of next space for a string in the buffer*/
608 DWORD dwStructPrinterInfoSize; /* size of a Printer_Info_X structure */
609 BOOL bCalcSpaceOnly=FALSE;/* if TRUE: don't store data, just calculate space*/
611 TRACE("entered.\n");
613 /* test whether we're requested to really fill in. If so,
614 * zero out the data area, and initialise some returns to zero,
615 * to prevent problems
617 if (lpbPrinters==NULL || cbBuf==0)
618 bCalcSpaceOnly=TRUE;
619 else
621 int i;
622 for (i=0; i<cbBuf; i++)
623 lpbPrinters[i]=0;
625 *lpdwReturned=0;
626 *lpdwNeeded = 0;
628 /* check for valid Flags */
629 if (dwType != PRINTER_ENUM_LOCAL && dwType != PRINTER_ENUM_NAME)
631 SetLastError(ERROR_INVALID_FLAGS);
632 return(0);
634 switch(dwLevel)
636 case 1:
637 return(TRUE);
638 case 2:
639 case 4:
640 case 5:
641 break;
642 default:
643 SetLastError(ERROR_INVALID_PARAMETER);
644 return(FALSE);
647 /* Enter critical section to prevent AddPrinters() et al. to
648 * modify whilst we're reading in the registry
650 InitializeCriticalSection(&PRINT32_RegistryBlocker);
651 EnterCriticalSection(&PRINT32_RegistryBlocker);
653 /* get a pointer to a list of all printer names in the registry */
654 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Printers, 0, KEY_READ,
655 &hPrinterListKey) !=ERROR_SUCCESS)
657 /* Oh no! An empty list of printers!
658 * (which is a valid configuration anyway)
660 TRACE("No entries in the Printers part of the registry\n");
663 /* count the number of entries and check if it fits in the buffer
665 while(RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
666 NULL, NULL, NULL, &FileTime)==ERROR_SUCCESS)
668 PrinterNameLength=255;
669 dwIndex++;
671 *lpdwReturned = dwIndex;
672 switch(dwLevel)
674 case 1:
675 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_1A);
676 break;
677 case 2:
678 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_2A);
679 break;
680 case 4:
681 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_4A);
682 break;
683 case 5:
684 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_5A);
685 break;
686 default:
687 dwStructPrinterInfoSize = 0;
688 break;
690 if (dwIndex*dwStructPrinterInfoSize+1 > cbBuf)
691 bCalcSpaceOnly = TRUE;
693 /* the strings which contain e.g. PrinterName, PortName, etc,
694 * are also stored in lpbPrinters, but after the regular structs.
695 * dwNextStringPos will always point to the next free place for a
696 * string.
698 dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize;
700 /* check each entry: if OK, add to list in corresponding INFO .
702 for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++)
704 PrinterNameLength=255;
705 if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
706 NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS)
707 break; /* exit for loop*/
709 /* check whether this printer is allowed in the list
710 * by comparing name to lpszName
712 if (dwType == PRINTER_ENUM_NAME)
713 if (strcmp(PrinterName,lpszName)!=0)
714 continue;
716 switch(dwLevel)
718 case 1:
719 /* FIXME: unimplemented */
720 break;
721 case 2:
722 bCalcSpaceOnly = ENUMPRINTERS_AddInfo2A(PrinterName, lpbPrinters,
723 dwIndex*dwStructPrinterInfoSize,
724 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
725 break;
726 case 4:
727 bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters,
728 dwIndex*dwStructPrinterInfoSize,
729 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
730 break;
731 case 5:
732 bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters,
733 dwIndex*dwStructPrinterInfoSize,
734 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
735 break;
738 RegCloseKey(hPrinterListKey);
739 *lpdwNeeded = dwNextStringPos;
741 if (bCalcSpaceOnly==TRUE)
743 if (lpbPrinters!=NULL)
745 int i;
746 for (i=0; i<cbBuf; i++)
747 lpbPrinters[i]=0;
749 *lpdwReturned=0;
751 LeaveCriticalSection(&PRINT32_RegistryBlocker);
752 return(TRUE);
755 /******************************************************************
756 * EnumPrinters32W [WINSPOOL.175]
759 BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
760 DWORD dwLevel, LPBYTE lpbPrinters,
761 DWORD cbBuf, LPDWORD lpdwNeeded,
762 LPDWORD lpdwReturned)
764 FIXME("Nearly empty stub\n");
765 *lpdwReturned=0;
766 *lpdwNeeded = 0;
767 return TRUE;
770 /******************************************************************
771 * AddMonitor32A [WINSPOOL.107]
774 BOOL WINAPI AddMonitorA(LPCSTR pName, DWORD Level, LPBYTE pMonitors)
776 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
777 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
778 return FALSE;
781 /******************************************************************
782 * DeletePrinterDriver32A [WINSPOOL.146]
785 BOOL WINAPI
786 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
788 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
789 debugstr_a(pDriverName));
790 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
791 return FALSE;
795 /******************************************************************
796 * DeleteMonitor32A [WINSPOOL.135]
799 BOOL WINAPI
800 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
802 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
803 debugstr_a(pMonitorName));
804 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
805 return FALSE;
809 /******************************************************************
810 * DeletePort32A [WINSPOOL.137]
813 BOOL WINAPI
814 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
816 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
817 debugstr_a(pPortName));
818 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
819 return FALSE;
822 /******************************************************************************
823 * SetPrinter32W [WINSPOOL.214]
825 BOOL WINAPI
826 SetPrinterW(
827 HANDLE hPrinter,
828 DWORD Level,
829 LPBYTE pPrinter,
830 DWORD Command) {
832 FIXME("():stub\n");
833 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
834 return FALSE;
837 /******************************************************************************
838 * WritePrinter32 [WINSPOOL.223]
840 BOOL WINAPI
841 WritePrinter(
842 HANDLE hPrinter,
843 LPVOID pBuf,
844 DWORD cbBuf,
845 LPDWORD pcWritten) {
847 FIXME("():stub\n");
848 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
849 return FALSE;
852 /*****************************************************************************
853 * AddForm32A [WINSPOOL.103]
855 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
857 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
858 return 1;
861 /*****************************************************************************
862 * AddForm32W [WINSPOOL.104]
864 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
866 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
867 return 1;
870 /*****************************************************************************
871 * AddJob32A [WINSPOOL.105]
873 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
874 DWORD cbBuf, LPDWORD pcbNeeded)
876 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
877 pcbNeeded);
878 return 1;
881 /*****************************************************************************
882 * AddJob32W [WINSPOOL.106]
884 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
885 LPDWORD pcbNeeded)
887 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
888 pcbNeeded);
889 return 1;
892 /*****************************************************************************
893 * AddPrinter32A [WINSPOOL.117]
895 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
897 FIXME("(%s,%ld,%p): stub\n", pName, Level, pPrinter);
898 return 0;
901 /*****************************************************************************
902 * AddPrinter32W [WINSPOOL.122]
904 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
906 FIXME("(%p,%ld,%p): stub\n", pName, Level, pPrinter);
907 return 0;
911 /*****************************************************************************
912 * ClosePrinter32 [WINSPOOL.126]
914 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
916 LPOPENEDPRINTERA lpOpenedPrinter;
918 if ((hPrinter != -1) && (hPrinter < NUM_PRINTER_MAX + 1))
920 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
921 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
922 lpOpenedPrinter->lpsPrinterName = NULL;
924 /* Free the memory of lpDefault if it has been initialized*/
925 if(lpOpenedPrinter->lpDefault != NULL)
927 HeapFree(GetProcessHeap(), 0,
928 lpOpenedPrinter->lpDefault->pDevMode);
929 HeapFree(GetProcessHeap(), 0,
930 lpOpenedPrinter->lpDefault->pDatatype);
931 HeapFree(GetProcessHeap(), 0,
932 lpOpenedPrinter->lpDefault);
933 lpOpenedPrinter->lpDefault = NULL;
936 lpOpenedPrinter->hPrinter = -1;
938 return TRUE;
940 return FALSE;
943 /*****************************************************************************
944 * DeleteForm32A [WINSPOOL.133]
946 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
948 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
949 return 1;
952 /*****************************************************************************
953 * DeleteForm32W [WINSPOOL.134]
955 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
957 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
958 return 1;
961 /*****************************************************************************
962 * DeletePrinter32 [WINSPOOL.143]
964 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
966 FIXME("(%d): stub\n", hPrinter);
967 return 1;
970 /*****************************************************************************
971 * SetPrinter32A [WINSPOOL.211]
973 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
974 DWORD Command)
976 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
977 return FALSE;
980 /*****************************************************************************
981 * SetJob32A [WINSPOOL.209]
983 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
984 LPBYTE pJob, DWORD Command)
986 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
987 Command);
988 return FALSE;
991 /*****************************************************************************
992 * SetJob32W [WINSPOOL.210]
994 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
995 LPBYTE pJob, DWORD Command)
997 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
998 Command);
999 return FALSE;
1002 /*****************************************************************************
1003 * GetForm32A [WINSPOOL.181]
1005 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1006 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1008 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
1009 Level,pForm,cbBuf,pcbNeeded);
1010 return FALSE;
1013 /*****************************************************************************
1014 * GetForm32W [WINSPOOL.182]
1016 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1017 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1019 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
1020 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
1021 return FALSE;
1024 /*****************************************************************************
1025 * SetForm32A [WINSPOOL.207]
1027 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1028 LPBYTE pForm)
1030 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1031 return FALSE;
1034 /*****************************************************************************
1035 * SetForm32W [WINSPOOL.208]
1037 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1038 LPBYTE pForm)
1040 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1041 return FALSE;
1044 /*****************************************************************************
1045 * ReadPrinter32 [WINSPOOL.202]
1047 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1048 LPDWORD pNoBytesRead)
1050 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1051 return FALSE;
1054 /*****************************************************************************
1055 * ResetPrinter32A [WINSPOOL.203]
1057 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1059 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1060 return FALSE;
1063 /*****************************************************************************
1064 * ResetPrinter32W [WINSPOOL.204]
1066 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1068 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1069 return FALSE;
1072 /*****************************************************************************
1073 * GetPrinter32A [WINSPOOL.187]
1075 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1076 DWORD cbBuf, LPDWORD pcbNeeded)
1078 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
1079 cbBuf, pcbNeeded);
1081 *pcbNeeded = sizeof(PRINTER_INFO_2A);
1083 if(cbBuf < *pcbNeeded) {
1084 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1085 return FALSE;
1087 memset(pPrinter, 0, cbBuf);
1089 return TRUE;
1092 /*****************************************************************************
1093 * GetPrinter32W [WINSPOOL.194]
1095 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1096 DWORD cbBuf, LPDWORD pcbNeeded)
1098 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
1099 cbBuf, pcbNeeded);
1100 return FALSE;
1103 /*****************************************************************************
1104 * GetPrinterDriver32A [WINSPOOL.190]
1106 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1107 DWORD Level, LPBYTE pDriverInfo,
1108 DWORD cbBuf, LPDWORD pcbNeeded)
1110 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1111 Level,pDriverInfo,cbBuf, pcbNeeded);
1112 return FALSE;
1115 /*****************************************************************************
1116 * GetPrinterDriver32W [WINSPOOL.193]
1118 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1119 DWORD Level, LPBYTE pDriverInfo,
1120 DWORD cbBuf, LPDWORD pcbNeeded)
1122 FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1123 Level,pDriverInfo,cbBuf, pcbNeeded);
1124 return FALSE;
1126 /*****************************************************************************
1127 * AddPrinterDriver32A [WINSPOOL.120]
1129 BOOL WINAPI AddPrinterDriverA(LPSTR printerName,DWORD level,
1130 LPBYTE pDriverInfo)
1132 FIXME("(%s,%ld,%p): stub\n",printerName,level,pDriverInfo);
1133 return FALSE;
1135 /*****************************************************************************
1136 * AddPrinterDriver32W [WINSPOOL.121]
1138 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
1139 LPBYTE pDriverInfo)
1141 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
1142 level,pDriverInfo);
1143 return FALSE;
1147 /*****************************************************************************
1148 * PrinterProperties [WINSPOOL.201]
1150 * Displays a dialog to set the properties of the printer.
1152 * RETURNS
1153 * nonzero on succes or zero on faillure
1155 * BUGS
1156 * implemented as stub only
1158 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
1159 HANDLE hPrinter /* handle to printer object */
1161 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
1162 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1163 return FALSE;