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