Module: wine Branch: master Commit: 2f08621d6217b93ab5cb2334588baa7f01a0d7a6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=2f08621d6217b93ab5cb233458...
Author: Detlef Riekenberg wine.dev@web.de Date: Mon Jun 30 21:49:31 2008 +0200
localspl: Implement fpEnumMonitors.
---
dlls/localspl/localspl_main.c | 185 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 183 insertions(+), 2 deletions(-)
diff --git a/dlls/localspl/localspl_main.c b/dlls/localspl/localspl_main.c index 1b828f0..b27ae7d 100644 --- a/dlls/localspl/localspl_main.c +++ b/dlls/localspl/localspl_main.c @@ -31,6 +31,7 @@ #include "ddk/winsplp.h" #include "winuser.h"
+#include "wine/list.h" #include "wine/debug.h" #include "wine/unicode.h" #include "localspl_private.h" @@ -49,6 +50,17 @@ typedef struct { } apd_data_t;
typedef struct { + struct list entry; + LPWSTR name; + LPWSTR dllname; + PMONITORUI monitorUI; + LPMONITOR monitor; + HMODULE hdll; + DWORD refcount; + DWORD dwMonitorSize; +} monitor_t; + +typedef struct { LPCWSTR envname; LPCWSTR subdir; DWORD driverversion; @@ -56,13 +68,13 @@ typedef struct { LPCWSTR versionsubdir; } printenv_t;
+ /* ############################### */
HINSTANCE LOCALSPL_hInstance = NULL;
static const PRINTPROVIDOR * pp = NULL;
- static const WCHAR backslashW[] = {'\',0}; static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0}; static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0}; @@ -82,6 +94,11 @@ static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0}; static const WCHAR locationW[] = {'L','o','c','a','t','i','o','n',0}; static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0}; static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0}; +static const WCHAR monitorsW[] = {'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','\', + 'M','o','n','i','t','o','r','s','\',0}; static const WCHAR monitorUIW[] = {'M','o','n','i','t','o','r','U','I',0}; static const WCHAR nameW[] = {'N','a','m','e',0}; static const WCHAR oem_urlW[] = {'O','E','M',' ','U','r','l',0}; @@ -116,6 +133,7 @@ static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_ sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W), 0, sizeof(DRIVER_INFO_8W)};
+ /****************************************************************** * apd_copyfile [internal] * @@ -284,6 +302,102 @@ static const printenv_t * validate_envW(LPCWSTR env) }
/***************************************************************************** + * enumerate the local monitors (INTERNAL) + * + * returns the needed size (in bytes) for pMonitors + * and *lpreturned is set to number of entries returned in pMonitors + * + * Language-Monitors are also installed in the same Registry-Location but + * they are filtered in Windows (not returned by EnumMonitors). + * We do no filtering to simplify our Code. + * + */ +static DWORD get_local_monitors(DWORD level, LPBYTE pMonitors, DWORD cbBuf, LPDWORD lpreturned) +{ + HKEY hroot = NULL; + HKEY hentry = NULL; + LPWSTR ptr; + LPMONITOR_INFO_2W mi; + WCHAR buffer[MAX_PATH]; + WCHAR dllname[MAX_PATH]; + DWORD dllsize; + DWORD len; + DWORD index = 0; + DWORD needed = 0; + DWORD numentries; + DWORD entrysize; + + entrysize = (level == 1) ? sizeof(MONITOR_INFO_1W) : sizeof(MONITOR_INFO_2W); + + numentries = *lpreturned; /* this is 0, when we scan the registry */ + len = entrysize * numentries; + ptr = (LPWSTR) &pMonitors[len]; + + numentries = 0; + len = sizeof(buffer)/sizeof(buffer[0]); + buffer[0] = '\0'; + + /* Windows creates the "Monitors"-Key on reboot / start "spooler" */ + if (RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) == ERROR_SUCCESS) { + /* Scan all Monitor-Registry-Keys */ + while (RegEnumKeyExW(hroot, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { + TRACE("Monitor_%d: %s\n", numentries, debugstr_w(buffer)); + dllsize = sizeof(dllname); + dllname[0] = '\0'; + + /* The Monitor 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 Monitor. */ + TRACE("using Driver: %s\n", debugstr_w(dllname)); + } + RegCloseKey(hentry); + } + + /* Windows returns only Port-Monitors here, but to simplify our code, + we do no filtering for Language-Monitors */ + if (dllname[0]) { + numentries++; + needed += entrysize; + needed += (len+1) * sizeof(WCHAR); /* len is lstrlenW(monitorname) */ + if (level > 1) { + /* we install and return only monitors for "Windows NT x86" */ + needed += (lstrlenW(x86_envnameW) +1) * sizeof(WCHAR); + needed += dllsize; + } + + /* required size is calculated. Now fill the user-buffer */ + if (pMonitors && (cbBuf >= needed)){ + mi = (LPMONITOR_INFO_2W) pMonitors; + pMonitors += entrysize; + + TRACE("%p: writing MONITOR_INFO_%dW #%d\n", mi, level, numentries); + mi->pName = ptr; + lstrcpyW(ptr, buffer); /* Name of the Monitor */ + ptr += (len+1); /* len is lstrlenW(monitorname) */ + if (level > 1) { + mi->pEnvironment = ptr; + lstrcpyW(ptr, x86_envnameW); /* fixed to "Windows NT x86" */ + ptr += (lstrlenW(x86_envnameW)+1); + + mi->pDLLName = ptr; + lstrcpyW(ptr, dllname); /* Name of the Driver-DLL */ + ptr += (dllsize / sizeof(WCHAR)); + } + } + } + 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; +} + +/***************************************************************************** * open_driver_reg [internal] * * opens the registry for the printer drivers depending on the given input @@ -583,6 +697,73 @@ static BOOL WINAPI fpAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDrive return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE); }
+/***************************************************************************** + * fpEnumMonitors [exported through PRINTPROVIDOR] + * + * Enumerate available Port-Monitors + * + * PARAMS + * pName [I] Servername or NULL (local Computer) + * Level [I] Structure-Level (1:Win9x+NT or 2:NT only) + * pMonitors [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 pMonitors + * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors + * + * RETURNS + * Success: TRUE + * Failure: FALSE and in pcbNeeded the Bytes required for buffer, if cbBuf is too small + * + * NOTES + * Windows reads the Registry once and cache the Results. + * + */ +BOOL WINAPI fpEnumMonitors(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf, + LPDWORD pcbNeeded, LPDWORD pcReturned) +{ + DWORD numentries = 0; + DWORD needed = 0; + LONG lres; + BOOL res = FALSE; + + TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors, + 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 em_cleanup; + } + + /* Scan all Monitor-Keys */ + numentries = 0; + needed = get_local_monitors(Level, NULL, 0, &numentries); + + /* we calculated the needed buffersize. now do more error-checks */ + if (cbBuf < needed) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + goto em_cleanup; + } + else if (!pMonitors || !pcReturned) { + SetLastError(RPC_X_NULL_REF_POINTER); + goto em_cleanup; + } + + /* fill the Buffer with the Monitor-Keys */ + needed = get_local_monitors(Level, pMonitors, cbBuf, &numentries); + res = TRUE; + +em_cleanup: + 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); +} + /***************************************************** * get_backend [internal] */ @@ -626,7 +807,7 @@ static const PRINTPROVIDOR * get_backend(void) NULL, /* fpGetForm */ NULL, /* fpSetForm */ NULL, /* fpEnumForms */ - NULL, /* fpEnumMonitors */ + fpEnumMonitors, NULL, /* fpEnumPorts */ NULL, /* fpAddPort */ NULL, /* fpConfigurePort */