From fdedc34872294d6702a2a4fcb7d4e37d25043a92 Mon Sep 17 00:00:00 2001 From: Klaas van Gend Date: Mon, 22 Mar 1999 12:40:24 +0000 Subject: [PATCH] Implementation of EnumPrintersA, info level 4 and 5. --- include/winspool.h | 47 +++++++ misc/printdrv.c | 337 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 377 insertions(+), 7 deletions(-) diff --git a/include/winspool.h b/include/winspool.h index e370a23372e..b4aa0c45760 100644 --- a/include/winspool.h +++ b/include/winspool.h @@ -182,6 +182,42 @@ DECL_WINELIB_TYPE_AW(PRINTER_INFO_2) DECL_WINELIB_TYPE_AW(PPRINTER_INFO_2) DECL_WINELIB_TYPE_AW(LPPRINTER_INFO_2) +typedef struct _PRINTER_INFO_4A { + LPSTR pPrinterName; + LPSTR pServerName; + DWORD Attributes; +} PRINTER_INFO_4A, *PPRINTER_INFO_4A, *LPPRINTER_INFO_4A; + +typedef struct _PRINTER_INFO_4W { + LPWSTR pPrinterName; + LPWSTR pServerName; + DWORD Attributes; +} PRINTER_INFO_4W, *PPRINTER_INFO_4W, *LPPRINTER_INFO_4W; + +DECL_WINELIB_TYPE_AW(PRINTER_INFO_4) +DECL_WINELIB_TYPE_AW(PPRINTER_INFO_4) +DECL_WINELIB_TYPE_AW(LPPRINTER_INFO_4) + +typedef struct _PRINTER_INFO_5A { + LPSTR pPrinterName; + LPSTR pPortName; + DWORD Attributes; + DWORD DeviceNotSelectedTimeOut; + DWORD TransmissionRetryTimeout; +} PRINTER_INFO_5A, *PPRINTER_INFO_5A, *LPPRINTER_INFO_5A; + +typedef struct _PRINTER_INFO_5W { + LPWSTR pPrinterName; + LPWSTR pPortName; + DWORD Attributes; + DWORD DeviceNotSelectedTimeOut; + DWORD TransmissionRetryTimeout; +} PRINTER_INFO_5W, *PPRINTER_INFO_5W, *LPPRINTER_INFO_5W; + +DECL_WINELIB_TYPE_AW(PRINTER_INFO_5) +DECL_WINELIB_TYPE_AW(PPRINTER_INFO_5) +DECL_WINELIB_TYPE_AW(LPPRINTER_INFO_5) + #endif /* Status */ /* DECLARATIONS */ @@ -225,6 +261,17 @@ BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter, BOOL WINAPI ClosePrinter (HANDLE phPrinter); +BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName, + DWORD dwLevel, LPBYTE lpbPrinters, + DWORD cbBuf, LPDWORD lpdwNeeded, + LPDWORD lpdwReturned); +BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName, + DWORD dwLevel, LPBYTE lpbPrinters, + DWORD cbBuf, LPDWORD lpdwNeeded, + LPDWORD lpdwReturned); +#define EnumPrinters WINELIB_NAME_AW(EnumPrinters) + + #ifdef __cplusplus } // extern "C" diff --git a/misc/printdrv.c b/misc/printdrv.c index 55e428693ea..0d3f7a0208e 100644 --- a/misc/printdrv.c +++ b/misc/printdrv.c @@ -401,19 +401,342 @@ BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter, return FALSE; } + /****************************************************************** - * EnumPrinters32A [WINSPOOL.174] + * ENUMPRINTERS_AddInfo4A internal * + * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos] + * for printer PrinterNameKey. + * Note that there is no check whether the information really fits! + * + * RETURNS + * FALSE if there is still space left in the buffer. + * + * BUGS: + * This function should not exist in Win95 mode, but does anyway. */ -BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName, - DWORD dwLevel, LPBYTE lpbPrinters, - DWORD cbBuf, LPDWORD lpdwNeeded, - LPDWORD lpdwReturned) +BOOL ENUMPRINTERS_AddInfo4A( + LPSTR lpszPrinterName,/* name of printer to fill struct for*/ + LPBYTE lpbPrinters, /* buffer which receives info*/ + DWORD dwNextStructPos, /* pos in buffer for struct */ + LPDWORD dwNextStringPos, /* pos in buffer for next string */ + DWORD dwBufSize, /* max size of buffer in bytes */ + BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */ +){ + HKEY hPrinterSettings; + DWORD DataType; + DWORD DataSize=8; + char Data[8]; + DWORD* DataPointer= (DWORD*) Data; + LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+ + strlen(lpszPrinterName)+2); + LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos]; + + lpPInfo4->pPrinterName = &lpbPrinters[*dwNextStringPos]; + *dwNextStringPos += strlen(lpszPrinterName)+1; + if (*dwNextStringPos > dwBufSize) + bCalcSpaceOnly=TRUE; + if (bCalcSpaceOnly==FALSE) + strcpy(lpPInfo4->pPrinterName, lpszPrinterName); + lpPInfo4->pServerName = NULL; + + /* open the registry to find the attributes of the printer */ + if (lpszPrinterSettings!=NULL) + { + strcpy(lpszPrinterSettings,Printers); + strcat(lpszPrinterSettings,lpszPrinterName); + } + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, + KEY_READ, &hPrinterSettings) != ERROR_SUCCESS) + { + FIXME(print, "The registry did not contain my printer anymore?\n"); + lpPInfo4->Attributes = 0; + } + else + { + RegQueryValueExA(hPrinterSettings, "Attributes", NULL, &DataType, + Data, &DataSize); + if (DataType==REG_DWORD) + lpPInfo4->Attributes = PRINTER_ATTRIBUTE_LOCAL + *DataPointer; + } + if (lpszPrinterSettings) + free(lpszPrinterSettings); + + return(bCalcSpaceOnly); +} + +/****************************************************************** + * ENUMPRINTERS_AddInfo5A internal + * + * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos] + * for printer PrinterNameKey. + * Settings are read from the registry. + * Note that there is no check whether the information really fits! + * RETURNS + * FALSE if there is still space left in the buffer. + */ +BOOL ENUMPRINTERS_AddInfo5A( + LPSTR lpszPrinterName,/* name of printer to fill struct for*/ + LPBYTE lpbPrinters, /* buffer which receives info*/ + DWORD dwNextStructPos, /* pos in buffer for struct */ + LPDWORD dwNextStringPos, /* pos in buffer for next string */ + DWORD dwBufSize, /* max size of buffer in bytes */ + BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */ +){ + HKEY hPrinterSettings; + DWORD DataType; + DWORD DataSize=255; + char Data[255]; + DWORD* DataPointer= (DWORD*) Data; + LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+ + strlen(lpszPrinterName)+2); + LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos]; + + /* copy the PrinterName into the structure */ + lpPInfo5->pPrinterName = &lpbPrinters[*dwNextStringPos]; + *dwNextStringPos += strlen(lpszPrinterName)+1; + if (*dwNextStringPos > dwBufSize) + bCalcSpaceOnly=TRUE; + if (bCalcSpaceOnly==FALSE) + strcpy(lpPInfo5->pPrinterName, lpszPrinterName); + + /* open the registry to find the attributes, etc of the printer */ + if (lpszPrinterSettings!=NULL) + { + strcpy(lpszPrinterSettings,Printers); + strcat(lpszPrinterSettings,lpszPrinterName); + } + if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, + KEY_READ, &hPrinterSettings) != ERROR_SUCCESS) + { + FIXME(print, "The registry did not contain my printer anymore?\n"); + lpPInfo5->Attributes = 0; + lpPInfo5->pPortName = NULL; + lpPInfo5->Attributes = 0; + lpPInfo5->DeviceNotSelectedTimeOut =0; + lpPInfo5->TransmissionRetryTimeout = 0; + } + else + { + RegQueryValueExA(hPrinterSettings, "Attributes", NULL, &DataType, + Data, &DataSize); + if (DataType==REG_DWORD) + lpPInfo5->Attributes = PRINTER_ATTRIBUTE_LOCAL + *DataPointer; + + DataSize=255; + RegQueryValueExA(hPrinterSettings, "txTimeout", NULL, &DataType, + Data, &DataSize); + if (DataType==REG_DWORD) + lpPInfo5->DeviceNotSelectedTimeOut = *DataPointer; + + DataSize=255; + RegQueryValueExA(hPrinterSettings, "dnsTimeout", NULL, &DataType, + Data, &DataSize); + if (DataType==REG_DWORD) + lpPInfo5->TransmissionRetryTimeout = *DataPointer; + + DataSize=255; + RegQueryValueExA(hPrinterSettings, "Port", NULL, &DataType, + Data, &DataSize); + lpPInfo5->pPortName = &lpbPrinters[*dwNextStringPos]; + *dwNextStringPos += DataSize+1; + if (*dwNextStringPos > dwBufSize) + bCalcSpaceOnly=TRUE; + if (bCalcSpaceOnly==FALSE) + strcpy(lpPInfo5->pPortName, Data); + } + + if (lpszPrinterSettings) + free(lpszPrinterSettings); + + return(bCalcSpaceOnly); +} + + +/****************************************************************** + * EnumPrintersA [WINSPOOL.174] + * + * Enumerates the available printers, print servers and print + * providers, depending on the specified flags, name and level. + * + * RETURNS: + * + * If level is set to 1: + * If level is set to 2: + * Not implemented yet! + * Returns TRUE with an empty list. + * + * If level is set to 4 (officially WinNT only): + * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL). + * Fast: Only the registry is queried to retrieve printer names, + * no connection to the driver is made. + * Returns an array of PRINTER_INFO_4 data structures in the + * lpbPrinters buffer. + * + * If level is set to 5 (officially WinNT4/Win9x only): + * Fast: Only the registry is queried to retrieve printer names, + * no connection to the driver is made. + * Returns an array of PRINTER_INFO_5 data structures in the + * lpbPrinters buffer. + * + * If level set to 3 or 6+: + * returns zero (faillure!) + * + * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError + * for information. + * + * BUGS: + * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented. + * - Only level 4 and 5 are implemented at the moment. + * - 16-bit printer drivers are not enumerated. + * - returned bytes used/needed do not match the real Windoze implementation + * + * NOTE: + * - In a regular Wine installation, no registry settings for printers + * exist, which makes this function return an empty list. + */ +BOOL WINAPI EnumPrintersA( + DWORD dwType, /* Types of print objects to enumerate */ + LPSTR lpszName, /* name of objects to enumerate */ + DWORD dwLevel, /* type of printer info structure */ + LPBYTE lpbPrinters,/* buffer which receives info*/ + DWORD cbBuf, /* max size of buffer in bytes */ + LPDWORD lpdwNeeded,/* pointer to var: # bytes used/needed */ + LPDWORD lpdwReturned/* number of entries returned */ + ) { - FIXME(print,"Nearly empty stub\n"); + HKEY hPrinterListKey; + DWORD dwIndex=0; + char PrinterName[255]; + DWORD PrinterNameLength=255; + FILETIME FileTime; + DWORD dwNextStringPos; /* position of next space for a string in the buffer*/ + DWORD dwStructPrinterInfoSize; /* size of a Printer_Info_X structure */ + BOOL bCalcSpaceOnly=FALSE;/* if TRUE: don't store data, just calculate space*/ + + TRACE(print, "EnumPrintersA\n"); + + /* check for valid Flags */ + if (dwType != PRINTER_ENUM_LOCAL && dwType != PRINTER_ENUM_NAME) + { + SetLastError(ERROR_INVALID_FLAGS); + return(0); + } + if (dwLevel == 1 || dwLevel == 2) + return(TRUE); + if (dwLevel != 4 && dwLevel != 5) + { + SetLastError(ERROR_INVALID_PARAMETER); + return(0); + } + + /* zero out the data area, and initialise some returns to zero, + * to prevent problems + */ +{ + int i; + for (i=0; i cbBuf) + bCalcSpaceOnly = TRUE; + + /* the strings which contain e.g. PrinterName, PortName, etc, + * are also stored in lpbPrinters, but after the regular structs. + * dwNextStringPos will always point to the next free place for a + * string. + */ + dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize; + + /* check each entry: if OK, add to list in corresponding INFO . + */ + for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++) + { + PrinterNameLength=255; + if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength, + NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS) + break; /* exit for loop*/ + + /* check whether this printer is allowed in the list + * by comparing name to lpszName + */ + if (dwType == PRINTER_ENUM_NAME) + if (strcmp(PrinterName,lpszName)!=0) + continue; + + switch(dwLevel) + { + case 1: + /* FIXME: unimplemented */ + break; + case 2: + /* FIXME: unimplemented */ + break; + case 4: + bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters, + dwIndex*dwStructPrinterInfoSize, + &dwNextStringPos, cbBuf, bCalcSpaceOnly); + break; + case 5: + bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters, + dwIndex*dwStructPrinterInfoSize, + &dwNextStringPos, cbBuf, bCalcSpaceOnly); + break; + } + } + RegCloseKey(hPrinterListKey); + *lpdwNeeded = dwNextStringPos; + + if (bCalcSpaceOnly==TRUE) + { + int i; + for (i=0; i