https://git.reactos.org/?p=reactos.git;a=commitdiff;h=17154c94c1acfedef9ad8…
commit 17154c94c1acfedef9ad801e48ad775c92966e51
Author: Stanislav Motylkov <x86corez(a)gmail.com>
AuthorDate: Mon May 23 23:54:41 2022 +0300
Commit: Stanislav Motylkov <x86corez(a)gmail.com>
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);