Detlef Riekenberg : localspl: Implement fpEnumMonitors.

Alexandre Julliard julliard at winehq.org
Wed Jul 2 06:03:43 CDT 2008


Module: wine
Branch: master
Commit: 2f08621d6217b93ab5cb2334588baa7f01a0d7a6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2f08621d6217b93ab5cb2334588baa7f01a0d7a6

Author: Detlef Riekenberg <wine.dev at 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 */




More information about the wine-cvs mailing list