From 212d1e36bf2ccd530b4495cd80f084b6e8636b24 Mon Sep 17 00:00:00 2001 From: Detlef Riekenberg Date: Wed, 14 Oct 2009 23:33:01 +0200 Subject: [PATCH] localspl: Implement fpEnumPrintProcessors. --- dlls/localspl/provider.c | 176 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 175 insertions(+), 1 deletion(-) diff --git a/dlls/localspl/provider.c b/dlls/localspl/provider.c index 790a1efea3f..5e4ba31cf4b 100644 --- a/dlls/localspl/provider.c +++ b/dlls/localspl/provider.c @@ -110,6 +110,12 @@ static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\', 'P','r','i','n','t','\\', 'E','n','v','i','r','o','n','m','e','n','t','s','\\', '%','s','\\','D','r','i','v','e','r','s','%','s',0 }; +static const WCHAR fmt_printprocessorsW[] = { 'S','y','s','t','e','m','\\', + 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', + 'C','o','n','t','r','o','l','\\', + 'P','r','i','n','t','\\', + 'E','n','v','i','r','o','n','m','e','n','t','s','\\','%','s','\\', + 'P','r','i','n','t',' ','P','r','o','c','e','s','s','o','r','s',0 }; static const WCHAR hardwareidW[] = {'H','a','r','d','w','a','r','e','I','D',0}; static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0}; static const WCHAR localportW[] = {'L','o','c','a','l',' ','P','o','r','t',0}; @@ -145,6 +151,7 @@ static const WCHAR winnt_cv_portsW[] = {'S','o','f','t','w','a','r','e','\\', 'W','i','n','d','o','w','s',' ','N','T','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'P','o','r','t','s',0}; +static const WCHAR winprintW[] = {'w','i','n','p','r','i','n','t',0}; static const WCHAR x64_envnameW[] = {'W','i','n','d','o','w','s',' ','x','6','4',0}; static const WCHAR x64_subdirW[] = {'x','6','4',0}; static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0}; @@ -819,6 +826,92 @@ static DWORD get_local_monitors(DWORD level, LPBYTE pMonitors, DWORD cbBuf, LPDW return needed; } +/***************************************************************************** + * enumerate the local print processors (INTERNAL) + * + * returns the needed size (in bytes) for pPPInfo + * and *lpreturned is set to number of entries returned in pPPInfo + * + */ +static DWORD get_local_printprocessors(LPWSTR regpathW, LPBYTE pPPInfo, DWORD cbBuf, LPDWORD lpreturned) +{ + HKEY hroot = NULL; + HKEY hentry = NULL; + LPWSTR ptr; + PPRINTPROCESSOR_INFO_1W ppi; + WCHAR buffer[MAX_PATH]; + WCHAR dllname[MAX_PATH]; + DWORD dllsize; + DWORD len; + DWORD index = 0; + DWORD needed = 0; + DWORD numentries; + + numentries = *lpreturned; /* this is 0, when we scan the registry */ + len = numentries * sizeof(PRINTPROCESSOR_INFO_1W); + ptr = (LPWSTR) &pPPInfo[len]; + + numentries = 0; + len = sizeof(buffer)/sizeof(buffer[0]); + buffer[0] = '\0'; + + if (RegCreateKeyW(HKEY_LOCAL_MACHINE, regpathW, &hroot) == ERROR_SUCCESS) { + /* add "winprint" first */ + numentries++; + needed = sizeof(PRINTPROCESSOR_INFO_1W) + sizeof(winprintW); + if (pPPInfo && (cbBuf >= needed)){ + ppi = (PPRINTPROCESSOR_INFO_1W) pPPInfo; + pPPInfo += sizeof(PRINTPROCESSOR_INFO_1W); + + TRACE("%p: writing PRINTPROCESSOR_INFO_1W #%d\n", ppi, numentries); + ppi->pName = ptr; + lstrcpyW(ptr, winprintW); /* Name of the Print Processor */ + ptr += sizeof(winprintW) / sizeof(WCHAR); + } + + /* Scan all Printprocessor Keys */ + while ((RegEnumKeyExW(hroot, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && + (lstrcmpiW(buffer, winprintW) != 0)) { + TRACE("PrintProcessor_%d: %s\n", numentries, debugstr_w(buffer)); + dllsize = sizeof(dllname); + dllname[0] = '\0'; + + /* The Print Processor must have a Driver-DLL */ + if (RegOpenKeyExW(hroot, buffer, 0, KEY_READ, &hentry) == ERROR_SUCCESS) { + if (RegQueryValueExW(hentry, driverW, NULL, NULL, (LPBYTE) dllname, &dllsize) == ERROR_SUCCESS) { + /* We found a valid DLL for this Print Processor */ + TRACE("using Driver: %s\n", debugstr_w(dllname)); + } + RegCloseKey(hentry); + } + + if (dllname[0]) { + numentries++; + needed += sizeof(PRINTPROCESSOR_INFO_1W); + needed += (len+1) * sizeof(WCHAR); /* len is lstrlenW(printprocessor name) */ + + /* required size is calculated. Now fill the user-buffer */ + if (pPPInfo && (cbBuf >= needed)){ + ppi = (PPRINTPROCESSOR_INFO_1W) pPPInfo; + pPPInfo += sizeof(PRINTPROCESSOR_INFO_1W); + + TRACE("%p: writing PRINTPROCESSOR_INFO_1W #%d\n", ppi, numentries); + ppi->pName = ptr; + lstrcpyW(ptr, buffer); /* Name of the Print Processor */ + ptr += (len+1); /* len is lstrlenW(printprosessor name) */ + } + } + index++; + len = sizeof(buffer)/sizeof(buffer[0]); + buffer[0] = '\0'; + } + RegCloseKey(hroot); + } + *lpreturned = numentries; + TRACE("need %d byte for %d entries\n", needed, numentries); + return needed; +} + /****************************************************************** * enumerate the local Ports from all loaded monitors (internal) * @@ -2000,6 +2093,87 @@ emP_cleanup: return (res); } +/***************************************************************************** + * fpEnumPrintProcessors [exported through PRINTPROVIDOR] + * + * Enumerate available Print Processors + * + * PARAMS + * pName [I] Servername or NULL (local Computer) + * pEnvironment [I] Printing-Environment or NULL (Default) + * Level [I] Structure-Level (Only 1 is allowed) + * pPPInfo [O] PTR to Buffer that receives the Result + * cbBuf [I] Size of Buffer at pMonitors + * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPPInfo + * pcReturned [O] PTR to DWORD that receives the number of Print Processors in pPPInfo + * + * RETURNS + * Success: TRUE + * Failure: FALSE and in pcbNeeded the Bytes required for pPPInfo, if cbBuf is too small + * + */ +static BOOL WINAPI fpEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, + LPBYTE pPPInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) +{ + const printenv_t * env; + LPWSTR regpathW = NULL; + DWORD numentries = 0; + DWORD needed = 0; + LONG lres; + BOOL res = FALSE; + + TRACE("(%s, %s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), debugstr_w(pEnvironment), + Level, pPPInfo, cbBuf, pcbNeeded, pcReturned); + + lres = copy_servername_from_name(pName, NULL); + if (lres) { + FIXME("server %s not supported\n", debugstr_w(pName)); + SetLastError(ERROR_INVALID_NAME); + goto epp_cleanup; + } + + if (Level != 1) { + SetLastError(ERROR_INVALID_LEVEL); + goto epp_cleanup; + } + + env = validate_envW(pEnvironment); + if (!env) + goto epp_cleanup; /* ERROR_INVALID_ENVIRONMENT */ + + regpathW = heap_alloc(sizeof(fmt_printprocessorsW) + + (lstrlenW(env->envname) * sizeof(WCHAR))); + + if (!regpathW) + goto epp_cleanup; + + wsprintfW(regpathW, fmt_printprocessorsW, env->envname); + + /* Scan all Printprocessor-Keys */ + numentries = 0; + needed = get_local_printprocessors(regpathW, NULL, 0, &numentries); + + /* we calculated the needed buffersize. now do more error-checks */ + if (cbBuf < needed) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto epp_cleanup; + } + + /* fill the Buffer with the Printprocessor Infos */ + needed = get_local_printprocessors(regpathW, pPPInfo, cbBuf, &numentries); + res = TRUE; + +epp_cleanup: + heap_free(regpathW); + if (pcbNeeded) *pcbNeeded = needed; + if (pcReturned) *pcReturned = numentries; + + TRACE("returning %d with %d (%d byte for %d entries)\n", + res, GetLastError(), needed, numentries); + + return (res); +} + /****************************************************************************** * fpOpenPrinter [exported through PRINTPROVIDOR] * @@ -2123,7 +2297,7 @@ void setup_provider(void) fpGetPrinterDriverDirectory, NULL, /* fpDeletePrinterDriver */ NULL, /* fpAddPrintProcessor */ - NULL, /* fpEnumPrintProcessors */ + fpEnumPrintProcessors, NULL, /* fpGetPrintProcessorDirectory */ NULL, /* fpDeletePrintProcessor */ NULL, /* fpEnumPrintProcessorDatatypes */