Jump to content

WinRT Object Libraries


 Share

Recommended Posts

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.

#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

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
>"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.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

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.

#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
Link to comment
Share on other sites

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 by argumentum
clarify

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

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.
 

#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

 

Link to comment
Share on other sites

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
...
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
>"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

 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

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 by MattyD
Link to comment
Share on other sites

 a quick update - 

I had discovered WinRT objects are all described in metadata files living in system32\WinMetaData -  So my thought was I could write something that generates the beginnings of those Interface libraries (i.e. the functions that wrap an interface) .

Not sure how much of a reality this will be, but I've started to attack the object that extracts the metadata anyhow. There's enough code there I think to add it to the zip!

That second "TypeLib" example demonstrates more or less where I'm up to.  Change the search string to pull all objects that match :) 

Link to comment
Share on other sites

Hi all

My first attempt at a generator is now largely going, so here are ~320 odd interface libraries for anyone looking to tackle Windows.Devices.xxxx classes!

The ObjCreateInterface() tags should also now work if people would rather go down that route.

I still have plenty of development to do here, so just expect some bugs and a bit of fluidity between uploads.

Link to comment
Share on other sites

  • MattyD changed the title to WinRT Object Libraries

Hi all - just uploaded v1.3

I'm still only dealing with Windows.Devices for now... I missed a bunch of interfaces last time around, so we're now in the vicinity ~850 with the latest upload.

  • Enumeration defs have been moved out of the interface libraries, and are now defined externally (see enums folder)
  • New class files - These group together all the interface and enumeration files that belong to a class into a single file
  • New Namespace files - These group related class files together into one place.  These are what you should include in your script! (along with WinRT.au3)
  • removed the winrt_blah files - these were libraries built on top of classes, which are now out of scope for this project!
    • I still have them if anyone would like a copy... MetaDataImport, DisplayMonitor and DeviceInformation,

I'll also eventually write up some documentation - but that'll be a little while off yet. In the meantime I'm more than happy to answer any questions. I realize the examples may be a bit opaque at the minute...

Link to comment
Share on other sites

Hi all - a new version is up.

I've made some massive changes behind the scenes to the generator script, so I'm hoping this will fix more things than it'll break!

A few notes...

  • The upload includes more interfaces that were hiding in the metadata under the "Activatable" custom attribute.
  • Enums with a value > 0x7FFFFFFF used to cause the script to crash - So to get around this we now need to use _WinRT_GetEnum($mMap, $iValue) to resolve numeric enums to their string representation.
  • Fixed a number of functions that I was mishandling when the return value was "none".
  • Better handling of functions that pass arrays in or out (when its not a return value). - I'm still not 100% happy with this yet, so be warned implementation will probably change down the track.
  • I still need to properly tackle paramatised interfaces, so that's another area that's likely to change.
Link to comment
Share on other sites

Hi @MattyD,First of all, thank you for this work you are doing.
From a first look at the WinRT UDF, I see that the _WinRT_WaitForAsync function is used to block the execution of the main script until the expected event is raised (or expires).
I would like to ask you if there is a way to use something similar to the AutoIt ObjEvent() function as an alternative (or maybe, even better, use that function directly). That is, give the user the possibility to pass the name of their own function attached to an event that will be called asynchronously when that event occurs?
I apologize in advance if I misunderstood the mechanism of the _WinRT_WaitForAsync() function ...
bye and thank you

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

Posted (edited)

Hey Gianni, thanks for the support. :)

I'm learning as I go here, and in short this is something that I'll need to look in to.

Registration shouldn't be an issue - objects have "add" and "remove" handler methods for this. Basically we need to figure out how to create the delegate to register.

Regarding _WinRT_WaitForAsync(), this works by polling the Async object's Status property, then calling its GetResult method which points you somewhere. So point being there's no callbacks involved in this process.  But you could also theoretically register a AsyncOperationCompletedHandler delegate, which would presumably fire on the completion of the operation.

So I guess we need to discover how to create delegate objects, then we can look at triggering user functions!

Edited by MattyD
clarity
Link to comment
Share on other sites

Hi all,

I haven't had a ton of time to throw at this of late, so just an incremental tonight (while I can still remember what's changed!). The generation script is largely the same as last go around.

  • Fixed tags for some interfaces  (functions with no params were incorrectly generated, invalidating the tag.)
  • WaitForAsync now accepts AsyncAction objects (previously it'd only work with AsyncOperation objects)
  • I'm trawling through all the inbuilt metadata files now, so there's literally thousands of libraries in this latest upload. I've hit the size limit for posting here, hence the sourceforge link up the top!
  • Updated the "calltips installer" script - this is now included in the zip file.
  • Updated the "class explorer" script to something that's hopefully a bit more presentable - this one is still a separate download.
Link to comment
Share on other sites

nice !. Added a Dark mode coloring for my setup

Spoiler
...
Global $g_IsDarkMode = IsDarkMode()
Init()
...
Func GetItemColour($iItem)
    Local $tItem, $tName
    Local $sFile, $pScope, $iTypeDef, $aProps, $iCol = $g_IsDarkMode ? 0xCCCCCC : 0x000000

    $tItem = DllStructCreate($tagLVITEM)
    $tName = DllStructCreate("wchar Text[260]")
    $tItem.Text = DllStructGetPtr($tName)
    $tItem.TextMax = 260
    GUICtrlSendMsg($hTypeDefs, $LVM_GETITEMTEXTW, $iItem, DllStructGetPtr($tItem))

    $sFile = _MetaData_GetMetaDataFile($tName.Text)
    $pScope = _MetaData_OpenScope($pDispenser, $sFile)
    $iTypeDef = _MetaData_FindTypeDef($pScope, $tName.Text)
    $aProps = _MetaData_GetTypeDefProps($pScope, $iTypeDef)

    If BitAND($aProps[1], 0x20) Then
        $iCol = $g_IsDarkMode ? 0xd47f7f : 0xAA0000
    Else
        Switch _MetaData_GetTokenName($pScope, $aProps[2])
            Case "System.Object"
                $iCol = $g_IsDarkMode ? 0x6666cc : 0x0000AA
            Case "System.Enum"
                $iCol = 0x0080AA
            Case "System.ValueType"
                $iCol = 0xAAAA00
            Case "System.MulticastDelegate"
                $iCol = 0x008000
            Case "System.Attribute"
                $iCol = 0x800080
            Case Else
;~              ConsoleWrite( _MetaData_GetTokenName($pScope, $aProps[2]) & @CRLF)
        EndSwitch
    EndIf

    _WinRT_DeleteObject($pScope)

    Return $iCol
EndFunc   ;==>GetItemColour

Func IsDarkMode() ; https://www.autoitscript.com/forum/topic/139260-autoit-snippets/?do=findComment&comment=1520332
    ; https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsyscolor
    Return (PerceivedBrightnessOfColor(_WinAPI_GetSysColor($COLOR_WINDOWTEXT)) _
             > PerceivedBrightnessOfColor(_WinAPI_GetSysColor($COLOR_WINDOW)))
    ; if the text is perceived as brighter than the background then Return True
EndFunc   ;==>IsDarkMode

Func PerceivedBrightnessOfColor($color)
    ; https://learn.microsoft.com/en-us/windows/apps/desktop/modernize/apply-windows-themes#know-when-dark-mode-is-enabled
    ; This function performs a quick calculation of the perceived brightness of a color, and takes into consideration
    ;           ways that different channels in an RGB color value contribute to how bright it looks to the human eye.
    Local $a = StringSplit(Hex($color, 6), ""), $r = 2 * Dec($a[1] & $a[2]), $g = 5 * Dec($a[3] & $a[4]), $b = 1 * Dec($a[5] & $a[6])
    Return ($r + $g + $b)
EndFunc   ;==>PerceivedBrightnessOfColor

image.png.feeb93092d9cc055e8a04c030b3fd65a.png

 

Follow the link to my code contribution ( and other things too ).
FAQ - Please Read Before Posting.
autoit_scripter_blue_userbar.png

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...