From ccfe6e9c9bea9da5689a7115a8386d3b79ef7fb5 Mon Sep 17 00:00:00 2001 From: Ian Pilcher Date: Wed, 21 Feb 2001 04:00:40 +0000 Subject: [PATCH] Implement EnumPrinterDataEx{A|W}. --- dlls/winspool/info.c | 383 ++++++++++++++++++++++++++++++++++++++++ dlls/winspool/winspool.drv.spec | 4 + include/winspool.h | 27 +++ 3 files changed, 414 insertions(+) diff --git a/dlls/winspool/info.c b/dlls/winspool/info.c index 42cc1c4249a..f5d96109f3c 100644 --- a/dlls/winspool/info.c +++ b/dlls/winspool/info.c @@ -2561,3 +2561,386 @@ DWORD WINAPI GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, return GetPrinterDataExW(hPrinter, PrinterDriverDataW, pValueName, pType, pData, nSize, pcbNeeded); } + +/******************************************************************************* + * EnumPrinterDataExW [WINSPOOL.197] + */ +DWORD WINAPI EnumPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, + LPBYTE pEnumValues, DWORD cbEnumValues, + LPDWORD pcbEnumValues, LPDWORD pnEnumValues) +{ + HKEY hkPrinter, hkSubKey; + DWORD r, ret, dwIndex, cValues, cbMaxValueNameLen, + cbValueNameLen, cbMaxValueLen, cbValueLen, + cbBufSize, dwType; + LPWSTR lpValueName; + HANDLE hHeap; + PBYTE lpValue; + PPRINTER_ENUM_VALUESW ppev; + + TRACE ("%08x %s\n", hPrinter, debugstr_w (pKeyName)); + + if (pKeyName == NULL || *pKeyName == 0) + return ERROR_INVALID_PARAMETER; + + ret = WINSPOOL_GetOpenedPrinterRegKey (hPrinter, &hkPrinter); + if (ret != ERROR_SUCCESS) + { + TRACE ("WINSPOOL_GetOpenedPrinterRegKey (%08x) returned %li\n", + hPrinter, ret); + return ret; + } + + ret = RegOpenKeyExW (hkPrinter, pKeyName, 0, KEY_READ, &hkSubKey); + if (ret != ERROR_SUCCESS) + { + r = RegCloseKey (hkPrinter); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + TRACE ("RegOpenKeyExW (%08x, %s) returned %li\n", hPrinter, + debugstr_w (pKeyName), ret); + return ret; + } + + ret = RegCloseKey (hkPrinter); + if (ret != ERROR_SUCCESS) + { + ERR ("RegCloseKey returned %li\n", ret); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + return ret; + } + + ret = RegQueryInfoKeyW (hkSubKey, NULL, NULL, NULL, NULL, NULL, NULL, + &cValues, &cbMaxValueNameLen, &cbMaxValueLen, NULL, NULL); + if (ret != ERROR_SUCCESS) + { + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + TRACE ("RegQueryInfoKeyW (%08x) returned %li\n", hkSubKey, ret); + return ret; + } + + TRACE ("RegQueryInfoKeyW returned cValues = %li, cbMaxValueNameLen = %li, " + "cbMaxValueLen = %li\n", cValues, cbMaxValueNameLen, cbMaxValueLen); + + if (cValues == 0) /* empty key */ + { + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + *pcbEnumValues = *pnEnumValues = 0; + return ERROR_SUCCESS; + } + + ++cbMaxValueNameLen; /* allow for trailing '\0' */ + + hHeap = GetProcessHeap (); + if (hHeap == (HANDLE) NULL) + { + ERR ("GetProcessHeap failed\n"); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + return ERROR_OUTOFMEMORY; + } + + lpValueName = HeapAlloc (hHeap, 0, cbMaxValueNameLen * sizeof (WCHAR)); + if (lpValueName == NULL) + { + ERR ("Failed to allocate %li bytes from process heap\n", + cbMaxValueNameLen * sizeof (WCHAR)); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + return ERROR_OUTOFMEMORY; + } + + lpValue = HeapAlloc (hHeap, 0, cbMaxValueLen); + if (lpValue == NULL) + { + ERR ("Failed to allocate %li bytes from process heap\n", cbMaxValueLen); + if (HeapFree (hHeap, 0, lpValueName) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + return ERROR_OUTOFMEMORY; + } + + TRACE ("pass 1: calculating buffer required for all names and values\n"); + + cbBufSize = cValues * sizeof (PRINTER_ENUM_VALUESW); + + TRACE ("%li bytes required for %li headers\n", cbBufSize, cValues); + + for (dwIndex = 0; dwIndex < cValues; ++dwIndex) + { + cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen; + ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen, + NULL, NULL, lpValue, &cbValueLen); + if (ret != ERROR_SUCCESS) + { + if (HeapFree (hHeap, 0, lpValue) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + if (HeapFree (hHeap, 0, lpValueName) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex, ret); + return ret; + } + + TRACE ("%s [%li]: name needs %li bytes, data needs %li bytes\n", + debugstr_w (lpValueName), dwIndex, + (cbValueNameLen + 1) * sizeof (WCHAR), cbValueLen); + + cbBufSize += (cbValueNameLen + 1) * sizeof (WCHAR); + cbBufSize += cbValueLen; + } + + TRACE ("%li bytes required for all %li values\n", cbBufSize, cValues); + + *pcbEnumValues = cbBufSize; + *pnEnumValues = cValues; + + if (cbEnumValues < cbBufSize) /* buffer too small */ + { + if (HeapFree (hHeap, 0, lpValue) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + if (HeapFree (hHeap, 0, lpValueName) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + TRACE ("%li byte buffer is not large enough\n", cbEnumValues); + return ERROR_MORE_DATA; + } + + TRACE ("pass 2: copying all names and values to buffer\n"); + + ppev = (PPRINTER_ENUM_VALUESW) pEnumValues; /* array of structs */ + pEnumValues += cValues * sizeof (PRINTER_ENUM_VALUESW); + + for (dwIndex = 0; dwIndex < cValues; ++dwIndex) + { + cbValueNameLen = cbMaxValueNameLen; cbValueLen = cbMaxValueLen; + ret = RegEnumValueW (hkSubKey, dwIndex, lpValueName, &cbValueNameLen, + NULL, &dwType, lpValue, &cbValueLen); + if (ret != ERROR_SUCCESS) + { + if (HeapFree (hHeap, 0, lpValue) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + if (HeapFree (hHeap, 0, lpValueName) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + TRACE ("RegEnumValueW (%li) returned %li\n", dwIndex, ret); + return ret; + } + + cbValueNameLen = (cbValueNameLen + 1) * sizeof (WCHAR); + memcpy (pEnumValues, lpValueName, cbValueNameLen); + ppev[dwIndex].pValueName = (LPWSTR) pEnumValues; + pEnumValues += cbValueNameLen; + + /* return # of *bytes* (including trailing \0), not # of chars */ + ppev[dwIndex].cbValueName = cbValueNameLen; + + ppev[dwIndex].dwType = dwType; + + memcpy (pEnumValues, lpValue, cbValueLen); + ppev[dwIndex].pData = pEnumValues; + pEnumValues += cbValueLen; + + ppev[dwIndex].cbData = cbValueLen; + + TRACE ("%s [%li]: copied name (%li bytes) and data (%li bytes)\n", + debugstr_w (lpValueName), dwIndex, cbValueNameLen, cbValueLen); + } + + if (HeapFree (hHeap, 0, lpValue) == 0) + { + ret = GetLastError (); + ERR ("HeapFree failed with code %li\n", ret); + if (HeapFree (hHeap, 0, lpValueName) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + return ret; + } + + if (HeapFree (hHeap, 0, lpValueName) == 0) + { + ret = GetLastError (); + ERR ("HeapFree failed with code %li\n", ret); + r = RegCloseKey (hkSubKey); + if (r != ERROR_SUCCESS) + WARN ("RegCloseKey returned %li\n", r); + return ret; + } + + ret = RegCloseKey (hkSubKey); + if (ret != ERROR_SUCCESS) + { + ERR ("RegCloseKey returned %li\n", ret); + return ret; + } + + return ERROR_SUCCESS; +} + +/******************************************************************************* + * EnumPrinterDataExA [WINSPOOL.196] + * + * This functions returns value names and REG_SZ, REG_EXPAND_SZ, and + * REG_MULTI_SZ values as ASCII strings in Unicode-sized buffers. This is + * what Windows 2000 SP1 does. + * + */ +DWORD WINAPI EnumPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, + LPBYTE pEnumValues, DWORD cbEnumValues, + LPDWORD pcbEnumValues, LPDWORD pnEnumValues) +{ + INT len; + LPWSTR pKeyNameW; + DWORD ret, dwIndex, dwBufSize; + HANDLE hHeap; + LPSTR pBuffer; + + TRACE ("%08x %s\n", hPrinter, pKeyName); + + if (pKeyName == NULL || *pKeyName == 0) + return ERROR_INVALID_PARAMETER; + + len = MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, NULL, 0); + if (len == 0) + { + ret = GetLastError (); + ERR ("MultiByteToWideChar failed with code %li\n", ret); + return ret; + } + + hHeap = GetProcessHeap (); + if (hHeap == (HANDLE) NULL) + { + ERR ("GetProcessHeap failed\n"); + return ERROR_OUTOFMEMORY; + } + + pKeyNameW = HeapAlloc (hHeap, 0, len * sizeof (WCHAR)); + if (pKeyNameW == NULL) + { + ERR ("Failed to allocate %li bytes from process heap\n", + (LONG) len * sizeof (WCHAR)); + return ERROR_OUTOFMEMORY; + } + + if (MultiByteToWideChar (CP_ACP, 0, pKeyName, -1, pKeyNameW, len) == 0) + { + ret = GetLastError (); + ERR ("MultiByteToWideChar failed with code %li\n", ret); + if (HeapFree (hHeap, 0, pKeyNameW) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + return ret; + } + + ret = EnumPrinterDataExW (hPrinter, pKeyNameW, pEnumValues, cbEnumValues, + pcbEnumValues, pnEnumValues); + if (ret != ERROR_SUCCESS) + { + if (HeapFree (hHeap, 0, pKeyNameW) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + TRACE ("EnumPrinterDataExW returned %li\n", ret); + return ret; + } + + if (HeapFree (hHeap, 0, pKeyNameW) == 0) + { + ret = GetLastError (); + ERR ("HeapFree failed with code %li\n", ret); + return ret; + } + + if (*pnEnumValues == 0) /* empty key */ + return ERROR_SUCCESS; + + dwBufSize = 0; + for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) + { + PPRINTER_ENUM_VALUESW ppev = + &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; + + if (dwBufSize < ppev->cbValueName) + dwBufSize = ppev->cbValueName; + + if (dwBufSize < ppev->cbData && (ppev->dwType == REG_SZ || + ppev->dwType == REG_EXPAND_SZ || ppev->dwType == REG_MULTI_SZ)) + dwBufSize = ppev->cbData; + } + + TRACE ("Largest Unicode name or value is %li bytes\n", dwBufSize); + + pBuffer = HeapAlloc (hHeap, 0, dwBufSize); + if (pBuffer == NULL) + { + ERR ("Failed to allocate %li bytes from process heap\n", dwBufSize); + return ERROR_OUTOFMEMORY; + } + + for (dwIndex = 0; dwIndex < *pnEnumValues; ++dwIndex) + { + PPRINTER_ENUM_VALUESW ppev = + &((PPRINTER_ENUM_VALUESW) pEnumValues)[dwIndex]; + + len = WideCharToMultiByte (CP_ACP, 0, ppev->pValueName, + ppev->cbValueName / sizeof (WCHAR), pBuffer, dwBufSize, NULL, + NULL); + if (len == 0) + { + ret = GetLastError (); + ERR ("WideCharToMultiByte failed with code %li\n", ret); + if (HeapFree (hHeap, 0, pBuffer) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + return ret; + } + + memcpy (ppev->pValueName, pBuffer, len); + + TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); + + if (ppev->dwType != REG_SZ && ppev->dwType != REG_EXPAND_SZ && + ppev->dwType != REG_MULTI_SZ) + continue; + + len = WideCharToMultiByte (CP_ACP, 0, (LPWSTR) ppev->pData, + ppev->cbData / sizeof (WCHAR), pBuffer, dwBufSize, NULL, NULL); + if (len == 0) + { + ret = GetLastError (); + ERR ("WideCharToMultiByte failed with code %li\n", ret); + if (HeapFree (hHeap, 0, pBuffer) == 0) + WARN ("HeapFree failed with code %li\n", GetLastError ()); + return ret; + } + + memcpy (ppev->pData, pBuffer, len); + + TRACE ("Converted '%s' from Unicode to ASCII\n", pBuffer); + TRACE (" (only first string of REG_MULTI_SZ printed)\n"); + } + + if (HeapFree (hHeap, 0, pBuffer) == 0) + { + ret = GetLastError (); + ERR ("HeapFree failed with code %li\n", ret); + return ret; + } + + return ERROR_SUCCESS; +} diff --git a/dlls/winspool/winspool.drv.spec b/dlls/winspool/winspool.drv.spec index 289bedc35e6..977b48d9e72 100644 --- a/dlls/winspool/winspool.drv.spec +++ b/dlls/winspool/winspool.drv.spec @@ -80,6 +80,10 @@ debug_channels (winspool) @ stub EnumPrintProcessorDatatypesW @ stub EnumPrintProcessorsA @ stub EnumPrintProcessorsW +@ stub EnumPrinterDataA +@ stdcall EnumPrinterDataExA(long str ptr long ptr ptr) EnumPrinterDataExA +@ stdcall EnumPrinterDataExW(long wstr ptr long ptr ptr) EnumPrinterDataExW +@ stub EnumPrinterDataW @ stdcall EnumPrinterDriversA(str str long ptr long ptr ptr) EnumPrinterDriversA @ stdcall EnumPrinterDriversW(wstr wstr long ptr long ptr ptr) EnumPrinterDriversW @ stdcall EnumPrintersA(long ptr long ptr long ptr ptr) EnumPrintersA diff --git a/include/winspool.h b/include/winspool.h index 1a1cc272d34..3e98df82272 100644 --- a/include/winspool.h +++ b/include/winspool.h @@ -763,6 +763,25 @@ DECL_WINELIB_TYPE_AW(PROVIDOR_INFO_1) DECL_WINELIB_TYPE_AW(PPROVIDOR_INFO_1) DECL_WINELIB_TYPE_AW(LPPROVIDOR_INFO_1) +typedef struct _PRINTER_ENUM_VALUESA { + LPSTR pValueName; + DWORD cbValueName; + DWORD dwType; + LPBYTE pData; + DWORD cbData; +} PRINTER_ENUM_VALUESA, *PPRINTER_ENUM_VALUESA; + +typedef struct _PRINTER_ENUM_VALUESW { + LPWSTR pValueName; + DWORD cbValueName; + DWORD dwType; + LPBYTE pData; + DWORD cbData; +} PRINTER_ENUM_VALUESW, *PPRINTER_ENUM_VALUESW; + +DECL_WINELIB_TYPE_AW(PRINTER_ENUM_VALUES) +DECL_WINELIB_TYPE_AW(PPRINTER_ENUM_VALUES) + /* DECLARATIONS */ INT WINAPI DeviceCapabilitiesA(LPCSTR pDevice,LPCSTR pPort,WORD fwCapability, LPSTR pOutput, LPDEVMODEA pDevMode); @@ -1083,6 +1102,14 @@ BOOL WINAPI DeletePrintProvidorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pPrintProvidorName); #define DeletePrintProvidor WINELIB_NAME_AW(DeletePrintProvidor) +DWORD WINAPI EnumPrinterDataExA(HANDLE hPrinter, LPCSTR pKeyName, + LPBYTE pEnumValues, DWORD cbEnumValues, + LPDWORD pcbEnumValues, LPDWORD pnEnumValues); +DWORD WINAPI EnumPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, + LPBYTE pEnumValues, DWORD cbEnumValues, + LPDWORD pcbEnumValues, LPDWORD pnEnumValues); +#define EnumPrinterDataEx WINELIB_NAME_AW(EnumPrinterDataEx) + #ifdef __cplusplus -- 2.11.4.GIT