junkew Posted Sunday at 04:36 PM Posted Sunday at 04:36 PM (edited) Any feedback on the code is appreciated. It compiles and runs so from that perspective no issues but still complex to understand when to use vtable or just hack by knowing the function numbers. no tesseract or other OCR libraries needed, just plain AutoIt and Windows libraries (on windows 11) So once in a while I still use AutoIt and now found out with Powershell 5.1 the WinRt on how to do stuff with the nice OCR gettext (thats also in Win11 Capture tool) and was wondering how to get this working in AutoIt Jumping back and forward in threads of this forum on AutoItObject, ObjCreateInterface, Com/Com++, Embedding .NET in AutoIt, CuiAutomation I already understand WinRt is another animal to get into AutoIt. I didnt want to hijack: Learning step 1 Understanding combase.dll and RoGetActivationFactory Made a very nice script that goes from Learning WinRt To understand the WinRt OCR To highlighting aspects of the rectangles found So much easier with AI then when I wrote the IUIAutomation library (took me months, now only several hours to understand the WinRt base as extension on traditional COM) expandcollapse popup; ===================================================================================== ; WINRT OCR SCRIPT - THE BULLETPROOF HYBRID METHOD ; ===================================================================================== #include "ScreenCapture.au3" #region --- GLOBALS & DLLS --- Global $hDLLComBase = DllOpen("combase.dll") Global $hDLLOle32 = DllOpen("ole32.dll") Global $hDLLShcore = DllOpen("shcore.dll") #endregion #region --- GUIDS & BLUEPRINTS --- Global Const $sIInspectable = "{AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90}" Global Const $sIAsyncInfoGUID = "{00000036-0000-0000-C000-000000000046}" Global Const $sIRandomAccessStreamGUID = "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}" Global Const $sIBitmapDecoderStaticsGUID = "{438CCB26-BCEF-4E95-BAD6-23A822E58D01}" Global Const $sIBitmapFrameWithSoftwareBitmapGUID = "{FE287C9A-420C-4963-87AD-691436E08383}" Global Const $sIOcrEngineStaticsGUID = "{5BFFA85A-3384-3540-9940-699120D428A8}" Global Const $sIOcrEngineGUID = "{5A14BC41-5B76-3140-B680-8825562683AC}" Global $tagIInspectable = _ "GetIids hresult(ulong*;ptr*);" & _ "GetRuntimeClassName hresult(ptr*);" & _ "GetTrustLevel hresult(int*);" Global $tagIAsyncInfo = $tagIInspectable & _ "get_Id hresult(uint*);" & _ "get_Status hresult(int*);" & _ "get_ErrorCode hresult(long*);" & _ "Cancel hresult();" & _ "Close hresult();" Global $tagIBitmapDecoderStatics = $tagIInspectable & _ "get_BmpDecoderId hresult(ptr*);" & _ "get_JpegDecoderId hresult(ptr*);" & _ "get_PngDecoderId hresult(ptr*);" & _ "get_TiffDecoderId hresult(ptr*);" & _ "get_GifDecoderId hresult(ptr*);" & _ "get_JpegXRDecoderId hresult(ptr*);" & _ "get_IcoDecoderId hresult(ptr*);" & _ "GetDecoderInformationEnumerator hresult(ptr*);" & _ "CreateAsync hresult(ptr;ptr*);" Global $tagIBitmapFrameWithSoftwareBitmap = $tagIInspectable & _ "GetSoftwareBitmapAsync hresult(ptr*);" Global $tagIOcrEngineStatics = $tagIInspectable & _ "get_MaxImageDimension hresult(uint*);" & _ "get_AvailableRecognizerLanguages hresult(ptr*);" & _ "IsLanguageSupported hresult(ptr;bool*);" & _ "TryCreateFromLanguage hresult(ptr;ptr*);" & _ "TryCreateFromUserProfileLanguages hresult(ptr*);" Global $tagIOcrEngine = $tagIInspectable & _ "RecognizeAsync hresult(ptr;ptr*);" & _ "get_RecognizerLanguage hresult(ptr*);" #endregion ; --- OCR RESULT BLUEPRINTS --- Global $tagIOcrResult = $tagIInspectable & _ "get_Lines hresult(ptr*);" & _ "get_TextAngle hresult(ptr*);" & _ "get_Text hresult(ptr*);" Global $tagIVectorView = $tagIInspectable & _ "GetAt hresult(uint;ptr*);" & _ "get_Size hresult(uint*);" Global $tagIOcrLine = $tagIInspectable & _ "get_Words hresult(ptr*);" & _ "get_Text hresult(ptr*);" Global $tagIOcrWord = $tagIInspectable & _ "get_BoundingRect hresult(ptr);" & _ "get_Text hresult(ptr*);" #region --- STEP 1 & 2: INIT & CAPTURE --- ConsoleWrite(">>> [Step 1] Initializing WinRT..." & @CRLF) DllCall($hDLLComBase, "long", "RoInitialize", "int", 1) Global $sTempImage = @TempDir & "\ocr_snapshot.png" ConsoleWrite(">>> [Step 2] Capturing screen to: " & $sTempImage & @CRLF) _ScreenCapture_Capture($sTempImage, 0, 0, 500, 500) Sleep(300) ; Geef de hardeschijf genoeg tijd om de foto te flushen #endregion #region --- STEP 3: CREATE WINRT STREAM --- ConsoleWrite(">>> [Step 3] Opening file as a WinRT Stream..." & @CRLF) Global $pStream = 0 Global $tIID_Stream = _WinRT_CreateGUID($sIRandomAccessStreamGUID) Global $aResStream = DllCall($hDLLShcore, "long", "CreateRandomAccessStreamOnFile", "wstr", $sTempImage, "dword", 0, "struct*", $tIID_Stream, "ptr*", 0) If Not @error And $aResStream[0] = 0 Then $pStream = $aResStream[4] ConsoleWrite(" + Success! Stream pointer: " & $pStream & @CRLF) Else ConsoleWrite(" ! Error: Failed to create Stream." & @CRLF) Exit EndIf #endregion #region --- STEP 4: BITMAP DECODER --- ConsoleWrite(">>> [Step 4] Creating BitmapDecoder..." & @CRLF) Global $pDecoderStatics = _WinRT_RoGetActivationFactory("Windows.Graphics.Imaging.BitmapDecoder", $sIBitmapDecoderStaticsGUID) Global $oDecoderStatics = ObjCreateInterface($pDecoderStatics, $sIBitmapDecoderStaticsGUID, $tagIBitmapDecoderStatics, True) Global $pTicket1 = 0 $oDecoderStatics.CreateAsync($pStream, $pTicket1) ; De Helper functie verzorgt het wachten en de VTable hack voor GetResults! Global $pBitmapDecoder = _WinRT_WaitAsync($pTicket1, "Decoder") If $pBitmapDecoder Then ConsoleWrite(" + Success! Decoder retrieved: " & $pBitmapDecoder & @CRLF) Else Exit EndIf #endregion #region --- STEP 5: SOFTWARE BITMAP --- ConsoleWrite(">>> [Step 5] Converting Decoder to SoftwareBitmap..." & @CRLF) ; We dwingen WinRT om de Decoder pointer te voorzien van de SoftwareBitmap lens Global $oBitmapFrame = ObjCreateInterface($pBitmapDecoder, $sIBitmapFrameWithSoftwareBitmapGUID, $tagIBitmapFrameWithSoftwareBitmap, True) Global $pTicket2 = 0 $oBitmapFrame.GetSoftwareBitmapAsync($pTicket2) Global $pSoftwareBitmap = _WinRT_WaitAsync($pTicket2, "SoftwareBitmap") If $pSoftwareBitmap Then ConsoleWrite(" + Success! SoftwareBitmap retrieved: " & $pSoftwareBitmap & @CRLF) Else Exit EndIf #endregion #region --- STEP 6: OCR ENGINE RECOGNIZE --- ConsoleWrite(">>> [Step 6] Feeding image to OCR Engine..." & @CRLF) Global $pOcrStatics = _WinRT_RoGetActivationFactory("Windows.Media.Ocr.OcrEngine", $sIOcrEngineStaticsGUID) Global $oOcrStatics = ObjCreateInterface($pOcrStatics, $sIOcrEngineStaticsGUID, $tagIOcrEngineStatics, True) Global $pOcrEnginePtr = 0 $oOcrStatics.TryCreateFromUserProfileLanguages($pOcrEnginePtr) Global $oOcrEngine = ObjCreateInterface($pOcrEnginePtr, $sIOcrEngineGUID, $tagIOcrEngine, True) ConsoleWrite(" -> Calling RecognizeAsync..." & @CRLF) Global $pTicket3 = 0 $oOcrEngine.RecognizeAsync($pSoftwareBitmap, $pTicket3) Global $pOcrResult = _WinRT_WaitAsync($pTicket3, "OCR_Engine") If $pOcrResult Then ConsoleWrite(" + ===========================================================" & @CRLF) ConsoleWrite(" + MEGA SUCCESS! OCR Result object retrieved: " & $pOcrResult & @CRLF) ConsoleWrite(" + THE IMAGE HAS BEEN SUCCESSFULLY READ BY WINDOWS!" & @CRLF) ConsoleWrite(" + ===========================================================" & @CRLF) Else ConsoleWrite(" ! Error: OCR Recognition failed." & @CRLF) EndIf #endregion #region --- STEP 7: EXTRACT TEXT, POSITIONS & VISUAL HUD DEMO --- ConsoleWrite(">>> [Step 7] Extracting OCR Text and Highlighting Bounding Boxes..." & @CRLF) Global $pVTable_Res = DllStructGetData(DllStructCreate("ptr", $pOcrResult), 1) ; 1. Complete tekst uitlezen Global $pGetText_Res = DllStructGetData(DllStructCreate("ptr", $pVTable_Res + (8 * (@AutoItX64 ? 8 : 4))), 1) Global $aCallText = DllCallAddress("long", $pGetText_Res, "ptr", $pOcrResult, "ptr*", 0) If Not @error And $aCallText[0] = 0 Then Global $hFullText = $aCallText[2] ConsoleWrite(" [VOLLEDIGE TEKST] ===================================" & @CRLF) ConsoleWrite(" " & _WinRT_GetHStringText($hFullText) & @CRLF) ConsoleWrite(" =====================================================" & @CRLF) _WinRT_DeleteHString($hFullText) EndIf ; 2. Lijnen en Woorden ophalen en live highlighten op het scherm Global $pLinesVector = 0 Global $pGetLines = DllStructGetData(DllStructCreate("ptr", $pVTable_Res + (6 * (@AutoItX64 ? 8 : 4))), 1) Global $aCallLines = DllCallAddress("long", $pGetLines, "ptr", $pOcrResult, "ptr*", 0) If Not @error And $aCallLines[0] = 0 Then $pLinesVector = $aCallLines[2] If $pLinesVector Then Global $pVTable_Lines = DllStructGetData(DllStructCreate("ptr", $pLinesVector), 1) Global $pGetAt_Lines = DllStructGetData(DllStructCreate("ptr", $pVTable_Lines + (6 * (@AutoItX64 ? 8 : 4))), 1) Global $pGetSize_Lines = DllStructGetData(DllStructCreate("ptr", $pVTable_Lines + (7 * (@AutoItX64 ? 8 : 4))), 1) Global $iLineCount = 0 Global $aCallSize = DllCallAddress("long", $pGetSize_Lines, "ptr", $pLinesVector, "uint*", 0) If Not @error And $aCallSize[0] = 0 Then $iLineCount = $aCallSize[2] ConsoleWrite(" -> Aantal tekstregels gevonden: " & $iLineCount & @CRLF) For $i = 0 To $iLineCount - 1 Global $pLine = 0 Global $aCallAt = DllCallAddress("long", $pGetAt_Lines, "ptr", $pLinesVector, "uint", $i, "ptr*", 0) If Not @error And $aCallAt[0] = 0 Then $pLine = $aCallAt[3] If $pLine Then Global $pVTable_Line = DllStructGetData(DllStructCreate("ptr", $pLine), 1) Global $pGetWords = DllStructGetData(DllStructCreate("ptr", $pVTable_Line + (6 * (@AutoItX64 ? 8 : 4))), 1) Global $pWordsVector = 0 Global $aCallWords = DllCallAddress("long", $pGetWords, "ptr", $pLine, "ptr*", 0) If Not @error And $aCallWords[0] = 0 Then $pWordsVector = $aCallWords[2] If $pWordsVector Then Global $pVTable_Words = DllStructGetData(DllStructCreate("ptr", $pWordsVector), 1) Global $pGetAt_Words = DllStructGetData(DllStructCreate("ptr", $pVTable_Words + (6 * (@AutoItX64 ? 8 : 4))), 1) Global $pGetSize_Words = DllStructGetData(DllStructCreate("ptr", $pVTable_Words + (7 * (@AutoItX64 ? 8 : 4))), 1) Global $iWordCount = 0 Global $aCallWSize = DllCallAddress("long", $pGetSize_Words, "ptr", $pWordsVector, "uint*", 0) If Not @error And $aCallWSize[0] = 0 Then $iWordCount = $aCallWSize[2] For $j = 0 To $iWordCount - 1 Global $pWord = 0 Global $aCallWAt = DllCallAddress("long", $pGetAt_Words, "ptr", $pWordsVector, "uint", $j, "ptr*", 0) If Not @error And $aCallWAt[0] = 0 Then $pWord = $aCallWAt[3] If $pWord Then Global $pVTable_Word = DllStructGetData(DllStructCreate("ptr", $pWord), 1) Global $pGetRect = DllStructGetData(DllStructCreate("ptr", $pVTable_Word + (6 * (@AutoItX64 ? 8 : 4))), 1) Global $pGetText_Word = DllStructGetData(DllStructCreate("ptr", $pVTable_Word + (7 * (@AutoItX64 ? 8 : 4))), 1) ; Tekst ophalen Global $hWordText = 0 Global $aCallWText = DllCallAddress("long", $pGetText_Word, "ptr", $pWord, "ptr*", 0) If Not @error And $aCallWText[0] = 0 Then $hWordText = $aCallWText[2] Global $sWordText = _WinRT_GetHStringText($hWordText) _WinRT_DeleteHString($hWordText) ; Coördinaten ophalen (Rect) Global $tRect = DllStructCreate("float X; float Y; float Width; float Height") DllCallAddress("long", $pGetRect, "ptr", $pWord, "ptr", DllStructGetPtr($tRect)) Local $fX = DllStructGetData($tRect, "X") Local $fY = DllStructGetData($tRect, "Y") Local $fW = DllStructGetData($tRect, "Width") Local $fH = DllStructGetData($tRect, "Height") ; --- DE DEMO MAGIE: RECHTHOEK TEKENEN OP HET SCHERM --- ; Parameters: Left, Right, Top, Bottom (volgens jouw functie-definitie) _UIA_DrawRect(Int($fX), Int($fX + $fW), Int($fY), Int($fY + $fH), 0x0000FF, 2) ; Kleine pauze zodat je de scanner live over het scherm ziet trekken (optioneel, zet op 0 voor instant) Sleep(15) ConsoleWrite(" Regel " & $i & " | Woord: '" & $sWordText & "' | Box: X=" & $fX & ", Y=" & $fY & ", W=" & $fW & ", H=" & $fH & @CRLF) EndIf Next EndIf EndIf Next EndIf #endregion #region --- CLEANUP --- FileDelete($sTempImage) DllCall($hDLLComBase, "none", "RoUninitialize") DllClose($hDLLComBase) DllClose($hDLLOle32) DllClose($hDLLShcore) #endregion #region --- HELPER FUNCTIONS --- ; De ultieme hybride Async Helper Func _WinRT_WaitAsync($pAsyncTicket, $sName = "Async") If $pAsyncTicket = 0 Then Return 0 ; 1. SAFE POLLING: We dwingen QueryInterface af via ObjCreateInterface Local $oAsyncInfo = ObjCreateInterface($pAsyncTicket, $sIAsyncInfoGUID, $tagIAsyncInfo, True) If Not IsObj($oAsyncInfo) Then Return 0 Local $iStatus = 0 While True $oAsyncInfo.get_Status($iStatus) If $iStatus >= 1 Then ExitLoop Sleep(10) WEnd If $iStatus <> 1 Then ConsoleWrite(" ! [" & $sName & "] Failed with status: " & $iStatus & @CRLF) Return 0 EndIf ; 2. RAW VTABLE HACK VOOR RESULTS: We weten dat GetResults altijd Index 8 is! Local $pVTable = DllStructGetData(DllStructCreate("ptr", $pAsyncTicket), 1) Local $pGetResultsFunc = DllStructGetData(DllStructCreate("ptr", $pVTable + (8 * (@AutoItX64 ? 8 : 4))), 1) Local $aCall = DllCallAddress("long", $pGetResultsFunc, "ptr", $pAsyncTicket, "ptr*", 0) If @error Or $aCall[0] <> 0 Then Return 0 Return $aCall[2] ; Het finale pointer resultaat! EndFunc Func _WinRT_RoGetActivationFactory($sClassID, $sIID) Local $hsClassID = _WinRT_CreateHString($sClassID) Local $tIID = _WinRT_CreateGUID($sIID) Local $aRes = DllCall($hDLLComBase, "long", "RoGetActivationFactory", "ptr", $hsClassID, "ptr", DllStructGetPtr($tIID), "ptr*", 0) _WinRT_DeleteHString($hsClassID) If @error Or $aRes[0] < 0 Then Return 0 Return $aRes[3] EndFunc Func _WinRT_CreateHString($sString) Local $aRes = DllCall($hDLLComBase, "long", "WindowsCreateString", "wstr", $sString, "uint", StringLen($sString), "ptr*", 0) If @error Or $aRes[0] < 0 Then Return 0 Return $aRes[3] EndFunc Func _WinRT_DeleteHString(ByRef $hString) If $hString = 0 Then Return DllCall($hDLLComBase, "long", "WindowsDeleteString", "ptr", $hString) $hString = 0 EndFunc Func _WinRT_GetHStringText($hString) If $hString = 0 Then Return "" Local $aRes = DllCall($hDLLComBase, "ptr", "WindowsGetStringRawBuffer", "ptr", $hString, "uint*", 0) If @error Or $aRes[0] = 0 Then Return "" Local $iLength = $aRes[2] If $iLength = 0 Then Return "" Local $tString = DllStructCreate("wchar[" & ($iLength + 1) & "]", $aRes[0]) Return DllStructGetData($tString, 1) EndFunc Func _WinRT_CreateGUID($sGUID) Local $tGUID = DllStructCreate("dword Data1;word Data2;word Data3;byte Data4[8]") DllCall($hDLLOle32, "long", "CLSIDFromString", "wstr", $sGUID, "struct*", $tGUID) Return $tGUID EndFunc ; Draw rectangle on screen. Func _UIA_DrawRect($tLeft, $tRight, $tTop, $tBottom, $color = 0xFF, $PenWidth = 4) Local $hDC, $hPen, $obj_orig, $x1, $x2, $y1, $y2 $x1 = $tLeft $x2 = $tRight $y1 = $tTop $y2 = $tBottom $hDC = _WinAPI_GetWindowDC(0) ; DC of entire screen (desktop) $hPen = _WinAPI_CreatePen(0, $PenWidth, $color) ; $PS_SOLID = 0 $obj_orig = _WinAPI_SelectObject($hDC, $hPen) _WinAPI_DrawLine($hDC, $x1, $y1, $x2, $y1) ; horizontal to right _WinAPI_DrawLine($hDC, $x2, $y1, $x2, $y2) ; vertical down on right _WinAPI_DrawLine($hDC, $x2, $y2, $x1, $y2) ; horizontal to left right _WinAPI_DrawLine($hDC, $x1, $y2, $x1, $y1) ; vertical up on left ; clear resources _WinAPI_SelectObject($hDC, $obj_orig) _WinAPI_DeleteObject($hPen) _WinAPI_ReleaseDC(0, $hDC) EndFunc ;==>_UIA_DrawRect #endregion Edited Sunday at 04:46 PM by junkew mLipok 1 FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
junkew Posted Sunday at 08:14 PM Author Posted Sunday at 08:14 PM And allways fun to reinvent the wheel 😉 found this one after I learned making above script. https://github.com/DanysysTeam/UWPOCR @Danyfirex mLipok and Danyfirex 1 1 FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
MattyD Posted Monday at 05:57 AM Posted Monday at 05:57 AM (edited) well done , Quick tip - There are a few exceptions, but generally you should release any object that you "aquire". You won't need to worry about any $pObject object "converted" to $oObject by ObjCreateInterface though. ObjCreateInterface does a QI/Release call on the ptr, so the refcount doesn't change at that point. But an $oObject.Release() is automatically called when $oObject goes out of scope. So that cancels out the original $pObject reference. But the collections etc. that you're passing directly to DllCallAddress() should probably be released at some point! Edited Monday at 05:59 AM by MattyD Danyfirex and junkew 2
junkew Posted yesterday at 07:45 PM Author Posted yesterday at 07:45 PM And made a small WinRt WinMD explorer as a learning exercise (not sure whom learned more me or AI, both didnt understand but together we made it 😉 ) in hours instead of months expandcollapse popup; ===================================================================================== ; WINMD METADATA EXPLORER - OCR-STYLE HYBRID METHOD (UITGEBREID) ; Gebaseerd op de bewezen technieken uit het WinRT OCR script. ; ; UITBREIDINGEN: ; - GUID per interface/type (via GuidAttribute custom attribute) ; - Gedecodeerde method-signatures (echte parameter-types i.p.v. ptr*) ; - Properties & Fields enumeratie ; - CRLF na elke method-definitie in de dtag string ; ===================================================================================== #include <GUIConstantsEx.au3> #include <TreeViewConstants.au3> #include <WindowsConstants.au3> #include <WinAPI.au3> #region --- GLOBALS & DLLS (persistente handles) --- Global $hDLLComBase = DllOpen("combase.dll") Global $hDLLOle32 = DllOpen("ole32.dll") Global $hDLLRoMetaData = DllOpen("rometadata.dll") #endregion #region --- GUIDS (CORRECTE WinRT-varianten) --- Global Const $sCLSID_CorMetaDataDispenser = "{E5CB7A31-7512-11D2-89CE-0080C792E5D8}" Global Const $sIID_IMetaDataDispenser = "{809C652E-7396-11D2-9771-00A0C9B4D50C}" Global Const $sIID_IMetaDataImport = "{7DAC8207-D3AE-4C75-9B67-92801A497D44}" Global Const $ofRead = 0x00000000 ; Token tabel-types Global Const $MDT_TypeDef = 0x02000000 Global Const $MDT_TypeRef = 0x01000000 Global Const $MDT_TypeSpec = 0x1B000000 Global Const $MDT_MethodDef = 0x06000000 #endregion #region --- ELEMENT TYPE CONSTANTEN (voor signature decoding) --- Global Const $ELEMENT_TYPE_VOID = 0x01 Global Const $ELEMENT_TYPE_BOOLEAN = 0x02 Global Const $ELEMENT_TYPE_CHAR = 0x03 Global Const $ELEMENT_TYPE_I1 = 0x04 Global Const $ELEMENT_TYPE_U1 = 0x05 Global Const $ELEMENT_TYPE_I2 = 0x06 Global Const $ELEMENT_TYPE_U2 = 0x07 Global Const $ELEMENT_TYPE_I4 = 0x08 Global Const $ELEMENT_TYPE_U4 = 0x09 Global Const $ELEMENT_TYPE_I8 = 0x0A Global Const $ELEMENT_TYPE_U8 = 0x0B Global Const $ELEMENT_TYPE_R4 = 0x0C Global Const $ELEMENT_TYPE_R8 = 0x0D Global Const $ELEMENT_TYPE_STRING = 0x0E Global Const $ELEMENT_TYPE_BYREF = 0x10 Global Const $ELEMENT_TYPE_VALUETYPE = 0x11 Global Const $ELEMENT_TYPE_CLASS = 0x12 Global Const $ELEMENT_TYPE_VAR = 0x13 Global Const $ELEMENT_TYPE_GENERICINST = 0x15 Global Const $ELEMENT_TYPE_I = 0x18 Global Const $ELEMENT_TYPE_U = 0x19 Global Const $ELEMENT_TYPE_OBJECT = 0x1C Global Const $ELEMENT_TYPE_SZARRAY = 0x1D ; Map: element-type -> leesbare naam Global $g_mElementType[] $g_mElementType[$ELEMENT_TYPE_VOID] = "Void" $g_mElementType[$ELEMENT_TYPE_BOOLEAN] = "Boolean" $g_mElementType[$ELEMENT_TYPE_CHAR] = "Char16" $g_mElementType[$ELEMENT_TYPE_I1] = "Int8" $g_mElementType[$ELEMENT_TYPE_U1] = "UInt8" $g_mElementType[$ELEMENT_TYPE_I2] = "Int16" $g_mElementType[$ELEMENT_TYPE_U2] = "UInt16" $g_mElementType[$ELEMENT_TYPE_I4] = "Int32" $g_mElementType[$ELEMENT_TYPE_U4] = "UInt32" $g_mElementType[$ELEMENT_TYPE_I8] = "Int64" $g_mElementType[$ELEMENT_TYPE_U8] = "UInt64" $g_mElementType[$ELEMENT_TYPE_R4] = "Single" $g_mElementType[$ELEMENT_TYPE_R8] = "Double" $g_mElementType[$ELEMENT_TYPE_STRING] = "String" $g_mElementType[$ELEMENT_TYPE_OBJECT] = "Object" ; Map: element-type -> AutoIt DllCall type (voor de dtag) Global $g_mAutoItType[] $g_mAutoItType[$ELEMENT_TYPE_VOID] = "none" $g_mAutoItType[$ELEMENT_TYPE_BOOLEAN] = "bool" $g_mAutoItType[$ELEMENT_TYPE_CHAR] = "word" $g_mAutoItType[$ELEMENT_TYPE_I1] = "byte" $g_mAutoItType[$ELEMENT_TYPE_U1] = "byte" $g_mAutoItType[$ELEMENT_TYPE_I2] = "short" $g_mAutoItType[$ELEMENT_TYPE_U2] = "ushort" $g_mAutoItType[$ELEMENT_TYPE_I4] = "long" $g_mAutoItType[$ELEMENT_TYPE_U4] = "ulong" $g_mAutoItType[$ELEMENT_TYPE_I8] = "int64" $g_mAutoItType[$ELEMENT_TYPE_U8] = "uint64" $g_mAutoItType[$ELEMENT_TYPE_R4] = "float" $g_mAutoItType[$ELEMENT_TYPE_R8] = "double" $g_mAutoItType[$ELEMENT_TYPE_STRING] = "ptr" $g_mAutoItType[$ELEMENT_TYPE_OBJECT] = "ptr" #endregion #region --- INTERFACE BLUEPRINTS (tags) --- Global $tagIMetaDataDispenser = _ "DefineScope hresult(ptr;dword;ptr;ptr*);" & _ "OpenScope hresult(wstr;dword;struct*;ptr*);" & _ "OpenScopeOnMemory hresult(ptr;dword;dword;struct*;ptr*);" ; IMetaDataImport - vtable in exacte cor.h volgorde ; Uitgebreid met GetPropertyProps, GetCustomAttributeByName, GetSigFromToken Global $tagIMetaDataImport = _ "CloseEnum none(ptr);" & _ "CountEnum hresult(ptr;ulong*);" & _ "ResetEnum hresult(ptr;ulong);" & _ "EnumTypeDefs hresult(ptr*;ptr;ulong;ulong*);" & _ "EnumInterfaceImpls hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumTypeRefs hresult(ptr*;ptr;ulong;ulong*);" & _ "FindTypeDefByName hresult(wstr;dword;dword*);" & _ "GetScopeProps hresult(ptr;ulong;ulong*;ptr);" & _ "GetModuleFromScope hresult(dword*);" & _ "GetTypeDefProps hresult(dword;ptr;ulong;ulong*;dword*;dword*);" & _ "GetInterfaceImplProps hresult(dword;dword*;dword*);" & _ "GetTypeRefProps hresult(dword;dword*;ptr;ulong;ulong*);" & _ "ResolveTypeRef hresult(dword;ptr;ptr*;dword*);" & _ "EnumMembers hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumMembersWithName hresult(ptr*;dword;wstr;ptr;ulong;ulong*);" & _ "EnumMethods hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumMethodsWithName hresult(ptr*;dword;wstr;ptr;ulong;ulong*);" & _ "EnumFields hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumFieldsWithName hresult(ptr*;dword;wstr;ptr;ulong;ulong*);" & _ "EnumParams hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumMemberRefs hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumMethodImpls hresult(ptr*;dword;ptr;ptr;ulong;ulong*);" & _ "EnumPermissionSets hresult(ptr*;dword;dword;ptr;ulong;ulong*);" & _ "FindMember hresult(dword;wstr;ptr;ulong;dword*);" & _ "FindMethod hresult(dword;wstr;ptr;ulong;dword*);" & _ "FindField hresult(dword;wstr;ptr;ulong;dword*);" & _ "FindMemberRef hresult(dword;wstr;ptr;ulong;dword*);" & _ "GetMethodProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;ptr*;ulong*;ulong*;dword*);" & _ "GetMemberRefProps hresult(dword;dword*;ptr;ulong;ulong*;ptr*;ulong*);" & _ "EnumProperties hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumEvents hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "GetEventProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;dword*;dword*;dword*;dword*;dword*;ptr;ulong;ulong*);" & _ "EnumMethodSemantics hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "GetMethodSemantics hresult(dword;dword;dword*);" & _ "GetClassLayout hresult(dword;dword*;ptr;ulong;ulong*;ulong*);" & _ "GetFieldMarshal hresult(dword;ptr*;ulong*);" & _ "GetRVA hresult(dword;ulong*;dword*);" & _ "GetPermissionSetProps hresult(dword;dword*;ptr*;ulong*);" & _ "GetSigFromToken hresult(dword;ptr*;ulong*);" & _ "GetModuleRefProps hresult(dword;ptr;ulong;ulong*);" & _ "EnumModuleRefs hresult(ptr*;ptr;ulong;ulong*);" & _ "GetTypeSpecFromToken hresult(dword;ptr*;ulong*);" & _ "GetNameFromToken hresult(dword;ptr*);" & _ "EnumUnresolvedMethods hresult(ptr*;ptr;ulong;ulong*);" & _ "GetUserString hresult(dword;ptr;ulong;ulong*);" & _ "GetPinvokeMap hresult(dword;dword*;ptr;ulong;ulong*;dword*);" & _ "EnumSignatures hresult(ptr*;ptr;ulong;ulong*);" & _ "EnumTypeSpecs hresult(ptr*;ptr;ulong;ulong*);" & _ "EnumUserStrings hresult(ptr*;ptr;ulong;ulong*);" & _ "GetParamForMethodIndex hresult(dword;ulong;dword*);" & _ "EnumCustomAttributes hresult(ptr*;dword;dword;ptr;ulong;ulong*);" & _ "GetCustomAttributeProps hresult(dword;dword*;dword*;ptr*;ulong*);" & _ "FindTypeRef hresult(dword;wstr;dword*);" & _ "GetMemberProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;ptr*;ulong*;dword*;dword*;dword*;ptr*;ulong*);" & _ "GetFieldProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;ptr*;ulong*;dword*;ptr*;ulong*);" & _ "GetPropertyProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;ptr*;ulong*;dword*;ptr*;ulong*;dword*;dword*;ptr;ulong;ulong*);" & _ "GetParamProps hresult(dword;dword*;ulong*;ptr;ulong;ulong*;dword*;dword*;ptr*;ulong*);" & _ "GetCustomAttributeByName hresult(dword;wstr;ptr*;ulong*);" & _ "IsValidToken bool(dword);" & _ "GetNestedClassProps hresult(dword;dword*);" & _ "GetNativeCallConvFromSig hresult(ptr;ulong;ulong*);" & _ "IsGlobal hresult(dword;int*);" #endregion #region --- PADEN --- Global $sWinMDDir = @SystemDir & "\WinMetadata" Global Const $sDefaultWinMDName = "Windows.Media.winmd" #endregion #region --- STEP 1: INIT WINRT & GUI --- ConsoleWrite(">>> [Step 1] Initializing WinRT & GUI..." & @CRLF) ConsoleWrite(" AutoIt bitness: " & (@AutoItX64 ? "x64" : "x86") & @CRLF) If Not @AutoItX64 Then ConsoleWrite(" ! WAARSCHUWING: rometadata.dll vereist x64!" & @CRLF) EndIf DllCall($hDLLComBase, "long", "RoInitialize", "int", 1) Global $hGUI = GUICreate("WinMD Explorer (OCR-stijl) - Uitgebreid", 1100, 750) GUICtrlCreateLabel("Selecteer WinMD Bestand:", 10, 10, 360, 20) Global $idComboWinMD = GUICtrlCreateCombo("", 10, 30, 360, 25) Global $idTree = GUICtrlCreateTreeView(10, 65, 360, 675, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT)) Global $idEditInfo = GUICtrlCreateEdit("", 380, 30, 710, 160) Global $idEditDTag = GUICtrlCreateEdit("", 380, 215, 710, 260) Global $idEditCode = GUICtrlCreateEdit("", 380, 500, 710, 240) GUICtrlCreateLabel("Type Informatie (GUID, Properties, Fields):", 380, 10, 400, 20) GUICtrlCreateLabel("Gegenereerde $dtag VTable String:", 380, 195, 400, 20) GUICtrlCreateLabel("AutoIt WinRT Boilerplate Code:", 380, 480, 400, 20) _PopulateWinMDCombo() GUISetState(@SW_SHOW) ConsoleWrite(" + GUI getoond." & @CRLF & @CRLF) #endregion ; Globale state Global $g_oImport = 0 Global $g_pImport = 0 Global $g_mTokens[10000] Global $g_hLastSelectedTreeItem = 0 Global $g_sLastSelectedWinMD = "" _LoadSelectedWinMD() ; --- MAIN LOOP --- While 1 Local $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE ExitLoop Case $idComboWinMD _LoadSelectedWinMD() EndSwitch Local $hSelectedTree = GUICtrlRead($idTree) If $hSelectedTree <> 0 And $hSelectedTree <> $g_hLastSelectedTreeItem Then $g_hLastSelectedTreeItem = $hSelectedTree _OnTreeItemSelected($hSelectedTree) EndIf WEnd ; --- CLEANUP --- ConsoleWrite(">>> Cleanup..." & @CRLF) DllCall($hDLLComBase, "none", "RoUninitialize") DllClose($hDLLComBase) DllClose($hDLLOle32) DllClose($hDLLRoMetaData) Exit ; ===================================================================================== ; STEP 2: DISPENSER ; ===================================================================================== Func _WinRT_GetMetaDataDispenser() Local $tCLSID = _WinRT_CreateGUID($sCLSID_CorMetaDataDispenser) Local $tIID = _WinRT_CreateGUID($sIID_IMetaDataDispenser) Local $aRes = DllCall($hDLLRoMetaData, "long", "MetaDataGetDispenser", _ "struct*", $tCLSID, "struct*", $tIID, "ptr*", 0) If @error Then Return 0 ConsoleWrite(StringFormat(" -> MetaDataGetDispenser HRESULT: 0x%08X | Ptr: 0x%X\n", $aRes[0], $aRes[3])) If $aRes[0] >= 0 And $aRes[3] <> 0 Then Return $aRes[3] Return 0 EndFunc ;==>_WinRT_GetMetaDataDispenser ; ===================================================================================== ; STEP 3: WINMD LADEN ; ===================================================================================== Func _LoadSelectedWinMD() Local $sSelectedFile = GUICtrlRead($idComboWinMD) If $sSelectedFile = "" Or $sSelectedFile = $g_sLastSelectedWinMD Then Return $g_sLastSelectedWinMD = $sSelectedFile Local $sFullPath = $sWinMDDir & "\" & $sSelectedFile ConsoleWrite("=================================================================" & @CRLF) ConsoleWrite(">>> LAAD: '" & $sSelectedFile & "'" & @CRLF) ConsoleWrite("=================================================================" & @CRLF) GUICtrlSendMsg($idTree, 0x1101, 0, 0) GUICtrlSetData($idEditInfo, "") GUICtrlSetData($idEditDTag, "") GUICtrlSetData($idEditCode, "") $g_hLastSelectedTreeItem = 0 ReDim $g_mTokens[10000] If Not FileExists($sFullPath) Then ConsoleWrite(" ! Bestand niet gevonden: " & $sFullPath & @CRLF) Return EndIf Local $pDispenser = _WinRT_GetMetaDataDispenser() If Not $pDispenser Then Return Local $oDispenser = ObjCreateInterface($pDispenser, $sIID_IMetaDataDispenser, $tagIMetaDataDispenser, True) If Not IsObj($oDispenser) Then Return ConsoleWrite(" + IMetaDataDispenser object aangemaakt." & @CRLF) Local $tIID_Import = _WinRT_CreateGUID($sIID_IMetaDataImport) $g_pImport = 0 Local $hr = $oDispenser.OpenScope($sFullPath, $ofRead, $tIID_Import, $g_pImport) ConsoleWrite(StringFormat(" -> OpenScope HRESULT: 0x%08X | Scope Ptr: 0x%X\n", $hr, $g_pImport)) If $hr < 0 Or $g_pImport = 0 Then Return $g_oImport = ObjCreateInterface($g_pImport, $sIID_IMetaDataImport, $tagIMetaDataImport, True) If Not IsObj($g_oImport) Then Return ConsoleWrite(" + IMetaDataImport object aangemaakt." & @CRLF) _PopulateTreeView($sSelectedFile) EndFunc ;==>_LoadSelectedWinMD ; ===================================================================================== ; STEP 4: TYPEDEFS ENUMEREREN ; ===================================================================================== Func _PopulateTreeView($sFileName) Local $idRootNode = GUICtrlCreateTreeViewItem($sFileName, $idTree) Local $hEnum = 0 Local $tTokens = DllStructCreate("dword Tokens[5000]") Local $iCount = 0 Local $hr = $g_oImport.EnumTypeDefs($hEnum, DllStructGetPtr($tTokens), 5000, $iCount) ConsoleWrite(StringFormat(" -> EnumTypeDefs HRESULT: 0x%08X | Aantal: %d\n", $hr, $iCount)) If $hEnum <> 0 Then $g_oImport.CloseEnum($hEnum) If $hr < 0 Or $iCount = 0 Then Return Local $iAdded = 0 For $i = 1 To $iCount Local $idToken = DllStructGetData($tTokens, "Tokens", $i) Local $tName = DllStructCreate("wchar Name[512]") Local $iNameLen = 0, $iFlags = 0, $iExtends = 0 Local $hrProp = $g_oImport.GetTypeDefProps($idToken, DllStructGetPtr($tName), 512, $iNameLen, $iFlags, $iExtends) If $hrProp < 0 Then ContinueLoop Local $sTypeName = DllStructGetData($tName, "Name") If $sTypeName <> "" Then Local $idItem = GUICtrlCreateTreeViewItem($sTypeName, $idRootNode) If $idItem > 0 And $idItem < UBound($g_mTokens) Then $g_mTokens[$idItem] = $idToken $iAdded += 1 EndIf Next ConsoleWrite(StringFormat(" + %d TypeDefs toegevoegd.\n\n", $iAdded)) EndFunc ;==>_PopulateTreeView ; ===================================================================================== ; EVENT: TreeView selectie ; ===================================================================================== Func _OnTreeItemSelected($idItem) Local $sText = GUICtrlRead($idItem, 1) If $idItem >= UBound($g_mTokens) Or $g_mTokens[$idItem] = 0 Then Return Local $idToken = $g_mTokens[$idItem] ConsoleWrite(StringFormat(">>> TypeDef geselecteerd: '%s' (Token: 0x%08X)\n", $sText, $idToken)) _ShowTypeInfo($sText, $idToken) _GenerateClassCode($sText, $idToken) EndFunc ;==>_OnTreeItemSelected ; ===================================================================================== ; UITBREIDING 1 & 3: TYPE INFO (GUID + Properties + Fields) ; ===================================================================================== Func _ShowTypeInfo($sClassName, $idTypeDefToken) Local $sInfo = "Type: " & $sClassName & @CRLF $sInfo &= "TypeDef Token: 0x" & Hex($idTypeDefToken, 8) & @CRLF ; --- GUID ophalen via GuidAttribute --- Local $sGUID = _MetaData_GetGUIDAttrib($idTypeDefToken) If $sGUID <> "" Then $sInfo &= "GUID (IID): " & $sGUID & @CRLF Else $sInfo &= "GUID (IID): <geen - dit type heeft geen GuidAttribute>" & @CRLF EndIf ; --- Properties enumereren --- $sInfo &= @CRLF & "--- Properties ---" & @CRLF Local $hEnum = 0 Local $tPropTokens = DllStructCreate("dword Tokens[200]") Local $iPropCount = 0 Local $hr = $g_oImport.EnumProperties($hEnum, $idTypeDefToken, DllStructGetPtr($tPropTokens), 200, $iPropCount) If $hEnum <> 0 Then $g_oImport.CloseEnum($hEnum) If $hr >= 0 And $iPropCount > 0 Then For $i = 1 To $iPropCount Local $idPropTkn = DllStructGetData($tPropTokens, "Tokens", $i) Local $sPropName = _MetaData_GetPropertyName($idPropTkn) If $sPropName <> "" Then $sInfo &= " " & $sPropName & @CRLF Next Else $sInfo &= " <geen properties>" & @CRLF EndIf ; --- Fields enumereren --- $sInfo &= @CRLF & "--- Fields ---" & @CRLF $hEnum = 0 Local $tFieldTokens = DllStructCreate("dword Tokens[200]") Local $iFieldCount = 0 $hr = $g_oImport.EnumFields($hEnum, $idTypeDefToken, DllStructGetPtr($tFieldTokens), 200, $iFieldCount) If $hEnum <> 0 Then $g_oImport.CloseEnum($hEnum) If $hr >= 0 And $iFieldCount > 0 Then For $i = 1 To $iFieldCount Local $idFieldTkn = DllStructGetData($tFieldTokens, "Tokens", $i) Local $sFieldName = _MetaData_GetFieldName($idFieldTkn) If $sFieldName <> "" Then $sInfo &= " " & $sFieldName & @CRLF Next Else $sInfo &= " <geen fields>" & @CRLF EndIf GUICtrlSetData($idEditInfo, $sInfo) EndFunc ;==>_ShowTypeInfo ; ===================================================================================== ; STEP 5: METHODEN + SIGNATURE DECODING + BOILERPLATE ; ===================================================================================== Func _GenerateClassCode($sClassName, $idTypeDefToken) Local $hEnum = 0 Local $tMethodTokens = DllStructCreate("dword Tokens[500]") Local $iMethodCount = 0 Local $hr = $g_oImport.EnumMethods($hEnum, $idTypeDefToken, DllStructGetPtr($tMethodTokens), 500, $iMethodCount) ConsoleWrite(StringFormat(" -> EnumMethods HRESULT: 0x%08X | Aantal: %d\n", $hr, $iMethodCount)) If $hEnum <> 0 Then $g_oImport.CloseEnum($hEnum) ; IInspectable-methoden staan altijd vooraan (elk op eigen regel met CRLF) Local $sDTag = "GetIids hresult(ulong*;ptr*);" & @CRLF $sDTag &= "GetRuntimeClassName hresult(ptr*);" & @CRLF $sDTag &= "GetTrustLevel hresult(int*);" & @CRLF If $hr >= 0 And $iMethodCount > 0 Then For $i = 1 To $iMethodCount Local $idMethodToken = DllStructGetData($tMethodTokens, "Tokens", $i) Local $tMethodName = DllStructCreate("wchar Name[256]") Local $iNameLen = 0, $iClass = 0, $iAttr = 0 Local $pSig = 0, $cbSig = 0, $iRVA = 0, $iImpl = 0 Local $hrM = $g_oImport.GetMethodProps($idMethodToken, $iClass, DllStructGetPtr($tMethodName), _ 256, $iNameLen, $iAttr, $pSig, $cbSig, $iRVA, $iImpl) If $hrM < 0 Then ContinueLoop Local $sMethodName = DllStructGetData($tMethodName, "Name") ; Sla .ctor / interne methoden over If $sMethodName = "" Or StringLeft($sMethodName, 1) = "." Then ContinueLoop ; --- UITBREIDING 2: signature decoderen --- Local $sAutoItSig = _MetaData_DecodeMethodSig($pSig, $cbSig) ConsoleWrite(StringFormat(" + [%d/%d] %s %s\n", $i, $iMethodCount, $sMethodName, $sAutoItSig)) ; Elke method op eigen regel met CRLF $sDTag &= $sMethodName & " " & $sAutoItSig & ";" & @CRLF Next EndIf Local $sClassSafe = StringReplace($sClassName, ".", "_") Local $sGUID = _MetaData_GetGUIDAttrib($idTypeDefToken) If $sGUID = "" Then $sGUID = "{PLAATS-HIER-DE-IID}" ; dtag string GUICtrlSetData($idEditDTag, '$tag' & $sClassSafe & ' = _' & @CRLF & '"' & $sDTag & '"') ; Boilerplate met echte GUID Local $sCode = _ '; === WINRT BOILERPLATE: ' & $sClassName & ' ===' & @CRLF & _ 'Global Const $sIID_' & $sClassSafe & ' = "' & $sGUID & '"' & @CRLF & @CRLF & _ '; Factory ophalen (OCR-stijl)' & @CRLF & _ 'Local $pFactory = _WinRT_RoGetActivationFactory("' & $sClassName & '", $sIID_' & $sClassSafe & ')' & @CRLF & _ 'Local $oObj = ObjCreateInterface($pFactory, $sIID_' & $sClassSafe & ', $tag' & $sClassSafe & ', True)' & @CRLF & _ 'If IsObj($oObj) Then' & @CRLF & _ ' ConsoleWrite("+ Geactiveerd!" & @CRLF)' & @CRLF & _ ' ; $oObj.MethodeNaam(...)' & @CRLF & _ 'EndIf' GUICtrlSetData($idEditCode, $sCode) EndFunc ;==>_GenerateClassCode ; ===================================================================================== ; UITBREIDING 1: GUID via GuidAttribute custom attribute ; ===================================================================================== Func _MetaData_GetGUIDAttrib($idToken) Local $pData = 0, $cbData = 0 Local $hr = $g_oImport.GetCustomAttributeByName($idToken, _ "Windows.Foundation.Metadata.GuidAttribute", $pData, $cbData) ; S_OK = 0. S_FALSE = 1 (attribuut niet aanwezig) If $hr <> 0 Or $pData = 0 Or $cbData < 20 Then Return "" ; De blob begint met 2 prolog-bytes (0x01 0x00), daarna de 16-byte GUID ; Lees de GUID uit het geheugen op $pData + 2 Local $tGUID = DllStructCreate("dword Data1;word Data2;word Data3;byte Data4[8]", $pData + 2) Local $iData1 = DllStructGetData($tGUID, "Data1") Local $iData2 = DllStructGetData($tGUID, "Data2") Local $iData3 = DllStructGetData($tGUID, "Data3") ; Data4 zijn 8 losse bytes Local $sData4 = "" For $i = 1 To 8 $sData4 &= Hex(DllStructGetData($tGUID, "Data4", $i), 2) Next Return StringFormat("{%08X-%04X-%04X-%s-%s}", $iData1, $iData2, $iData3, _ StringLeft($sData4, 4), StringMid($sData4, 5)) EndFunc ;==>_MetaData_GetGUIDAttrib ; ===================================================================================== ; UITBREIDING 3: Property naam ophalen ; ===================================================================================== Func _MetaData_GetPropertyName($idPropTkn) Local $tName = DllStructCreate("wchar Name[256]") Local $iClass = 0, $iNameLen = 0, $iFlags = 0 Local $pSig = 0, $cbSig = 0, $iCPlusTypeFlag = 0 Local $pDefVal = 0, $cbDefVal = 0 Local $iSetter = 0, $iGetter = 0 Local $tOtherMethods = DllStructCreate("dword[10]") Local $iOtherCount = 0 Local $hr = $g_oImport.GetPropertyProps($idPropTkn, $iClass, DllStructGetPtr($tName), 256, $iNameLen, _ $iFlags, $pSig, $cbSig, $iCPlusTypeFlag, $pDefVal, $cbDefVal, _ $iSetter, $iGetter, DllStructGetPtr($tOtherMethods), 10, $iOtherCount) If $hr < 0 Then Return "" Return DllStructGetData($tName, "Name") EndFunc ;==>_MetaData_GetPropertyName ; ===================================================================================== ; UITBREIDING 3: Field naam ophalen ; ===================================================================================== Func _MetaData_GetFieldName($idFieldTkn) Local $tName = DllStructCreate("wchar Name[256]") Local $iClass = 0, $iNameLen = 0, $iAttr = 0 Local $pSig = 0, $cbSig = 0, $iCPlusTypeFlag = 0 Local $pValue = 0, $cchValue = 0 Local $hr = $g_oImport.GetFieldProps($idFieldTkn, $iClass, DllStructGetPtr($tName), 256, $iNameLen, _ $iAttr, $pSig, $cbSig, $iCPlusTypeFlag, $pValue, $cchValue) If $hr < 0 Then Return "" Return DllStructGetData($tName, "Name") EndFunc ;==>_MetaData_GetFieldName ; ===================================================================================== ; UITBREIDING 2: Method signature decoderen naar AutoIt DllCall types ; Geeft iets als: hresult(ptr;float;bool*) terug ; ===================================================================================== Func _MetaData_DecodeMethodSig($pSig, $cbSig) ; Fallback als er geen signature is If $pSig = 0 Or $cbSig = 0 Then Return "hresult(ptr*)" ; Kopieer de signature-blob naar een leesbare struct Local $tSig = DllStructCreate("byte[" & $cbSig & "]", $pSig) Local $iReadPtr = 1 ; Byte 1: calling convention (HASTHIS etc.) - overslaan $iReadPtr += 1 ; Byte 2: aantal parameters (compressed int) Local $iParamCount = __ReadCompressedInt($tSig, $iReadPtr) ; Return type (het eerste "type" na de param-count is de return type) Local $sRetType = __ReadSigType($tSig, $iReadPtr) ; WinRT-methoden geven altijd HRESULT terug; de "echte" return komt als ; laatste out-param. We bouwen de AutoIt-signatuur op met HRESULT. Local $sResult = "hresult(" ; De parameters Local $sParams = "" For $p = 1 To $iParamCount Local $sParamType = __ReadSigType($tSig, $iReadPtr) If $sParams <> "" Then $sParams &= ";" $sParams &= $sParamType Next ; De WinRT-return-waarde wordt als out-param toegevoegd (behalve bij Void) If $sRetType <> "none" Then If $sParams <> "" Then $sParams &= ";" $sParams &= $sRetType & "*" EndIf ; Als er helemaal geen params/return zijn -> minimaal ptr* If $sParams = "" Then $sParams = "ptr*" $sResult &= $sParams & ")" Return $sResult EndFunc ;==>_MetaData_DecodeMethodSig ; --- Lees een enkel type uit de signature-blob --- Func __ReadSigType(ByRef $tSig, ByRef $iReadPtr) Local $iType = DllStructGetData($tSig, 1, $iReadPtr) $iReadPtr += 1 Switch $iType Case $ELEMENT_TYPE_VOID Return "none" Case $ELEMENT_TYPE_BOOLEAN Return "bool" Case $ELEMENT_TYPE_CHAR Return "word" Case $ELEMENT_TYPE_I1, $ELEMENT_TYPE_U1 Return "byte" Case $ELEMENT_TYPE_I2 Return "short" Case $ELEMENT_TYPE_U2 Return "ushort" Case $ELEMENT_TYPE_I4 Return "long" Case $ELEMENT_TYPE_U4 Return "ulong" Case $ELEMENT_TYPE_I8 Return "int64" Case $ELEMENT_TYPE_U8 Return "uint64" Case $ELEMENT_TYPE_R4 Return "float" Case $ELEMENT_TYPE_R8 Return "double" Case $ELEMENT_TYPE_STRING Return "ptr" ; HSTRING Case $ELEMENT_TYPE_OBJECT Return "ptr" Case $ELEMENT_TYPE_I Return "ptr" ; IntPtr Case $ELEMENT_TYPE_U Return "ptr" ; UIntPtr Case $ELEMENT_TYPE_BYREF ; ByRef -> onderliggend type + * Return __ReadSigType($tSig, $iReadPtr) & "*" Case $ELEMENT_TYPE_VALUETYPE, $ELEMENT_TYPE_CLASS ; Gevolgd door een compressed token -> we lezen het weg __ReadCompressedInt($tSig, $iReadPtr) Return "ptr" ; struct of interface-pointer Case $ELEMENT_TYPE_GENERICINST ; Generic instance: type + arg-count + args. Behandel als ptr. __ReadSigType($tSig, $iReadPtr) ; het generieke type Local $iArgs = __ReadCompressedInt($tSig, $iReadPtr) For $a = 1 To $iArgs __ReadSigType($tSig, $iReadPtr) ; args wegleze Next Return "ptr" Case $ELEMENT_TYPE_SZARRAY ; Array: element-type + we behandelen als ptr __ReadSigType($tSig, $iReadPtr) Return "ptr" Case $ELEMENT_TYPE_VAR ; Generic type var: gevolgd door index __ReadCompressedInt($tSig, $iReadPtr) Return "ptr" Case Else Return "ptr" ; onbekend -> veilige fallback EndSwitch EndFunc ;==>__ReadSigType ; --- Lees een ECMA-335 compressed integer --- Func __ReadCompressedInt(ByRef $tSig, ByRef $iReadPtr) Local $iByte1 = DllStructGetData($tSig, 1, $iReadPtr) If BitAND($iByte1, 0x80) = 0 Then ; 1-byte waarde $iReadPtr += 1 Return $iByte1 ElseIf BitAND($iByte1, 0xC0) = 0x80 Then ; 2-byte waarde Local $iByte2 = DllStructGetData($tSig, 1, $iReadPtr + 1) $iReadPtr += 2 Return BitOR(BitShift(BitAND($iByte1, 0x3F), -8), $iByte2) Else ; 4-byte waarde Local $iByte2 = DllStructGetData($tSig, 1, $iReadPtr + 1) Local $iByte3 = DllStructGetData($tSig, 1, $iReadPtr + 2) Local $iByte4 = DllStructGetData($tSig, 1, $iReadPtr + 3) $iReadPtr += 4 Return BitOR(BitShift(BitAND($iByte1, 0x1F), -24), _ BitShift($iByte2, -16), _ BitShift($iByte3, -8), $iByte4) EndIf EndFunc ;==>__ReadCompressedInt ; ===================================================================================== ; DROPDOWN VULLEN ; ===================================================================================== Func _PopulateWinMDCombo() Local $hSearch = FileFindFirstFile($sWinMDDir & "\*.winmd") If $hSearch = -1 Then Return Local $sFileList = "", $sFileName = "" While 1 $sFileName = FileFindNextFile($hSearch) If @error Then ExitLoop $sFileList &= $sFileName & "|" WEnd FileClose($hSearch) GUICtrlSetData($idComboWinMD, $sFileList, $sDefaultWinMDName) EndFunc ;==>_PopulateWinMDCombo ; ===================================================================================== ; HELPER FUNCTIONS (OCR-stijl) ; ===================================================================================== Func _WinRT_CreateGUID($sGUID) Local $tGUID = DllStructCreate("dword Data1;word Data2;word Data3;byte Data4[8]") DllCall($hDLLOle32, "long", "CLSIDFromString", "wstr", $sGUID, "struct*", $tGUID) Return $tGUID EndFunc ;==>_WinRT_CreateGUID Func _WinRT_CreateHString($sString) Local $aRes = DllCall($hDLLComBase, "long", "WindowsCreateString", "wstr", $sString, "uint", StringLen($sString), "ptr*", 0) If @error Or $aRes[0] < 0 Then Return 0 Return $aRes[3] EndFunc ;==>_WinRT_CreateHString Func _WinRT_DeleteHString(ByRef $hString) If $hString = 0 Then Return DllCall($hDLLComBase, "long", "WindowsDeleteString", "ptr", $hString) $hString = 0 EndFunc ;==>_WinRT_DeleteHString Func _WinRT_GetHStringText($hString) If $hString = 0 Then Return "" Local $aRes = DllCall($hDLLComBase, "ptr", "WindowsGetStringRawBuffer", "ptr", $hString, "uint*", 0) If @error Or $aRes[0] = 0 Then Return "" Local $iLength = $aRes[2] If $iLength = 0 Then Return "" Local $tString = DllStructCreate("wchar[" & ($iLength + 1) & "]", $aRes[0]) Return DllStructGetData($tString, 1) EndFunc ;==>_WinRT_GetHStringText FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
junkew Posted yesterday at 09:18 PM Author Posted yesterday at 09:18 PM And as we can dynamically explore we can also dynamically do all stuff without all the includes generated. Should split it to a UDF logic and demo part, probably some delay while loading but probably not that visible expandcollapse popup; ===================================================================================== ; DEMO ; ===================================================================================== ConsoleWrite(">>> [Demo] Universele WinRT Import Engine..." & @CRLF) Local $sTargetClass = "Windows.Globalization.Calendar" ConsoleWrite(">>> [Demo] Importeren: " & $sTargetClass & @CRLF) Local $bImportSuccess = _WinRT_Dynamic_Import($sTargetClass) If $bImportSuccess Then ConsoleWrite(">>> [Demo] Succes! Interface runtime opgebouwd." & @CRLF) Local $oCalendar = Eval("WinRT_Windows_Globalization_Calendar") If IsObj($oCalendar) Then ConsoleWrite(">>> [Demo] Object benaderd via Eval()." & @CRLF) ; --- Test property getters (WinRT properties hebben get_ prefix!) --- Local $iYear = 0 Local $hr = $oCalendar.get_Year($iYear) ConsoleWrite(">>> [Demo] get_Year HRESULT: 0x" & Hex($hr, 8) & " | Jaar: " & $iYear & @CRLF) Local $iMonth = 0 $hr = $oCalendar.get_Month($iMonth) ConsoleWrite(">>> [Demo] get_Month HRESULT: 0x" & Hex($hr, 8) & " | Maand: " & $iMonth & @CRLF) Local $iDay = 0 $hr = $oCalendar.get_Day($iDay) ConsoleWrite(">>> [Demo] get_Day HRESULT: 0x" & Hex($hr, 8) & " | Dag: " & $iDay & @CRLF) Local $iHour = 0 $hr = $oCalendar.get_Hour($iHour) ConsoleWrite(">>> [Demo] get_Hour HRESULT: 0x" & Hex($hr, 8) & " | Uur: " & $iHour & @CRLF) MsgBox(64, "WinRT Dynamic Engine", _ $sTargetClass & " is runtime geïmporteerd en geactiveerd!" & @CRLF & @CRLF & _ "Huidige datum volgens WinRT Calendar:" & @CRLF & _ "Jaar: " & $iYear & @CRLF & _ "Maand: " & $iMonth & @CRLF & _ "Dag: " & $iDay & @CRLF & _ "Uur: " & $iHour) Else ConsoleWrite("! [Demo] Gegenereerd element is geen object." & @CRLF) EndIf Else ConsoleWrite("! [Demo] Import mislukt. Foutcode: " & @error & @CRLF) EndIf Full script to copy/paste expandcollapse popup#pragma compile(x64, true) ; ===================================================================================== ; WINRT UNIVERSAL DYNAMIC ENGINE & DEMO (GECORRIGEERD) ; ; KERN-INZICHT: Een RuntimeClass (bv. Windows.Globalization.Calendar) is GEEN ; interface. Je moet via de metadata de DEFAULT INTERFACE (bv. ICalendar) vinden, ; die IID + methoden ophalen, RoActivateInstance de class, en dan QueryInterface ; naar de default interface. ; ===================================================================================== #include <AutoItConstants.au3> #include <WinAPI.au3> #include <Array.au3> #region --- GLOBALS & DLL CONTEXT --- ; ===================================================================================== ; De volledige IMetaDataImport tag (als globale const) ; ===================================================================================== Global Const $GLOBAL_tagImport = _ "CloseEnum none(ptr);CountEnum hresult(ptr;ulong*);ResetEnum hresult(ptr;ulong);" & _ "EnumTypeDefs hresult(ptr*;ptr;ulong;ulong*);EnumInterfaceImpls hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumTypeRefs hresult(ptr*;ptr;ulong;ulong*);FindTypeDefByName hresult(wstr;dword;dword*);" & _ "GetScopeProps hresult(ptr;ulong;ulong*;ptr);GetModuleFromScope hresult(dword*);" & _ "GetTypeDefProps hresult(dword;ptr;ulong;ulong*;dword*;dword*);GetInterfaceImplProps hresult(dword;dword*;dword*);" & _ "GetTypeRefProps hresult(dword;dword*;ptr;ulong;ulong*);ResolveTypeRef hresult(dword;ptr;ptr*;dword*);" & _ "EnumMembers hresult(ptr*;dword;ptr;ulong;ulong*);EnumMembersWithName hresult(ptr*;dword;wstr;ptr;ulong;ulong*);" & _ "EnumMethods hresult(ptr*;dword;ptr;ulong;ulong*);EnumMethodsWithName hresult(ptr*;dword;wstr;ptr;ulong;ulong*);" & _ "EnumFields hresult(ptr*;dword;ptr;ulong;ulong*);EnumFieldsWithName hresult(ptr*;dword;wstr;ptr;ulong;ulong*);" & _ "EnumParams hresult(ptr*;dword;ptr;ulong;ulong*);EnumMemberRefs hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "EnumMethodImpls hresult(ptr*;dword;ptr;ptr;ulong;ulong*);EnumPermissionSets hresult(ptr*;dword;dword;ptr;ulong;ulong*);" & _ "FindMember hresult(dword;wstr;ptr;ulong;dword*);FindMethod hresult(dword;wstr;ptr;ulong;dword*);" & _ "FindField hresult(dword;wstr;ptr;ulong;dword*);FindMemberRef hresult(dword;wstr;ptr;ulong;dword*);" & _ "GetMethodProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;ptr*;ulong*;ulong*;dword*);" & _ "GetMemberRefProps hresult(dword;dword*;ptr;ulong;ulong*;ptr*;ulong*);" & _ "EnumProperties hresult(ptr*;dword;ptr;ulong;ulong*);EnumEvents hresult(ptr*;dword;ptr;ulong;ulong*);" & _ "GetEventProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;dword*;dword*;dword*;dword*;dword*;ptr;ulong;ulong*);" & _ "EnumMethodSemantics hresult(ptr*;dword;ptr;ulong;ulong*);GetMethodSemantics hresult(dword;dword;dword*);" & _ "GetClassLayout hresult(dword;dword*;ptr;ulong;ulong*;ulong*);GetFieldMarshal hresult(dword;ptr*;ulong*);" & _ "GetRVA hresult(dword;ulong*;dword*);GetPermissionSetProps hresult(dword;dword*;ptr*;ulong*);" & _ "GetSigFromToken hresult(dword;ptr*;ulong*);GetModuleRefProps hresult(dword;ptr;ulong;ulong*);" & _ "EnumModuleRefs hresult(ptr*;ptr;ulong;ulong*);GetTypeSpecFromToken hresult(dword;ptr*;ulong*);" & _ "GetNameFromToken hresult(dword;ptr*);EnumUnresolvedMethods hresult(ptr*;ptr;ulong;ulong*);" & _ "GetUserString hresult(dword;ptr;ulong;ulong*);GetPinvokeMap hresult(dword;dword*;ptr;ulong;ulong*;dword*);" & _ "EnumSignatures hresult(ptr*;ptr;ulong;ulong*);EnumTypeSpecs hresult(ptr*;ptr;ulong;ulong*);" & _ "EnumUserStrings hresult(ptr*;ptr;ulong;ulong*);GetParamForMethodIndex hresult(dword;ulong;dword*);" & _ "EnumCustomAttributes hresult(ptr*;dword;dword;ptr;ulong;ulong*);GetCustomAttributeProps hresult(dword;dword*;dword*;ptr*;ulong*);" & _ "FindTypeRef hresult(dword;wstr;dword*);GetMemberProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;ptr*;ulong*;dword*;dword*;dword*;ptr*;ulong*);" & _ "GetFieldProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;ptr*;ulong*;dword*;ptr*;ulong*);" & _ "GetPropertyProps hresult(dword;dword*;ptr;ulong;ulong*;dword*;ptr*;ulong*;dword*;ptr*;ulong*;dword*;dword*;ptr;ulong;ulong*);" & _ "GetParamProps hresult(dword;dword*;ulong*;ptr;ulong;ulong*;dword*;dword*;ptr*;ulong*);" & _ "GetCustomAttributeByName hresult(dword;wstr;ptr*;ulong*);IsValidToken bool(dword);" & _ "GetNestedClassProps hresult(dword;dword*);GetNativeCallConvFromSig hresult(ptr;ulong;ulong*);IsGlobal hresult(dword;int*);" Global $hDLLWinTypes = DllOpen("wintypes.dll") Global $hDLLComBase = DllOpen("combase.dll") Global $hDLLOle32 = DllOpen("ole32.dll") Global $hDLLRoMetaData = DllOpen("rometadata.dll") Local $aInit = DllCall($hDLLComBase, "long", "RoInitialize", "int", 0) ; 0 = STA If @error Then MsgBox(16, "Fout", "Kan WinRT niet initialiseren. Draai als x64!") Exit EndIf ; S_OK (0), S_FALSE (1) en RPC_E_CHANGED_MODE (0x80010106) zijn allemaal OK ConsoleWrite(" + RoInitialize HRESULT: 0x" & Hex($aInit[0], 8) & @CRLF) ; Vaste metadata GUIDs Global Const $sCLSID_CorMetaDataDispenser = "{E5CB7A31-7512-11D2-89CE-0080C792E5D8}" Global Const $sIID_IMetaDataDispenser = "{809C652E-7396-11D2-9771-00A0C9B4D50C}" Global Const $sIID_IMetaDataImport = "{7DAC8207-D3AE-4C75-9B67-92801A497D44}" ; Token tabel-types Global Const $MDT_TypeDef = 0x02000000 Global Const $MDT_TypeRef = 0x01000000 Global Const $MDT_TypeSpec = 0x1B000000 ; TypeDef flag: interface Global Const $tdInterface = 0x00000020 ; Globale metadata-objecten (herbruikbaar per winmd) Global $g_oImport = 0 #endregion ; ===================================================================================== ; DEMO ; ===================================================================================== ConsoleWrite(">>> [Demo] Universele WinRT Import Engine..." & @CRLF) Local $sTargetClass = "Windows.Globalization.Calendar" ConsoleWrite(">>> [Demo] Importeren: " & $sTargetClass & @CRLF) Local $bImportSuccess = _WinRT_Dynamic_Import($sTargetClass) If $bImportSuccess Then ConsoleWrite(">>> [Demo] Succes! Interface runtime opgebouwd." & @CRLF) Local $oCalendar = Eval("WinRT_Windows_Globalization_Calendar") If IsObj($oCalendar) Then ConsoleWrite(">>> [Demo] Object benaderd via Eval()." & @CRLF) ; --- Test property getters (WinRT properties hebben get_ prefix!) --- Local $iYear = 0 Local $hr = $oCalendar.get_Year($iYear) ConsoleWrite(">>> [Demo] get_Year HRESULT: 0x" & Hex($hr, 8) & " | Jaar: " & $iYear & @CRLF) Local $iMonth = 0 $hr = $oCalendar.get_Month($iMonth) ConsoleWrite(">>> [Demo] get_Month HRESULT: 0x" & Hex($hr, 8) & " | Maand: " & $iMonth & @CRLF) Local $iDay = 0 $hr = $oCalendar.get_Day($iDay) ConsoleWrite(">>> [Demo] get_Day HRESULT: 0x" & Hex($hr, 8) & " | Dag: " & $iDay & @CRLF) Local $iHour = 0 $hr = $oCalendar.get_Hour($iHour) ConsoleWrite(">>> [Demo] get_Hour HRESULT: 0x" & Hex($hr, 8) & " | Uur: " & $iHour & @CRLF) MsgBox(64, "WinRT Dynamic Engine", _ $sTargetClass & " is runtime geïmporteerd en geactiveerd!" & @CRLF & @CRLF & _ "Huidige datum volgens WinRT Calendar:" & @CRLF & _ "Jaar: " & $iYear & @CRLF & _ "Maand: " & $iMonth & @CRLF & _ "Dag: " & $iDay & @CRLF & _ "Uur: " & $iHour) Else ConsoleWrite("! [Demo] Gegenereerd element is geen object." & @CRLF) EndIf Else ConsoleWrite("! [Demo] Import mislukt. Foutcode: " & @error & @CRLF) EndIf DllCall($hDLLComBase, "none", "RoUninitialize") DllClose($hDLLComBase) DllClose($hDLLOle32) DllClose($hDLLRoMetaData) Exit ; ===================================================================================== ; UNIVERSAL ENGINE ; ===================================================================================== Func _WinRT_Dynamic_Import($sClassName) Local $sClassSafe = StringReplace($sClassName, ".", "_") If Eval("WinRT_" & $sClassSafe) <> "" Then Return True ; --- 1. Vind de .winmd file van deze class --- Local $sWinMDFullPath = _WinRT_LocateMetaDataFile($sClassName) If @error Or $sWinMDFullPath = "" Then Return SetError(2, 0, False) ConsoleWrite(" + Metadata: " & $sWinMDFullPath & @CRLF) ; --- 2. Open de winmd via dispenser + import --- Local $oImport = _WinRT_OpenMetaData($sWinMDFullPath) If @error Or Not IsObj($oImport) Then Return SetError(3, 0, False) $g_oImport = $oImport ; --- 3. Vind het TypeDef-token van de RuntimeClass --- Local $idClassToken = 0 $oImport.FindTypeDefByName($sClassName, 0, $idClassToken) If $idClassToken = 0 Then Return SetError(5, 0, False) ConsoleWrite(" + RuntimeClass token: 0x" & Hex($idClassToken, 8) & @CRLF) ; --- 4. Vind de DEFAULT INTERFACE van deze class --- Local $idIfaceToken = _MetaData_GetDefaultInterfaceToken($idClassToken) If @error Or $idIfaceToken = 0 Then ConsoleWrite(" ! Kon default interface niet vinden." & @CRLF) Return SetError(6, 0, False) EndIf ConsoleWrite(" + Default interface token: 0x" & Hex($idIfaceToken, 8) & @CRLF) ; --- 5. Haal naam + IID + methoden van de DEFAULT INTERFACE op --- Local $sIfaceName = _MetaData_GetTypeName($idIfaceToken) ConsoleWrite(" + Default interface: " & $sIfaceName & @CRLF) Local $sIID = _MetaData_GetGUIDAttrib($idIfaceToken) If $sIID = "" Then ConsoleWrite(" ! Interface heeft geen GuidAttribute." & @CRLF) Return SetError(6, 0, False) EndIf ConsoleWrite(" + Interface IID: " & $sIID & @CRLF) ; Bouw de dtag van de INTERFACE (compact, geen CRLF) Local $sDTag = _MetaData_BuildDTag($idIfaceToken) ConsoleWrite(" + dtag opgebouwd (" & StringLen($sDTag) & " chars)." & @CRLF) ; --- 6. Activeer de RuntimeClass -> IInspectable* --- Local $pInspectable = _WinRT_ActivateInstance($sClassName) If @error Or $pInspectable = 0 Then ConsoleWrite(" ! RoActivateInstance mislukt (@error=" & @error & ")." & @CRLF) Return SetError(7, 0, False) EndIf ConsoleWrite(" + IInspectable pointer: 0x" & Hex($pInspectable) & @CRLF) ; --- 7. QueryInterface naar de default interface --- Local $tIID_Iface = _CreateGUID($sIID) ; QueryInterface is altijd vtable-index 0 Local $pVTable = DllStructGetData(DllStructCreate("ptr", $pInspectable), 1) Local $pQI = DllStructGetData(DllStructCreate("ptr", $pVTable), 1) Local $aQI = DllCallAddress("long", $pQI, "ptr", $pInspectable, _ "struct*", $tIID_Iface, "ptr*", 0) ConsoleWrite(" -> QueryInterface HRESULT: 0x" & Hex($aQI[0], 8) & " | Ptr: 0x" & Hex($aQI[3]) & @CRLF) If $aQI[0] < 0 Or $aQI[3] = 0 Then ConsoleWrite(" ! QueryInterface naar interface mislukt!" & @CRLF) Return SetError(8, 0, False) EndIf Local $pIface = $aQI[3] ; --- 8. ObjCreateInterface met de default interface IID + dtag (in EEN keer!) --- Local $oDynamicObject = ObjCreateInterface($pIface, $sIID, $sDTag) If IsObj($oDynamicObject) Then Assign("WinRT_" & $sClassSafe, $oDynamicObject, $ASSIGN_FORCEGLOBAL) ConsoleWrite(" + Object toegewezen aan WinRT_" & $sClassSafe & @CRLF) Return True EndIf ConsoleWrite(" ! ObjCreateInterface mislukt." & @CRLF) Return False EndFunc ;==>_WinRT_Dynamic_Import ; ===================================================================================== ; KERNSTAP: Vind de default interface via EnumInterfaceImpls + DefaultAttribute ; ===================================================================================== Func _MetaData_GetDefaultInterfaceToken($idClassToken) Local $hEnum = 0 Local $tImplTokens = DllStructCreate("dword Tokens[100]") Local $iCount = 0 Local $hr = $g_oImport.EnumInterfaceImpls($hEnum, $idClassToken, DllStructGetPtr($tImplTokens), 100, $iCount) If $hEnum <> 0 Then $g_oImport.CloseEnum($hEnum) If $hr < 0 Or $iCount = 0 Then Return SetError(1, 0, 0) ConsoleWrite(" -> " & $iCount & " interface-implementaties gevonden." & @CRLF) ; Zoek de impl met DefaultAttribute Local $idFallbackIface = 0 For $i = 1 To $iCount Local $idImplToken = DllStructGetData($tImplTokens, "Tokens", $i) ; Haal class + interface-token uit deze impl Local $iClassTkn = 0, $iIfaceTkn = 0 $g_oImport.GetInterfaceImplProps($idImplToken, $iClassTkn, $iIfaceTkn) ; Onthoud de eerste als fallback If $idFallbackIface = 0 Then $idFallbackIface = $iIfaceTkn ; Check of deze impl de DefaultAttribute heeft Local $pData = 0, $cbData = 0 Local $hrAttr = $g_oImport.GetCustomAttributeByName($idImplToken, _ "Windows.Foundation.Metadata.DefaultAttribute", $pData, $cbData) If $hrAttr = 0 Then ; S_OK = default gevonden! ConsoleWrite(" -> DefaultAttribute gevonden op impl " & $i & @CRLF) ; $iIfaceTkn kan TypeRef of TypeDef zijn -> resolve naar TypeDef Return _MetaData_ResolveToTypeDef($iIfaceTkn) EndIf Next ; Geen default gevonden -> gebruik de eerste als fallback ConsoleWrite(" -> Geen DefaultAttribute; gebruik eerste interface." & @CRLF) Return _MetaData_ResolveToTypeDef($idFallbackIface) EndFunc ;==>_MetaData_GetDefaultInterfaceToken ; ===================================================================================== ; Resolve een interface-token (TypeRef of TypeDef) naar een lokaal TypeDef-token ; ===================================================================================== Func _MetaData_ResolveToTypeDef($iToken) Local $iTableType = BitAND($iToken, 0xFF000000) If $iTableType = $MDT_TypeDef Then ; Al een TypeDef in deze scope Return $iToken ElseIf $iTableType = $MDT_TypeRef Then ; TypeRef -> haal de naam op en zoek de TypeDef via FindTypeDefByName Local $sName = _MetaData_GetTypeRefName($iToken) If $sName = "" Then Return SetError(1, 0, 0) Local $idTypeDef = 0 Local $hr = $g_oImport.FindTypeDefByName($sName, 0, $idTypeDef) If $hr < 0 Or $idTypeDef = 0 Then ; Interface leeft in een ANDER winmd bestand ConsoleWrite(" ! Interface '" & $sName & "' zit in ander winmd (cross-scope)." & @CRLF) Return SetError(2, 0, 0) EndIf Return $idTypeDef Else ; TypeSpec (generiek) - niet ondersteund in deze basis-engine ConsoleWrite(" ! TypeSpec (generiek type) niet ondersteund." & @CRLF) Return SetError(3, 0, 0) EndIf EndFunc ;==>_MetaData_ResolveToTypeDef ; ===================================================================================== ; Naam van een TypeDef-token ; ===================================================================================== Func _MetaData_GetTypeName($idTypeDefToken) Local $tName = DllStructCreate("wchar Name[512]") Local $iNameLen = 0, $iFlags = 0, $iExtends = 0 Local $hr = $g_oImport.GetTypeDefProps($idTypeDefToken, DllStructGetPtr($tName), 512, $iNameLen, $iFlags, $iExtends) If $hr < 0 Then Return "" Return DllStructGetData($tName, "Name") EndFunc ;==>_MetaData_GetTypeName ; ===================================================================================== ; Naam van een TypeRef-token ; ===================================================================================== Func _MetaData_GetTypeRefName($idTypeRefToken) Local $tName = DllStructCreate("wchar Name[512]") Local $iResScope = 0, $iNameLen = 0 Local $hr = $g_oImport.GetTypeRefProps($idTypeRefToken, $iResScope, DllStructGetPtr($tName), 512, $iNameLen) If $hr < 0 Then Return "" Return DllStructGetData($tName, "Name") EndFunc ;==>_MetaData_GetTypeRefName ; ===================================================================================== ; Bouw dtag string van een interface-TypeDef ; ===================================================================================== ; ===================================================================================== ; Bouw dtag string van een interface-TypeDef (COMPACT - geen CRLF!) ; ===================================================================================== Func _MetaData_BuildDTag($idIfaceToken) Local $hEnum = 0 Local $tMethodTokens = DllStructCreate("dword Tokens[500]") Local $iMethodCount = 0 $g_oImport.EnumMethods($hEnum, $idIfaceToken, DllStructGetPtr($tMethodTokens), 500, $iMethodCount) If $hEnum <> 0 Then $g_oImport.CloseEnum($hEnum) ; IInspectable-basis (compact, geen CRLF) Local $sDTag = "GetIids hresult(ulong*;ptr*);GetRuntimeClassName hresult(ptr*);GetTrustLevel hresult(int*);" Local $mSeenNames[] ; map voor unieke namen For $i = 1 To $iMethodCount Local $idMethodToken = DllStructGetData($tMethodTokens, "Tokens", $i) Local $tMethodName = DllStructCreate("wchar Name[256]") Local $iClass = 0, $iNameLen = 0, $iAttr = 0, $pSig = 0, $cbSig = 0, $iRVA = 0, $iImpl = 0 $g_oImport.GetMethodProps($idMethodToken, $iClass, DllStructGetPtr($tMethodName), _ 256, $iNameLen, $iAttr, $pSig, $cbSig, $iRVA, $iImpl) Local $sMethodName = DllStructGetData($tMethodName, "Name") If $sMethodName = "" Or StringLeft($sMethodName, 1) = "." Then ContinueLoop ; Overloaded namen uniek maken (ObjCreateInterface eist unieke namen!) If MapExists($mSeenNames, $sMethodName) Then $mSeenNames[$sMethodName] += 1 $sMethodName = $sMethodName & "_" & $mSeenNames[$sMethodName] Else $mSeenNames[$sMethodName] = 0 EndIf Local $sAutoItSig = _MetaData_DecodeMethodSig($pSig, $cbSig) ConsoleWrite(" + " & $sMethodName & " " & $sAutoItSig & @CRLF) ; COMPACT: geen CRLF, alleen ; als scheiding (zoals werkende OCR-tags) $sDTag &= $sMethodName & " " & $sAutoItSig & ";" Next Return $sDTag EndFunc ;==>_MetaData_BuildDTag ; ===================================================================================== ; GUID via GuidAttribute ; ===================================================================================== Func _MetaData_GetGUIDAttrib($idToken) Local $pData = 0, $cbData = 0 Local $hr = $g_oImport.GetCustomAttributeByName($idToken, _ "Windows.Foundation.Metadata.GuidAttribute", $pData, $cbData) If $hr <> 0 Or $pData = 0 Or $cbData < 20 Then Return "" Local $tGUID = DllStructCreate("dword Data1;word Data2;word Data3;byte Data4[8]", $pData + 2) Local $sData4 = "" For $i = 1 To 8 $sData4 &= Hex(DllStructGetData($tGUID, "Data4", $i), 2) Next Return StringFormat("{%08X-%04X-%04X-%s-%s}", _ DllStructGetData($tGUID, "Data1"), DllStructGetData($tGUID, "Data2"), _ DllStructGetData($tGUID, "Data3"), StringLeft($sData4, 4), StringMid($sData4, 5)) EndFunc ;==>_MetaData_GetGUIDAttrib ; ===================================================================================== ; WinRT HELPERS ; ===================================================================================== Func _WinRT_LocateMetaDataFile($sClassName) Local $aHString = DllCall($hDLLComBase, "long", "WindowsCreateString", _ "wstr", $sClassName, "dword", StringLen($sClassName), "ptr*", 0) If @error Or $aHString[0] < 0 Then Return SetError(1, 0, "") Local $hString = $aHString[3] ;~ Local $aGetFile = DllCall($hDLLComBase, "long", "RoGetMetaDataFile", _ ;~ "ptr", $hString, "ptr", 0, "ptr*", 0, "ptr*", 0) #fix Local $aGetFile = DllCall($hDLLWinTypes, "long", "RoGetMetaDataFile", _ "ptr", $hString, _ ; name (HSTRING) "ptr", 0, _ ; metaDataDispenser (NULL) "ptr*", 0, _ ; metaDataFilePath (out HSTRING) -> $aGetFile[3] "ptr*", 0, _ ; metaDataImport (out) -> $aGetFile[4] "ptr*", 0) ; typeDefToken (out) -> $aGetFile[5] DllCall($hDLLComBase, "long", "WindowsDeleteString", "ptr", $hString) If @error Or $aGetFile[0] < 0 Then Return SetError(2, 0, "") Local $hPath = $aGetFile[3] Local $aRaw = DllCall($hDLLComBase, "ptr", "WindowsGetStringRawBuffer", "ptr", $hPath, "uint*", 0) Local $sPath = "" If Not @error And $aRaw[0] <> 0 Then Local $tStr = DllStructCreate("wchar[" & ($aRaw[2] + 1) & "]", $aRaw[0]) $sPath = DllStructGetData($tStr, 1) EndIf DllCall($hDLLComBase, "long", "WindowsDeleteString", "ptr", $hPath) Return $sPath EndFunc ;==>_WinRT_LocateMetaDataFile Func _WinRT_OpenMetaData($sWinMDPath) Local $tCLSID = _CreateGUID($sCLSID_CorMetaDataDispenser) Local $tIID = _CreateGUID($sIID_IMetaDataDispenser) Local $aDisp = DllCall($hDLLRoMetaData, "long", "MetaDataGetDispenser", _ "struct*", $tCLSID, "struct*", $tIID, "ptr*", 0) If @error Or $aDisp[0] < 0 Then Return SetError(1, 0, 0) Local $tagDisp = "DefineScope hresult(ptr;dword;ptr;ptr*);OpenScope hresult(wstr;dword;struct*;ptr*);OpenScopeOnMemory hresult(ptr;dword;dword;struct*;ptr*);" Local $oDispenser = ObjCreateInterface($aDisp[3], $sIID_IMetaDataDispenser, $tagDisp, True) If Not IsObj($oDispenser) Then Return SetError(2, 0, 0) Local $tIID_Import = _CreateGUID($sIID_IMetaDataImport) Local $pImport = 0 Local $hr = $oDispenser.OpenScope($sWinMDPath, 0, $tIID_Import, $pImport) If $hr < 0 Or $pImport = 0 Then Return SetError(3, 0, 0) Return ObjCreateInterface($pImport, $sIID_IMetaDataImport, $GLOBAL_tagImport, True) EndFunc ;==>_WinRT_OpenMetaData Func _WinRT_ActivateInstance($sClassName) Local $aHString = DllCall($hDLLComBase, "long", "WindowsCreateString", _ "wstr", $sClassName, "dword", StringLen($sClassName), "ptr*", 0) If @error Or $aHString[0] < 0 Then Return SetError(1, 0, 0) Local $hString = $aHString[3] Local $aAct = DllCall($hDLLComBase, "long", "RoActivateInstance", "ptr", $hString, "ptr*", 0) DllCall($hDLLComBase, "long", "WindowsDeleteString", "ptr", $hString) If @error Or $aAct[0] < 0 Or $aAct[2] = 0 Then Return SetError(2, 0, 0) Return $aAct[2] EndFunc ;==>_WinRT_ActivateInstance Func _CreateGUID($sGUID) Local $tGUID = DllStructCreate("dword Data1;word Data2;word Data3;byte Data4[8]") DllCall($hDLLOle32, "long", "CLSIDFromString", "wstr", $sGUID, "struct*", $tGUID) Return $tGUID EndFunc ;==>_CreateGUID ; ===================================================================================== ; ECMA-335 SIGNATURE DECODER ; ===================================================================================== Func _MetaData_DecodeMethodSig($pSig, $cbSig) If $pSig = 0 Or $cbSig = 0 Then Return "hresult(ptr*)" Local $tSig = DllStructCreate("byte[" & $cbSig & "]", $pSig) Local $iReadPtr = 2 Local $iParamCount = __ReadCompressedInt($tSig, $iReadPtr) Local $sRetType = __ReadSigType($tSig, $iReadPtr) Local $sParams = "" For $p = 1 To $iParamCount Local $sParamType = __ReadSigType($tSig, $iReadPtr) If $sParams <> "" Then $sParams &= ";" $sParams &= $sParamType Next If $sRetType <> "none" Then If $sParams <> "" Then $sParams &= ";" $sParams &= $sRetType & "*" EndIf If $sParams = "" Then $sParams = "ptr*" Return "hresult(" & $sParams & ")" EndFunc ;==>_MetaData_DecodeMethodSig Func __ReadSigType(ByRef $tSig, ByRef $iReadPtr) Local $iType = DllStructGetData($tSig, 1, $iReadPtr) $iReadPtr += 1 Switch $iType Case 0x01 Return "none" Case 0x02 Return "bool" Case 0x03 Return "word" Case 0x04, 0x05 Return "byte" Case 0x06 Return "short" Case 0x07 Return "ushort" Case 0x08 Return "long" Case 0x09 Return "ulong" Case 0x0A Return "int64" Case 0x0B Return "uint64" Case 0x0C Return "float" Case 0x0D Return "double" Case 0x0E, 0x1C, 0x18, 0x19 Return "ptr" Case 0x10 Return __ReadSigType($tSig, $iReadPtr) & "*" Case 0x11, 0x12 __ReadCompressedInt($tSig, $iReadPtr) Return "ptr" Case 0x15 __ReadSigType($tSig, $iReadPtr) Local $iArgs = __ReadCompressedInt($tSig, $iReadPtr) For $a = 1 To $iArgs __ReadSigType($tSig, $iReadPtr) Next Return "ptr" Case 0x1D __ReadSigType($tSig, $iReadPtr) Return "ptr" Case 0x13 __ReadCompressedInt($tSig, $iReadPtr) Return "ptr" Case Else Return "ptr" EndSwitch EndFunc ;==>__ReadSigType Func __ReadCompressedInt(ByRef $tSig, ByRef $iReadPtr) Local $iByte1 = DllStructGetData($tSig, 1, $iReadPtr) If BitAND($iByte1, 0x80) = 0 Then $iReadPtr += 1 Return $iByte1 ElseIf BitAND($iByte1, 0xC0) = 0x80 Then Local $iByte2 = DllStructGetData($tSig, 1, $iReadPtr + 1) $iReadPtr += 2 Return BitOR(BitShift(BitAND($iByte1, 0x3F), -8), $iByte2) Else Local $iByte2 = DllStructGetData($tSig, 1, $iReadPtr + 1) Local $iByte3 = DllStructGetData($tSig, 1, $iReadPtr + 2) Local $iByte4 = DllStructGetData($tSig, 1, $iReadPtr + 3) $iReadPtr += 4 Return BitOR(BitShift(BitAND($iByte1, 0x1F), -24), _ BitShift($iByte2, -16), BitShift($iByte3, -8), $iByte4) EndIf EndFunc ;==>__ReadCompressedInt Gianni 1 FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
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