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);