https://git.reactos.org/?p=reactos.git;a=commitdiff;h=17154c94c1acfedef9ad801e48ad775c92966e51

commit 17154c94c1acfedef9ad801e48ad775c92966e51
Author:     Stanislav Motylkov <[email protected]>
AuthorDate: Mon May 23 23:54:41 2022 +0300
Commit:     Stanislav Motylkov <[email protected]>
CommitDate: Mon May 23 23:54:41 2022 +0300

    [DESKMON] Implement GetMonitorDevInstID function
    
    - Now our deskmon.cpl extension works on Windows XP and 2003
      and does open the monitor device properties correctly.
    - Also "Properties" button should be disabled
      when no Device Instance ID found for the monitor.
---
 dll/shellext/deskmon/CMakeLists.txt |   2 +-
 dll/shellext/deskmon/deskmon.c      | 144 ++++++++++++++++++++++++++++++++++--
 2 files changed, 139 insertions(+), 7 deletions(-)

diff --git a/dll/shellext/deskmon/CMakeLists.txt 
b/dll/shellext/deskmon/CMakeLists.txt
index d01e2e09870..2f85372577b 100644
--- a/dll/shellext/deskmon/CMakeLists.txt
+++ b/dll/shellext/deskmon/CMakeLists.txt
@@ -15,6 +15,6 @@ add_library(deskmon MODULE
 
 set_module_type(deskmon win32dll UNICODE)
 target_link_libraries(deskmon uuid)
-add_importlibs(deskmon user32 gdi32 comctl32 ole32 msvcrt kernel32 ntdll)
+add_importlibs(deskmon user32 gdi32 comctl32 ole32 setupapi msvcrt kernel32 
ntdll)
 add_pch(deskmon precomp.h SOURCE)
 add_cd_file(TARGET deskmon DESTINATION reactos/system32 FOR all)
diff --git a/dll/shellext/deskmon/deskmon.c b/dll/shellext/deskmon/deskmon.c
index 16bdd2372e4..21551a6ceb5 100644
--- a/dll/shellext/deskmon/deskmon.c
+++ b/dll/shellext/deskmon/deskmon.c
@@ -1,6 +1,8 @@
 #include "precomp.h"
 
 #include <tchar.h>
+#include <winreg.h>
+#include <cfgmgr32.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -8,6 +10,8 @@
 #include "resource.h"
 
 static HINSTANCE hInstance;
+static BOOL bFoundAdapter;
+static DEVINST diAdapter;
 
 #ifdef UNICODE
 typedef INT_PTR (WINAPI *PDEVICEPROPERTIES)(HWND,LPCWSTR,LPCWSTR,BOOL);
@@ -17,11 +21,115 @@ typedef INT_PTR (WINAPI 
*PDEVICEPROPERTIES)(HWND,LPCSTR,LPCSTR,BOOL);
 #define FUNC_DEVICEPROPERTIES "DevicePropertiesA"
 #endif
 
+/**
+ * @brief
+ * Converts a Hardware ID (DeviceID from EnumDisplayDevices)
+ * to an unique Device Instance ID.
+ *
+ * @param[in] lpDeviceID
+ * A pointer to a null-terminated string
+ * containing a Hardware ID concatenated with driver key.
+ * e.g. "Monitor\Default_Monitor\{4D36E96E-E325-11CE-BFC1-08002BE10318}\0000"
+ *
+ * @return
+ * A pointer to a null-terminated string
+ * containing an unique Device Instance ID
+ * or NULL in case of error.
+ * e.g. "DISPLAY\DEFAULT_MONITOR\4&2ABFAA30&0&00000001&00&02"
+ *
+ * @remarks
+ * The caller must free the returned string with LocalFree.
+ */
 static LPTSTR
 GetMonitorDevInstID(LPCTSTR lpDeviceID)
 {
-    /* FIXME: Implement, allocate returned string with LocalAlloc! */
-    return NULL;
+    CONFIGRET cr;
+    DEVINST diChild;
+    TCHAR szProperty[256];
+    DWORD dwSize;
+    LPTSTR lpDevInstId = NULL;
+
+    if (!bFoundAdapter)
+        return NULL;
+
+    /* Look for child monitor devices of selected video adapter */
+    cr = CM_Get_Child(&diChild, diAdapter, 0);
+    if (cr != CR_SUCCESS)
+    {
+        DPRINT1("CM_Get_Child failed: %d\n", cr);
+        return NULL;
+    }
+
+    do
+    {
+        /* Get Hardware ID for each of them */
+        dwSize = sizeof(szProperty) - sizeof(TCHAR);
+
+        cr = CM_Get_DevNode_Registry_Property(diChild,
+                                              CM_DRP_HARDWAREID,
+                                              NULL,
+                                              szProperty,
+                                              &dwSize,
+                                              0);
+        if (cr != CR_SUCCESS)
+        {
+            DPRINT1("CM_Get_DevNode_Registry_Property failed: %d\n", cr);
+            continue;
+        }
+
+        /* Concatenate with driver key */
+        _tcscat(szProperty, TEXT("\\"));
+        dwSize = sizeof(szProperty) - sizeof(TCHAR);
+        dwSize -= _tcslen(szProperty) * sizeof(TCHAR);
+
+        cr = CM_Get_DevNode_Registry_Property(diChild,
+                                              CM_DRP_DRIVER,
+                                              NULL,
+                                              szProperty + _tcslen(szProperty),
+                                              &dwSize,
+                                              0);
+        if (cr != CR_SUCCESS)
+        {
+            DPRINT1("CM_Get_DevNode_Registry_Property failed: %d\n", cr);
+            continue;
+        }
+
+        /* If the strings match, this is our monitor device node */
+        if (_tcscmp(szProperty, lpDeviceID) == 0)
+        {
+            cr = CM_Get_Device_ID_Size(&dwSize,
+                                       diChild,
+                                       0);
+            if (cr != CR_SUCCESS)
+            {
+                DPRINT1("CM_Get_Device_ID_Size failed: %d\n", cr);
+                break;
+            }
+
+            lpDevInstId = LocalAlloc(LMEM_FIXED,
+                                     (dwSize + 1) * sizeof(TCHAR));
+            if (lpDevInstId == NULL)
+            {
+                DPRINT1("LocalAlloc failed\n");
+                break;
+            }
+
+            cr = CM_Get_Device_ID(diChild,
+                                  lpDevInstId,
+                                  dwSize + 1,
+                                  0);
+            if (cr != CR_SUCCESS)
+            {
+                DPRINT1("CM_Get_Device_ID failed: %d\n", cr);
+                LocalFree((HLOCAL)lpDevInstId);
+                lpDevInstId = NULL;
+            }
+
+            break;
+        }
+    } while (CM_Get_Sibling(&diChild, diChild, 0) == CR_SUCCESS);
+
+    return lpDevInstId;
 }
 
 static VOID
@@ -44,9 +152,9 @@ ShowMonitorProperties(PDESKMONITOR This)
                 if (pDeviceProperties != NULL)
                 {
                     pDeviceProperties(This->hwndDlg,
-                                       NULL,
-                                       This->SelMonitor->dd.DeviceID,
-                                       FALSE);
+                                      NULL,
+                                      lpDevInstID,
+                                      FALSE);
                 }
 
                 FreeLibrary(hDevMgr);
@@ -61,6 +169,7 @@ static VOID
 UpdateMonitorSelection(PDESKMONITOR This)
 {
     INT i;
+    LPTSTR lpDevInstID = NULL;
 
     if (This->dwMonitorCount > 1)
     {
@@ -83,9 +192,15 @@ UpdateMonitorSelection(PDESKMONITOR This)
     else
         This->SelMonitor = This->Monitors;
 
+    if (This->SelMonitor != NULL)
+        lpDevInstID = GetMonitorDevInstID(This->SelMonitor->dd.DeviceID);
+
     EnableWindow(GetDlgItem(This->hwndDlg,
                             IDC_MONITORPROPERTIES),
-                 This->SelMonitor != NULL);
+                 lpDevInstID != NULL && lpDevInstID[0] != TEXT('\0'));
+
+    if (lpDevInstID != NULL)
+        LocalFree((HLOCAL)lpDevInstID);
 }
 
 static VOID
@@ -230,6 +345,8 @@ static VOID
 InitMonitorDialog(PDESKMONITOR This)
 {
     PDESKMONINFO pmi, pminext, *pmilink;
+    LPTSTR lpDeviceId;
+    CONFIGRET cr;
     DISPLAY_DEVICE dd;
     BOOL bRet;
     INT i;
@@ -248,6 +365,21 @@ InitMonitorDialog(PDESKMONITOR This)
     This->SelMonitor = NULL;
     This->dwMonitorCount = 0;
 
+    bFoundAdapter = FALSE;
+    lpDeviceId = QueryDeskCplString(This->pdtobj,
+                                    
RegisterClipboardFormat(DESK_EXT_DISPLAYID));
+
+    if (lpDeviceId != NULL && lpDeviceId[0] != TEXT('\0'))
+    {
+        cr = CM_Locate_DevNode(&diAdapter,
+                               lpDeviceId,
+                               CM_LOCATE_DEVNODE_NORMAL);
+        bFoundAdapter = (cr == CR_SUCCESS);
+
+        if (!bFoundAdapter)
+            DPRINT1("CM_Locate_DevNode failed: %d\n", cr);
+    }
+
     if (This->lpDisplayDevice != NULL)
         LocalFree((HLOCAL)This->lpDisplayDevice);
 

Reply via email to