4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
16 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(winspool)
22 CRITICAL_SECTION PRINT32_RegistryBlocker;
24 typedef struct _OPENEDPRINTERA
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()
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(),
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(),
89 sizeof(OPENEDPRINTERA));
90 pOpenedPrinter->hPrinter = i + 1;
91 WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter);
92 return pOpenedPrinter;
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((printerHandle <=0) ||
107 (printerHandle > (pOpenedPrinterDPA->nItemCount - 1)))
110 pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, printerHandle);
112 return pOpenedPrinter;
115 /******************************************************************
116 * DeviceCapabilities32A [WINSPOOL.151]
119 INT WINAPI DeviceCapabilitiesA(LPCSTR pDeivce,LPCSTR pPort, WORD cap,
120 LPSTR pOutput, LPDEVMODEA lpdm)
122 return GDI_CallDeviceCapabilities16(pDeivce, pPort, cap, pOutput, lpdm);
127 /*****************************************************************************
128 * DeviceCapabilities32W
130 INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort,
131 WORD fwCapability, LPWSTR pOutput,
132 const DEVMODEW *pDevMode)
134 FIXME("(%p,%p,%d,%p,%p): stub\n",
135 pDevice, pPort, fwCapability, pOutput, pDevMode);
139 /******************************************************************
140 * DocumentProperties32A [WINSPOOL.155]
143 LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
144 LPSTR pDeviceName, LPDEVMODEA pDevModeOutput,
145 LPDEVMODEA pDevModeInput,DWORD fMode )
147 LPOPENEDPRINTERA lpOpenedPrinter;
148 LPSTR lpName = pDeviceName;
150 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
151 hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode
155 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
156 if(!lpOpenedPrinter) {
157 SetLastError(ERROR_INVALID_HANDLE);
160 lpName = lpOpenedPrinter->lpsPrinterName;
163 return GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, NULL,
164 pDevModeInput, NULL, fMode);
169 /*****************************************************************************
170 * DocumentProperties32W
172 LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter,
174 LPDEVMODEW pDevModeOutput,
175 LPDEVMODEW pDevModeInput, DWORD fMode)
177 FIXME("(%d,%d,%s,%p,%p,%ld): stub\n",
178 hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput,
184 /******************************************************************
185 * OpenPrinter32A [WINSPOOL.196]
188 BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter,
189 LPPRINTER_DEFAULTSA pDefault)
191 /* Not implemented: use the DesiredAccess of pDefault to set
192 the access rights to the printer */
194 LPOPENEDPRINTERA lpOpenedPrinter;
196 TRACE("(printerName: %s, pDefault %p\n", lpPrinterName, pDefault);
198 /* Get a place in the opened printer buffer*/
199 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntryA();
201 if((lpOpenedPrinter != NULL) && (lpPrinterName !=NULL) &&
204 /* Get the name of the printer */
205 lpOpenedPrinter->lpsPrinterName =
206 HeapAlloc(GetProcessHeap(), 0, lstrlenA(lpPrinterName));
207 lstrcpyA(lpOpenedPrinter->lpsPrinterName, lpPrinterName);
209 /* Get the unique handle of the printer*/
210 *phPrinter = lpOpenedPrinter->hPrinter;
212 if (pDefault != NULL)
214 /* Allocate enough memory for the lpDefault structure */
215 lpOpenedPrinter->lpDefault =
216 HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA));
217 lpOpenedPrinter->lpDefault->pDevMode =
218 HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA));
219 lpOpenedPrinter->lpDefault->pDatatype =
220 HeapAlloc(GetProcessHeap(), 0, lstrlenA(pDefault->pDatatype));
222 /*Copy the information from incoming parameter*/
223 memcpy(lpOpenedPrinter->lpDefault->pDevMode, pDefault->pDevMode,
225 lstrcpyA(lpOpenedPrinter->lpDefault->pDatatype,
226 pDefault->pDatatype);
227 lpOpenedPrinter->lpDefault->DesiredAccess =
228 pDefault->DesiredAccess;
234 if(lpOpenedPrinter == NULL)
235 FIXME("Reach the OpenedPrinterTable maximum, augment this max.\n");
239 /******************************************************************
240 * OpenPrinter32W [WINSPOOL.197]
243 BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
244 LPPRINTER_DEFAULTSW pDefault)
246 FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter,
248 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
255 /******************************************************************
256 * ENUMPRINTERS_GetDWORDFromRegistryA internal
258 * Reads a DWORD from registry KeyName
261 * value on OK or NULL on error
263 DWORD ENUMPRINTERS_GetDWORDFromRegistryA(
264 HKEY hPrinterSettings, /* handle to registry key */
265 LPSTR KeyName /* name key to retrieve string from*/
272 if (RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
273 Data, &DataSize)!=ERROR_SUCCESS)
274 FIXME("Query of register '%s' didn't succeed?\n", KeyName);
275 if (DataType == REG_DWORD_LITTLE_ENDIAN)
276 Result = Data[0] + (Data[1]<<8) + (Data[2]<<16) + (Data[3]<<24);
277 if (DataType == REG_DWORD_BIG_ENDIAN)
278 Result = Data[3] + (Data[2]<<8) + (Data[1]<<16) + (Data[0]<<24);
283 /******************************************************************
284 * ENUMPRINTERS_AddStringFromRegistryA internal
286 * Reads a string from registry KeyName and writes it at
287 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
290 * FALSE if there is still space left in the buffer.
292 BOOL ENUMPRINTERS_AddStringFromRegistryA(
293 HKEY hPrinterSettings, /* handle to registry key */
294 LPSTR KeyName, /* name key to retrieve string from*/
295 LPSTR* Dest, /* pointer to write string addres to */
296 LPBYTE lpbPrinters, /* buffer which receives info*/
297 LPDWORD dwNextStringPos,/* pos in buffer for next string */
298 DWORD dwBufSize, /* max size of buffer in bytes */
299 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
303 LPSTR Data = (LPSTR) malloc(DataSize*sizeof(char));
305 while(RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType,
306 Data, &DataSize)==ERROR_MORE_DATA)
308 Data = (LPSTR) realloc(Data, DataSize+2);
311 if (DataType == REG_SZ)
313 if (bCalcSpaceOnly==FALSE)
314 *Dest = &lpbPrinters[*dwNextStringPos];
315 *dwNextStringPos += DataSize+1;
316 if (*dwNextStringPos > dwBufSize)
318 if (bCalcSpaceOnly==FALSE)
320 if (DataSize==0) /* DataSize = 0 means empty string, even though*/
321 *Dest[0]=0; /* the data itself needs not to be empty */
327 WARN("Expected string setting, got something else from registry");
331 return(bCalcSpaceOnly);
336 /******************************************************************
337 * ENUMPRINTERS_AddInfo2A internal
339 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
340 * for printer PrinterNameKey.
341 * Note that there is no check whether the information really fits!
344 * FALSE if there is still space left in the buffer.
347 * This function should not only read the registry but also ask the driver
350 BOOL ENUMPRINTERS_AddInfo2A(
351 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
352 LPBYTE lpbPrinters, /* buffer which receives info*/
353 DWORD dwNextStructPos, /* pos in buffer for struct */
354 LPDWORD dwNextStringPos, /* pos in buffer for next string */
355 DWORD dwBufSize, /* max size of buffer in bytes */
356 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
358 HKEY hPrinterSettings;
361 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
362 strlen(lpszPrinterName)+2);
363 LPPRINTER_INFO_2A lpPInfo2 = (LPPRINTER_INFO_2A) &lpbPrinters[dwNextStructPos];
365 /* open the registry to find the attributes, etc of the printer */
366 if (lpszPrinterSettings!=NULL)
368 strcpy(lpszPrinterSettings,Printers);
369 strcat(lpszPrinterSettings,lpszPrinterName);
371 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
372 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
374 WARN("The registry did not contain my printer anymore?\n");
378 if (bCalcSpaceOnly==FALSE)
379 lpPInfo2->pServerName = NULL;
380 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
381 "Name", &(lpPInfo2->pPrinterName),
382 lpbPrinters, dwNextStringPos,
383 dwBufSize, bCalcSpaceOnly);
384 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
385 "Share Name", &(lpPInfo2->pShareName),
386 lpbPrinters, dwNextStringPos,
387 dwBufSize, bCalcSpaceOnly);
388 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
389 "Port", &(lpPInfo2->pPortName),
390 lpbPrinters, dwNextStringPos,
391 dwBufSize, bCalcSpaceOnly);
392 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
393 "Printer Driver", &(lpPInfo2->pDriverName),
394 lpbPrinters, dwNextStringPos,
395 dwBufSize, bCalcSpaceOnly);
396 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
397 "Description", &(lpPInfo2->pComment),
398 lpbPrinters, dwNextStringPos,
399 dwBufSize, bCalcSpaceOnly);
400 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
401 "Location", &(lpPInfo2->pLocation),
402 lpbPrinters, dwNextStringPos,
403 dwBufSize, bCalcSpaceOnly);
405 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
406 "Separator File", &(lpPInfo2->pSepFile),
407 lpbPrinters, dwNextStringPos,
408 dwBufSize, bCalcSpaceOnly);
409 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
410 "Print Processor", &(lpPInfo2->pPrintProcessor),
411 lpbPrinters, dwNextStringPos,
412 dwBufSize, bCalcSpaceOnly);
413 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
414 "Datatype", &(lpPInfo2->pDatatype),
415 lpbPrinters, dwNextStringPos,
416 dwBufSize, bCalcSpaceOnly);
417 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
418 "Parameters", &(lpPInfo2->pParameters),
419 lpbPrinters, dwNextStringPos,
420 dwBufSize, bCalcSpaceOnly);
421 if (bCalcSpaceOnly == FALSE)
423 lpPInfo2->pSecurityDescriptor = NULL; /* EnumPrinters doesn't return this*/
425 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
426 lpPInfo2->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
427 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
428 lpPInfo2->Priority = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
430 lpPInfo2->DefaultPriority = ENUMPRINTERS_GetDWORDFromRegistryA(
431 hPrinterSettings, "Default Priority");
432 lpPInfo2->StartTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
434 lpPInfo2->UntilTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
436 lpPInfo2->Status = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
438 lpPInfo2->cJobs = 0; /* FIXME: according to MSDN, this does not
439 * reflect the TotalJobs Key ??? */
440 lpPInfo2->AveragePPM = 0; /* FIXME: according to MSDN, this does not
441 * reflect the TotalPages Key ??? */
443 /* and read the devModes structure... */
444 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
445 NULL, &DevSize); /* should return ERROR_MORE_DATA */
446 lpPInfo2->pDevMode = (LPDEVMODEA) &lpbPrinters[*dwNextStringPos];
447 *dwNextStringPos += DevSize + 1;
449 if (*dwNextStringPos > dwBufSize)
451 if (bCalcSpaceOnly==FALSE)
452 RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType,
453 (LPBYTE)lpPInfo2->pDevMode, &DevSize);
456 if (lpszPrinterSettings)
457 free(lpszPrinterSettings);
459 return(bCalcSpaceOnly);
462 /******************************************************************
463 * ENUMPRINTERS_AddInfo4A internal
465 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
466 * for printer PrinterNameKey.
467 * Note that there is no check whether the information really fits!
470 * FALSE if there is still space left in the buffer.
473 * This function should not exist in Win95 mode, but does anyway.
475 BOOL ENUMPRINTERS_AddInfo4A(
476 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
477 LPBYTE lpbPrinters, /* buffer which receives info*/
478 DWORD dwNextStructPos, /* pos in buffer for struct */
479 LPDWORD dwNextStringPos, /* pos in buffer for next string */
480 DWORD dwBufSize, /* max size of buffer in bytes */
481 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
483 HKEY hPrinterSettings;
484 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
485 strlen(lpszPrinterName)+2);
486 LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos];
488 /* open the registry to find the attributes of the printer */
489 if (lpszPrinterSettings!=NULL)
491 strcpy(lpszPrinterSettings,Printers);
492 strcat(lpszPrinterSettings,lpszPrinterName);
494 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
495 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
497 WARN("The registry did not contain my printer anymore?\n");
501 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
502 "Name", &(lpPInfo4->pPrinterName),
503 lpbPrinters, dwNextStringPos,
504 dwBufSize, bCalcSpaceOnly);
505 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
506 if (bCalcSpaceOnly==FALSE)
507 lpPInfo4->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
508 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
510 if (lpszPrinterSettings)
511 free(lpszPrinterSettings);
513 return(bCalcSpaceOnly);
516 /******************************************************************
517 * ENUMPRINTERS_AddInfo5A internal
519 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
520 * for printer PrinterNameKey.
521 * Settings are read from the registry.
522 * Note that there is no check whether the information really fits!
524 * FALSE if there is still space left in the buffer.
526 BOOL ENUMPRINTERS_AddInfo5A(
527 LPSTR lpszPrinterName,/* name of printer to fill struct for*/
528 LPBYTE lpbPrinters, /* buffer which receives info*/
529 DWORD dwNextStructPos, /* pos in buffer for struct */
530 LPDWORD dwNextStringPos, /* pos in buffer for next string */
531 DWORD dwBufSize, /* max size of buffer in bytes */
532 BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */
534 HKEY hPrinterSettings;
535 LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+
536 strlen(lpszPrinterName)+2);
537 LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos];
539 /* open the registry to find the attributes, etc of the printer */
540 if (lpszPrinterSettings!=NULL)
542 strcpy(lpszPrinterSettings,Printers);
543 strcat(lpszPrinterSettings,lpszPrinterName);
545 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0,
546 KEY_READ, &hPrinterSettings) != ERROR_SUCCESS)
548 WARN("The registry did not contain my printer anymore?\n");
552 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
553 "Name", &(lpPInfo5->pPrinterName),
554 lpbPrinters, dwNextStringPos,
555 dwBufSize, bCalcSpaceOnly);
556 bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings,
557 "Port", &(lpPInfo5->pPortName), lpbPrinters,
558 dwNextStringPos, dwBufSize, bCalcSpaceOnly);
559 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
560 if (bCalcSpaceOnly == FALSE)
562 lpPInfo5->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
563 "Attributes") +PRINTER_ATTRIBUTE_LOCAL;
564 lpPInfo5->DeviceNotSelectedTimeOut
565 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
567 lpPInfo5->TransmissionRetryTimeout
568 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings,
573 if (lpszPrinterSettings)
574 free(lpszPrinterSettings);
576 return(bCalcSpaceOnly);
580 /******************************************************************
581 * EnumPrintersA [WINSPOOL.174]
583 * Enumerates the available printers, print servers and print
584 * providers, depending on the specified flags, name and level.
588 * If level is set to 1:
589 * Not implemented yet!
590 * Returns TRUE with an empty list.
592 * If level is set to 2:
593 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
594 * Returns an array of PRINTER_INFO_2 data structures in the
595 * lpbPrinters buffer. Note that according to MSDN also an
596 * OpenPrinter should be performed on every remote printer.
598 * If level is set to 4 (officially WinNT only):
599 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
600 * Fast: Only the registry is queried to retrieve printer names,
601 * no connection to the driver is made.
602 * Returns an array of PRINTER_INFO_4 data structures in the
603 * lpbPrinters buffer.
605 * If level is set to 5 (officially WinNT4/Win9x only):
606 * Fast: Only the registry is queried to retrieve printer names,
607 * no connection to the driver is made.
608 * Returns an array of PRINTER_INFO_5 data structures in the
609 * lpbPrinters buffer.
611 * If level set to 3 or 6+:
612 * returns zero (faillure!)
614 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
618 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
619 * - Only levels 2, 4 and 5 are implemented at the moment.
620 * - 16-bit printer drivers are not enumerated.
621 * - Returned amount of bytes used/needed does not match the real Windoze
622 * implementation (as in this implementation, all strings are part
623 * of the buffer, whereas Win32 keeps them somewhere else)
624 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
627 * - In a regular Wine installation, no registry settings for printers
628 * exist, which makes this function return an empty list.
630 BOOL WINAPI EnumPrintersA(
631 DWORD dwType, /* Types of print objects to enumerate */
632 LPSTR lpszName, /* name of objects to enumerate */
633 DWORD dwLevel, /* type of printer info structure */
634 LPBYTE lpbPrinters, /* buffer which receives info */
635 DWORD cbBuf, /* max size of buffer in bytes */
636 LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */
637 LPDWORD lpdwReturned /* number of entries returned */
640 HKEY hPrinterListKey;
642 char PrinterName[255];
643 DWORD PrinterNameLength=255;
645 DWORD dwNextStringPos; /* position of next space for a string in the buffer*/
646 DWORD dwStructPrinterInfoSize; /* size of a Printer_Info_X structure */
647 BOOL bCalcSpaceOnly=FALSE;/*if TRUE: don't store data, just calculate space*/
651 /* test whether we're requested to really fill in. If so,
652 * zero out the data area, and initialise some returns to zero,
653 * to prevent problems
655 if (lpbPrinters==NULL || cbBuf==0)
660 for (i=0; i<cbBuf; i++)
666 /* check for valid Flags */
667 if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME)))
669 FIXME("dwType = %08lx\n", dwType);
670 SetLastError(ERROR_INVALID_FLAGS);
682 SetLastError(ERROR_INVALID_PARAMETER);
686 /* Enter critical section to prevent AddPrinters() et al. to
687 * modify whilst we're reading in the registry
689 InitializeCriticalSection(&PRINT32_RegistryBlocker);
690 EnterCriticalSection(&PRINT32_RegistryBlocker);
692 /* get a pointer to a list of all printer names in the registry */
693 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Printers, 0, KEY_READ,
694 &hPrinterListKey) !=ERROR_SUCCESS)
696 /* Oh no! An empty list of printers!
697 * (which is a valid configuration anyway)
699 TRACE("No entries in the Printers part of the registry\n");
702 /* count the number of entries and check if it fits in the buffer
704 while(RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
705 NULL, NULL, NULL, &FileTime)==ERROR_SUCCESS)
707 PrinterNameLength=255;
710 *lpdwReturned = dwIndex;
714 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_1A);
717 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_2A);
720 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_4A);
723 dwStructPrinterInfoSize = sizeof(PRINTER_INFO_5A);
726 dwStructPrinterInfoSize = 0;
729 if (dwIndex*dwStructPrinterInfoSize+1 > cbBuf)
730 bCalcSpaceOnly = TRUE;
732 /* the strings which contain e.g. PrinterName, PortName, etc,
733 * are also stored in lpbPrinters, but after the regular structs.
734 * dwNextStringPos will always point to the next free place for a
737 dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize;
739 /* check each entry: if OK, add to list in corresponding INFO .
741 for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++)
743 PrinterNameLength=255;
744 if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength,
745 NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS)
746 break; /* exit for loop*/
748 /* check whether this printer is allowed in the list
749 * by comparing name to lpszName
751 if (dwType & PRINTER_ENUM_NAME)
752 if (strcmp(PrinterName,lpszName)!=0)
758 /* FIXME: unimplemented */
761 bCalcSpaceOnly = ENUMPRINTERS_AddInfo2A(PrinterName, lpbPrinters,
762 dwIndex*dwStructPrinterInfoSize,
763 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
766 bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters,
767 dwIndex*dwStructPrinterInfoSize,
768 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
771 bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters,
772 dwIndex*dwStructPrinterInfoSize,
773 &dwNextStringPos, cbBuf, bCalcSpaceOnly);
777 RegCloseKey(hPrinterListKey);
778 *lpdwNeeded = dwNextStringPos;
780 if (bCalcSpaceOnly==TRUE)
782 if (lpbPrinters!=NULL)
785 for (i=0; i<cbBuf; i++)
790 LeaveCriticalSection(&PRINT32_RegistryBlocker);
794 /******************************************************************
795 * EnumPrinters32W [WINSPOOL.175]
798 BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName,
799 DWORD dwLevel, LPBYTE lpbPrinters,
800 DWORD cbBuf, LPDWORD lpdwNeeded,
801 LPDWORD lpdwReturned)
803 FIXME("Nearly empty stub\n");
809 /******************************************************************
810 * AddMonitor32A [WINSPOOL.107]
813 BOOL WINAPI AddMonitorA(LPCSTR pName, DWORD Level, LPBYTE pMonitors)
815 FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors);
816 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
820 /******************************************************************
821 * DeletePrinterDriver32A [WINSPOOL.146]
825 DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName)
827 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
828 debugstr_a(pDriverName));
829 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
834 /******************************************************************
835 * DeleteMonitor32A [WINSPOOL.135]
839 DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName)
841 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment),
842 debugstr_a(pMonitorName));
843 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
848 /******************************************************************
849 * DeletePort32A [WINSPOOL.137]
853 DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName)
855 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd,
856 debugstr_a(pPortName));
857 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
861 /******************************************************************************
862 * SetPrinter32W [WINSPOOL.214]
872 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
876 /******************************************************************************
877 * WritePrinter32 [WINSPOOL.223]
887 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
891 /*****************************************************************************
892 * AddForm32A [WINSPOOL.103]
894 BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
896 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
900 /*****************************************************************************
901 * AddForm32W [WINSPOOL.104]
903 BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm)
905 FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm);
909 /*****************************************************************************
910 * AddJob32A [WINSPOOL.105]
912 BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData,
913 DWORD cbBuf, LPDWORD pcbNeeded)
915 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
920 /*****************************************************************************
921 * AddJob32W [WINSPOOL.106]
923 BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf,
926 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf,
931 /*****************************************************************************
932 * AddPrinter32A [WINSPOOL.117]
934 HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
936 PRINTER_INFO_2A *pi = (PRINTER_INFO_2A *) pPrinter;
939 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
941 TRACE("(%s,%ld,%p)\n", pName, Level, pPrinter);
944 FIXME("pName = `%s' - unsupported\n", pName);
945 SetLastError(ERROR_INVALID_PARAMETER);
949 WARN("Level = %ld\n", Level);
950 SetLastError(ERROR_INVALID_LEVEL);
954 SetLastError(ERROR_INVALID_PARAMETER);
957 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
959 ERR("Can't create Printers key\n");
962 if(RegOpenKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) ==
964 SetLastError(ERROR_PRINTER_ALREADY_EXISTS);
965 RegCloseKey(hkeyPrinter);
966 RegCloseKey(hkeyPrinters);
969 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
971 ERR("Can't create Drivers key\n");
972 RegCloseKey(hkeyPrinters);
975 if(RegOpenKeyA(hkeyDrivers, pi->pDriverName, &hkeyDriver) !=
977 WARN("Can't find driver `%s'\n", pi->pDriverName);
978 RegCloseKey(hkeyPrinters);
979 RegCloseKey(hkeyDrivers);
980 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER);
983 RegCloseKey(hkeyDriver);
984 RegCloseKey(hkeyDrivers);
985 if(strcasecmp(pi->pPrintProcessor, "WinPrint")) { /* FIXME */
986 WARN("Can't find processor `%s'\n", pi->pPrintProcessor);
987 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
988 RegCloseKey(hkeyPrinters);
991 if(RegCreateKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) !=
993 WARN("Can't create printer `%s'\n", pi->pPrinterName);
994 SetLastError(ERROR_INVALID_PRINTER_NAME);
995 RegCloseKey(hkeyPrinters);
998 RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD,
999 (LPSTR)&pi->Attributes, sizeof(DWORD));
1000 RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY,
1001 (LPSTR)&pi->pDevMode,
1002 pi->pDevMode ? pi->pDevMode->dmSize : 0);
1003 RegSetValueExA(hkeyPrinter, "Description", 0, REG_SZ, pi->pComment, 0);
1004 RegSetValueExA(hkeyPrinter, "Location", 0, REG_SZ, pi->pLocation, 0);
1005 RegSetValueExA(hkeyPrinter, "Name", 0, REG_SZ, pi->pPrinterName, 0);
1006 RegSetValueExA(hkeyPrinter, "Parameters", 0, REG_SZ, pi->pParameters, 0);
1007 RegSetValueExA(hkeyPrinter, "Port", 0, REG_SZ, pi->pPortName, 0);
1008 RegSetValueExA(hkeyPrinter, "Print Processor", 0, REG_SZ,
1009 pi->pPrintProcessor, 0);
1010 RegSetValueExA(hkeyPrinter, "Printer Driver", 0, REG_SZ, pi->pDriverName,
1012 RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD,
1013 (LPSTR)&pi->Priority, sizeof(DWORD));
1014 RegSetValueExA(hkeyPrinter, "Separator File", 0, REG_SZ, pi->pSepFile, 0);
1015 RegSetValueExA(hkeyPrinter, "Share Name", 0, REG_SZ, pi->pShareName, 0);
1016 RegSetValueExA(hkeyPrinter, "Start Time", 0, REG_DWORD,
1017 (LPSTR)&pi->StartTime, sizeof(DWORD));
1018 RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD,
1019 (LPSTR)&pi->Status, sizeof(DWORD));
1020 RegSetValueExA(hkeyPrinter, "Until Time", 0, REG_DWORD,
1021 (LPSTR)&pi->UntilTime, sizeof(DWORD));
1023 RegCloseKey(hkeyPrinter);
1024 RegCloseKey(hkeyPrinters);
1025 if(!OpenPrinterA(pi->pPrinterName, &retval, NULL)) {
1026 ERR("OpenPrinter failing\n");
1032 /*****************************************************************************
1033 * AddPrinter32W [WINSPOOL.122]
1035 HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter)
1037 FIXME("(%p,%ld,%p): stub\n", pName, Level, pPrinter);
1042 /*****************************************************************************
1043 * ClosePrinter32 [WINSPOOL.126]
1045 BOOL WINAPI ClosePrinter(HANDLE hPrinter)
1047 LPOPENEDPRINTERA lpOpenedPrinter;
1049 TRACE("Handle %d\n", hPrinter);
1051 if (!pOpenedPrinterDPA)
1054 if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1)))
1056 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
1057 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName);
1058 lpOpenedPrinter->lpsPrinterName = NULL;
1060 /* Free the memory of lpDefault if it has been initialized*/
1061 if(lpOpenedPrinter->lpDefault != NULL)
1063 HeapFree(GetProcessHeap(), 0,
1064 lpOpenedPrinter->lpDefault->pDevMode);
1065 HeapFree(GetProcessHeap(), 0,
1066 lpOpenedPrinter->lpDefault->pDatatype);
1067 HeapFree(GetProcessHeap(), 0,
1068 lpOpenedPrinter->lpDefault);
1069 lpOpenedPrinter->lpDefault = NULL;
1072 lpOpenedPrinter->hPrinter = -1;
1079 /*****************************************************************************
1080 * DeleteForm32A [WINSPOOL.133]
1082 BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName)
1084 FIXME("(%d,%s): stub\n", hPrinter, pFormName);
1088 /*****************************************************************************
1089 * DeleteForm32W [WINSPOOL.134]
1091 BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName)
1093 FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName));
1097 /*****************************************************************************
1098 * DeletePrinter32 [WINSPOOL.143]
1100 BOOL WINAPI DeletePrinter(HANDLE hPrinter)
1102 FIXME("(%d): stub\n", hPrinter);
1106 /*****************************************************************************
1107 * SetPrinter32A [WINSPOOL.211]
1109 BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1112 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command);
1116 /*****************************************************************************
1117 * SetJob32A [WINSPOOL.209]
1119 BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level,
1120 LPBYTE pJob, DWORD Command)
1122 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1127 /*****************************************************************************
1128 * SetJob32W [WINSPOOL.210]
1130 BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level,
1131 LPBYTE pJob, DWORD Command)
1133 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob,
1138 /*****************************************************************************
1139 * GetForm32A [WINSPOOL.181]
1141 BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1142 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1144 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName,
1145 Level,pForm,cbBuf,pcbNeeded);
1149 /*****************************************************************************
1150 * GetForm32W [WINSPOOL.182]
1152 BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1153 LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded)
1155 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,
1156 debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded);
1160 /*****************************************************************************
1161 * SetForm32A [WINSPOOL.207]
1163 BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level,
1166 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1170 /*****************************************************************************
1171 * SetForm32W [WINSPOOL.208]
1173 BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level,
1176 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm);
1180 /*****************************************************************************
1181 * ReadPrinter32 [WINSPOOL.202]
1183 BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf,
1184 LPDWORD pNoBytesRead)
1186 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead);
1190 /*****************************************************************************
1191 * ResetPrinter32A [WINSPOOL.203]
1193 BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault)
1195 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1199 /*****************************************************************************
1200 * ResetPrinter32W [WINSPOOL.204]
1202 BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault)
1204 FIXME("(%d, %p): stub\n", hPrinter, pDefault);
1209 /*****************************************************************************
1210 * WINSPOOL_GetStringFromRegA
1212 * Get ValueName from hkey storing result in str. buflen is space left in str
1214 static BOOL WINSPOOL_GetStringFromRegA(HKEY hkey, LPCSTR ValueName, LPSTR ptr,
1215 DWORD buflen, DWORD *needed)
1217 DWORD sz = buflen, type;
1220 ret = RegQueryValueExA(hkey, ValueName, 0, &type, ptr, &sz);
1222 if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) {
1223 ERR("Got ret = %ld\n", ret);
1231 /*****************************************************************************
1232 * GetPrinter32A [WINSPOOL.187]
1234 BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1235 DWORD cbBuf, LPDWORD pcbNeeded)
1237 OPENEDPRINTERA *lpOpenedPrinter;
1238 DWORD size, needed = 0;
1240 HKEY hkeyPrinter, hkeyPrinters;
1242 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
1244 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
1245 if(!lpOpenedPrinter) {
1246 SetLastError(ERROR_INVALID_HANDLE);
1249 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1251 ERR("Can't create Printers key\n");
1254 if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1256 ERR("Can't find opened printer `%s' in registry\n",
1257 lpOpenedPrinter->lpsPrinterName);
1258 RegCloseKey(hkeyPrinters);
1259 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1266 PRINTER_INFO_2A *pi2 = (PRINTER_INFO_2A *)pPrinter;
1268 size = sizeof(PRINTER_INFO_2A);
1270 ptr = pPrinter + size;
1272 memset(pPrinter, 0, size);
1277 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, cbBuf, &size);
1278 if(cbBuf && size <= cbBuf) {
1279 pi2->pPrinterName = ptr;
1285 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, cbBuf, &size);
1286 if(cbBuf && size <= cbBuf) {
1287 pi2->pPortName = ptr;
1293 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Printer Driver", ptr, cbBuf,
1295 if(cbBuf && size <= cbBuf) {
1296 pi2->pDriverName = ptr;
1302 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Default DevMode", ptr, cbBuf,
1304 if(cbBuf && size <= cbBuf) {
1305 pi2->pDevMode = (LPDEVMODEA)ptr;
1311 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Print Processor", ptr, cbBuf,
1313 if(cbBuf && size <= cbBuf) {
1314 pi2->pPrintProcessor = ptr;
1325 PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A *)pPrinter;
1327 size = sizeof(PRINTER_INFO_5A);
1329 ptr = pPrinter + size;
1331 memset(pPrinter, 0, size);
1336 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, cbBuf, &size);
1337 if(cbBuf && size <= cbBuf) {
1338 pi5->pPrinterName = ptr;
1344 WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, cbBuf, &size);
1345 if(cbBuf && size <= cbBuf) {
1346 pi5->pPortName = ptr;
1356 FIXME("Unimplemented level %ld\n", Level);
1357 SetLastError(ERROR_INVALID_LEVEL);
1358 RegCloseKey(hkeyPrinters);
1359 RegCloseKey(hkeyPrinter);
1363 RegCloseKey(hkeyPrinter);
1364 RegCloseKey(hkeyPrinters);
1366 if(pcbNeeded) *pcbNeeded = needed;
1367 if(cbBuf) return TRUE;
1368 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1373 /*****************************************************************************
1374 * GetPrinter32W [WINSPOOL.194]
1376 BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
1377 DWORD cbBuf, LPDWORD pcbNeeded)
1379 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter,
1385 /*****************************************************************************
1386 * GetPrinterDriver32A [WINSPOOL.190]
1388 BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment,
1389 DWORD Level, LPBYTE pDriverInfo,
1390 DWORD cbBuf, LPDWORD pcbNeeded)
1392 OPENEDPRINTERA *lpOpenedPrinter;
1393 char DriverName[100];
1394 DWORD ret, type, size, dw, needed = 0;
1396 HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
1398 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,pEnvironment,
1399 Level,pDriverInfo,cbBuf, pcbNeeded);
1401 lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter);
1402 if(!lpOpenedPrinter) {
1403 SetLastError(ERROR_INVALID_HANDLE);
1407 FIXME("pEnvironment = `%s'\n", pEnvironment);
1408 SetLastError(ERROR_INVALID_ENVIRONMENT);
1411 if(Level < 1 || Level > 3) {
1412 SetLastError(ERROR_INVALID_LEVEL);
1415 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
1417 ERR("Can't create Printers key\n");
1420 if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter)
1422 ERR("Can't find opened printer `%s' in registry\n",
1423 lpOpenedPrinter->lpsPrinterName);
1424 RegCloseKey(hkeyPrinters);
1425 SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */
1428 size = sizeof(DriverName);
1429 ret = RegQueryValueExA(hkeyPrinter, "Printer Driver", 0, &type, DriverName,
1431 RegCloseKey(hkeyPrinter);
1432 RegCloseKey(hkeyPrinters);
1433 if(ret != ERROR_SUCCESS) {
1434 ERR("Can't get DriverName for printer `%s'\n",
1435 lpOpenedPrinter->lpsPrinterName);
1438 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1440 ERR("Can't create Drivers key\n");
1443 if(RegOpenKeyA(hkeyDrivers, DriverName, &hkeyDriver)
1445 ERR("Can't find driver `%s' in registry\n", DriverName);
1446 RegCloseKey(hkeyDrivers);
1447 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
1453 size = sizeof(DRIVER_INFO_1A);
1456 size = sizeof(DRIVER_INFO_2A);
1459 size = sizeof(DRIVER_INFO_3A);
1462 ERR("Invalid level\n");
1467 ptr = pDriverInfo + size;
1473 size = strlen(DriverName) + 1;
1476 strcpy(ptr, DriverName);
1478 ((DRIVER_INFO_1A *)pDriverInfo)->pName = ptr;
1480 ((DRIVER_INFO_2A *)pDriverInfo)->pName = ptr;
1486 DRIVER_INFO_2A *di2 = (DRIVER_INFO_2A *)pDriverInfo;
1489 if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw,
1492 WARN("Can't get Version\n");
1496 size = strlen("Wine") + 1; /* FIXME */
1499 strcpy(ptr, "Wine");
1500 di2->pEnvironment = ptr;
1506 WINSPOOL_GetStringFromRegA(hkeyDriver, "Driver", ptr, cbBuf, &size);
1507 if(cbBuf && size <= cbBuf) {
1508 di2->pDriverPath = ptr;
1514 WINSPOOL_GetStringFromRegA(hkeyDriver, "Data File", ptr, cbBuf, &size);
1515 if(cbBuf && size <= cbBuf) {
1516 di2->pDataFile = ptr;
1522 WINSPOOL_GetStringFromRegA(hkeyDriver, "Configuration File", ptr,
1524 if(cbBuf && size <= cbBuf) {
1525 di2->pConfigFile = ptr;
1533 DRIVER_INFO_3A *di3 = (DRIVER_INFO_3A *)pDriverInfo;
1535 WINSPOOL_GetStringFromRegA(hkeyDriver, "Help File", ptr, cbBuf, &size);
1536 if(cbBuf && size <= cbBuf) {
1537 di3->pHelpFile = ptr;
1543 WINSPOOL_GetStringFromRegA(hkeyDriver, "Dependent Files", ptr, cbBuf,
1545 if(cbBuf && size <= cbBuf) {
1546 di3->pDependentFiles = ptr;
1552 WINSPOOL_GetStringFromRegA(hkeyDriver, "Monitor", ptr, cbBuf, &size);
1553 if(cbBuf && size <= cbBuf) {
1554 di3->pMonitorName = ptr;
1560 WINSPOOL_GetStringFromRegA(hkeyDriver, "DataType", ptr, cbBuf, &size);
1561 if(cbBuf && size <= cbBuf) {
1562 di3->pDefaultDataType = ptr;
1568 RegCloseKey(hkeyDriver);
1569 RegCloseKey(hkeyDrivers);
1571 if(pcbNeeded) *pcbNeeded = needed;
1572 if(cbBuf) return TRUE;
1573 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1577 /*****************************************************************************
1578 * GetPrinterDriver32W [WINSPOOL.193]
1580 BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment,
1581 DWORD Level, LPBYTE pDriverInfo,
1582 DWORD cbBuf, LPDWORD pcbNeeded)
1584 FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment,
1585 Level,pDriverInfo,cbBuf, pcbNeeded);
1589 /*****************************************************************************
1590 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1592 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
1593 DWORD Level, LPBYTE pDriverDirectory,
1594 DWORD cbBuf, LPDWORD pcbNeeded)
1598 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level,
1599 pDriverDirectory, cbBuf, pcbNeeded);
1601 FIXME("pName = `%s' - unsupported\n", pName);
1602 SetLastError(ERROR_INVALID_PARAMETER);
1605 if(pEnvironment != NULL) {
1606 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment);
1607 SetLastError(ERROR_INVALID_ENVIRONMENT);
1610 if(Level != 1) /* win95 ignores this so we just carry on */
1611 WARN("Level = %ld - assuming 1\n", Level);
1613 /* FIXME should read from registry */
1614 needed = GetSystemDirectoryA(pDriverDirectory, cbBuf);
1617 *pcbNeeded = needed;
1618 if(needed > cbBuf) {
1619 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1626 /*****************************************************************************
1627 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1629 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
1630 DWORD Level, LPBYTE pDriverDirectory,
1631 DWORD cbBuf, LPDWORD pcbNeeded)
1633 LPSTR pNameA = NULL, pEnvironmentA = NULL;
1637 pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName );
1639 pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment );
1640 ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level,
1641 pDriverDirectory, cbBuf, pcbNeeded );
1643 HeapFree( GetProcessHeap(), 0, pNameA );
1645 HeapFree( GetProcessHeap(), 0, pEnvironment );
1650 /*****************************************************************************
1651 * AddPrinterDriver32A [WINSPOOL.120]
1653 BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo)
1656 HKEY hkeyDrivers, hkeyName;
1658 TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo);
1660 if(level != 2 && level != 3) {
1661 SetLastError(ERROR_INVALID_LEVEL);
1665 FIXME("pName= `%s' - unsupported\n", pName);
1666 SetLastError(ERROR_INVALID_PARAMETER);
1670 WARN("pDriverInfo == NULL");
1671 SetLastError(ERROR_INVALID_PARAMETER);
1676 di3 = *(DRIVER_INFO_3A *)pDriverInfo;
1678 memset(&di3, 0, sizeof(di3));
1679 *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo;
1682 if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile ||
1684 SetLastError(ERROR_INVALID_PARAMETER);
1687 if(!di3.pDefaultDataType) di3.pDefaultDataType = "";
1688 if(!di3.pDependentFiles) di3.pDependentFiles = "\0";
1689 if(!di3.pHelpFile) di3.pHelpFile = "";
1690 if(!di3.pMonitorName) di3.pMonitorName = "";
1692 if(di3.pEnvironment) {
1693 FIXME("pEnvironment = `%s'\n", di3.pEnvironment);
1694 SetLastError(ERROR_INVALID_ENVIRONMENT);
1697 if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
1699 ERR("Can't create Drivers key\n");
1703 if(level == 2) { /* apparently can't overwrite with level2 */
1704 if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) {
1705 RegCloseKey(hkeyName);
1706 RegCloseKey(hkeyDrivers);
1707 WARN("Trying to create existing printer driver `%s'\n", di3.pName);
1708 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED);
1712 if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) {
1713 RegCloseKey(hkeyDrivers);
1714 ERR("Can't create Name key\n");
1717 RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile,
1719 RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0);
1720 RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0);
1721 RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion,
1723 RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0);
1724 RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ,
1725 di3.pDependentFiles, 0);
1726 RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0);
1727 RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0);
1728 RegCloseKey(hkeyName);
1729 RegCloseKey(hkeyDrivers);
1733 /*****************************************************************************
1734 * AddPrinterDriver32W [WINSPOOL.121]
1736 BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level,
1739 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName),
1745 /*****************************************************************************
1746 * PrinterProperties [WINSPOOL.201]
1748 * Displays a dialog to set the properties of the printer.
1751 * nonzero on succes or zero on faillure
1754 * implemented as stub only
1756 BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */
1757 HANDLE hPrinter /* handle to printer object */
1759 FIXME("(%d,%d): stub\n", hWnd, hPrinter);
1760 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1764 /*****************************************************************************
1765 * EnumJobsA [WINSPOOL.162]
1768 BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
1769 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
1773 if(pcbNeeded) *pcbNeeded = 0;
1774 if(pcReturned) *pcReturned = 0;
1779 /*****************************************************************************
1780 * EnumJobsW [WINSPOOL.163]
1783 BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
1784 DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded,
1788 if(pcbNeeded) *pcbNeeded = 0;
1789 if(pcReturned) *pcReturned = 0;