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(!pOpenedPrinterDPA
) return NULL
;
107 if((printerHandle
<=0) ||
108 (printerHandle
> (pOpenedPrinterDPA
->nItemCount
- 1)))
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 return GDI_CallDeviceCapabilities16(pDeivce
, pPort
, cap
, pOutput
, lpdm
);
128 /*****************************************************************************
129 * DeviceCapabilities32W
131 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
132 WORD fwCapability
, LPWSTR pOutput
,
133 const DEVMODEW
*pDevMode
)
135 FIXME("(%p,%p,%d,%p,%p): stub\n",
136 pDevice
, pPort
, fwCapability
, pOutput
, pDevMode
);
140 /******************************************************************
141 * DocumentProperties32A [WINSPOOL.155]
144 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
145 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
146 LPDEVMODEA pDevModeInput
,DWORD fMode
)
148 LPOPENEDPRINTERA lpOpenedPrinter
;
149 LPSTR lpName
= pDeviceName
;
151 TRACE("(%d,%d,%s,%p,%p,%ld)\n",
152 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
156 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
157 if(!lpOpenedPrinter
) {
158 SetLastError(ERROR_INVALID_HANDLE
);
161 lpName
= lpOpenedPrinter
->lpsPrinterName
;
164 return GDI_CallExtDeviceMode16(hWnd
, pDevModeOutput
, lpName
, NULL
,
165 pDevModeInput
, NULL
, fMode
);
170 /*****************************************************************************
171 * DocumentProperties32W
173 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
175 LPDEVMODEW pDevModeOutput
,
176 LPDEVMODEW pDevModeInput
, DWORD fMode
)
178 FIXME("(%d,%d,%s,%p,%p,%ld): stub\n",
179 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
185 /******************************************************************
186 * OpenPrinter32A [WINSPOOL.196]
189 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
190 LPPRINTER_DEFAULTSA pDefault
)
192 /* Not implemented: use the DesiredAccess of pDefault to set
193 the access rights to the printer */
195 LPOPENEDPRINTERA lpOpenedPrinter
;
197 TRACE("(printerName: %s, pDefault %p\n", lpPrinterName
, pDefault
);
199 /* Get a place in the opened printer buffer*/
200 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterEntryA();
202 if((lpOpenedPrinter
!= NULL
) && (lpPrinterName
!=NULL
) &&
205 /* Get the name of the printer */
206 lpOpenedPrinter
->lpsPrinterName
=
207 HeapAlloc(GetProcessHeap(), 0, lstrlenA(lpPrinterName
));
208 lstrcpyA(lpOpenedPrinter
->lpsPrinterName
, lpPrinterName
);
210 /* Get the unique handle of the printer*/
211 *phPrinter
= lpOpenedPrinter
->hPrinter
;
213 if (pDefault
!= NULL
)
215 /* Allocate enough memory for the lpDefault structure */
216 lpOpenedPrinter
->lpDefault
=
217 HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA
));
218 lpOpenedPrinter
->lpDefault
->pDevMode
=
219 HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA
));
220 lpOpenedPrinter
->lpDefault
->pDatatype
=
221 HeapAlloc(GetProcessHeap(), 0, lstrlenA(pDefault
->pDatatype
));
223 /*Copy the information from incoming parameter*/
224 memcpy(lpOpenedPrinter
->lpDefault
->pDevMode
, pDefault
->pDevMode
,
226 lstrcpyA(lpOpenedPrinter
->lpDefault
->pDatatype
,
227 pDefault
->pDatatype
);
228 lpOpenedPrinter
->lpDefault
->DesiredAccess
=
229 pDefault
->DesiredAccess
;
235 if(lpOpenedPrinter
== NULL
)
236 FIXME("Reach the OpenedPrinterTable maximum, augment this max.\n");
240 /******************************************************************
241 * OpenPrinter32W [WINSPOOL.197]
244 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
245 LPPRINTER_DEFAULTSW pDefault
)
247 FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName
), phPrinter
,
249 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
256 /******************************************************************
257 * ENUMPRINTERS_GetDWORDFromRegistryA internal
259 * Reads a DWORD from registry KeyName
262 * value on OK or NULL on error
264 DWORD
ENUMPRINTERS_GetDWORDFromRegistryA(
265 HKEY hPrinterSettings
, /* handle to registry key */
266 LPSTR KeyName
/* name key to retrieve string from*/
273 if (RegQueryValueExA(hPrinterSettings
, KeyName
, NULL
, &DataType
,
274 Data
, &DataSize
)!=ERROR_SUCCESS
)
275 FIXME("Query of register '%s' didn't succeed?\n", KeyName
);
276 if (DataType
== REG_DWORD_LITTLE_ENDIAN
)
277 Result
= Data
[0] + (Data
[1]<<8) + (Data
[2]<<16) + (Data
[3]<<24);
278 if (DataType
== REG_DWORD_BIG_ENDIAN
)
279 Result
= Data
[3] + (Data
[2]<<8) + (Data
[1]<<16) + (Data
[0]<<24);
284 /******************************************************************
285 * ENUMPRINTERS_AddStringFromRegistryA internal
287 * Reads a string from registry KeyName and writes it at
288 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
291 * FALSE if there is still space left in the buffer.
293 BOOL
ENUMPRINTERS_AddStringFromRegistryA(
294 HKEY hPrinterSettings
, /* handle to registry key */
295 LPSTR KeyName
, /* name key to retrieve string from*/
296 LPSTR
* Dest
, /* pointer to write string addres to */
297 LPBYTE lpbPrinters
, /* buffer which receives info*/
298 LPDWORD dwNextStringPos
,/* pos in buffer for next string */
299 DWORD dwBufSize
, /* max size of buffer in bytes */
300 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
304 LPSTR Data
= (LPSTR
) malloc(DataSize
*sizeof(char));
306 while(RegQueryValueExA(hPrinterSettings
, KeyName
, NULL
, &DataType
,
307 Data
, &DataSize
)==ERROR_MORE_DATA
)
309 Data
= (LPSTR
) realloc(Data
, DataSize
+2);
312 if (DataType
== REG_SZ
)
314 if (bCalcSpaceOnly
==FALSE
)
315 *Dest
= &lpbPrinters
[*dwNextStringPos
];
316 *dwNextStringPos
+= DataSize
+1;
317 if (*dwNextStringPos
> dwBufSize
)
319 if (bCalcSpaceOnly
==FALSE
)
321 if (DataSize
==0) /* DataSize = 0 means empty string, even though*/
322 *Dest
[0]=0; /* the data itself needs not to be empty */
328 WARN("Expected string setting, got something else from registry");
332 return(bCalcSpaceOnly
);
337 /******************************************************************
338 * ENUMPRINTERS_AddInfo2A internal
340 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
341 * for printer PrinterNameKey.
342 * Note that there is no check whether the information really fits!
345 * FALSE if there is still space left in the buffer.
348 * This function should not only read the registry but also ask the driver
351 BOOL
ENUMPRINTERS_AddInfo2A(
352 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
353 LPBYTE lpbPrinters
, /* buffer which receives info*/
354 DWORD dwNextStructPos
, /* pos in buffer for struct */
355 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
356 DWORD dwBufSize
, /* max size of buffer in bytes */
357 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
359 HKEY hPrinterSettings
;
362 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
363 strlen(lpszPrinterName
)+2);
364 LPPRINTER_INFO_2A lpPInfo2
= (LPPRINTER_INFO_2A
) &lpbPrinters
[dwNextStructPos
];
366 /* open the registry to find the attributes, etc of the printer */
367 if (lpszPrinterSettings
!=NULL
)
369 strcpy(lpszPrinterSettings
,Printers
);
370 strcat(lpszPrinterSettings
,lpszPrinterName
);
372 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
373 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
375 WARN("The registry did not contain my printer anymore?\n");
379 if (bCalcSpaceOnly
==FALSE
)
380 lpPInfo2
->pServerName
= NULL
;
381 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
382 "Name", &(lpPInfo2
->pPrinterName
),
383 lpbPrinters
, dwNextStringPos
,
384 dwBufSize
, bCalcSpaceOnly
);
385 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
386 "Share Name", &(lpPInfo2
->pShareName
),
387 lpbPrinters
, dwNextStringPos
,
388 dwBufSize
, bCalcSpaceOnly
);
389 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
390 "Port", &(lpPInfo2
->pPortName
),
391 lpbPrinters
, dwNextStringPos
,
392 dwBufSize
, bCalcSpaceOnly
);
393 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
394 "Printer Driver", &(lpPInfo2
->pDriverName
),
395 lpbPrinters
, dwNextStringPos
,
396 dwBufSize
, bCalcSpaceOnly
);
397 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
398 "Description", &(lpPInfo2
->pComment
),
399 lpbPrinters
, dwNextStringPos
,
400 dwBufSize
, bCalcSpaceOnly
);
401 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
402 "Location", &(lpPInfo2
->pLocation
),
403 lpbPrinters
, dwNextStringPos
,
404 dwBufSize
, bCalcSpaceOnly
);
406 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
407 "Separator File", &(lpPInfo2
->pSepFile
),
408 lpbPrinters
, dwNextStringPos
,
409 dwBufSize
, bCalcSpaceOnly
);
410 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
411 "Print Processor", &(lpPInfo2
->pPrintProcessor
),
412 lpbPrinters
, dwNextStringPos
,
413 dwBufSize
, bCalcSpaceOnly
);
414 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
415 "Datatype", &(lpPInfo2
->pDatatype
),
416 lpbPrinters
, dwNextStringPos
,
417 dwBufSize
, bCalcSpaceOnly
);
418 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
419 "Parameters", &(lpPInfo2
->pParameters
),
420 lpbPrinters
, dwNextStringPos
,
421 dwBufSize
, bCalcSpaceOnly
);
422 if (bCalcSpaceOnly
== FALSE
)
424 lpPInfo2
->pSecurityDescriptor
= NULL
; /* EnumPrinters doesn't return this*/
426 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
427 lpPInfo2
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
428 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
429 lpPInfo2
->Priority
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
431 lpPInfo2
->DefaultPriority
= ENUMPRINTERS_GetDWORDFromRegistryA(
432 hPrinterSettings
, "Default Priority");
433 lpPInfo2
->StartTime
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
435 lpPInfo2
->UntilTime
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
437 lpPInfo2
->Status
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
439 lpPInfo2
->cJobs
= 0; /* FIXME: according to MSDN, this does not
440 * reflect the TotalJobs Key ??? */
441 lpPInfo2
->AveragePPM
= 0; /* FIXME: according to MSDN, this does not
442 * reflect the TotalPages Key ??? */
444 /* and read the devModes structure... */
445 RegQueryValueExA(hPrinterSettings
, "pDevMode", NULL
, &DataType
,
446 NULL
, &DevSize
); /* should return ERROR_MORE_DATA */
447 lpPInfo2
->pDevMode
= (LPDEVMODEA
) &lpbPrinters
[*dwNextStringPos
];
448 *dwNextStringPos
+= DevSize
+ 1;
450 if (*dwNextStringPos
> dwBufSize
)
452 if (bCalcSpaceOnly
==FALSE
)
453 RegQueryValueExA(hPrinterSettings
, "pDevMode", NULL
, &DataType
,
454 (LPBYTE
)lpPInfo2
->pDevMode
, &DevSize
);
457 if (lpszPrinterSettings
)
458 free(lpszPrinterSettings
);
460 return(bCalcSpaceOnly
);
463 /******************************************************************
464 * ENUMPRINTERS_AddInfo4A internal
466 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
467 * for printer PrinterNameKey.
468 * Note that there is no check whether the information really fits!
471 * FALSE if there is still space left in the buffer.
474 * This function should not exist in Win95 mode, but does anyway.
476 BOOL
ENUMPRINTERS_AddInfo4A(
477 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
478 LPBYTE lpbPrinters
, /* buffer which receives info*/
479 DWORD dwNextStructPos
, /* pos in buffer for struct */
480 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
481 DWORD dwBufSize
, /* max size of buffer in bytes */
482 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
484 HKEY hPrinterSettings
;
485 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
486 strlen(lpszPrinterName
)+2);
487 LPPRINTER_INFO_4A lpPInfo4
= (LPPRINTER_INFO_4A
) &lpbPrinters
[dwNextStructPos
];
489 /* open the registry to find the attributes of the printer */
490 if (lpszPrinterSettings
!=NULL
)
492 strcpy(lpszPrinterSettings
,Printers
);
493 strcat(lpszPrinterSettings
,lpszPrinterName
);
495 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
496 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
498 WARN("The registry did not contain my printer anymore?\n");
502 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
503 "Name", &(lpPInfo4
->pPrinterName
),
504 lpbPrinters
, dwNextStringPos
,
505 dwBufSize
, bCalcSpaceOnly
);
506 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
507 if (bCalcSpaceOnly
==FALSE
)
508 lpPInfo4
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
509 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
511 if (lpszPrinterSettings
)
512 free(lpszPrinterSettings
);
514 return(bCalcSpaceOnly
);
517 /******************************************************************
518 * ENUMPRINTERS_AddInfo5A internal
520 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
521 * for printer PrinterNameKey.
522 * Settings are read from the registry.
523 * Note that there is no check whether the information really fits!
525 * FALSE if there is still space left in the buffer.
527 BOOL
ENUMPRINTERS_AddInfo5A(
528 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
529 LPBYTE lpbPrinters
, /* buffer which receives info*/
530 DWORD dwNextStructPos
, /* pos in buffer for struct */
531 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
532 DWORD dwBufSize
, /* max size of buffer in bytes */
533 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
535 HKEY hPrinterSettings
;
536 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
537 strlen(lpszPrinterName
)+2);
538 LPPRINTER_INFO_5A lpPInfo5
= (LPPRINTER_INFO_5A
) &lpbPrinters
[dwNextStructPos
];
540 /* open the registry to find the attributes, etc of the printer */
541 if (lpszPrinterSettings
!=NULL
)
543 strcpy(lpszPrinterSettings
,Printers
);
544 strcat(lpszPrinterSettings
,lpszPrinterName
);
546 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
547 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
549 WARN("The registry did not contain my printer anymore?\n");
553 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
554 "Name", &(lpPInfo5
->pPrinterName
),
555 lpbPrinters
, dwNextStringPos
,
556 dwBufSize
, bCalcSpaceOnly
);
557 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
558 "Port", &(lpPInfo5
->pPortName
), lpbPrinters
,
559 dwNextStringPos
, dwBufSize
, bCalcSpaceOnly
);
560 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
561 if (bCalcSpaceOnly
== FALSE
)
563 lpPInfo5
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
564 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
565 lpPInfo5
->DeviceNotSelectedTimeOut
566 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
568 lpPInfo5
->TransmissionRetryTimeout
569 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
574 if (lpszPrinterSettings
)
575 free(lpszPrinterSettings
);
577 return(bCalcSpaceOnly
);
581 /******************************************************************
582 * EnumPrintersA [WINSPOOL.174]
584 * Enumerates the available printers, print servers and print
585 * providers, depending on the specified flags, name and level.
589 * If level is set to 1:
590 * Not implemented yet!
591 * Returns TRUE with an empty list.
593 * If level is set to 2:
594 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
595 * Returns an array of PRINTER_INFO_2 data structures in the
596 * lpbPrinters buffer. Note that according to MSDN also an
597 * OpenPrinter should be performed on every remote printer.
599 * If level is set to 4 (officially WinNT only):
600 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
601 * Fast: Only the registry is queried to retrieve printer names,
602 * no connection to the driver is made.
603 * Returns an array of PRINTER_INFO_4 data structures in the
604 * lpbPrinters buffer.
606 * If level is set to 5 (officially WinNT4/Win9x only):
607 * Fast: Only the registry is queried to retrieve printer names,
608 * no connection to the driver is made.
609 * Returns an array of PRINTER_INFO_5 data structures in the
610 * lpbPrinters buffer.
612 * If level set to 3 or 6+:
613 * returns zero (faillure!)
615 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
619 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
620 * - Only levels 2, 4 and 5 are implemented at the moment.
621 * - 16-bit printer drivers are not enumerated.
622 * - Returned amount of bytes used/needed does not match the real Windoze
623 * implementation (as in this implementation, all strings are part
624 * of the buffer, whereas Win32 keeps them somewhere else)
625 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
628 * - In a regular Wine installation, no registry settings for printers
629 * exist, which makes this function return an empty list.
631 BOOL WINAPI
EnumPrintersA(
632 DWORD dwType
, /* Types of print objects to enumerate */
633 LPSTR lpszName
, /* name of objects to enumerate */
634 DWORD dwLevel
, /* type of printer info structure */
635 LPBYTE lpbPrinters
, /* buffer which receives info */
636 DWORD cbBuf
, /* max size of buffer in bytes */
637 LPDWORD lpdwNeeded
, /* pointer to var: # bytes used/needed */
638 LPDWORD lpdwReturned
/* number of entries returned */
641 HKEY hPrinterListKey
;
643 char PrinterName
[255];
644 DWORD PrinterNameLength
=255;
646 DWORD dwNextStringPos
; /* position of next space for a string in the buffer*/
647 DWORD dwStructPrinterInfoSize
; /* size of a Printer_Info_X structure */
648 BOOL bCalcSpaceOnly
=FALSE
;/*if TRUE: don't store data, just calculate space*/
652 /* test whether we're requested to really fill in. If so,
653 * zero out the data area, and initialise some returns to zero,
654 * to prevent problems
656 if (lpbPrinters
==NULL
|| cbBuf
==0)
661 for (i
=0; i
<cbBuf
; i
++)
667 /* check for valid Flags */
668 if (!((dwType
& PRINTER_ENUM_LOCAL
) || (dwType
& PRINTER_ENUM_NAME
)))
670 FIXME("dwType = %08lx\n", dwType
);
671 SetLastError(ERROR_INVALID_FLAGS
);
683 SetLastError(ERROR_INVALID_PARAMETER
);
687 /* Enter critical section to prevent AddPrinters() et al. to
688 * modify whilst we're reading in the registry
690 InitializeCriticalSection(&PRINT32_RegistryBlocker
);
691 EnterCriticalSection(&PRINT32_RegistryBlocker
);
693 /* get a pointer to a list of all printer names in the registry */
694 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, Printers
, 0, KEY_READ
,
695 &hPrinterListKey
) !=ERROR_SUCCESS
)
697 /* Oh no! An empty list of printers!
698 * (which is a valid configuration anyway)
700 TRACE("No entries in the Printers part of the registry\n");
703 /* count the number of entries and check if it fits in the buffer
705 while(RegEnumKeyExA(hPrinterListKey
, dwIndex
, PrinterName
, &PrinterNameLength
,
706 NULL
, NULL
, NULL
, &FileTime
)==ERROR_SUCCESS
)
708 PrinterNameLength
=255;
711 *lpdwReturned
= dwIndex
;
715 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_1A
);
718 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_2A
);
721 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_4A
);
724 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_5A
);
727 dwStructPrinterInfoSize
= 0;
730 if (dwIndex
*dwStructPrinterInfoSize
+1 > cbBuf
)
731 bCalcSpaceOnly
= TRUE
;
733 /* the strings which contain e.g. PrinterName, PortName, etc,
734 * are also stored in lpbPrinters, but after the regular structs.
735 * dwNextStringPos will always point to the next free place for a
738 dwNextStringPos
=(dwIndex
+1)*dwStructPrinterInfoSize
;
740 /* check each entry: if OK, add to list in corresponding INFO .
742 for(dwIndex
=0; dwIndex
< *lpdwReturned
; dwIndex
++)
744 PrinterNameLength
=255;
745 if (RegEnumKeyExA(hPrinterListKey
, dwIndex
, PrinterName
, &PrinterNameLength
,
746 NULL
, NULL
, NULL
, &FileTime
)!=ERROR_SUCCESS
)
747 break; /* exit for loop*/
749 /* check whether this printer is allowed in the list
750 * by comparing name to lpszName
752 if (dwType
& PRINTER_ENUM_NAME
)
753 if (strcmp(PrinterName
,lpszName
)!=0)
759 /* FIXME: unimplemented */
762 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo2A(PrinterName
, lpbPrinters
,
763 dwIndex
*dwStructPrinterInfoSize
,
764 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
767 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo4A(PrinterName
, lpbPrinters
,
768 dwIndex
*dwStructPrinterInfoSize
,
769 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
772 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo5A(PrinterName
, lpbPrinters
,
773 dwIndex
*dwStructPrinterInfoSize
,
774 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
778 RegCloseKey(hPrinterListKey
);
779 *lpdwNeeded
= dwNextStringPos
;
781 if (bCalcSpaceOnly
==TRUE
)
783 if (lpbPrinters
!=NULL
)
786 for (i
=0; i
<cbBuf
; i
++)
791 LeaveCriticalSection(&PRINT32_RegistryBlocker
);
795 /******************************************************************
796 * EnumPrinters32W [WINSPOOL.175]
799 BOOL WINAPI
EnumPrintersW(DWORD dwType
, LPWSTR lpszName
,
800 DWORD dwLevel
, LPBYTE lpbPrinters
,
801 DWORD cbBuf
, LPDWORD lpdwNeeded
,
802 LPDWORD lpdwReturned
)
804 FIXME("Nearly empty stub\n");
810 /******************************************************************
811 * AddMonitor32A [WINSPOOL.107]
814 BOOL WINAPI
AddMonitorA(LPCSTR pName
, DWORD Level
, LPBYTE pMonitors
)
816 FIXME("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
817 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
821 /******************************************************************
822 * DeletePrinterDriver32A [WINSPOOL.146]
826 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
828 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
829 debugstr_a(pDriverName
));
830 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
835 /******************************************************************
836 * DeleteMonitor32A [WINSPOOL.135]
840 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
842 FIXME("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
843 debugstr_a(pMonitorName
));
844 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
849 /******************************************************************
850 * DeletePort32A [WINSPOOL.137]
854 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
856 FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
857 debugstr_a(pPortName
));
858 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
862 /******************************************************************************
863 * SetPrinter32W [WINSPOOL.214]
873 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
877 /******************************************************************************
878 * WritePrinter32 [WINSPOOL.223]
888 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
892 /*****************************************************************************
893 * AddForm32A [WINSPOOL.103]
895 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
897 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
901 /*****************************************************************************
902 * AddForm32W [WINSPOOL.104]
904 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
906 FIXME("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
910 /*****************************************************************************
911 * AddJob32A [WINSPOOL.105]
913 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
914 DWORD cbBuf
, LPDWORD pcbNeeded
)
916 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
921 /*****************************************************************************
922 * AddJob32W [WINSPOOL.106]
924 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
927 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
932 /*****************************************************************************
933 * AddPrinter32A [WINSPOOL.117]
935 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
937 PRINTER_INFO_2A
*pi
= (PRINTER_INFO_2A
*) pPrinter
;
940 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
942 TRACE("(%s,%ld,%p)\n", pName
, Level
, pPrinter
);
945 FIXME("pName = `%s' - unsupported\n", pName
);
946 SetLastError(ERROR_INVALID_PARAMETER
);
950 WARN("Level = %ld\n", Level
);
951 SetLastError(ERROR_INVALID_LEVEL
);
955 SetLastError(ERROR_INVALID_PARAMETER
);
958 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
960 ERR("Can't create Printers key\n");
963 if(RegOpenKeyA(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) ==
965 SetLastError(ERROR_PRINTER_ALREADY_EXISTS
);
966 RegCloseKey(hkeyPrinter
);
967 RegCloseKey(hkeyPrinters
);
970 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
972 ERR("Can't create Drivers key\n");
973 RegCloseKey(hkeyPrinters
);
976 if(RegOpenKeyA(hkeyDrivers
, pi
->pDriverName
, &hkeyDriver
) !=
978 WARN("Can't find driver `%s'\n", pi
->pDriverName
);
979 RegCloseKey(hkeyPrinters
);
980 RegCloseKey(hkeyDrivers
);
981 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
);
984 RegCloseKey(hkeyDriver
);
985 RegCloseKey(hkeyDrivers
);
986 if(strcasecmp(pi
->pPrintProcessor
, "WinPrint")) { /* FIXME */
987 WARN("Can't find processor `%s'\n", pi
->pPrintProcessor
);
988 SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR
);
989 RegCloseKey(hkeyPrinters
);
992 if(RegCreateKeyA(hkeyPrinters
, pi
->pPrinterName
, &hkeyPrinter
) !=
994 WARN("Can't create printer `%s'\n", pi
->pPrinterName
);
995 SetLastError(ERROR_INVALID_PRINTER_NAME
);
996 RegCloseKey(hkeyPrinters
);
999 RegSetValueExA(hkeyPrinter
, "Attributes", 0, REG_DWORD
,
1000 (LPSTR
)&pi
->Attributes
, sizeof(DWORD
));
1001 RegSetValueExA(hkeyPrinter
, "Default DevMode", 0, REG_BINARY
,
1002 (LPSTR
)&pi
->pDevMode
,
1003 pi
->pDevMode
? pi
->pDevMode
->dmSize
: 0);
1004 RegSetValueExA(hkeyPrinter
, "Description", 0, REG_SZ
, pi
->pComment
, 0);
1005 RegSetValueExA(hkeyPrinter
, "Location", 0, REG_SZ
, pi
->pLocation
, 0);
1006 RegSetValueExA(hkeyPrinter
, "Name", 0, REG_SZ
, pi
->pPrinterName
, 0);
1007 RegSetValueExA(hkeyPrinter
, "Parameters", 0, REG_SZ
, pi
->pParameters
, 0);
1008 RegSetValueExA(hkeyPrinter
, "Port", 0, REG_SZ
, pi
->pPortName
, 0);
1009 RegSetValueExA(hkeyPrinter
, "Print Processor", 0, REG_SZ
,
1010 pi
->pPrintProcessor
, 0);
1011 RegSetValueExA(hkeyPrinter
, "Printer Driver", 0, REG_SZ
, pi
->pDriverName
,
1013 RegSetValueExA(hkeyPrinter
, "Priority", 0, REG_DWORD
,
1014 (LPSTR
)&pi
->Priority
, sizeof(DWORD
));
1015 RegSetValueExA(hkeyPrinter
, "Separator File", 0, REG_SZ
, pi
->pSepFile
, 0);
1016 RegSetValueExA(hkeyPrinter
, "Share Name", 0, REG_SZ
, pi
->pShareName
, 0);
1017 RegSetValueExA(hkeyPrinter
, "Start Time", 0, REG_DWORD
,
1018 (LPSTR
)&pi
->StartTime
, sizeof(DWORD
));
1019 RegSetValueExA(hkeyPrinter
, "Status", 0, REG_DWORD
,
1020 (LPSTR
)&pi
->Status
, sizeof(DWORD
));
1021 RegSetValueExA(hkeyPrinter
, "Until Time", 0, REG_DWORD
,
1022 (LPSTR
)&pi
->UntilTime
, sizeof(DWORD
));
1024 RegCloseKey(hkeyPrinter
);
1025 RegCloseKey(hkeyPrinters
);
1026 if(!OpenPrinterA(pi
->pPrinterName
, &retval
, NULL
)) {
1027 ERR("OpenPrinter failing\n");
1033 /*****************************************************************************
1034 * AddPrinter32W [WINSPOOL.122]
1036 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1038 FIXME("(%p,%ld,%p): stub\n", pName
, Level
, pPrinter
);
1043 /*****************************************************************************
1044 * ClosePrinter32 [WINSPOOL.126]
1046 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
1048 LPOPENEDPRINTERA lpOpenedPrinter
;
1050 TRACE("Handle %d\n", hPrinter
);
1052 if (!pOpenedPrinterDPA
)
1055 if ((hPrinter
!= -1) && (hPrinter
< (pOpenedPrinterDPA
->nItemCount
- 1)))
1057 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
1058 HeapFree(GetProcessHeap(), 0, lpOpenedPrinter
->lpsPrinterName
);
1059 lpOpenedPrinter
->lpsPrinterName
= NULL
;
1061 /* Free the memory of lpDefault if it has been initialized*/
1062 if(lpOpenedPrinter
->lpDefault
!= NULL
)
1064 HeapFree(GetProcessHeap(), 0,
1065 lpOpenedPrinter
->lpDefault
->pDevMode
);
1066 HeapFree(GetProcessHeap(), 0,
1067 lpOpenedPrinter
->lpDefault
->pDatatype
);
1068 HeapFree(GetProcessHeap(), 0,
1069 lpOpenedPrinter
->lpDefault
);
1070 lpOpenedPrinter
->lpDefault
= NULL
;
1073 lpOpenedPrinter
->hPrinter
= -1;
1080 /*****************************************************************************
1081 * DeleteForm32A [WINSPOOL.133]
1083 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
1085 FIXME("(%d,%s): stub\n", hPrinter
, pFormName
);
1089 /*****************************************************************************
1090 * DeleteForm32W [WINSPOOL.134]
1092 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
1094 FIXME("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
1098 /*****************************************************************************
1099 * DeletePrinter32 [WINSPOOL.143]
1101 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
1103 FIXME("(%d): stub\n", hPrinter
);
1107 /*****************************************************************************
1108 * SetPrinter32A [WINSPOOL.211]
1110 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1113 FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
1117 /*****************************************************************************
1118 * SetJob32A [WINSPOOL.209]
1120 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1121 LPBYTE pJob
, DWORD Command
)
1123 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1128 /*****************************************************************************
1129 * SetJob32W [WINSPOOL.210]
1131 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1132 LPBYTE pJob
, DWORD Command
)
1134 FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1139 /*****************************************************************************
1140 * GetForm32A [WINSPOOL.181]
1142 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1143 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1145 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1146 Level
,pForm
,cbBuf
,pcbNeeded
);
1150 /*****************************************************************************
1151 * GetForm32W [WINSPOOL.182]
1153 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1154 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1156 FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1157 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1161 /*****************************************************************************
1162 * SetForm32A [WINSPOOL.207]
1164 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1167 FIXME("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1171 /*****************************************************************************
1172 * SetForm32W [WINSPOOL.208]
1174 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1177 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1181 /*****************************************************************************
1182 * ReadPrinter32 [WINSPOOL.202]
1184 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1185 LPDWORD pNoBytesRead
)
1187 FIXME("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1191 /*****************************************************************************
1192 * ResetPrinter32A [WINSPOOL.203]
1194 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1196 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1200 /*****************************************************************************
1201 * ResetPrinter32W [WINSPOOL.204]
1203 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1205 FIXME("(%d, %p): stub\n", hPrinter
, pDefault
);
1210 /*****************************************************************************
1211 * WINSPOOL_GetStringFromRegA
1213 * Get ValueName from hkey storing result in str. buflen is space left in str
1215 static BOOL
WINSPOOL_GetStringFromRegA(HKEY hkey
, LPCSTR ValueName
, LPSTR ptr
,
1216 DWORD buflen
, DWORD
*needed
)
1218 DWORD sz
= buflen
, type
;
1221 ret
= RegQueryValueExA(hkey
, ValueName
, 0, &type
, ptr
, &sz
);
1223 if(ret
!= ERROR_SUCCESS
&& ret
!= ERROR_MORE_DATA
) {
1224 ERR("Got ret = %ld\n", ret
);
1232 /*****************************************************************************
1233 * GetPrinter32A [WINSPOOL.187]
1235 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1236 DWORD cbBuf
, LPDWORD pcbNeeded
)
1238 OPENEDPRINTERA
*lpOpenedPrinter
;
1239 DWORD size
, needed
= 0;
1241 HKEY hkeyPrinter
, hkeyPrinters
;
1243 TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter
,Level
,pPrinter
,cbBuf
, pcbNeeded
);
1245 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
1246 if(!lpOpenedPrinter
) {
1247 SetLastError(ERROR_INVALID_HANDLE
);
1250 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1252 ERR("Can't create Printers key\n");
1255 if(RegOpenKeyA(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1257 ERR("Can't find opened printer `%s' in registry\n",
1258 lpOpenedPrinter
->lpsPrinterName
);
1259 RegCloseKey(hkeyPrinters
);
1260 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1267 PRINTER_INFO_2A
*pi2
= (PRINTER_INFO_2A
*)pPrinter
;
1269 size
= sizeof(PRINTER_INFO_2A
);
1271 ptr
= pPrinter
+ size
;
1273 memset(pPrinter
, 0, size
);
1278 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Name", ptr
, cbBuf
, &size
);
1279 if(cbBuf
&& size
<= cbBuf
) {
1280 pi2
->pPrinterName
= ptr
;
1286 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Port", ptr
, cbBuf
, &size
);
1287 if(cbBuf
&& size
<= cbBuf
) {
1288 pi2
->pPortName
= ptr
;
1294 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Printer Driver", ptr
, cbBuf
,
1296 if(cbBuf
&& size
<= cbBuf
) {
1297 pi2
->pDriverName
= ptr
;
1303 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Default DevMode", ptr
, cbBuf
,
1305 if(cbBuf
&& size
<= cbBuf
) {
1306 pi2
->pDevMode
= (LPDEVMODEA
)ptr
;
1312 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Print Processor", ptr
, cbBuf
,
1314 if(cbBuf
&& size
<= cbBuf
) {
1315 pi2
->pPrintProcessor
= ptr
;
1326 PRINTER_INFO_5A
*pi5
= (PRINTER_INFO_5A
*)pPrinter
;
1328 size
= sizeof(PRINTER_INFO_5A
);
1330 ptr
= pPrinter
+ size
;
1332 memset(pPrinter
, 0, size
);
1337 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Name", ptr
, cbBuf
, &size
);
1338 if(cbBuf
&& size
<= cbBuf
) {
1339 pi5
->pPrinterName
= ptr
;
1345 WINSPOOL_GetStringFromRegA(hkeyPrinter
, "Port", ptr
, cbBuf
, &size
);
1346 if(cbBuf
&& size
<= cbBuf
) {
1347 pi5
->pPortName
= ptr
;
1357 FIXME("Unimplemented level %ld\n", Level
);
1358 SetLastError(ERROR_INVALID_LEVEL
);
1359 RegCloseKey(hkeyPrinters
);
1360 RegCloseKey(hkeyPrinter
);
1364 RegCloseKey(hkeyPrinter
);
1365 RegCloseKey(hkeyPrinters
);
1367 if(pcbNeeded
) *pcbNeeded
= needed
;
1368 if(cbBuf
) return TRUE
;
1369 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1374 /*****************************************************************************
1375 * GetPrinter32W [WINSPOOL.194]
1377 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1378 DWORD cbBuf
, LPDWORD pcbNeeded
)
1380 FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pPrinter
,
1386 /*****************************************************************************
1387 * GetPrinterDriver32A [WINSPOOL.190]
1389 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
1390 DWORD Level
, LPBYTE pDriverInfo
,
1391 DWORD cbBuf
, LPDWORD pcbNeeded
)
1393 OPENEDPRINTERA
*lpOpenedPrinter
;
1394 char DriverName
[100];
1395 DWORD ret
, type
, size
, dw
, needed
= 0;
1397 HKEY hkeyPrinter
, hkeyPrinters
, hkeyDriver
, hkeyDrivers
;
1399 TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter
,pEnvironment
,
1400 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1402 lpOpenedPrinter
= WINSPOOL_GetOpenedPrinterA(hPrinter
);
1403 if(!lpOpenedPrinter
) {
1404 SetLastError(ERROR_INVALID_HANDLE
);
1408 FIXME("pEnvironment = `%s'\n", pEnvironment
);
1409 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1412 if(Level
< 1 || Level
> 3) {
1413 SetLastError(ERROR_INVALID_LEVEL
);
1416 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Printers
, &hkeyPrinters
) !=
1418 ERR("Can't create Printers key\n");
1421 if(RegOpenKeyA(hkeyPrinters
, lpOpenedPrinter
->lpsPrinterName
, &hkeyPrinter
)
1423 ERR("Can't find opened printer `%s' in registry\n",
1424 lpOpenedPrinter
->lpsPrinterName
);
1425 RegCloseKey(hkeyPrinters
);
1426 SetLastError(ERROR_INVALID_PRINTER_NAME
); /* ? */
1429 size
= sizeof(DriverName
);
1430 ret
= RegQueryValueExA(hkeyPrinter
, "Printer Driver", 0, &type
, DriverName
,
1432 RegCloseKey(hkeyPrinter
);
1433 RegCloseKey(hkeyPrinters
);
1434 if(ret
!= ERROR_SUCCESS
) {
1435 ERR("Can't get DriverName for printer `%s'\n",
1436 lpOpenedPrinter
->lpsPrinterName
);
1439 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
1441 ERR("Can't create Drivers key\n");
1444 if(RegOpenKeyA(hkeyDrivers
, DriverName
, &hkeyDriver
)
1446 ERR("Can't find driver `%s' in registry\n", DriverName
);
1447 RegCloseKey(hkeyDrivers
);
1448 SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER
); /* ? */
1454 size
= sizeof(DRIVER_INFO_1A
);
1457 size
= sizeof(DRIVER_INFO_2A
);
1460 size
= sizeof(DRIVER_INFO_3A
);
1463 ERR("Invalid level\n");
1468 ptr
= pDriverInfo
+ size
;
1474 size
= strlen(DriverName
) + 1;
1477 strcpy(ptr
, DriverName
);
1479 ((DRIVER_INFO_1A
*)pDriverInfo
)->pName
= ptr
;
1481 ((DRIVER_INFO_2A
*)pDriverInfo
)->pName
= ptr
;
1487 DRIVER_INFO_2A
*di2
= (DRIVER_INFO_2A
*)pDriverInfo
;
1490 if(RegQueryValueExA(hkeyDriver
, "Version", 0, &type
, (PBYTE
)&dw
,
1493 WARN("Can't get Version\n");
1497 size
= strlen("Wine") + 1; /* FIXME */
1500 strcpy(ptr
, "Wine");
1501 di2
->pEnvironment
= ptr
;
1507 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Driver", ptr
, cbBuf
, &size
);
1508 if(cbBuf
&& size
<= cbBuf
) {
1509 di2
->pDriverPath
= ptr
;
1515 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Data File", ptr
, cbBuf
, &size
);
1516 if(cbBuf
&& size
<= cbBuf
) {
1517 di2
->pDataFile
= ptr
;
1523 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Configuration File", ptr
,
1525 if(cbBuf
&& size
<= cbBuf
) {
1526 di2
->pConfigFile
= ptr
;
1534 DRIVER_INFO_3A
*di3
= (DRIVER_INFO_3A
*)pDriverInfo
;
1536 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Help File", ptr
, cbBuf
, &size
);
1537 if(cbBuf
&& size
<= cbBuf
) {
1538 di3
->pHelpFile
= ptr
;
1544 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Dependent Files", ptr
, cbBuf
,
1546 if(cbBuf
&& size
<= cbBuf
) {
1547 di3
->pDependentFiles
= ptr
;
1553 WINSPOOL_GetStringFromRegA(hkeyDriver
, "Monitor", ptr
, cbBuf
, &size
);
1554 if(cbBuf
&& size
<= cbBuf
) {
1555 di3
->pMonitorName
= ptr
;
1561 WINSPOOL_GetStringFromRegA(hkeyDriver
, "DataType", ptr
, cbBuf
, &size
);
1562 if(cbBuf
&& size
<= cbBuf
) {
1563 di3
->pDefaultDataType
= ptr
;
1569 RegCloseKey(hkeyDriver
);
1570 RegCloseKey(hkeyDrivers
);
1572 if(pcbNeeded
) *pcbNeeded
= needed
;
1573 if(cbBuf
) return TRUE
;
1574 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1578 /*****************************************************************************
1579 * GetPrinterDriver32W [WINSPOOL.193]
1581 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
1582 DWORD Level
, LPBYTE pDriverInfo
,
1583 DWORD cbBuf
, LPDWORD pcbNeeded
)
1585 FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter
,pEnvironment
,
1586 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1590 /*****************************************************************************
1591 * GetPrinterDriverDirectoryA [WINSPOOL.191]
1593 BOOL WINAPI
GetPrinterDriverDirectoryA(LPSTR pName
, LPSTR pEnvironment
,
1594 DWORD Level
, LPBYTE pDriverDirectory
,
1595 DWORD cbBuf
, LPDWORD pcbNeeded
)
1599 TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName
, pEnvironment
, Level
,
1600 pDriverDirectory
, cbBuf
, pcbNeeded
);
1602 FIXME("pName = `%s' - unsupported\n", pName
);
1603 SetLastError(ERROR_INVALID_PARAMETER
);
1606 if(pEnvironment
!= NULL
) {
1607 FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment
);
1608 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1611 if(Level
!= 1) /* win95 ignores this so we just carry on */
1612 WARN("Level = %ld - assuming 1\n", Level
);
1614 /* FIXME should read from registry */
1615 needed
= GetSystemDirectoryA(pDriverDirectory
, cbBuf
);
1618 *pcbNeeded
= needed
;
1619 if(needed
> cbBuf
) {
1620 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1627 /*****************************************************************************
1628 * GetPrinterDriverDirectoryW [WINSPOOL.192]
1630 BOOL WINAPI
GetPrinterDriverDirectoryW(LPWSTR pName
, LPWSTR pEnvironment
,
1631 DWORD Level
, LPBYTE pDriverDirectory
,
1632 DWORD cbBuf
, LPDWORD pcbNeeded
)
1634 LPSTR pNameA
= NULL
, pEnvironmentA
= NULL
;
1638 pNameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pName
);
1640 pEnvironmentA
= HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment
);
1641 ret
= GetPrinterDriverDirectoryA( pNameA
, pEnvironmentA
, Level
,
1642 pDriverDirectory
, cbBuf
, pcbNeeded
);
1644 HeapFree( GetProcessHeap(), 0, pNameA
);
1646 HeapFree( GetProcessHeap(), 0, pEnvironment
);
1651 /*****************************************************************************
1652 * AddPrinterDriver32A [WINSPOOL.120]
1654 BOOL WINAPI
AddPrinterDriverA(LPSTR pName
, DWORD level
, LPBYTE pDriverInfo
)
1657 HKEY hkeyDrivers
, hkeyName
;
1659 TRACE("(%s,%ld,%p)\n",pName
,level
,pDriverInfo
);
1661 if(level
!= 2 && level
!= 3) {
1662 SetLastError(ERROR_INVALID_LEVEL
);
1666 FIXME("pName= `%s' - unsupported\n", pName
);
1667 SetLastError(ERROR_INVALID_PARAMETER
);
1671 WARN("pDriverInfo == NULL");
1672 SetLastError(ERROR_INVALID_PARAMETER
);
1677 di3
= *(DRIVER_INFO_3A
*)pDriverInfo
;
1679 memset(&di3
, 0, sizeof(di3
));
1680 *(DRIVER_INFO_2A
*)&di3
= *(DRIVER_INFO_2A
*)pDriverInfo
;
1683 if(!di3
.pName
|| !di3
.pDriverPath
|| !di3
.pConfigFile
||
1685 SetLastError(ERROR_INVALID_PARAMETER
);
1688 if(!di3
.pDefaultDataType
) di3
.pDefaultDataType
= "";
1689 if(!di3
.pDependentFiles
) di3
.pDependentFiles
= "\0";
1690 if(!di3
.pHelpFile
) di3
.pHelpFile
= "";
1691 if(!di3
.pMonitorName
) di3
.pMonitorName
= "";
1693 if(di3
.pEnvironment
) {
1694 FIXME("pEnvironment = `%s'\n", di3
.pEnvironment
);
1695 SetLastError(ERROR_INVALID_ENVIRONMENT
);
1698 if(RegCreateKeyA(HKEY_LOCAL_MACHINE
, Drivers
, &hkeyDrivers
) !=
1700 ERR("Can't create Drivers key\n");
1704 if(level
== 2) { /* apparently can't overwrite with level2 */
1705 if(RegOpenKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) == ERROR_SUCCESS
) {
1706 RegCloseKey(hkeyName
);
1707 RegCloseKey(hkeyDrivers
);
1708 WARN("Trying to create existing printer driver `%s'\n", di3
.pName
);
1709 SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED
);
1713 if(RegCreateKeyA(hkeyDrivers
, di3
.pName
, &hkeyName
) != ERROR_SUCCESS
) {
1714 RegCloseKey(hkeyDrivers
);
1715 ERR("Can't create Name key\n");
1718 RegSetValueExA(hkeyName
, "Configuration File", 0, REG_SZ
, di3
.pConfigFile
,
1720 RegSetValueExA(hkeyName
, "Data File", 0, REG_SZ
, di3
.pDataFile
, 0);
1721 RegSetValueExA(hkeyName
, "Driver", 0, REG_SZ
, di3
.pDriverPath
, 0);
1722 RegSetValueExA(hkeyName
, "Version", 0, REG_DWORD
, (LPSTR
)&di3
.cVersion
,
1724 RegSetValueExA(hkeyName
, "Datatype", 0, REG_SZ
, di3
.pDefaultDataType
, 0);
1725 RegSetValueExA(hkeyName
, "Dependent Files", 0, REG_MULTI_SZ
,
1726 di3
.pDependentFiles
, 0);
1727 RegSetValueExA(hkeyName
, "Help File", 0, REG_SZ
, di3
.pHelpFile
, 0);
1728 RegSetValueExA(hkeyName
, "Monitor", 0, REG_SZ
, di3
.pMonitorName
, 0);
1729 RegCloseKey(hkeyName
);
1730 RegCloseKey(hkeyDrivers
);
1734 /*****************************************************************************
1735 * AddPrinterDriver32W [WINSPOOL.121]
1737 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
1740 FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
1746 /*****************************************************************************
1747 * PrinterProperties [WINSPOOL.201]
1749 * Displays a dialog to set the properties of the printer.
1752 * nonzero on succes or zero on faillure
1755 * implemented as stub only
1757 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* handle to parent window */
1758 HANDLE hPrinter
/* handle to printer object */
1760 FIXME("(%d,%d): stub\n", hWnd
, hPrinter
);
1761 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1765 /*****************************************************************************
1766 * EnumJobsA [WINSPOOL.162]
1769 BOOL WINAPI
EnumJobsA(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
1770 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1774 if(pcbNeeded
) *pcbNeeded
= 0;
1775 if(pcReturned
) *pcReturned
= 0;
1780 /*****************************************************************************
1781 * EnumJobsW [WINSPOOL.163]
1784 BOOL WINAPI
EnumJobsW(HANDLE hPrinter
, DWORD FirstJob
, DWORD NoJobs
,
1785 DWORD Level
, LPBYTE pJob
, DWORD cbBuf
, LPDWORD pcbNeeded
,
1789 if(pcbNeeded
) *pcbNeeded
= 0;
1790 if(pcReturned
) *pcReturned
= 0;