MattyD Posted August 29 Share Posted August 29 (edited) Hi folks, Attached below is one way of attacking WinRT Objects. These are essentially COM objects, however they don't have an IDispatch interface so ObjCreate() cannot be used. It is possible to expose them using ObjCreateInterface though. Alternately, DllCallAddress() may be used to access an object's functions directly from memory. I'm using the latter mainly because that's the path I started down first! To make sense of whats in the attachment... WinRTCore,au3 - Internal helper functions for interface libraries Iblah.au3 - Interface libraries. Essentially these wrap the functions in an interface's vtable Includes tags which may be used with ObjCreateInterface (these are largely untested though!) Includes enum definitions that relate to the interface WinRT.au3 - Core high level functions that sit on top of interface libraries Includes Async and Collection implementations etc. So basic high level functionality. WinRT_blah.au3 - High level functions that sit on top of interface libraries Ok I may have over-engineered this a bit... I'm unsure if its the best appproach, but its something to go off for the next WinRT object that I'll need to attack Original post: Spoiler Hi folks, So long story short - with Win11 starting to ignore a display's EDID, I was looking for a way to get to a displays displayID block. I'm nowhere close to achieving this yet, but have made some inroads. Basically it seems I need to get to this: https://learn.microsoft.com/en-us/uwp/api/windows.devices.display.displaymonitor.getdescriptor?view=winrt-26100 - And that brings us to WinRT. So we're basically dealing with COM objects without an iDispatch interface. This is unhelpful for us as it effectively takes away use of AutoIt's Object datatype. But fun fact - If we know how an object is structured in memory, it seems we can access its methods via the DllCallAddress() function. This is space that I'm currently stumbling around in. I'm not going to pretend I'm an expert in this - but here's a starting point if its useful to anyone And of course happy to talk more detail about whats going on, but be prepared some text walls! expandcollapse popup#AutoIt3Wrapper_UseX64=Y #include <winapi.au3> #include <array.au3> ; Reqires at least Win8 - Tested on Win 11 23H2 ; This demo is not robust at all, there is pitiful error checking!! ; Com error code reference: ; https://learn.microsoft.com/en-us/windows/win32/com/com-error-codes-1 Global $hDLLComBase = DllOpen("Combase.dll") Global Const $PTR_LEN = @AutoItX64 ? 8 : 4 Global Const $sIUnknown = "{00000000-0000-0000-C000-000000000046}" Global Const $sIInspectable = "{AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90}" Global Const $sIActivationFactory = "{00000035-0000-0000-C000-000000000046}" Global Const $sIDisplayMonitorStatics = "{6EAE698F-A228-4C05-821D-B695D667DE8E}" ; We can request a pointer to a different interface, but I've started at the beginning Local $pObject = RoGetActivationFactory("Windows.Devices.Display.DisplayMonitor", $sIUnknown) ; QueryInterface should set @error if the interface is not supported. ConsoleWrite("IUnknown::QueryInterface failure test:" & @CRLF) Local $pDummy = IUnknown_QueryInterface($pObject, "{00000000-0000-0000-0000-000000000000}") If @error Then DispError() ; @errror should be E_NOINTERFACE. ConsoleWrite(@CRLF) ; Worked my way through the other IUnknown functions.. ; The reference count should increment and decrement ConsoleWrite("IUnknown::AddRef and IUnknown::RemoveRef test:" & @CRLF) For $i = 1 To 5 ConsoleWrite("RefCount: " & IUnknown_AddRef($pObject) & @CRLF) Next For $i = 1 To 5 ConsoleWrite("RefCount: " & IUnknown_RemoveRef($pObject) & @CRLF) Next ConsoleWrite(@CRLF) ; We can see what Interfaces are available via IInspectable ; Its a WinRT object, so IInspectable definately should exist! Local $pIInspectable = IUnknown_QueryInterface($pObject, $sIInspectable) Local $aIIDs = IInspectable_GetIids($pIInspectable) ; I find IActivationFactory and IDisplayMonitorStatics on my system. ; OLE View also shows me {9B0AFA0D-CF76-4FEA-BDC5-88F6DD7A6986}. No idea what this is or where it comes from??? ConsoleWrite("IInspectable::GetIids test: " & @CRLF) ConsoleWrite("Retrieve supported interfaces of the object - (excluding IUnknown & IInspectable)" & @CRLF) For $i = 0 To UBound($aIIDs) - 1 ConsoleWrite(" " & $aIIDs[$i] & @CRLF) Next ConsoleWrite(@CRLF) ; We're on a factory interface - so no suprise that this fails (works as documented). ConsoleWrite("IInspectable::GetRuntimeClassName failure test:" & @CRLF) $sClassName = IInspectable_GetRuntimeClassName($pIInspectable) If @error Then DispError() ; @errror should be E_ILLEGAL_METHOD_CALL. ConsoleWrite(@CRLF) ; IUnknown and IIspectable by and large seem to work - So I next attack ActivationFactory ConsoleWrite("IActivationFactory::ActivateInstance test:" & @CRLF) ; Get the correct interface $pActFactory = IUnknown_QueryInterface($pObject, $sIActivationFactory) Local $pInst = IActivationFactory_ActivateInstance($pActFactory) If @error Then DispError() ; I Get E_NOTIMPL. I guess thats all we can do for now unless I've stuffed up the function. ; Could also RoGetActivationFactory be doing something here?? - anyway I don't really know what I'm doing, so moving on... ; On to IDisplayMonitorStatics. This presumably inherits from IInspectable. ; From what I can gather I should be able to these funcs to enum monitors. ; Doco is hard to find, but OLE View has this... ;~ [Guid("6eae698f-a228-4c05-821d-b695d667de8e")] ;~ interface IDisplayMonitorStatics ;~ { ;~ /* Methods */ ;~ string GetDeviceSelector(); ;~ IAsyncOperation`1 FromIdAsync(string deviceId); ;~ IAsyncOperation`1 FromInterfaceIdAsync(string deviceInterfaceId); ;~ } ConsoleWrite(@CRLF & "IDisplayMonitorStatics test:" & @CRLF) $pDispMonStatics = IUnknown_QueryInterface($pObject, $sIDisplayMonitorStatics) ; Not sure if OLEView is wrong, most likely I'm missing something! ; But the GetDeviceSelector func seems to output the HString via a parameter - its not the return value $sSelector = IDisplayMonitorStatics_GetDeviceSelector($pDispMonStatics) ConsoleWrite($sSelector & @CRLF) ;Should output a AQS string ConsoleWrite(@CRLF) ; Thats all I've got for now! ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func IUnknown_QueryInterface($pThis, $sIID) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt($pVTable) Local $tIID = CreateGUID($sIID) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "struct*", $tIID, "ptr*", 0) Return SetError($aRet[0], 0, $aRet[3]) EndFunc ;==>IUnknown_QueryInterface Func IUnknown_AddRef($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis) Return $aRet[0] EndFunc ;==>IUnknown_AddRef Func IUnknown_RemoveRef($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 2 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis) Return $aRet[0] EndFunc ;==>IUnknown_RemoveRef Func IInspectable_GetIids($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 3 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "long*", 0, "ptr*", 0) Local $iCount = $aRet[2], $asIIDs[2] For $i = 0 To $iCount - 1 $asIIDs[$i] = ReadGUIDAt(Ptr($aRet[3] + ($i * 16))) Next CoTaskMemFree($aRet[3]) Return SetError($aRet[0], 0, $asIIDs) EndFunc ;==>IInspectable_GetIids Func IInspectable_GetRuntimeClassName($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 4 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "handle*", 0) Local $sClassName = ReadHString($aRet[2]) DeleteHString($aRet[2]) Return SetError($aRet[0], 0, $sClassName) EndFunc ;==>IInspectable_GetRuntimeClassName Func IInspectable_GetTrustLevel($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 5 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "int*", 0) Return SetError($aRet[0], 0, $aRet[2]) EndFunc ;==>IInspectable_GetTrustLevel Func IActivationFactory_ActivateInstance($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Return SetError($aRet[0], 0, $aRet[2]) EndFunc ;==>IActivationFactory_ActivateInstance Func IDisplayMonitorStatics_GetDeviceSelector($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0, "ptr*", 0) Local $sSelector = ReadHString($aRet[2]) DeleteHString($aRet[2]) Return SetError($aRet[0], 0, $sSelector) EndFunc ;==>IDisplayMonitorStatics_GetDeviceSelector Func DispError($iError = @error) Local Const $iMaxWidth = 0xFF Local $iFlags = $FORMAT_MESSAGE_FROM_SYSTEM Local $tBuff = DllStructCreate(StringFormat("wchar[%d]", $iMaxWidth)) Local $pBuff = DllStructGetPtr($tBuff) Local $iCount = _WinAPI_FormatMessage($iFlags, 0, $iError, 0, $pBuff, $iMaxWidth, 0) ConsoleWrite("[0x" & Hex($iError) & "] " & StringStripWS(DllStructGetData($tBuff, 1), 3) & @CRLF) EndFunc ;==>DispError Func RoGetActivationFactory($sClassID, $sIID) Local $hsClassID = CreateHString($sClassID) Local $tIID = CreateGUID($sIID) Local $aRes = DllCall($hDLLComBase, "long", "RoGetActivationFactory", "handle", $hsClassID, "ptr", DllStructGetPtr($tIID), "ptr*", 0) DeleteHString($hsClassID) Return $aRes[3] EndFunc ;==>RoGetActivationFactory Func CreateHString($sString) Local $aRes = DllCall($hDLLComBase, "int", "WindowsCreateString", "wstr", $sString, "uint", StringLen($sString), "ptr*", 0) If Not @error Then Return $aRes[3] EndFunc ;==>CreateHString Func DeleteHString(ByRef $hString) Local $aRes = DllCall($hDLLComBase, "int", "WindowsDeleteString", "ptr", $hString) If Not @error Then $hString = 0 EndFunc ;==>DeleteHString Func ReadHString(ByRef $hString) Local $aRes = DllCall($hDLLComBase, "wstr", "WindowsGetStringRawBuffer", "ptr", $hString, "int*", 0) If Not @error Then Return $aRes[0] EndFunc ;==>ReadHString Func CreateGUID($sGUID) Local $tGUID = DllStructCreate($tagGUID) $aGUID = StringSplit(StringRegExpReplace($sGUID, "[{}]", ""), "-", 2) If UBound($aGUID) <> 5 Then Return False $tGUID.Data1 = Dec($aGUID[0]) $tGUID.Data2 = Dec($aGUID[1]) $tGUID.Data3 = Dec($aGUID[2]) $tGUID.Data4 = Binary("0x" & $aGUID[3] & $aGUID[4]) Return $tGUID EndFunc ;==>CreateGUID Func ReadGUIDAt($pGUID) Local $tGUID = DllStructCreate($tagGUID, $pGUID) Local $sGUID = "{" $sGUID &= Hex($tGUID.Data1, 8) & "-" $sGUID &= Hex($tGUID.Data2, 4) & "-" $sGUID &= Hex($tGUID.Data3, 4) & "-" $sGUID &= StringMid($tGUID.Data4, 3, 4) & "-" $sGUID &= StringMid($tGUID.Data4, 7, 12) & "}" Return $sGUID EndFunc ;==>ReadGUIDAt Func GetPtrAt($pPtr) Local $tPtr = DllStructCreate("ptr ptr", $pPtr) Return $tPtr.ptr EndFunc ;==>GetPtrAt Func CoTaskMemFree($pBlock) DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pBlock) EndFunc ;==>CoTaskMemFree WinRT_Demo_v1.zip Edited September 5 by MattyD argumentum 1 Link to comment Share on other sites More sharing options...
ahmet Posted August 29 Share Posted August 29 Does ObjaCreateInterface do something similar? Link to comment Share on other sites More sharing options...
MattyD Posted August 29 Author Share Posted August 29 Ah yes - I originally looked at that and decided it wasn't going to play.. But now I can make a bit more sense of the doco - and yeah, you're right - it'll probably work. Here's an IInspectable::GetIIds example with ObjCreateInterface. expandcollapse popup#include <winapi.au3> #include <array.au3> Global $hDLLComBase = DllOpen("Combase.dll") Global Const $sIUnknown = "{00000000-0000-0000-C000-000000000046}" Global Const $sIInspectable = "{AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90}" Local $tagIInspectabe = _ "GetIids hresult(ulong*; ptr*); " & _ "GetRuntimeClassName hresult(ptr*); " & _ "GetTrustLevel hresult(long*);" Local $pObject = RoGetActivationFactory("Windows.Devices.Display.DisplayMonitor", $sIUnknown) $oIInspectable = ObjCreateInterface($pObject, $sIInspectable, $tagIInspectabe, True) Local $iCount, $pIIDS $oIInspectable.GetIids($iCount, $pIIDS) Local $asIIDs[$iCount] For $i = 0 To $iCount - 1 $asIIDs[$i] = ReadGUIDAt(Ptr($pIIDS + ($i * 16))) Next CoTaskMemFree($pIIDS) _ArrayDisplay($asIIDs) ;;;;;;;;;;;;;;;;;;;;;;;;;; Func RoGetActivationFactory($sClassID, $sIID) Local $hsClassID = CreateHString($sClassID) Local $tIID = CreateGUID($sIID) Local $aRes = DllCall($hDLLComBase, "long", "RoGetActivationFactory", "handle", $hsClassID, "ptr", DllStructGetPtr($tIID), "ptr*", 0) DeleteHString($hsClassID) Return $aRes[3] EndFunc ;==>RoGetActivationFactory Func CreateHString($sString) Local $aRes = DllCall($hDLLComBase, "int", "WindowsCreateString", "wstr", $sString, "uint", StringLen($sString), "ptr*", 0) If Not @error Then Return $aRes[3] EndFunc ;==>CreateHString Func DeleteHString(ByRef $hString) Local $aRes = DllCall($hDLLComBase, "int", "WindowsDeleteString", "ptr", $hString) If Not @error Then $hString = 0 EndFunc ;==>DeleteHString Func ReadHString(ByRef $hString) Local $aRes = DllCall($hDLLComBase, "wstr", "WindowsGetStringRawBuffer", "ptr", $hString, "int*", 0) If Not @error Then Return $aRes[0] EndFunc ;==>ReadHString Func CreateGUID($sGUID) Local $tGUID = DllStructCreate($tagGUID) $aGUID = StringSplit(StringRegExpReplace($sGUID, "[{}]", ""), "-", 2) If UBound($aGUID) <> 5 Then Return False $tGUID.Data1 = Dec($aGUID[0]) $tGUID.Data2 = Dec($aGUID[1]) $tGUID.Data3 = Dec($aGUID[2]) $tGUID.Data4 = Binary("0x" & $aGUID[3] & $aGUID[4]) Return $tGUID EndFunc ;==>CreateGUID Func ReadGUIDAt($pGUID) Local $tGUID = DllStructCreate($tagGUID, $pGUID) Local $sGUID = "{" $sGUID &= Hex($tGUID.Data1, 8) & "-" $sGUID &= Hex($tGUID.Data2, 4) & "-" $sGUID &= Hex($tGUID.Data3, 4) & "-" $sGUID &= StringMid($tGUID.Data4, 3, 4) & "-" $sGUID &= StringMid($tGUID.Data4, 7, 12) & "}" Return $sGUID EndFunc ;==>ReadGUIDAt Func CoTaskMemFree($pBlock) DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pBlock) EndFunc ;==>CoTaskMemFree Link to comment Share on other sites More sharing options...
argumentum Posted August 29 Share Posted August 29 Func DispError($iError = @error, $iScriptLineNumber = @ScriptLineNumber) Local Const $iMaxWidth = 0xFF Local $iFlags = $FORMAT_MESSAGE_FROM_SYSTEM Local $tBuff = DllStructCreate(StringFormat("wchar[%d]", $iMaxWidth)) Local $pBuff = DllStructGetPtr($tBuff) Local $iCount = _WinAPI_FormatMessage($iFlags, 0, $iError, 0, $pBuff, $iMaxWidth, 0) ConsoleWrite('(' & $iScriptLineNumber & ",0) [0x" & Hex($iError) & "] " & StringStripWS(DllStructGetData($tBuff, 1), 3) & @CRLF) EndFunc ;==>DispError ..that way I can jump to the line in the script. Spoiler expandcollapse popup>"D:\Utilities\AutoIt3\SciTE\..\AutoIt3.exe" "D:\Utilities\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /run /prod /ErrorStdOut /in "D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt.au3" /UserParams +>11:52:28 Starting AutoIt3Wrapper (pid=37728) 23.402.1150.10 from:SciTE.exe (4.4.6.0) Keyboard:00000409 OS:WIN_11/2009 CPU:X64 OS:X64 Environment(Language:0409) CodePage:0 utf8.auto.check:4 +> SciTEDir => D:\Utilities\AutoIt3\SciTE UserDir => C:\Users\Tester\AppData\Local\AutoIt v3\SciTE\AutoIt3Wrapper SCITE_USERHOME => C:\Users\Tester\AppData\Local\AutoIt v3\SciTE >Running AU3Check (3.3.17.0) from:D:\Utilities\AutoIt3 input:D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt.au3 +>11:52:29 AU3Check ended. rc:0 >Running:(3.3.16.1):D:\Utilities\AutoIt3\autoit3_x64.exe "D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt.au3" +>Setting Hotkeys...--> Press Ctrl+Alt+Break to Restart. --> Press Ctrl+BREAK to Stop. IUnknown::QueryInterface failure test: (26,0) [0x80004002] No such interface supported IUnknown::AddRef and IUnknown::RemoveRef test: RefCount: 3 RefCount: 4 RefCount: 5 RefCount: 6 RefCount: 7 RefCount: 6 RefCount: 5 RefCount: 4 RefCount: 3 RefCount: 2 IInspectable::GetIids test: Retrieve supported interfaces of the object - (excluding IUnknown & IInspectable) {00000035-0000-0000-C000-000000000046} {6EAE698F-A228-4C05-821D-B695D667DE8E} IInspectable::GetRuntimeClassName failure test: (57,0) [0x8000000E] A method was called at an unexpected time. IActivationFactory::ActivateInstance test: (65,0) [0x80004001] Not implemented IDisplayMonitorStatics test: (System.Devices.InterfaceClassGuid:="{E6F07B5F-EE97-4a90-B076-33F57BF4EAA7}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True) OR System.Devices.ChallengeAep:=System.StructuredQueryType.Boolean#False > +>11:52:29 AutoIt3 ended. rc:0 +>11:52:29 AutoIt3Wrapper Finished. >Exit code: 0 Time: 1.28 and that is what I got ( in case this info is useful ) Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
MattyD Posted August 31 Author Share Posted August 31 Thanks mate, I didn't know you could do that with the line numbers in scite, that's quite handy - The output is also the same as what I see on my end. For anyone following along, I threw a it more time at this today and made a bit more progress. I think that I may have managed to populate a collection of displaymonitor objects. Gotta say that the Rust doco has been invaluable for deciphering those vtables. expandcollapse popup#AutoIt3Wrapper_UseX64=Y #Tidy_Parameters=/sf #include <winapi.au3> #include <array.au3> ; Com error code reference: ; https://learn.microsoft.com/en-us/windows/win32/com/com-error-codes-1 Global $hDLLComBase = DllOpen("Combase.dll") Global Const $PTR_LEN = @AutoItX64 ? 8 : 4 Global Const $sIUnknown = "{00000000-0000-0000-C000-000000000046}" Global Const $sIInspectable = "{AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90}" Global Const $sIActivationFactory = "{00000035-0000-0000-C000-000000000046}" Global Const $sIDisplayMonitorStatics = "{6EAE698F-A228-4C05-821D-B695D667DE8E}" Global Const $sIDeviceInformationStatics = "{C17F100E-3A46-4A78-8013-769DC9B97390}" Global Const $sIAsyncInfo = "{00000036-0000-0000-C000-000000000046}" Global Enum $ASync_Started = 0, $ASync_Completed, $ASync_Canceled, $ASync_Error ConsoleWrite("Get AQS String" & @CRLF) ConsoleWrite('Get "Windows.Devices.Display.DisplayMonitor" Activation Factory, IDisplayMonitorStatics' & @CRLF) $pMonStatics = RoGetActivationFactory("Windows.Devices.Display.DisplayMonitor", $sIDisplayMonitorStatics) DispError() ConsoleWrite("Call IDisplayMonitorStatics::GetDeviceSelector" & @CRLF) $sDevSelector = IDisplayMonitorStatics_GetDeviceSelector($pMonStatics) DispError() ConsoleWrite($sDevSelector & @CRLF) ConsoleWrite(@CRLF) ConsoleWrite("Get Device Collection:" & @CRLF) ConsoleWrite('Get "Windows.Devices.Enumeration.DeviceInformation" Activation Factory, IDeviceInformationStatics' & @CRLF) $pDevInfo = RoGetActivationFactory("Windows.Devices.Enumeration.DeviceInformation", $sIDeviceInformationStatics) DispError() ConsoleWrite("Call IDeviceInformationStatics::FindAllAsyncAqsFilter with AQS string that we aquired earlier" & @CRLF) $pAsync = IDeviceInformationStatics_FindAllAsyncAqsFilter($pDevInfo, $sDevSelector) DispError() ConsoleWrite("Wait for ASync routine..." & @CRLF) ConsoleWrite("Get AsyncInfo Interface:" & @CRLF) $pAsyncInfo = IUnknown_QueryInterface($pAsync, $sIAsyncInfo) DispError() Do Sleep(10) Until IASyncInfo_Status($pAsyncInfo) ConsoleWrite("Async Finished. We want the status to be 1 - i.e. 'completed':" & @CRLF) ConsoleWrite("Async status=" & IASyncInfo_Status($pAsyncInfo) & @CRLF) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func CoTaskMemFree($pBlock) DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pBlock) EndFunc ;==>CoTaskMemFree Func CreateGUID($sGUID) Local $tGUID = DllStructCreate($tagGUID) $aGUID = StringSplit(StringRegExpReplace($sGUID, "[{}]", ""), "-", 2) If UBound($aGUID) <> 5 Then Return False $tGUID.Data1 = Dec($aGUID[0]) $tGUID.Data2 = Dec($aGUID[1]) $tGUID.Data3 = Dec($aGUID[2]) $tGUID.Data4 = Binary("0x" & $aGUID[3] & $aGUID[4]) Return $tGUID EndFunc ;==>CreateGUID Func CreateHString($sString) Local $aRes = DllCall($hDLLComBase, "int", "WindowsCreateString", "wstr", $sString, "uint", StringLen($sString), "ptr*", 0) If Not @error Then Return $aRes[3] EndFunc ;==>CreateHString Func DeleteHString(ByRef $hString) Local $aRes = DllCall($hDLLComBase, "int", "WindowsDeleteString", "ptr", $hString) If Not @error Then $hString = 0 EndFunc ;==>DeleteHString Func DispError($iError = @error, $iScriptLineNumber = @ScriptLineNumber) Local Const $iMaxWidth = 0xFF Local $iFlags = $FORMAT_MESSAGE_FROM_SYSTEM Local $tBuff = DllStructCreate(StringFormat("wchar[%d]", $iMaxWidth)) Local $pBuff = DllStructGetPtr($tBuff) Local $iCount = _WinAPI_FormatMessage($iFlags, 0, $iError, 0, $pBuff, $iMaxWidth, 0) ConsoleWrite('(' & $iScriptLineNumber & ",0) [0x" & Hex($iError) & "] " & StringStripWS(DllStructGetData($tBuff, 1), 3) & @CRLF) EndFunc ;==>DispError Func GetPtrAt($pPtr) Local $tPtr = DllStructCreate("ptr ptr", $pPtr) Return $tPtr.ptr EndFunc ;==>GetPtrAt Func IActivationFactory_ActivateInstance($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Return SetError($aRet[0], 0, $aRet[2]) EndFunc ;==>IActivationFactory_ActivateInstance Func IASyncInfo_Cancel($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 9 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis) Return SetError($aRet[0]) EndFunc ;==>IASyncInfo_Cancel Func IASyncInfo_Close($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 10 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis) Return SetError($aRet[0]) EndFunc ;==>IASyncInfo_Close Func IASyncInfo_ErrorCode($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 8 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "long*", 0) Return SetError($aRet[0], 0, $aRet[2]) EndFunc ;==>IASyncInfo_ErrorCode Func IASyncInfo_ID($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "uint*", 0) Return SetError($aRet[0], 0, $aRet[2]) EndFunc ;==>IASyncInfo_ID Func IASyncInfo_Status($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 7 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "uint*", 0) Return SetError($aRet[0], 0, $aRet[2]) EndFunc ;==>IASyncInfo_Status Func IDeviceInformationStatics_FindAllAsyncAqsFilter($pThis, $sFilter) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 10 * $PTR_LEN)) Local $hsFilter = CreateHString($sFilter) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr", $hsFilter, "ptr*", 0) DeleteHString($hsFilter) Return SetError($aRet[0], 0, $aRet[3]) EndFunc ;==>IDeviceInformationStatics_FindAllAsyncAqsFilter Func IDisplayMonitorStatics_FromIdAsync($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 7 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0, "ptr*", 0) Local $sSelector = ReadHString($aRet[2]) DeleteHString($aRet[2]) Return SetError($aRet[0], 0, $sSelector) EndFunc ;==>IDisplayMonitorStatics_FromIdAsync Func IDisplayMonitorStatics_GetDeviceSelector($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Local $sSelector = ReadHString($aRet[2]) DeleteHString($aRet[2]) Return SetError($aRet[0], 0, $sSelector) EndFunc ;==>IDisplayMonitorStatics_GetDeviceSelector Func IInspectable_GetIids($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 3 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "long*", 0, "ptr*", 0) Local $iCount = $aRet[2], $asIIDs[$iCount] For $i = 0 To $iCount - 1 $asIIDs[$i] = ReadGUIDAt(Ptr($aRet[3] + ($i * 16))) Next CoTaskMemFree($aRet[3]) Return SetError($aRet[0], 0, $asIIDs) EndFunc ;==>IInspectable_GetIids Func IInspectable_GetRuntimeClassName($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 4 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "handle*", 0) Local $sClassName = ReadHString($aRet[2]) DeleteHString($aRet[2]) Return SetError($aRet[0], 0, $sClassName) EndFunc ;==>IInspectable_GetRuntimeClassName Func IInspectable_GetTrustLevel($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 5 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "int*", 0) Return SetError($aRet[0], 0, $aRet[2]) EndFunc ;==>IInspectable_GetTrustLevel Func IUnknown_AddRef($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis) Return $aRet[0] EndFunc ;==>IUnknown_AddRef Func IUnknown_QueryInterface($pThis, $sIID) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt($pVTable) Local $tIID = CreateGUID($sIID) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis, "struct*", $tIID, "ptr*", 0) Return SetError($aRet[0], 0, $aRet[3]) EndFunc ;==>IUnknown_QueryInterface Func IUnknown_RemoveRef($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 2 * $PTR_LEN)) Local $aRet = DllCallAddress("long", $pFunc, "ptr", $pThis) Return $aRet[0] EndFunc ;==>IUnknown_RemoveRef Func ReadGUIDAt($pGUID) Local $tGUID = DllStructCreate($tagGUID, $pGUID) Local $sGUID = "{" $sGUID &= Hex($tGUID.Data1, 8) & "-" $sGUID &= Hex($tGUID.Data2, 4) & "-" $sGUID &= Hex($tGUID.Data3, 4) & "-" $sGUID &= StringMid($tGUID.Data4, 3, 4) & "-" $sGUID &= StringMid($tGUID.Data4, 7, 12) & "}" Return $sGUID EndFunc ;==>ReadGUIDAt Func ReadHString(ByRef $hString) Local $aRes = DllCall($hDLLComBase, "wstr", "WindowsGetStringRawBuffer", "ptr", $hString, "int*", 0) If Not @error Then Return $aRes[0] EndFunc ;==>ReadHString Func RoActivateInstance($sClassID) $hsClassID = CreateHString($sClassID) Local $aRes = DllCall($hDLLComBase, "long", "RoActivateInstance", "handle", $hsClassID, "ptr*", 0) DeleteHString($hsClassID) Return SetError($aRes[0], 0, $aRes[2]) EndFunc ;==>RoActivateInstance Func RoGetActivationFactory($sClassID, $sIID) Local $hsClassID = CreateHString($sClassID) Local $tIID = CreateGUID($sIID) Local $aRes = DllCall($hDLLComBase, "long", "RoGetActivationFactory", "handle", $hsClassID, "ptr", DllStructGetPtr($tIID), "ptr*", 0) DeleteHString($hsClassID) Return SetError($aRes[0], 0, $aRes[3]) EndFunc ;==>RoGetActivationFactory argumentum and Danyfirex 2 Link to comment Share on other sites More sharing options...
argumentum Posted August 31 Share Posted August 31 (edited) SleepOnTimer(0, 0) ; init. the timer Do If Not SleepOnTimer(10, 5000) Then ExitLoop ; if time longer than expected, exit the loop Until IASyncInfo_Status($pAsyncInfo) ConsoleWrite("Async Finished. We want the status to be 1 - i.e. 'completed':" & @CRLF) ConsoleWrite("Async status=" & IASyncInfo_Status($pAsyncInfo) & @CRLF) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func SleepOnTimer($iSleepMs, $iTimeoutMs) Local Static $hTimer = TimerInit() If Not $iTimeoutMs Then $hTimer = TimerInit() ; init / reset to now Return 0 EndIf Sleep($iSleepMs) If TimerDiff($hTimer) > $iTimeoutMs Then Return SetError(1, TimerDiff($hTimer), 0) Return TimerDiff($hTimer) EndFunc Since I don't know much but this may take a long time in WinXP or some other failure, I thought that the SleepOnTimer() would be a good idea. We are waiting anyway, might as well give it some safety. And my report of the console: Spoiler >"D:\Utilities\AutoIt3\SciTE\..\AutoIt3.exe" "D:\Utilities\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /run /prod /ErrorStdOut /in "D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt_v3.au3" /UserParams +>12:20:44 Starting AutoIt3Wrapper (pid=37900) 23.402.1150.10 from:SciTE.exe (4.4.6.0) Keyboard:00000409 OS:WIN_11/2009 CPU:X64 OS:X64 Environment(Language:0409) CodePage:0 utf8.auto.check:4 +> SciTEDir => D:\Utilities\AutoIt3\SciTE UserDir => C:\Users\Tester\AppData\Local\AutoIt v3\SciTE\AutoIt3Wrapper SCITE_USERHOME => C:\Users\Tester\AppData\Local\AutoIt v3\SciTE >Running AU3Check (3.3.17.0) from:D:\Utilities\AutoIt3 input:D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt_v3.au3 +>12:20:44 AU3Check ended. rc:0 >Running:(3.3.16.1):D:\Utilities\AutoIt3\autoit3_x64.exe "D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt_v3.au3" +>Setting Hotkeys...--> Press Ctrl+Alt+Break to Restart. --> Press Ctrl+BREAK to Stop. Get AQS String Get "Windows.Devices.Display.DisplayMonitor" Activation Factory, IDisplayMonitorStatics (25,0) [0x00000000] The operation completed successfully. Call IDisplayMonitorStatics::GetDeviceSelector (28,0) [0x00000000] The operation completed successfully. (System.Devices.InterfaceClassGuid:="{E6F07B5F-EE97-4a90-B076-33F57BF4EAA7}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True) OR System.Devices.ChallengeAep:=System.StructuredQueryType.Boolean#False Get Device Collection: Get "Windows.Devices.Enumeration.DeviceInformation" Activation Factory, IDeviceInformationStatics (35,0) [0x00000000] The operation completed successfully. Call IDeviceInformationStatics::FindAllAsyncAqsFilter with AQS string that we aquired earlier (38,0) [0x00000000] The operation completed successfully. Wait for ASync routine... Get AsyncInfo Interface: (42,0) [0x00000000] The operation completed successfully. Async Finished. We want the status to be 1 - i.e. 'completed': Async status=1 > +>12:20:44 AutoIt3 ended. rc:0 +>12:20:44 AutoIt3Wrapper Finished. >Exit code: 0 Time: 1.371 Do let me know if these console output are welcomed/useful to this project, otherwise am spamming the thread Edited August 31 by argumentum clarify Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
MattyD Posted September 2 Author Share Posted September 2 Yep absolutely agree. Resource management and error handling had already gone out the window, so I decided the slap-dash approach was good enough for a demo! I'll have a proper run at putting something together soon and report back. Think I'm starting to get a handle on things too, so shouldn't need that console output. But thanks, I did appreciate the support Lastly, I finally managed to pull those descriptor blobs! Well the EDID of my screen anyway.The DisplayID block - if present - needs to be a particular version for windows to use it, so I guess it's not surprising that mine doesn't show. expandcollapse popup#AutoIt3Wrapper_UseX64=Y #Tidy_Parameters=/sf #include <winapi.au3> #include <array.au3> ; Com error code reference: ; https://learn.microsoft.com/en-us/windows/win32/com/com-error-codes-1 Global $hDLLComBase = DllOpen("Combase.dll") Global Const $PTR_LEN = @AutoItX64 ? 8 : 4 Global Const $sIUnknown = "{00000000-0000-0000-C000-000000000046}" Global Const $sIInspectable = "{AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90}" Global Const $sIActivationFactory = "{00000035-0000-0000-C000-000000000046}" Global Const $sIDisplayMonitorStatics = "{6EAE698F-A228-4C05-821D-B695D667DE8E}" Global Const $sIDeviceInformationStatics = "{C17F100E-3A46-4A78-8013-769DC9B97390}" Global Const $sIAsyncInfo = "{00000036-0000-0000-C000-000000000046}" Global Const $sIDeviceInformation = "{ABA0FB95-4398-489D-8E44-E6130927011F}" Global Const $sIDisplayMonitor = "{1f6b15d4-1d01-4c51-87e2-6f954a772b59}" Global Enum $Async_Started = 0, $Async_Completed, $Async_Canceled, $Async_Error ConsoleWrite("Get AQS String" & @CRLF) ConsoleWrite('Get "Windows.Devices.Display.DisplayMonitor" Activation Factory, IDisplayMonitorStatics' & @CRLF) $pMonStatics = RoGetActivationFactory("Windows.Devices.Display.DisplayMonitor", $sIDisplayMonitorStatics) DispError() ConsoleWrite("Call IDisplayMonitorStatics::GetDeviceSelector" & @CRLF) $sDevSelector = IDisplayMonitorStatics_GetDeviceSelector($pMonStatics) DispError() ConsoleWrite($sDevSelector & @CRLF) ConsoleWrite(@CRLF) ConsoleWrite("Get Device Collection:" & @CRLF) ConsoleWrite('Get "Windows.Devices.Enumeration.DeviceInformation" Activation Factory, IDeviceInformationStatics' & @CRLF) $pDevInfoFact = RoGetActivationFactory("Windows.Devices.Enumeration.DeviceInformation", $sIDeviceInformationStatics) DispError() ConsoleWrite("Call IDeviceInformationStatics::FindAllAsyncAqsFilter with AQS string that we aquired earlier" & @CRLF) $pAsync = IDeviceInformationStatics_FindAllAsyncAqsFilter($pDevInfoFact, $sDevSelector) DispError() ConsoleWrite("Wait for Async routine..." & @CRLF) ConsoleWrite("Get AsyncInfo Interface:" & @CRLF) $pAsyncInfo = IUnknown_QueryInterface($pAsync, $sIAsyncInfo) DispError() Do Sleep(10) Until IAsyncInfo_Status($pAsyncInfo) ConsoleWrite("Async Finished. We want the status to be 1 - i.e. 'completed':" & @CRLF) ConsoleWrite("Async status=" & IAsyncInfo_Status($pAsyncInfo) & @CRLF) ConsoleWrite("GetResult of Async:" & @CRLF) $pDevInfoCol = IAsyncOperation_GetResults($pAsync) DispError() ConsoleWrite("Collection size=" & IVectorView_Size($pDevInfoCol) & @CRLF) ConsoleWrite(@CRLF) ConsoleWrite("Get First DisplayMonitor Obj" & @CRLF) ConsoleWrite("Get the fisrt item of our collection:" & @CRLF) $pDevinfo = IVectorView_GetAt($pDevInfoCol, 0) DispError() ConsoleWrite("Get the name:" & @CRLF) $sDevName = IDeviceInformation_Name($pDevinfo) DispError() ConsoleWrite("Device Name = " & $sDevName & @CRLF) ConsoleWrite("Get Device Interface ID:" & @CRLF) $sDevInterfaceId = IDeviceInformation_Id($pDevinfo) DispError() ConsoleWrite($sDevInterfaceId & @CRLF) ConsoleWrite("Get DisplayMonitor from Device Interface Id:" & @CRLF) $pAsync2 = IDisplayMonitorStatics_FromInterfaceIdAsync($pMonStatics, $sDevInterfaceId) DispError() ConsoleWrite("Kick off Async..." & @CRLF) $pAsyncInfo2 = IUnknown_QueryInterface($pAsync2, $sIAsyncInfo) DispError() Do Sleep(10) Until IAsyncInfo_Status($pAsyncInfo2) ConsoleWrite("Get the object." & @CRLF) $pMonitor = IAsyncOperation_GetResults($pAsync2) DispError() ConsoleWrite("Confirm what we have (cause we can!)" & @CRLF) ConsoleWrite(IInspectable_GetRuntimeClassName($pMonitor) & @CRLF) DispError() ConsoleWrite(@CRLF) ConsoleWrite("Get descriptors..." & @CRLF) ConsoleWrite("Display EDID:" & @CRLF) ConsoleWrite(IDisplayMonitor_GetDescriptor($pMonitor, 0) & @CRLF) ConsoleWrite("Display DisplayID:" & @CRLF) ConsoleWrite(IDisplayMonitor_GetDescriptor($pMonitor, 1) & @CRLF) ConsoleWrite(@CRLF) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Func CoTaskMemFree($pBlock) DllCall("ole32.dll", "none", "CoTaskMemFree", "ptr", $pBlock) EndFunc ;==>CoTaskMemFree Func CreateGUID($sGUID) Local $tGUID = DllStructCreate($tagGUID) $aGUID = StringSplit(StringRegExpReplace($sGUID, "[{}]", ""), "-", 2) If UBound($aGUID) <> 5 Then Return False $tGUID.Data1 = Dec($aGUID[0]) $tGUID.Data2 = Dec($aGUID[1]) $tGUID.Data3 = Dec($aGUID[2]) $tGUID.Data4 = Binary("0x" & $aGUID[3] & $aGUID[4]) Return $tGUID EndFunc ;==>CreateGUID Func CreateHString($sString) Local $aCall = DllCall($hDLLComBase, "int", "WindowsCreateString", "wstr", $sString, "uint", StringLen($sString), "ptr*", 0) If Not @error Then Return $aCall[3] EndFunc ;==>CreateHString Func DeleteHString(ByRef $hString) Local $aCall = DllCall($hDLLComBase, "int", "WindowsDeleteString", "ptr", $hString) If Not @error Then $hString = 0 EndFunc ;==>DeleteHString Func DispError($iError = @error, $iScriptLineNumber = @ScriptLineNumber) Local Const $iMaxWidth = 0xFF Local $iFlags = $FORMAT_MESSAGE_FROM_SYSTEM Local $tBuff = DllStructCreate(StringFormat("wchar[%d]", $iMaxWidth)) Local $pBuff = DllStructGetPtr($tBuff) Local $iCount = _WinAPI_FormatMessage($iFlags, 0, $iError, 0, $pBuff, $iMaxWidth, 0) ConsoleWrite('(' & $iScriptLineNumber & ",0) [0x" & Hex($iError) & "] " & StringStripWS(DllStructGetData($tBuff, 1), 3) & @CRLF) EndFunc ;==>DispError Func GetPtrAt($pPtr) Local $tPtr = DllStructCreate("ptr ptr", $pPtr) Return $tPtr.ptr EndFunc ;==>GetPtrAt Func IActivationFactory_ActivateInstance($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IActivationFactory_ActivateInstance Func IAsyncInfo_Cancel($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 9 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis) Return SetError($aCall[0]) EndFunc ;==>IAsyncInfo_Cancel Func IAsyncInfo_Close($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 10 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis) Return SetError($aCall[0]) EndFunc ;==>IAsyncInfo_Close Func IAsyncInfo_ErrorCode($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 8 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "long*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IAsyncInfo_ErrorCode Func IAsyncInfo_ID($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "uint*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IAsyncInfo_ID Func IAsyncInfo_Status($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 7 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "uint*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IAsyncInfo_Status Func IAsyncOperation_GetResults($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 8 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IAsyncOperation_GetResults Func IDeviceInformation_EnclosureLocation($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 10 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IDeviceInformation_EnclosureLocation Func IDeviceInformation_Id($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Local $sID = ReadHString($aCall[2]) DeleteHString($aCall[2]) Return SetError($aCall[0], 0, $sID) EndFunc ;==>IDeviceInformation_Id Func IDeviceInformation_IsDefault($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 9 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "bool*", 0) Return SetError($aCall[0], 0, $aCall[2] = True) EndFunc ;==>IDeviceInformation_IsDefault Func IDeviceInformation_IsEnabled($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 8 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "bool*", 0) Return SetError($aCall[0], 0, $aCall[2] = True) EndFunc ;==>IDeviceInformation_IsEnabled Func IDeviceInformation_Name($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 7 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Local $sName = ReadHString($aCall[2]) DeleteHString($aCall[2]) Return SetError($aCall[0], 0, $sName) EndFunc ;==>IDeviceInformation_Name Func IDeviceInformation_Properties($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 11 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IDeviceInformation_Properties Func IDeviceInformationStatics_FindAllAsyncAqsFilter($pThis, $sFilter) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 10 * $PTR_LEN)) Local $hsFilter = CreateHString($sFilter) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr", $hsFilter, "ptr*", 0) DeleteHString($hsFilter) Return SetError($aCall[0], 0, $aCall[3]) EndFunc ;==>IDeviceInformationStatics_FindAllAsyncAqsFilter Func IDisplayMonitor_GetDescriptor($pThis, $iKind) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 25 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "long", $iKind, "long*", 0, "ptr*", 0) Local $tData $tData = DllStructCreate(StringFormat("byte Data[%d]", $aCall[3]), $aCall[4]) Return SetError($aCall[0], 0, IsDllStruct($tData) ? $tData.Data : Binary("0x")) EndFunc ;==>IDisplayMonitor_GetDescriptor Func IDisplayMonitorStatics_FromInterfaceIdAsync($pThis, $sDevInterfaceId) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 8 * $PTR_LEN)) $hsDevIface = CreateHString($sDevInterfaceId) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr", $hsDevIface, "ptr*", 0) DeleteHString($hsDevIface) Return SetError($aCall[0], 0, $aCall[3]) EndFunc ;==>IDisplayMonitorStatics_FromInterfaceIdAsync Func IDisplayMonitorStatics_GetDeviceSelector($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "ptr*", 0) Local $sSelector = ReadHString($aCall[2]) DeleteHString($aCall[2]) Return SetError($aCall[0], 0, $sSelector) EndFunc ;==>IDisplayMonitorStatics_GetDeviceSelector Func IInspectable_GetIids($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 3 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "long*", 0, "ptr*", 0) Local $pGUIDArray = $aCall[3], $iError = $aCall[0], $iCount = $aCall[2], $asIIDs[$iCount] For $i = 0 To $iCount - 1 $aCall = DllCall($hDLLComBase, "int", "StringFromIID", "ptr", Ptr($pGUIDArray + ($i * 16)), "wstr*", 0) $asIIDs[$i] = $aCall[2] Next CoTaskMemFree($pGUIDArray) Return SetError($aCall[0], 0, $asIIDs) EndFunc ;==>IInspectable_GetIids Func IInspectable_GetRuntimeClassName($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 4 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "handle*", 0) Local $sClassName = ReadHString($aCall[2]) DeleteHString($aCall[2]) Return SetError($aCall[0], 0, $sClassName) EndFunc ;==>IInspectable_GetRuntimeClassName Func IInspectable_GetTrustLevel($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 5 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "int*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IInspectable_GetTrustLevel Func IUnknown_AddRef($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis) Return $aCall[0] EndFunc ;==>IUnknown_AddRef Func IUnknown_QueryInterface($pThis, $sIID) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt($pVTable) Local $tIID = CreateGUID($sIID) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "struct*", $tIID, "ptr*", 0) Return SetError($aCall[0], 0, $aCall[3]) EndFunc ;==>IUnknown_QueryInterface Func IUnknown_Release($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 2 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis) Return $aCall[0] EndFunc ;==>IUnknown_Release Func IVectorView_GetAt($pThis, $iIndex) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 6 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "uint", $iIndex, "ptr*", 0) Return SetError($aCall[0], 0, $aCall[3]) EndFunc ;==>IVectorView_GetAt Func IVectorView_Size($pThis) Local $pVTable = GetPtrAt($pThis) Local $pFunc = GetPtrAt(Ptr($pVTable + 7 * $PTR_LEN)) Local $aCall = DllCallAddress("long", $pFunc, "ptr", $pThis, "uint*", 0) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>IVectorView_Size Func ReadGUIDAt($pGUID) Local $tGUID = DllStructCreate($tagGUID, $pGUID) Local $sGUID = "{" $sGUID &= Hex($tGUID.Data1, 8) & "-" $sGUID &= Hex($tGUID.Data2, 4) & "-" $sGUID &= Hex($tGUID.Data3, 4) & "-" $sGUID &= StringMid($tGUID.Data4, 3, 4) & "-" $sGUID &= StringMid($tGUID.Data4, 7, 12) & "}" Return $sGUID EndFunc ;==>ReadGUIDAt Func ReadHString(ByRef $hString) Local $aCall = DllCall($hDLLComBase, "wstr", "WindowsGetStringRawBuffer", "ptr", $hString, "int*", 0) If Not @error Then Return $aCall[0] EndFunc ;==>ReadHString Func RoActivateInstance($sClassID) $hsClassID = CreateHString($sClassID) Local $aCall = DllCall($hDLLComBase, "long", "RoActivateInstance", "handle", $hsClassID, "ptr*", 0) DeleteHString($hsClassID) Return SetError($aCall[0], 0, $aCall[2]) EndFunc ;==>RoActivateInstance Func RoGetActivationFactory($sClassID, $sIID) Local $hsClassID = CreateHString($sClassID) Local $tIID = CreateGUID($sIID) Local $aCall = DllCall($hDLLComBase, "long", "RoGetActivationFactory", "handle", $hsClassID, "ptr", DllStructGetPtr($tIID), "ptr*", 0) DeleteHString($hsClassID) Return SetError($aCall[0], 0, $aCall[3]) EndFunc ;==>RoGetActivationFactory Danyfirex and argumentum 2 Link to comment Share on other sites More sharing options...
argumentum Posted September 2 Share Posted September 2 2 hours ago, MattyD said: Lastly, I finally managed to pull those descriptor blobs! Well the EDID of my screen anyway.The DisplayID block - if present - needs to be a particular version for windows to use it, so I guess it's not surprising that mine doesn't show. I pulled both my monitors ( on 23H2 ), no blob that I can see either. Spoiler expandcollapse popup... ConsoleWrite("Collection size=" & IVectorView_Size($pDevInfoCol) & @CRLF) ConsoleWrite(@CRLF) For $iIndex = 0 To IVectorView_Size($pDevInfoCol) - 1 ConsoleWrite("=== ------------------- Mon. # " & $iIndex + 1 & " ----------------------- ===" & @CRLF) ConsoleWrite("Get First DisplayMonitor Obj" & @CRLF) ConsoleWrite("Get the fisrt item of our collection:" & @CRLF) $pDevinfo = IVectorView_GetAt($pDevInfoCol, $iIndex) DispError() ConsoleWrite("Get the name:" & @CRLF) $sDevName = IDeviceInformation_Name($pDevinfo) DispError() ConsoleWrite("Device Name = " & $sDevName & @CRLF) ConsoleWrite("Get Device Interface ID:" & @CRLF) $sDevInterfaceId = IDeviceInformation_Id($pDevinfo) DispError() ConsoleWrite($sDevInterfaceId & @CRLF) ConsoleWrite("Get DisplayMonitor from Device Interface Id:" & @CRLF) $pAsync2 = IDisplayMonitorStatics_FromInterfaceIdAsync($pMonStatics, $sDevInterfaceId) DispError() ConsoleWrite("Kick off Async..." & @CRLF) $pAsyncInfo2 = IUnknown_QueryInterface($pAsync2, $sIAsyncInfo) DispError() Do Sleep(10) Until IAsyncInfo_Status($pAsyncInfo2) ConsoleWrite("Get the object." & @CRLF) $pMonitor = IAsyncOperation_GetResults($pAsync2) DispError() ConsoleWrite("Confirm what we have (cause we can!)" & @CRLF) ConsoleWrite(IInspectable_GetRuntimeClassName($pMonitor) & @CRLF) DispError() ConsoleWrite(@CRLF) ConsoleWrite("Get descriptors..." & @CRLF) ConsoleWrite("Display EDID:" & @CRLF) ConsoleWrite(IDisplayMonitor_GetDescriptor($pMonitor, 0) & @CRLF) ConsoleWrite("Display DisplayID:" & @CRLF) ConsoleWrite(IDisplayMonitor_GetDescriptor($pMonitor, 1) & @CRLF) ConsoleWrite(@CRLF) Next ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ... and yes, very nice. In case anyone playing with those PiKVM needing a Display EDID that works by pulling one of yours, here are mine. Spoiler expandcollapse popup>"D:\Utilities\AutoIt3\SciTE\..\AutoIt3.exe" "D:\Utilities\AutoIt3\SciTE\AutoIt3Wrapper\AutoIt3Wrapper.au3" /run /prod /ErrorStdOut /in "D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt_v4.au3" /UserParams +>11:13:18 Starting AutoIt3Wrapper (pid=35632) 23.402.1150.10 from:SciTE.exe (4.4.6.0) Keyboard:00000409 OS:WIN_11/2009 CPU:X64 OS:X64 Environment(Language:0409) CodePage:0 utf8.auto.check:4 +> SciTEDir => D:\Utilities\AutoIt3\SciTE UserDir => C:\Users\Tester\AppData\Local\AutoIt v3\SciTE\AutoIt3Wrapper SCITE_USERHOME => C:\Users\Tester\AppData\Local\AutoIt v3\SciTE >Running AU3Check (3.3.17.0) from:D:\Utilities\AutoIt3 input:D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt_v4.au3 +>11:13:18 AU3Check ended. rc:0 >Running:(3.3.16.1):D:\Utilities\AutoIt3\autoit3_x64.exe "D:\Users\Tester\Downloads\ITaskbarList\ITaskbarList\212222-working-with-winrt-objects-in-memory\au3.212222-working-with-winrt_v4.au3" +>Setting Hotkeys...--> Press Ctrl+Alt+Break to Restart. --> Press Ctrl+BREAK to Stop. Get AQS String Get "Windows.Devices.Display.DisplayMonitor" Activation Factory, IDisplayMonitorStatics (27,0) [0x00000000] The operation completed successfully. Call IDisplayMonitorStatics::GetDeviceSelector (30,0) [0x00000000] The operation completed successfully. (System.Devices.InterfaceClassGuid:="{E6F07B5F-EE97-4a90-B076-33F57BF4EAA7}" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True) OR System.Devices.ChallengeAep:=System.StructuredQueryType.Boolean#False Get Device Collection: Get "Windows.Devices.Enumeration.DeviceInformation" Activation Factory, IDeviceInformationStatics (37,0) [0x00000000] The operation completed successfully. Call IDeviceInformationStatics::FindAllAsyncAqsFilter with AQS string that we aquired earlier (40,0) [0x00000000] The operation completed successfully. Wait for Async routine... Get AsyncInfo Interface: (44,0) [0x00000000] The operation completed successfully. Async Finished. We want the status to be 1 - i.e. 'completed': Async status=1 GetResult of Async: (52,0) [0x00000000] The operation completed successfully. Collection size=2 === ------------------- Mon. # 1 ----------------------- === Get First DisplayMonitor Obj Get the fisrt item of our collection: (63,0) [0x00000000] The operation completed successfully. Get the name: (66,0) [0x00000000] The operation completed successfully. Device Name = Generic Monitor (LS27A800U) Get Device Interface ID: (71,0) [0x00000000] The operation completed successfully. \\?\DISPLAY#SAM71A4#5&2464ea33&0&UID4353#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} Get DisplayMonitor from Device Interface Id: (75,0) [0x00000000] The operation completed successfully. Kick off Async... (78,0) [0x00000000] The operation completed successfully. Get the object. (84,0) [0x00000000] The operation completed successfully. Confirm what we have (cause we can!) Windows.Devices.Display.DisplayMonitor (87,0) [0x00000000] The operation completed successfully. Get descriptors... Display EDID: 0x00FFFFFFFFFFFF004C2DA47132575843351F0104B53C22783A0495AE5241AE260F5054BFEF80714F810081C08180A9C0B300950001014DD000A0F0703E803020350055502100001A000000FD001E4B1E873C000A202020202020000000FC004C53323741383030550A202020000000FF0048345A524330313330300A202001DB02031CF0475F101F041303122309070783010000E305C000E3060501023A801871382D40582C450055502100001E565E00A0A0A029503020350055502100001A04740030F2705A80B0588A0055502100001E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000036 Display DisplayID: === ------------------- Mon. # 2 ----------------------- === Get First DisplayMonitor Obj Get the fisrt item of our collection: (63,0) [0x00000000] The operation completed successfully. Get the name: (66,0) [0x00000000] The operation completed successfully. Device Name = Generic Monitor (LG ULTRAWIDE) Get Device Interface ID: (71,0) [0x00000000] The operation completed successfully. \\?\DISPLAY#GSM76F9#5&2464ea33&0&UID4352#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} Get DisplayMonitor from Device Interface Id: (75,0) [0x00000000] The operation completed successfully. Kick off Async... (78,0) [0x00000000] The operation completed successfully. Get the object. (84,0) [0x00000000] The operation completed successfully. Confirm what we have (cause we can!) Windows.Devices.Display.DisplayMonitor (87,0) [0x00000000] The operation completed successfully. Get descriptors... Display EDID: 0x00FFFFFFFFFFFF001E6DF97607110800051C010380502278EACA95A6554EA1260F5054256B807140818081C0A9C0B300D1C08100D1CFCD4600A0A0381F4030203A001E4E3100001A003A801871382D40582C4500132A2100001E000000FD00384B1E5A18000A202020202020000000FC004C4720554C545241574944450A01E302031AF12309070747100403011F13128301000065030C0014008C0AD08A20E02D10103E96001E4E31000018295900A0A038274030203A001E4E3100001A000000000000000000000000000000000000000000000000000000000000000000000000000000FF003830354E544E48464A3634370A000000000000000000000090 Display DisplayID: > +>11:13:18 AutoIt3 ended. rc:0 +>11:13:18 AutoIt3Wrapper Finished. >Exit code: 0 Time: 1.316 MattyD 1 Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
MattyD Posted September 5 Author Share Posted September 5 (edited) Ok so I've uploaded something that's still pretty rough... I'll fix any glaring mistakes, but TBH I'll probably not develop this much further - at least in the immediate future. Anyway, I figure it might help someone in the future who's going down this particular rabbit hole Edit - My console output for the demo script if its of interest... Spoiler >Handy funcs for development: (8,0) [0x00000000] The operation completed successfully. (10,0) Supported Interfaces: Class: Windows.Foundation.Collections.IVectorView`1<Windows.Devices.Enumeration.DeviceInformation> {E170688F-3495-5BF6-AAB5-9CAC17E0F10F} {00000038-0000-0000-C000-000000000046} {DD9F8A5D-EC98-5F4B-A3EA-9C8B5AD53C4B} (11,0) Class: Windows.Foundation.Collections.IVectorView`1<Windows.Devices.Enumeration.DeviceInformation> >List Monitors... +---------------------------------------- + Get Display: Generic Monitor (S22D300) +---------------------------------------- Name: S22D300 DeviceID : \\?\DISPLAY#SAM0B3F#4&10d8532f&0&UID4145#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} Adapter DeviceID : \\?\PCI#VEN_8086&DEV_46A8&SUBSYS_0B0C1028&REV_0C#3&11583659&1&10#{5b45201d-f2f2-4f3b-85bb-30ff1f953599} Adapter LUID : 83394 Adapter TargetID : 4145 Connection Kind : Wired Physical Connector : HDMI Usage : Standard Native Resolution : [ 1920, 1080 ] Screen Size in Inches : [ 18.779528, 10.551181 ] DPI (X, Y) : [ 102.238991, 102.358208 ] Dolby Vision in HDR Supported : False Chroma (R,G,B,W): [ 0.646984, 0.333508 ] [ 0.321789, 0.626477 ] [ 0.157727, 0.061047 ] [ 0.313000, 0.329602 ] Luminance in nits (max, min, MaxFALL): [ 270, 0.5, 270 ] EDID: 0x00FFFFFFFFFFFF004C2D3F0B35415A5A1819010380301B782A9561A55552A0280F5054BFEF80714F81C0810081809500A9C0B3000101023A801871382D40582C4500DD0C1100001E011D007251D01E206E285500DD0C1100001E000000FD00324B1E5111000A202020202020000000FC00533232443330300A202020202001A0020311B14690041F13120365030C001000011D00BC52D01E20B8285540DD0C1100001E8C0AD090204031200C405500DD0C110000188C0AD08A20E02D10103E9600DD0C11000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050 DisplayId: +---------------------------------------- + Get Display: NB225283 +---------------------------------------- Name: DeviceID : \\?\DISPLAY#SHP14E2#4&10d8532f&0&UID8388688#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7} Adapter DeviceID : \\?\PCI#VEN_8086&DEV_46A8&SUBSYS_0B0C1028&REV_0C#3&11583659&1&10#{5b45201d-f2f2-4f3b-85bb-30ff1f953599} Adapter LUID : 83394 Adapter TargetID : 8388688 Connection Kind : Internal Physical Connector : Unknown Usage : Standard Native Resolution : [ 1920, 1080 ] Screen Size in Inches : [ 12.165355, 6.850394 ] DPI (X, Y) : [ 157.825241, 157.655167 ] Dolby Vision in HDR Supported : False Chroma (R,G,B,W): [ 0.640148, 0.329602 ] [ 0.300305, 0.600109 ] [ 0.149914, 0.060070 ] [ 0.313000, 0.328625 ] Luminance in nits (max, min, MaxFALL): [ 270, 0.5, 270 ] EDID: 0x00FFFFFFFFFFFF004D10E214000000000E1D0104A51F11780EDE50A3544C99260F5054000000010101010101010101010101010101011A3680A070381E403020350035AE10000018482B80A070381E403020350035AE10000018000000FE005436594D34814C513134304D3100000000000241031E011200000A010A202000A70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 DisplayId: Edited September 5 by MattyD argumentum 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now