2 * Implementation of some printer driver bits
4 * Copyright 1996 John Harvey
5 * Copyright 1998 Andreas Mohr
6 * Copyright 1999 Klaas van Gend
14 #include "wine/wingdi16.h"
18 #include "debugtools.h"
20 DECLARE_DEBUG_CHANNEL(gdi
)
21 DECLARE_DEBUG_CHANNEL(print
)
23 CRITICAL_SECTION PRINT32_RegistryBlocker
;
25 static char PrinterModel
[] = "Printer Model";
26 static char DefaultDevMode
[] = "Default DevMode";
27 static char PrinterDriverData
[] = "PrinterDriverData";
28 static char Printers
[] = "System\\CurrentControlSet\\Control\\Print\\Printers\\";
30 /******************************************************************
31 * StartDoc16 [GDI.377]
34 INT16 WINAPI
StartDoc16( HDC16 hdc
, const DOCINFO16
*lpdoc
)
37 TRACE_(print
)("(%p)\n", lpdoc
);
38 TRACE_(print
)("%d 0x%lx:0x%p 0x%lx:0x%p\n",lpdoc
->cbSize
,
39 lpdoc
->lpszDocName
,PTR_SEG_TO_LIN(lpdoc
->lpszDocName
),
40 lpdoc
->lpszOutput
,PTR_SEG_TO_LIN(lpdoc
->lpszOutput
));
41 TRACE_(print
)("%d %s %s\n",lpdoc
->cbSize
,
42 (LPSTR
)PTR_SEG_TO_LIN(lpdoc
->lpszDocName
),
43 (LPSTR
)PTR_SEG_TO_LIN(lpdoc
->lpszOutput
));
44 retVal
= Escape16(hdc
, STARTDOC
,
45 strlen((LPSTR
)PTR_SEG_TO_LIN(lpdoc
->lpszDocName
)), lpdoc
->lpszDocName
, 0);
46 TRACE_(print
)("Escape16 returned %d\n",retVal
);
50 /******************************************************************
54 INT16 WINAPI
EndPage16( HDC16 hdc
)
57 retVal
= Escape16(hdc
, NEWFRAME
, 0, 0, 0);
58 TRACE_(print
)("Escape16 returned %d\n",retVal
);
62 /******************************************************************
63 * StartDoc32A [GDI32.347]
66 INT WINAPI
StartDocA(HDC hdc
,const DOCINFOA
* doc
)
68 FIXME_(gdi
)("stub\n");
69 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
70 return 0; /* failure*/
73 /*************************************************************************
74 * StartDoc32W [GDI32.348]
77 INT WINAPI
StartDocW(HDC hdc
, const DOCINFOW
* doc
) {
78 FIXME_(gdi
)("stub\n");
79 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
80 return 0; /* failure*/
83 /******************************************************************
84 * StartPage32 [GDI32.349]
87 INT WINAPI
StartPage(HDC hdc
)
89 FIXME_(gdi
)("stub\n");
90 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
91 return 0; /* failure*/
94 /******************************************************************
95 * EndPage32 [GDI32.77]
98 INT WINAPI
EndPage(HDC hdc
)
100 FIXME_(gdi
)("stub\n");
101 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
102 return 0; /* failure*/
105 /******************************************************************
109 INT16 WINAPI
EndDoc16(HDC16 hdc
)
111 return Escape16(hdc
, ENDDOC
, 0, 0, 0);
114 /******************************************************************
115 * EndDoc32 [GDI32.76]
118 INT WINAPI
EndDoc(HDC hdc
)
120 FIXME_(gdi
)("stub\n");
121 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
122 return 0; /* failure*/
125 /******************************************************************************
126 * AbortDoc16 [GDI.382]
128 INT16 WINAPI
AbortDoc16(HDC16 hdc
)
130 return Escape16(hdc
, ABORTDOC
, 0, 0, 0);
133 /******************************************************************************
134 * AbortDoc32 [GDI32.0]
136 INT WINAPI
AbortDoc(HDC hdc
)
138 FIXME_(gdi
)("(%d): stub\n", hdc
);
142 /******************************************************************
143 * DrvGetPrinterDataInternal
145 * Helper for DrvGetPrinterData
147 static DWORD
DrvGetPrinterDataInternal(LPSTR RegStr_Printer
,
148 LPBYTE lpPrinterData
, int cbData
, int what
)
152 DWORD dwType
, cbQueryData
;
154 if (!(RegOpenKeyA(HKEY_LOCAL_MACHINE
, RegStr_Printer
, &hkey
))) {
155 if (what
== INT_PD_DEFAULT_DEVMODE
) { /* "Default DevMode" */
156 if (!(RegQueryValueExA(hkey
, DefaultDevMode
, 0, &dwType
, 0, &cbQueryData
))) {
159 else if ((cbQueryData
) && (cbQueryData
<= cbData
)) {
160 cbQueryData
= cbData
;
161 if (RegQueryValueExA(hkey
, DefaultDevMode
, 0,
162 &dwType
, lpPrinterData
, &cbQueryData
))
166 } else { /* "Printer Driver" */
168 RegQueryValueExA(hkey
, "Printer Driver", 0,
169 &dwType
, lpPrinterData
, &cbQueryData
);
173 if (hkey
) RegCloseKey(hkey
);
177 /******************************************************************
178 * DrvGetPrinterData [GDI.282]
181 DWORD WINAPI
DrvGetPrinterData16(LPSTR lpPrinter
, LPSTR lpProfile
,
182 LPDWORD lpType
, LPBYTE lpPrinterData
,
183 int cbData
, LPDWORD lpNeeded
)
185 LPSTR RegStr_Printer
;
186 HKEY hkey
= 0, hkey2
= 0;
188 DWORD dwType
, PrinterAttr
, cbPrinterAttr
, SetData
, size
;
190 if (HIWORD(lpPrinter
))
191 TRACE_(print
)("printer %s\n",lpPrinter
);
193 TRACE_(print
)("printer %p\n",lpPrinter
);
194 if (HIWORD(lpProfile
))
195 TRACE_(print
)("profile %s\n",lpProfile
);
197 TRACE_(print
)("profile %p\n",lpProfile
);
198 TRACE_(print
)("lpType %p\n",lpType
);
200 if ((!lpPrinter
) || (!lpProfile
) || (!lpNeeded
))
201 return ERROR_INVALID_PARAMETER
;
203 RegStr_Printer
= HeapAlloc(GetProcessHeap(), 0,
204 strlen(Printers
) + strlen(lpPrinter
) + 2);
205 strcpy(RegStr_Printer
, Printers
);
206 strcat(RegStr_Printer
, lpPrinter
);
208 if (((DWORD
)lpProfile
== INT_PD_DEFAULT_DEVMODE
) || (HIWORD(lpProfile
) &&
209 (!strcmp(lpProfile
, DefaultDevMode
)))) {
210 size
= DrvGetPrinterDataInternal(RegStr_Printer
, lpPrinterData
, cbData
,
211 INT_PD_DEFAULT_DEVMODE
);
214 if ((lpPrinterData
) && (*lpNeeded
> cbData
))
215 res
= ERROR_MORE_DATA
;
217 else res
= ERROR_INVALID_PRINTER_NAME
;
220 if (((DWORD
)lpProfile
== INT_PD_DEFAULT_MODEL
) || (HIWORD(lpProfile
) &&
221 (!strcmp(lpProfile
, PrinterModel
)))) {
223 if (!lpPrinterData
) goto failed
;
225 res
= ERROR_MORE_DATA
;
228 size
= DrvGetPrinterDataInternal(RegStr_Printer
, lpPrinterData
, cbData
,
229 INT_PD_DEFAULT_MODEL
);
230 if ((size
+1) && (lpType
))
233 res
= ERROR_INVALID_PRINTER_NAME
;
237 if ((res
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, RegStr_Printer
, &hkey
)))
240 if ((res
= RegQueryValueExA(hkey
, "Attributes", 0,
241 &dwType
, (LPBYTE
)&PrinterAttr
, &cbPrinterAttr
)))
243 if ((res
= RegOpenKeyA(hkey
, PrinterDriverData
, &hkey2
)))
246 res
= RegQueryValueExA(hkey2
, lpProfile
, 0,
247 lpType
, lpPrinterData
, lpNeeded
);
248 if ((res
!= ERROR_CANTREAD
) &&
250 (PRINTER_ATTRIBUTE_ENABLE_BIDI
|PRINTER_ATTRIBUTE_NETWORK
))
251 == PRINTER_ATTRIBUTE_NETWORK
))
253 if (!(res
) && (*lpType
== REG_DWORD
) && (*(LPDWORD
)lpPrinterData
== -1))
254 res
= ERROR_INVALID_DATA
;
259 RegSetValueExA(hkey2
, lpProfile
, 0, REG_DWORD
, (LPBYTE
)&SetData
, 4); /* no result returned */
264 if (hkey2
) RegCloseKey(hkey2
);
265 if (hkey
) RegCloseKey(hkey
);
266 HeapFree(GetProcessHeap(), 0, RegStr_Printer
);
271 /******************************************************************
272 * DrvSetPrinterData [GDI.281]
275 DWORD WINAPI
DrvSetPrinterData16(LPSTR lpPrinter
, LPSTR lpProfile
,
276 DWORD lpType
, LPBYTE lpPrinterData
,
279 LPSTR RegStr_Printer
;
283 if (HIWORD(lpPrinter
))
284 TRACE_(print
)("printer %s\n",lpPrinter
);
286 TRACE_(print
)("printer %p\n",lpPrinter
);
287 if (HIWORD(lpProfile
))
288 TRACE_(print
)("profile %s\n",lpProfile
);
290 TRACE_(print
)("profile %p\n",lpProfile
);
291 TRACE_(print
)("lpType %08lx\n",lpType
);
293 if ((!lpPrinter
) || (!lpProfile
) ||
294 ((DWORD
)lpProfile
== INT_PD_DEFAULT_MODEL
) || (HIWORD(lpProfile
) &&
295 (!strcmp(lpProfile
, PrinterModel
))))
296 return ERROR_INVALID_PARAMETER
;
298 RegStr_Printer
= HeapAlloc(GetProcessHeap(), 0,
299 strlen(Printers
) + strlen(lpPrinter
) + 2);
300 strcpy(RegStr_Printer
, Printers
);
301 strcat(RegStr_Printer
, lpPrinter
);
303 if (((DWORD
)lpProfile
== INT_PD_DEFAULT_DEVMODE
) || (HIWORD(lpProfile
) &&
304 (!strcmp(lpProfile
, DefaultDevMode
)))) {
305 if ( RegOpenKeyA(HKEY_LOCAL_MACHINE
, RegStr_Printer
, &hkey
)
307 RegSetValueExA(hkey
, DefaultDevMode
, 0, REG_BINARY
,
308 lpPrinterData
, dwSize
) != ERROR_SUCCESS
)
309 res
= ERROR_INVALID_PRINTER_NAME
;
313 strcat(RegStr_Printer
, "\\");
315 if( (res
= RegOpenKeyA(HKEY_LOCAL_MACHINE
, RegStr_Printer
, &hkey
)) ==
319 res
= RegDeleteValueA(hkey
, lpProfile
);
321 res
= RegSetValueExA(hkey
, lpProfile
, 0, lpType
,
322 lpPrinterData
, dwSize
);
326 if (hkey
) RegCloseKey(hkey
);
327 HeapFree(GetProcessHeap(), 0, RegStr_Printer
);
332 /******************************************************************
333 * DeviceCapabilities32A [WINSPOOL.151]
336 INT WINAPI
DeviceCapabilitiesA(LPCSTR printer
,LPCSTR target
,WORD z
,
337 LPSTR a
,LPDEVMODEA b
)
339 FIXME_(print
)("(%s,%s,%d,%p,%p):stub.\n",printer
,target
,z
,a
,b
);
344 /*****************************************************************************
345 * DeviceCapabilities32W
347 INT WINAPI
DeviceCapabilitiesW(LPCWSTR pDevice
, LPCWSTR pPort
,
348 WORD fwCapability
, LPWSTR pOutput
,
349 const DEVMODEW
*pDevMode
)
351 FIXME_(print
)("(%p,%p,%d,%p,%p): stub\n",
352 pDevice
, pPort
, fwCapability
, pOutput
, pDevMode
);
356 /******************************************************************
357 * DocumentProperties32A [WINSPOOL.155]
360 LONG WINAPI
DocumentPropertiesA(HWND hWnd
,HANDLE hPrinter
,
361 LPSTR pDeviceName
, LPDEVMODEA pDevModeOutput
,
362 LPDEVMODEA pDevModeInput
,DWORD fMode
)
364 FIXME_(print
)("(%d,%d,%s,%p,%p,%ld):stub.\n",
365 hWnd
,hPrinter
,pDeviceName
,pDevModeOutput
,pDevModeInput
,fMode
371 /*****************************************************************************
372 * DocumentProperties32W
374 LONG WINAPI
DocumentPropertiesW(HWND hWnd
, HANDLE hPrinter
,
376 LPDEVMODEW pDevModeOutput
,
377 LPDEVMODEW pDevModeInput
, DWORD fMode
)
379 FIXME_(print
)("(%d,%d,%s,%p,%p,%ld): stub\n",
380 hWnd
,hPrinter
,debugstr_w(pDeviceName
),pDevModeOutput
,pDevModeInput
,
386 /******************************************************************
387 * OpenPrinter32A [WINSPOOL.196]
390 BOOL WINAPI
OpenPrinterA(LPSTR lpPrinterName
,HANDLE
*phPrinter
,
391 LPPRINTER_DEFAULTSA pDefault
)
393 FIXME_(print
)("(%s,%p,%p):stub\n",debugstr_a(lpPrinterName
), phPrinter
,
395 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
399 /******************************************************************
400 * OpenPrinter32W [WINSPOOL.197]
403 BOOL WINAPI
OpenPrinterW(LPWSTR lpPrinterName
,HANDLE
*phPrinter
,
404 LPPRINTER_DEFAULTSW pDefault
)
406 FIXME_(print
)("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName
), phPrinter
,
408 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
415 /******************************************************************
416 * ENUMPRINTERS_GetDWORDFromRegistryA internal
418 * Reads a DWORD from registry KeyName
421 * value on OK or NULL on error
423 DWORD
ENUMPRINTERS_GetDWORDFromRegistryA(
424 HKEY hPrinterSettings
, /* handle to registry key */
425 LPSTR KeyName
/* name key to retrieve string from*/
432 if (RegQueryValueExA(hPrinterSettings
, KeyName
, NULL
, &DataType
,
433 Data
, &DataSize
)!=ERROR_SUCCESS
)
434 FIXME_(print
)("Query of register didn't succeed?");
435 if (DataType
== REG_DWORD_LITTLE_ENDIAN
)
436 Result
= Data
[0] + (Data
[1]<<8) + (Data
[2]<<16) + (Data
[3]<<24);
437 if (DataType
== REG_DWORD_BIG_ENDIAN
)
438 Result
= Data
[3] + (Data
[2]<<8) + (Data
[1]<<16) + (Data
[0]<<24);
443 /******************************************************************
444 * ENUMPRINTERS_AddStringFromRegistryA internal
446 * Reads a string from registry KeyName and writes it at
447 * lpbPrinters[dwNextStringPos]. Store reference to string in Dest.
450 * FALSE if there is still space left in the buffer.
452 BOOL
ENUMPRINTERS_AddStringFromRegistryA(
453 HKEY hPrinterSettings
, /* handle to registry key */
454 LPSTR KeyName
, /* name key to retrieve string from*/
455 LPSTR
* Dest
, /* pointer to write string addres to */
456 LPBYTE lpbPrinters
, /* buffer which receives info*/
457 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
458 DWORD dwBufSize
, /* max size of buffer in bytes */
459 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
463 LPSTR Data
= (LPSTR
) malloc(DataSize
*sizeof(char));
465 while(RegQueryValueExA(hPrinterSettings
, KeyName
, NULL
, &DataType
,
466 Data
, &DataSize
)==ERROR_MORE_DATA
)
468 Data
= (LPSTR
) realloc(Data
, DataSize
+2);
471 if (DataType
== REG_SZ
)
473 if (bCalcSpaceOnly
==FALSE
)
474 *Dest
= &lpbPrinters
[*dwNextStringPos
];
475 *dwNextStringPos
+= DataSize
+1;
476 if (*dwNextStringPos
> dwBufSize
)
478 if (bCalcSpaceOnly
==FALSE
)
480 if (DataSize
==0) /* DataSize = 0 means empty string, even though*/
481 *Dest
[0]=0; /* the data itself needs not to be empty */
487 WARN_(print
)("Expected string setting, got something else from registry");
491 return(bCalcSpaceOnly
);
496 /******************************************************************
497 * ENUMPRINTERS_AddInfo2A internal
499 * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos]
500 * for printer PrinterNameKey.
501 * Note that there is no check whether the information really fits!
504 * FALSE if there is still space left in the buffer.
507 * This function should not only read the registry but also ask the driver
510 BOOL
ENUMPRINTERS_AddInfo2A(
511 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
512 LPBYTE lpbPrinters
, /* buffer which receives info*/
513 DWORD dwNextStructPos
, /* pos in buffer for struct */
514 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
515 DWORD dwBufSize
, /* max size of buffer in bytes */
516 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
518 HKEY hPrinterSettings
;
521 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
522 strlen(lpszPrinterName
)+2);
523 LPPRINTER_INFO_2A lpPInfo2
= (LPPRINTER_INFO_2A
) &lpbPrinters
[dwNextStructPos
];
525 /* open the registry to find the attributes, etc of the printer */
526 if (lpszPrinterSettings
!=NULL
)
528 strcpy(lpszPrinterSettings
,Printers
);
529 strcat(lpszPrinterSettings
,lpszPrinterName
);
531 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
532 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
534 WARN_(print
)("The registry did not contain my printer anymore?\n");
538 if (bCalcSpaceOnly
==FALSE
)
539 lpPInfo2
->pServerName
= NULL
;
540 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
541 "Name", &(lpPInfo2
->pPrinterName
),
542 lpbPrinters
, dwNextStringPos
,
543 dwBufSize
, bCalcSpaceOnly
);
544 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
545 "Share Name", &(lpPInfo2
->pShareName
),
546 lpbPrinters
, dwNextStringPos
,
547 dwBufSize
, bCalcSpaceOnly
);
548 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
549 "Port", &(lpPInfo2
->pPortName
),
550 lpbPrinters
, dwNextStringPos
,
551 dwBufSize
, bCalcSpaceOnly
);
552 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
553 "Printer Driver", &(lpPInfo2
->pDriverName
),
554 lpbPrinters
, dwNextStringPos
,
555 dwBufSize
, bCalcSpaceOnly
);
556 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
557 "Description", &(lpPInfo2
->pComment
),
558 lpbPrinters
, dwNextStringPos
,
559 dwBufSize
, bCalcSpaceOnly
);
560 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
561 "Location", &(lpPInfo2
->pLocation
),
562 lpbPrinters
, dwNextStringPos
,
563 dwBufSize
, bCalcSpaceOnly
);
565 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
566 "Separator File", &(lpPInfo2
->pSepFile
),
567 lpbPrinters
, dwNextStringPos
,
568 dwBufSize
, bCalcSpaceOnly
);
569 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
570 "Print Processor", &(lpPInfo2
->pPrintProcessor
),
571 lpbPrinters
, dwNextStringPos
,
572 dwBufSize
, bCalcSpaceOnly
);
573 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
574 "Datatype", &(lpPInfo2
->pDatatype
),
575 lpbPrinters
, dwNextStringPos
,
576 dwBufSize
, bCalcSpaceOnly
);
577 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
578 "Parameters", &(lpPInfo2
->pParameters
),
579 lpbPrinters
, dwNextStringPos
,
580 dwBufSize
, bCalcSpaceOnly
);
581 if (bCalcSpaceOnly
== FALSE
)
583 lpPInfo2
->pSecurityDescriptor
= NULL
; /* EnumPrinters doesn't return this*/
585 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
586 lpPInfo2
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
587 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
588 lpPInfo2
->Priority
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
590 lpPInfo2
->DefaultPriority
= ENUMPRINTERS_GetDWORDFromRegistryA(
591 hPrinterSettings
, "Default Priority");
592 lpPInfo2
->StartTime
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
594 lpPInfo2
->UntilTime
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
596 lpPInfo2
->Status
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
598 lpPInfo2
->cJobs
= 0; /* FIXME: according to MSDN, this does not
599 * reflect the TotalJobs Key ??? */
600 lpPInfo2
->AveragePPM
= 0; /* FIXME: according to MSDN, this does not
601 * reflect the TotalPages Key ??? */
603 /* and read the devModes structure... */
604 RegQueryValueExA(hPrinterSettings
, "pDevMode", NULL
, &DataType
,
605 NULL
, &DevSize
); /* should return ERROR_MORE_DATA */
606 lpPInfo2
->pDevMode
= (LPDEVMODEA
) &lpbPrinters
[*dwNextStringPos
];
607 *dwNextStringPos
+= DevSize
+ 1;
609 if (*dwNextStringPos
> dwBufSize
)
611 if (bCalcSpaceOnly
==FALSE
)
612 RegQueryValueExA(hPrinterSettings
, "pDevMode", NULL
, &DataType
,
613 (LPBYTE
)lpPInfo2
->pDevMode
, &DevSize
);
616 if (lpszPrinterSettings
)
617 free(lpszPrinterSettings
);
619 return(bCalcSpaceOnly
);
622 /******************************************************************
623 * ENUMPRINTERS_AddInfo4A internal
625 * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos]
626 * for printer PrinterNameKey.
627 * Note that there is no check whether the information really fits!
630 * FALSE if there is still space left in the buffer.
633 * This function should not exist in Win95 mode, but does anyway.
635 BOOL
ENUMPRINTERS_AddInfo4A(
636 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
637 LPBYTE lpbPrinters
, /* buffer which receives info*/
638 DWORD dwNextStructPos
, /* pos in buffer for struct */
639 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
640 DWORD dwBufSize
, /* max size of buffer in bytes */
641 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
643 HKEY hPrinterSettings
;
644 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
645 strlen(lpszPrinterName
)+2);
646 LPPRINTER_INFO_4A lpPInfo4
= (LPPRINTER_INFO_4A
) &lpbPrinters
[dwNextStructPos
];
648 /* open the registry to find the attributes of the printer */
649 if (lpszPrinterSettings
!=NULL
)
651 strcpy(lpszPrinterSettings
,Printers
);
652 strcat(lpszPrinterSettings
,lpszPrinterName
);
654 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
655 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
657 WARN_(print
)("The registry did not contain my printer anymore?\n");
661 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
662 "Name", &(lpPInfo4
->pPrinterName
),
663 lpbPrinters
, dwNextStringPos
,
664 dwBufSize
, bCalcSpaceOnly
);
665 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
666 if (bCalcSpaceOnly
==FALSE
)
667 lpPInfo4
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
668 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
670 if (lpszPrinterSettings
)
671 free(lpszPrinterSettings
);
673 return(bCalcSpaceOnly
);
676 /******************************************************************
677 * ENUMPRINTERS_AddInfo5A internal
679 * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos]
680 * for printer PrinterNameKey.
681 * Settings are read from the registry.
682 * Note that there is no check whether the information really fits!
684 * FALSE if there is still space left in the buffer.
686 BOOL
ENUMPRINTERS_AddInfo5A(
687 LPSTR lpszPrinterName
,/* name of printer to fill struct for*/
688 LPBYTE lpbPrinters
, /* buffer which receives info*/
689 DWORD dwNextStructPos
, /* pos in buffer for struct */
690 LPDWORD dwNextStringPos
, /* pos in buffer for next string */
691 DWORD dwBufSize
, /* max size of buffer in bytes */
692 BOOL bCalcSpaceOnly
/* TRUE if out-of-space in buffer */
694 HKEY hPrinterSettings
;
695 LPSTR lpszPrinterSettings
= (LPSTR
) malloc(strlen(Printers
)+
696 strlen(lpszPrinterName
)+2);
697 LPPRINTER_INFO_5A lpPInfo5
= (LPPRINTER_INFO_5A
) &lpbPrinters
[dwNextStructPos
];
699 /* open the registry to find the attributes, etc of the printer */
700 if (lpszPrinterSettings
!=NULL
)
702 strcpy(lpszPrinterSettings
,Printers
);
703 strcat(lpszPrinterSettings
,lpszPrinterName
);
705 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, lpszPrinterSettings
, 0,
706 KEY_READ
, &hPrinterSettings
) != ERROR_SUCCESS
)
708 WARN_(print
)("The registry did not contain my printer anymore?\n");
712 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
713 "Name", &(lpPInfo5
->pPrinterName
),
714 lpbPrinters
, dwNextStringPos
,
715 dwBufSize
, bCalcSpaceOnly
);
716 bCalcSpaceOnly
= ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings
,
717 "Port", &(lpPInfo5
->pPortName
), lpbPrinters
,
718 dwNextStringPos
, dwBufSize
, bCalcSpaceOnly
);
719 /* FIXME: Attributes gets LOCAL as no REMOTE exists*/
720 if (bCalcSpaceOnly
== FALSE
)
722 lpPInfo5
->Attributes
= ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
723 "Attributes") +PRINTER_ATTRIBUTE_LOCAL
;
724 lpPInfo5
->DeviceNotSelectedTimeOut
725 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
727 lpPInfo5
->TransmissionRetryTimeout
728 = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings
,
733 if (lpszPrinterSettings
)
734 free(lpszPrinterSettings
);
736 return(bCalcSpaceOnly
);
740 /******************************************************************
741 * EnumPrintersA [WINSPOOL.174]
743 * Enumerates the available printers, print servers and print
744 * providers, depending on the specified flags, name and level.
748 * If level is set to 1:
749 * Not implemented yet!
750 * Returns TRUE with an empty list.
752 * If level is set to 2:
753 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
754 * Returns an array of PRINTER_INFO_2 data structures in the
755 * lpbPrinters buffer. Note that according to MSDN also an
756 * OpenPrinter should be performed on every remote printer.
758 * If level is set to 4 (officially WinNT only):
759 * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL.
760 * Fast: Only the registry is queried to retrieve printer names,
761 * no connection to the driver is made.
762 * Returns an array of PRINTER_INFO_4 data structures in the
763 * lpbPrinters buffer.
765 * If level is set to 5 (officially WinNT4/Win9x only):
766 * Fast: Only the registry is queried to retrieve printer names,
767 * no connection to the driver is made.
768 * Returns an array of PRINTER_INFO_5 data structures in the
769 * lpbPrinters buffer.
771 * If level set to 3 or 6+:
772 * returns zero (faillure!)
774 * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError
778 * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented.
779 * - Only levels 2, 4 and 5 are implemented at the moment.
780 * - 16-bit printer drivers are not enumerated.
781 * - Returned amount of bytes used/needed does not match the real Windoze
782 * implementation (as in this implementation, all strings are part
783 * of the buffer, whereas Win32 keeps them somewhere else)
784 * - At level 2, EnumPrinters should also call OpenPrinter for remote printers.
787 * - In a regular Wine installation, no registry settings for printers
788 * exist, which makes this function return an empty list.
790 BOOL WINAPI
EnumPrintersA(
791 DWORD dwType
, /* Types of print objects to enumerate */
792 LPSTR lpszName
, /* name of objects to enumerate */
793 DWORD dwLevel
, /* type of printer info structure */
794 LPBYTE lpbPrinters
,/* buffer which receives info*/
795 DWORD cbBuf
, /* max size of buffer in bytes */
796 LPDWORD lpdwNeeded
,/* pointer to var: # bytes used/needed */
797 LPDWORD lpdwReturned
/* number of entries returned */
800 HKEY hPrinterListKey
;
802 char PrinterName
[255];
803 DWORD PrinterNameLength
=255;
805 DWORD dwNextStringPos
; /* position of next space for a string in the buffer*/
806 DWORD dwStructPrinterInfoSize
; /* size of a Printer_Info_X structure */
807 BOOL bCalcSpaceOnly
=FALSE
;/* if TRUE: don't store data, just calculate space*/
809 TRACE_(print
)("entered.\n");
811 /* test whether we're requested to really fill in. If so,
812 * zero out the data area, and initialise some returns to zero,
813 * to prevent problems
815 if (lpbPrinters
==NULL
|| cbBuf
==0)
820 for (i
=0; i
<cbBuf
; i
++)
826 /* check for valid Flags */
827 if (dwType
!= PRINTER_ENUM_LOCAL
&& dwType
!= PRINTER_ENUM_NAME
)
829 SetLastError(ERROR_INVALID_FLAGS
);
841 SetLastError(ERROR_INVALID_PARAMETER
);
845 /* Enter critical section to prevent AddPrinters() et al. to
846 * modify whilst we're reading in the registry
848 InitializeCriticalSection(&PRINT32_RegistryBlocker
);
849 EnterCriticalSection(&PRINT32_RegistryBlocker
);
851 /* get a pointer to a list of all printer names in the registry */
852 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE
, Printers
, 0, KEY_READ
,
853 &hPrinterListKey
) !=ERROR_SUCCESS
)
855 /* Oh no! An empty list of printers!
856 * (which is a valid configuration anyway)
858 TRACE_(print
)("No entries in the Printers part of the registry\n");
861 /* count the number of entries and check if it fits in the buffer
863 while(RegEnumKeyExA(hPrinterListKey
, dwIndex
, PrinterName
, &PrinterNameLength
,
864 NULL
, NULL
, NULL
, &FileTime
)==ERROR_SUCCESS
)
866 PrinterNameLength
=255;
869 *lpdwReturned
= dwIndex
;
873 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_1A
);
876 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_2A
);
879 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_4A
);
882 dwStructPrinterInfoSize
= sizeof(PRINTER_INFO_5A
);
885 dwStructPrinterInfoSize
= 0;
888 if (dwIndex
*dwStructPrinterInfoSize
+1 > cbBuf
)
889 bCalcSpaceOnly
= TRUE
;
891 /* the strings which contain e.g. PrinterName, PortName, etc,
892 * are also stored in lpbPrinters, but after the regular structs.
893 * dwNextStringPos will always point to the next free place for a
896 dwNextStringPos
=(dwIndex
+1)*dwStructPrinterInfoSize
;
898 /* check each entry: if OK, add to list in corresponding INFO .
900 for(dwIndex
=0; dwIndex
< *lpdwReturned
; dwIndex
++)
902 PrinterNameLength
=255;
903 if (RegEnumKeyExA(hPrinterListKey
, dwIndex
, PrinterName
, &PrinterNameLength
,
904 NULL
, NULL
, NULL
, &FileTime
)!=ERROR_SUCCESS
)
905 break; /* exit for loop*/
907 /* check whether this printer is allowed in the list
908 * by comparing name to lpszName
910 if (dwType
== PRINTER_ENUM_NAME
)
911 if (strcmp(PrinterName
,lpszName
)!=0)
917 /* FIXME: unimplemented */
920 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo2A(PrinterName
, lpbPrinters
,
921 dwIndex
*dwStructPrinterInfoSize
,
922 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
925 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo4A(PrinterName
, lpbPrinters
,
926 dwIndex
*dwStructPrinterInfoSize
,
927 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
930 bCalcSpaceOnly
= ENUMPRINTERS_AddInfo5A(PrinterName
, lpbPrinters
,
931 dwIndex
*dwStructPrinterInfoSize
,
932 &dwNextStringPos
, cbBuf
, bCalcSpaceOnly
);
936 RegCloseKey(hPrinterListKey
);
937 *lpdwNeeded
= dwNextStringPos
;
939 if (bCalcSpaceOnly
==TRUE
)
941 if (lpbPrinters
!=NULL
)
944 for (i
=0; i
<cbBuf
; i
++)
949 LeaveCriticalSection(&PRINT32_RegistryBlocker
);
953 /******************************************************************
954 * EnumPrinters32W [WINSPOOL.175]
957 BOOL WINAPI
EnumPrintersW(DWORD dwType
, LPWSTR lpszName
,
958 DWORD dwLevel
, LPBYTE lpbPrinters
,
959 DWORD cbBuf
, LPDWORD lpdwNeeded
,
960 LPDWORD lpdwReturned
)
962 FIXME_(print
)("Nearly empty stub\n");
968 /******************************************************************
969 * AddMonitor32A [WINSPOOL.107]
972 BOOL WINAPI
AddMonitorA(LPCSTR pName
, DWORD Level
, LPBYTE pMonitors
)
974 FIXME_(print
)("(%s,%lx,%p):stub!\n", pName
, Level
, pMonitors
);
975 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
979 /******************************************************************
980 * DeletePrinterDriver32A [WINSPOOL.146]
984 DeletePrinterDriverA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pDriverName
)
986 FIXME_(print
)("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
987 debugstr_a(pDriverName
));
988 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
993 /******************************************************************
994 * DeleteMonitor32A [WINSPOOL.135]
998 DeleteMonitorA (LPSTR pName
, LPSTR pEnvironment
, LPSTR pMonitorName
)
1000 FIXME_(print
)("(%s,%s,%s):stub\n",debugstr_a(pName
),debugstr_a(pEnvironment
),
1001 debugstr_a(pMonitorName
));
1002 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1007 /******************************************************************
1008 * DeletePort32A [WINSPOOL.137]
1012 DeletePortA (LPSTR pName
, HWND hWnd
, LPSTR pPortName
)
1014 FIXME_(print
)("(%s,0x%08x,%s):stub\n",debugstr_a(pName
),hWnd
,
1015 debugstr_a(pPortName
));
1016 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1020 /******************************************************************************
1021 * SetPrinter32W [WINSPOOL.214]
1030 FIXME_(print
)("():stub\n");
1031 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1035 /******************************************************************************
1036 * WritePrinter32 [WINSPOOL.223]
1043 LPDWORD pcWritten
) {
1045 FIXME_(print
)("():stub\n");
1046 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1050 /*****************************************************************************
1051 * AddForm32A [WINSPOOL.103]
1053 BOOL WINAPI
AddFormA(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
1055 FIXME_(print
)("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
1059 /*****************************************************************************
1060 * AddForm32W [WINSPOOL.104]
1062 BOOL WINAPI
AddFormW(HANDLE hPrinter
, DWORD Level
, LPBYTE pForm
)
1064 FIXME_(print
)("(%d,%ld,%p): stub\n", hPrinter
, Level
, pForm
);
1068 /*****************************************************************************
1069 * AddJob32A [WINSPOOL.105]
1071 BOOL WINAPI
AddJobA(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
,
1072 DWORD cbBuf
, LPDWORD pcbNeeded
)
1074 FIXME_(print
)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
1079 /*****************************************************************************
1080 * AddJob32W [WINSPOOL.106]
1082 BOOL WINAPI
AddJobW(HANDLE hPrinter
, DWORD Level
, LPBYTE pData
, DWORD cbBuf
,
1085 FIXME_(print
)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pData
, cbBuf
,
1090 /*****************************************************************************
1091 * AddPrinter32A [WINSPOOL.117]
1093 HANDLE WINAPI
AddPrinterA(LPSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1095 FIXME_(print
)("(%s,%ld,%p): stub\n", pName
, Level
, pPrinter
);
1099 /*****************************************************************************
1100 * AddPrinter32W [WINSPOOL.122]
1102 HANDLE WINAPI
AddPrinterW(LPWSTR pName
, DWORD Level
, LPBYTE pPrinter
)
1104 FIXME_(print
)("(%p,%ld,%p): stub\n", pName
, Level
, pPrinter
);
1109 /*****************************************************************************
1110 * ClosePrinter32 [WINSPOOL.126]
1112 BOOL WINAPI
ClosePrinter(HANDLE hPrinter
)
1114 FIXME_(print
)("(%d): stub\n", hPrinter
);
1118 /*****************************************************************************
1119 * DeleteForm32A [WINSPOOL.133]
1121 BOOL WINAPI
DeleteFormA(HANDLE hPrinter
, LPSTR pFormName
)
1123 FIXME_(print
)("(%d,%s): stub\n", hPrinter
, pFormName
);
1127 /*****************************************************************************
1128 * DeleteForm32W [WINSPOOL.134]
1130 BOOL WINAPI
DeleteFormW(HANDLE hPrinter
, LPWSTR pFormName
)
1132 FIXME_(print
)("(%d,%s): stub\n", hPrinter
, debugstr_w(pFormName
));
1136 /*****************************************************************************
1137 * DeletePrinter32 [WINSPOOL.143]
1139 BOOL WINAPI
DeletePrinter(HANDLE hPrinter
)
1141 FIXME_(print
)("(%d): stub\n", hPrinter
);
1145 /*****************************************************************************
1146 * SetPrinter32A [WINSPOOL.211]
1148 BOOL WINAPI
SetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1151 FIXME_(print
)("(%d,%ld,%p,%ld): stub\n",hPrinter
,Level
,pPrinter
,Command
);
1155 /*****************************************************************************
1156 * SetJob32A [WINSPOOL.209]
1158 BOOL WINAPI
SetJobA(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1159 LPBYTE pJob
, DWORD Command
)
1161 FIXME_(print
)("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1166 /*****************************************************************************
1167 * SetJob32W [WINSPOOL.210]
1169 BOOL WINAPI
SetJobW(HANDLE hPrinter
, DWORD JobId
, DWORD Level
,
1170 LPBYTE pJob
, DWORD Command
)
1172 FIXME_(print
)("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter
,JobId
,Level
,pJob
,
1177 /*****************************************************************************
1178 * GetForm32A [WINSPOOL.181]
1180 BOOL WINAPI
GetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1181 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1183 FIXME_(print
)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pFormName
,
1184 Level
,pForm
,cbBuf
,pcbNeeded
);
1188 /*****************************************************************************
1189 * GetForm32W [WINSPOOL.182]
1191 BOOL WINAPI
GetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1192 LPBYTE pForm
, DWORD cbBuf
, LPDWORD pcbNeeded
)
1194 FIXME_(print
)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,
1195 debugstr_w(pFormName
),Level
,pForm
,cbBuf
,pcbNeeded
);
1199 /*****************************************************************************
1200 * SetForm32A [WINSPOOL.207]
1202 BOOL WINAPI
SetFormA(HANDLE hPrinter
, LPSTR pFormName
, DWORD Level
,
1205 FIXME_(print
)("(%d,%s,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1209 /*****************************************************************************
1210 * SetForm32W [WINSPOOL.208]
1212 BOOL WINAPI
SetFormW(HANDLE hPrinter
, LPWSTR pFormName
, DWORD Level
,
1215 FIXME_(print
)("(%d,%p,%ld,%p): stub\n",hPrinter
,pFormName
,Level
,pForm
);
1219 /*****************************************************************************
1220 * ReadPrinter32 [WINSPOOL.202]
1222 BOOL WINAPI
ReadPrinter(HANDLE hPrinter
, LPVOID pBuf
, DWORD cbBuf
,
1223 LPDWORD pNoBytesRead
)
1225 FIXME_(print
)("(%d,%p,%ld,%p): stub\n",hPrinter
,pBuf
,cbBuf
,pNoBytesRead
);
1229 /*****************************************************************************
1230 * ResetPrinter32A [WINSPOOL.203]
1232 BOOL WINAPI
ResetPrinterA(HANDLE hPrinter
, LPPRINTER_DEFAULTSA pDefault
)
1234 FIXME_(print
)("(%d, %p): stub\n", hPrinter
, pDefault
);
1238 /*****************************************************************************
1239 * ResetPrinter32W [WINSPOOL.204]
1241 BOOL WINAPI
ResetPrinterW(HANDLE hPrinter
, LPPRINTER_DEFAULTSW pDefault
)
1243 FIXME_(print
)("(%d, %p): stub\n", hPrinter
, pDefault
);
1247 /*****************************************************************************
1248 * GetPrinter32A [WINSPOOL.187]
1250 BOOL WINAPI
GetPrinterA(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1251 DWORD cbBuf
, LPDWORD pcbNeeded
)
1253 FIXME_(print
)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pPrinter
,
1258 /*****************************************************************************
1259 * GetPrinter32W [WINSPOOL.194]
1261 BOOL WINAPI
GetPrinterW(HANDLE hPrinter
, DWORD Level
, LPBYTE pPrinter
,
1262 DWORD cbBuf
, LPDWORD pcbNeeded
)
1264 FIXME_(print
)("(%d,%ld,%p,%ld,%p): stub\n", hPrinter
, Level
, pPrinter
,
1269 /*****************************************************************************
1270 * GetPrinterDriver32A [WINSPOOL.190]
1272 BOOL WINAPI
GetPrinterDriverA(HANDLE hPrinter
, LPSTR pEnvironment
,
1273 DWORD Level
, LPBYTE pDriverInfo
,
1274 DWORD cbBuf
, LPDWORD pcbNeeded
)
1276 FIXME_(print
)("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter
,pEnvironment
,
1277 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1281 /*****************************************************************************
1282 * GetPrinterDriver32W [WINSPOOL.193]
1284 BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter
, LPWSTR pEnvironment
,
1285 DWORD Level
, LPBYTE pDriverInfo
,
1286 DWORD cbBuf
, LPDWORD pcbNeeded
)
1288 FIXME_(print
)("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter
,pEnvironment
,
1289 Level
,pDriverInfo
,cbBuf
, pcbNeeded
);
1292 /*****************************************************************************
1293 * AddPrinterDriver32A [WINSPOOL.120]
1295 BOOL WINAPI
AddPrinterDriverA(LPSTR printerName
,DWORD level
,
1298 FIXME_(print
)("(%s,%ld,%p): stub\n",printerName
,level
,pDriverInfo
);
1301 /*****************************************************************************
1302 * AddPrinterDriver32W [WINSPOOL.121]
1304 BOOL WINAPI
AddPrinterDriverW(LPWSTR printerName
,DWORD level
,
1307 FIXME_(print
)("(%s,%ld,%p): stub\n",debugstr_w(printerName
),
1313 /*****************************************************************************
1314 * PrinterProperties [WINSPOOL.201]
1316 * Displays a dialog to set the properties of the printer.
1319 * nonzero on succes or zero on faillure
1322 * implemented as stub only
1324 BOOL WINAPI
PrinterProperties(HWND hWnd
, /* handle to parent window */
1325 HANDLE hPrinter
/* handle to printer object */
1327 FIXME_(print
)("(%d,%d): stub\n", hWnd
, hPrinter
);
1328 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);