Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 09/05/2024 in all areas

  1. Hello. Here is a sample. #AutoIt3Wrapper_UseX64=n ;~ #RequireAdmin #include <WinAPISysWin.au3> #include ".\UIASpy\Includes\UIA_Constants.au3" HotKeySet("{ESC}", "Quit") ;Press ESC key to quit _Test() Func Quit() Exit EndFunc ;==>Quit Func _Test() ; Create UI Automation object Local $oUIAutomation = ObjCreateInterface($sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtag_IUIAutomation) If Not IsObj($oUIAutomation) Then Return ConsoleWrite("$oUIAutomation ERR" & @CRLF) ConsoleWrite("$oUIAutomation OK" & @CRLF) ; Get Desktop element Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement($pDesktop) $oDesktop = ObjCreateInterface($pDesktop, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) If Not IsObj($oDesktop) Then Return ConsoleWrite("$oDesktop ERR" & @CRLF) ConsoleWrite("$oDesktop OK" & @CRLF) While Sleep(30) Local $hHandle = WinGetHandle("[ACTIVE]") If _WinAPI_GetClassName($hHandle) <> "Chrome_WidgetWin_1" Then ContinueLoop ConsoleWrite(WinGetTitle($hHandle) & @CRLF) Local $pCondition ; Note that $UIA_ClassNamePropertyId maybe ia a CASE SENSITIVE condition $oUIAutomation.CreatePropertyCondition($UIA_NativeWindowHandlePropertyId, Int($hHandle), $pCondition) ;hwnd need to be converted to int If Not $pCondition Then ContinueLoop ConsoleWrite("$pCondition OK") ;When searching for top-level windows on the desktop, be sure to specify TreeScope_Children in the scope parameter, not TreeScope_Descendants. ;A search through the entire subtree of the desktop could iterate through thousands of items and lead to a stack overflow. Local $pWindow $oDesktop.FindFirst($TreeScope_Children, $pCondition, $pWindow) Local $oWindow = ObjCreateInterface($pWindow, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) If Not IsObj($oWindow) Then ContinueLoop ConsoleWrite("$oWindow OK") Local $pCondition0 $oUIAutomation.CreatePropertyCondition($UIA_ClassNamePropertyId, "Chrome_WidgetWin_1", $pCondition0) If Not $pCondition0 Then ContinueLoop ConsoleWrite("$pCondition0 OK" & @CRLF) Local $pPaneChrome, $oPaneChrome $oWindow.FindFirst($TreeScope_Descendants, $pCondition0, $pPaneChrome) $oPaneChrome = ObjCreateInterface($pPaneChrome, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) If Not IsObj($oPaneChrome) Then ContinueLoop ConsoleWrite("$oPaneChrome OK" & @CRLF) Local $pCondition0 $oUIAutomation.CreatePropertyCondition($UIA_ControlTypePropertyId, $UIA_PaneControlTypeId, $pCondition0) If Not $pCondition0 Then ContinueLoop ConsoleWrite("$pCondition0 OK" & @CRLF) Local $pPaneFirst, $oPaneFirst $oPaneChrome.FindFirst($TreeScope_Children, $pCondition0, $pPaneFirst) $oPaneFirst = ObjCreateInterface($pPaneFirst, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) If Not IsObj($oPaneFirst) Then ContinueLoop ConsoleWrite("$oPaneFirst OK" & @CRLF) Local $pCondition1 $oUIAutomation.CreatePropertyCondition($UIA_ControlTypePropertyId, $UIA_TextControlTypeId, $pCondition1) If Not $pCondition1 Then ContinueLoop ConsoleWrite("$pCondition1 OK" & @CRLF) Local $pText1, $oText1 $oPaneFirst.FindFirst($TreeScope_Descendants, $pCondition1, $pText1) $oText1 = ObjCreateInterface($pText1, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement) If Not IsObj($oText1) Then ContinueLoop ConsoleWrite("$oText1 OK" & @CRLF) Local $sValue = "" $oText1.GetCurrentPropertyValue($UIA_NamePropertyId, $sValue) ConsoleWrite($sValue & @CRLF) ToolTip($sValue,Default,Default,"Link") WEnd EndFunc ;==>_Test Saludos
    3 points
  2. ConsoleWrite(FileGetVersion("msvcp140.dll") & @CRLF) ; 14.28.29334.0 and that version on my PC is not from "C:\Windows\System32\msvcp140.dll", is from "C:\Windows\System32\DriverStore\FileRepository\iclsclient.inf_amd64_fc84dfa25a6a7727\lib\msvcp140.dll" Why ?, how?, .. no clue. ( PC with the old SciTE, I forgot what virtual PC I tested the new beta on )
    2 points
  3. Hi, The rule is still in force and Melba still cleans up. M23
    2 points
  4. MattyD

    WinRT Object Libraries

    Hi folks, Attached below is one way of attacking WinRT Objects. These are essentially COM objects, however they don't have an IDispatch interface so ObjCreate() cannot be used. It is possible to expose them using ObjCreateInterface though. Alternately, DllCallAddress() may be used to access an object's functions directly from memory. I'm using the latter mainly because that's the path I started down first! To make sense of whats in the attachment... WinRT.au3 - Core high level functions that sit on top of interface libraries Includes Async and Collection implementations etc. So basic high level functionality. WinRTCore.au3 - Internal helper functions for interface libraries Interface Folder - Interface libraries (there are over 850 of these!). Essentially these wrap the functions in an interface's vtable Includes tags which may be used with ObjCreateInterface Enums Folder - Contains map datatypes that can be used to convert enumeration strings to their numeric type, or vice versa Classes Folder - doesn't actually contain code - A class file includes interface and enum files that belong to a class. Namespaces Folder - doesn't actually contain code - A namespace file includes classes that are related. Bonus: I've also uploaded a rudimentary WinRT Class Explorer if it happens to be useful to anyone. Bonus2: I've added a tool that installs/removes calltips for interface libraries. Original post: WinRT Libraries - Latest ClassExplorer.zip
    1 point
  5. That works great. It's been a while since I could see a SciTE editor on this machine. I don't know what the limitations are with this version. But it is running. Thank you very much. You have been very helpfull!!!
    1 point
  6. I can confirm I have the same files listed. Plus a few others from from version 14.29 and one file from 14.10. I am running Windows 7, 64bit. Your Scite, Lexilla and Scintilla are older files I see. They should have the date of: 8/21/2024 The installer will have the old version, you will have to replace those with the single Scite, Lexilla and Scintilla files from the Scite x86/x64 here: https://www.autoitscript.com/autoit3/scite/download/beta_SciTE4AutoIt3/SciTE5-with-DynamicFunctions/ This reports 14.40.33810.0 for me.
    1 point
  7. donnyh13: Thank you for the reply... I installed both of the files as Administrator. I'm still getting the same error. Would you mind checking to see if you have the same files in: C:\Windows\System32 msvcp140.dll 4/27/2024 11:20:20 PM A msvcp140_1.dll 4/27/2024 11:20:20 PM A msvcp140_2.dll 4/27/2024 11:20:20 PM A msvcp140_atomic_wait.dll 4/27/2024 11:20:20 PM A msvcp140_clr0400.dll 6/24/2022 2:31:26 PM A msvcp140_codecvt_ids.dll 4/27/2024 11:20:20 PM A Are you running Windows Pro 64bit? I am. Maybe I'm not running the latest version of SciTE? api DIR 9/4/2024 11:04:33 PM - au3Stripper DIR 9/4/2024 11:04:33 PM - AutoIt3Wrapper DIR 9/4/2024 11:04:34 PM - CodeWizard DIR 9/4/2024 11:04:34 PM - Defs DIR 9/4/2024 11:04:35 PM - Koda DIR 9/4/2024 11:04:34 PM - lua DIR 9/4/2024 11:04:33 PM - Properties DIR 9/4/2024 11:04:33 PM - SciTE Jump DIR 9/4/2024 11:04:35 PM - SciTEConfig DIR 9/4/2024 11:04:35 PM - Tidy DIR 9/4/2024 11:04:34 PM - au3.keywords.properties 91599 9/19/2022 11:35:22 AM A install.log 17994 9/4/2024 11:04:35 PM A install_user.log 876 9/4/2024 11:04:35 PM A Lexilla.dll 890368 12/3/2023 3:54:22 AM A License.txt 868 6/20/2011 4:47:06 AM A luaCOPYRIGHT 1562 1/2/2010 2:15:48 PM A Scintilla.dll 646144 12/3/2023 3:54:16 AM A SciTE.exe 1155584 12/3/2023 3:54:28 AM A SciTE4AutoIt3.chm 2484057 12/27/2023 5:32:06 AM A SciTE4AutoIt3.url 67 9/4/2024 11:04:35 PM A SciTEGlobal.properties 22095 10/3/2023 10:37:06 AM A SciTEUser.properties 59 9/4/2024 11:04:35 PM A SciTEVersion.ini 55 9/4/2024 11:04:46 PM A uninst.exe 62478 9/4/2024 11:04:35 PM A Thank you
    1 point
  8. MattyD

    WinRT Object Libraries

    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...
    1 point
  9. I think you still have to add the SCITE_USERHOME environment variable, which normally is set by the SciTE4AutoIt3 installer! The installation now assumes it is portable, so will try to get stuff from the SciTE.exe directory. So, try to add environment variable: SCITE_USERHOME= C:\Users\MyUsername\AppData\Local\AutoIt v3\SciTE
    1 point
  10. 1 point
  11. Pretty sure you do not want to copy DLL's around as most of them are reentrant as far as I know, meaning that when they are once loaded they will not be loaded again, and you do not want possible different versions on your system and the wrong one being in memory.
    1 point
  12. Thanks for the quick feedback. Well taken. Just updated the code for relative default paths and added and example 8 image dataset, 4 with masks and 4 people without masks. Let me know your thoughts from there. Joe
    1 point
  13. r2du-soft

    SystemTray_Refresh

    ; Refresh taskbar icons without killing explorer.exe Func RefreshTaskbarIcons() ; Constants for the Windows message Local $HWND_BROADCAST = 0xFFFF Local $WM_SETTINGCHANGE = 0x001A ; Send a message to all windows to refresh taskbar icons DllCall("user32.dll", "int", "SendMessageTimeout", _ "hwnd", $HWND_BROADCAST, _ "uint", $WM_SETTINGCHANGE, _ "wparam", 0, _ "lparam", "str", "TrayIcons", _ "uint", 2, _ "uint", 1000, _ "uint*", 0) EndFunc ; Call the function to refresh taskbar icons RefreshTaskbarIcons()
    1 point
  14. Andreik

    File Detect Type

    You can use TrIDLib. It's capable to ID many files based on their signature. Here is a full list with definitions. #include-once #include <Array.au3> Global Const $TRID_GET_RES_NUM = 1 ; Get the number of results Global Const $TRID_GET_RES_FILETYPE = 2 ; Filetype descriptions Global Const $TRID_GET_RES_FILEEXT = 3 ; Filetype extension Global Const $TRID_GET_RES_POINTS = 4 ; Matching points Global Const $TRID_GET_VER = 1001 ; TrIDLib version Global Const $TRID_GET_DEFSNUM = 1004 ; Filetypes definitions loaded $aInfo = TrIDLib_AnalyzeFile('<FilePath>') _ArrayDisplay($aInfo) Func TrIDLib_AnalyzeFile($sFile, $DefsPack = '', $bVerbose = False, $LibPath = 'TrIDLib.dll') Local $aRet, $hTrIDLib, $iTotal = 0 $hTrIDLib = DllOpen($LibPath) If $hTrIDLib = -1 Then Return False If $bVerbose Then $aRet = DllCall($hTrIDLib, 'int', 'TrID_GetInfo', 'int', $TRID_GET_VER, 'int', 0, 'str', 0) ConsoleWrite(Round($aRet[0] / 100, 2) & @CRLF) EndIf $aRet = DllCall($hTrIDLib, 'int', 'TrID_LoadDefsPack', 'str', $DefsPack) If Not $aRet[0] Then DllClose($hTrIDLib) Return Null EndIf If Not FileExists($sFile) Then Return Null $aRet = DllCall($hTrIDLib, 'int', 'TrID_SubmitFileA', 'str', $sFile) If Not $aRet[0] Then DllClose($hTrIDLib) Return Null EndIf $aRet = DllCall($hTrIDLib, 'int', 'TrID_Analyze') If Not $aRet[0] Then DllClose($hTrIDLib) Return Null EndIf $aRet = DllCall($hTrIDLib, 'int', 'TrID_GetInfo', 'int', $TRID_GET_RES_NUM, 'int', 0, 'str', 9) If $aRet[0] < 1 Then DllClose($hTrIDLib) Return Null EndIf Local $aMatches[$aRet[0] + 1][4] $aMatches[0][0] = $aRet[0] For $Index = 1 To $aRet[0] $aRet = DllCall($hTrIDLib, 'int', 'TrID_GetInfo', 'int', $TRID_GET_RES_FILETYPE, 'int', $Index, 'str', 0) $aMatches[$Index][0] = $aRet[3] $aRet = DllCall($hTrIDLib, 'int', 'TrID_GetInfo', 'int', $TRID_GET_RES_FILEEXT, 'int', $Index, 'str', 0) $aMatches[$Index][1] = $aRet[3] $aRet = DllCall($hTrIDLib, 'int', 'TrID_GetInfo', 'int', $TRID_GET_RES_POINTS, 'int', $Index, 'str', 0) $aMatches[$Index][2] = $aRet[0] $iTotal += $aRet[0] Next If $iTotal > 0 Then For $Index = 1 To $aMatches[0][0] $aMatches[$Index][3] = Round($aMatches[$Index][2] * 100 / $iTotal, 2) Next EndIf DllClose($hTrIDLib) Return $aMatches EndFunc Here you can download the required dll.
    1 point
  15. argumentum

    WinRT Object Libraries

    I pulled both my monitors ( on 23H2 ), no blob that I can see either. 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.
    1 point
  16. Get all texts in a Chrome document This example shows how to extract all texts in a Chrome document. The previous webpage (page 2) is used as an example. Don't forget this: To be able to spy on web content in Google Chrome it's necessary to enable accessibility by entering chrome://accessibility/ in the address bar of a new tab item, and then check the five check boxes that are located in a column in upper left corner down along the left edge. Then the accessibility tab can be closed again. It's a global setting that applies to all open and new tabs until Chrome is closed. Without accessibility enabled you are only able to investigate the outer elements of Chrome but not web content. SampleCode1.au3 shows how to find the first text (SampleCode1-a.au3 is the code generated directly by UIASpy): #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 ;#AutoIt3Wrapper_UseX64=n ; If target application is running as 32 bit code ;#AutoIt3Wrapper_UseX64=y ; If target application is running as 64 bit code #include "UIA_Constants.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_Functions.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_SafeArray.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_Variant.au3" ; Can be copied from UIASpy Includes folder Opt( "MustDeclareVars", 1 ) Example() Func Example() ; Create UI Automation object Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtag_IUIAutomation ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) ; Get Desktop element Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement( $pDesktop ) $oDesktop = ObjCreateInterface( $pDesktop, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement ) If Not IsObj( $oDesktop ) Then Return ConsoleWrite( "$oDesktop ERR" & @CRLF ) ConsoleWrite( "$oDesktop OK" & @CRLF ) ; --- Find window/control --- ConsoleWrite( "--- Find window/control ---" & @CRLF ) Local $pCondition0 $oUIAutomation.CreatePropertyCondition( $UIA_ClassNamePropertyId, "Chrome_WidgetWin_1", $pCondition0 ) If Not $pCondition0 Then Return ConsoleWrite( "$pCondition0 ERR" & @CRLF ) ConsoleWrite( "$pCondition0 OK" & @CRLF ) Local $pPane1, $oPane1 $oDesktop.FindFirst( $TreeScope_Descendants, $pCondition0, $pPane1 ) $oPane1 = ObjCreateInterface( $pPane1, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement ) If Not IsObj( $oPane1 ) Then Return ConsoleWrite( "$oPane1 ERR" & @CRLF ) ConsoleWrite( "$oPane1 OK" & @CRLF ) ; --- Find window/control --- ConsoleWrite( "--- Find window/control ---" & @CRLF ) Local $pCondition1 $oUIAutomation.CreatePropertyCondition( $UIA_ControlTypePropertyId, $UIA_TextControlTypeId, $pCondition1 ) If Not $pCondition1 Then Return ConsoleWrite( "$pCondition1 ERR" & @CRLF ) ConsoleWrite( "$pCondition1 OK" & @CRLF ) Local $pText1, $oText1 $oPane1.FindFirst( $TreeScope_Descendants, $pCondition1, $pText1 ) $oText1 = ObjCreateInterface( $pText1, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement ) If Not IsObj( $oText1 ) Then Return ConsoleWrite( "$oText1 ERR" & @CRLF ) ConsoleWrite( "$oText1 OK" & @CRLF ) EndFunc SciTE output: $oUIAutomation OK $oDesktop OK --- Find window/control --- $pCondition0 OK $oPane1 OK --- Find window/control --- $pCondition1 OK $oText1 OK SampleCode2.au3 shows how to find all texts (SampleCode2-a.au3 is the code generated directly by UIASpy): #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 ;#AutoIt3Wrapper_UseX64=n ; If target application is running as 32 bit code ;#AutoIt3Wrapper_UseX64=y ; If target application is running as 64 bit code #include "UIA_Constants.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_Functions.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_SafeArray.au3" ; Can be copied from UIASpy Includes folder ;#include "UIA_Variant.au3" ; Can be copied from UIASpy Includes folder Opt( "MustDeclareVars", 1 ) Example() Func Example() ; Create UI Automation object Local $oUIAutomation = ObjCreateInterface( $sCLSID_CUIAutomation, $sIID_IUIAutomation, $dtag_IUIAutomation ) If Not IsObj( $oUIAutomation ) Then Return ConsoleWrite( "$oUIAutomation ERR" & @CRLF ) ConsoleWrite( "$oUIAutomation OK" & @CRLF ) ; Get Desktop element Local $pDesktop, $oDesktop $oUIAutomation.GetRootElement( $pDesktop ) $oDesktop = ObjCreateInterface( $pDesktop, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement ) If Not IsObj( $oDesktop ) Then Return ConsoleWrite( "$oDesktop ERR" & @CRLF ) ConsoleWrite( "$oDesktop OK" & @CRLF ) ; --- Find window/control --- ConsoleWrite( "--- Find window/control ---" & @CRLF ) Local $pCondition0 $oUIAutomation.CreatePropertyCondition( $UIA_ClassNamePropertyId, "Chrome_WidgetWin_1", $pCondition0 ) If Not $pCondition0 Then Return ConsoleWrite( "$pCondition0 ERR" & @CRLF ) ConsoleWrite( "$pCondition0 OK" & @CRLF ) Local $pPane1, $oPane1 $oDesktop.FindFirst( $TreeScope_Descendants, $pCondition0, $pPane1 ) $oPane1 = ObjCreateInterface( $pPane1, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement ) If Not IsObj( $oPane1 ) Then Return ConsoleWrite( "$oPane1 ERR" & @CRLF ) ConsoleWrite( "$oPane1 OK" & @CRLF ) ; --- Find window/control --- ConsoleWrite( "--- Find window/control ---" & @CRLF ) Local $pCondition1 $oUIAutomation.CreatePropertyCondition( $UIA_ControlTypePropertyId, $UIA_TextControlTypeId, $pCondition1 ) If Not $pCondition1 Then Return ConsoleWrite( "$pCondition1 ERR" & @CRLF ) ConsoleWrite( "$pCondition1 OK" & @CRLF ) #cs Local $pText1, $oText1 $oPane1.FindFirst( $TreeScope_Descendants, $pCondition1, $pText1 ) $oText1 = ObjCreateInterface( $pText1, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement ) If Not IsObj( $oText1 ) Then Return ConsoleWrite( "$oText1 ERR" & @CRLF ) ConsoleWrite( "$oText1 OK" & @CRLF ) #ce Local $pElements $oPane1.FindAll( $TreeScope_Descendants, $pCondition1, $pElements ) ; --- Code Snippets --- ConsoleWrite( "--- Code Snippets ---" & @CRLF ) Local $oUIElementArray1, $iLength1 ; $pElements is a pointer to an UI Automation element array $oUIElementArray1 = ObjCreateInterFace( $pElements, $sIID_IUIAutomationElementArray, $dtag_IUIAutomationElementArray ) $oUIElementArray1.Length( $iLength1 ) If Not $iLength1 Then Return ConsoleWrite( "$iLength1 = 0 ERR" & @CRLF ) ConsoleWrite( "$iLength1 = " & $iLength1 & @CRLF ) ; --- Code Snippets --- ConsoleWrite( "--- Code Snippets ---" & @CRLF ) Local $pElement1, $oElement1, $sValue1 For $i = 0 To $iLength1 - 1 $oUIElementArray1.GetElement( $i, $pElement1 ) $oElement1 = ObjCreateInterface( $pElement1, $sIID_IUIAutomationElement, $dtag_IUIAutomationElement ) $oElement1.GetCurrentPropertyValue( $UIA_NamePropertyId, $sValue1 ) ConsoleWrite( "$sValue1 = " & $sValue1 & @CRLF ) Next EndFunc SampleCode2.au3 is a continuation of SampleCode1.au3 where FindFirst is replaced with FindAll and code snippets are added to Create an UI Automation element array from pointer Traverse an array to get access to individual elements The code snippets are added ín two steps in UIASpy. It's only possible to use item 2 if item 1 is completed. Item 2 is simply not shown in the listview unless item 1 is completed. SciTE output (in part, see SampleCode2.txt): $oUIAutomation OK $oDesktop OK --- Find window/control --- $pCondition0 OK $oPane1 OK --- Find window/control --- $pCondition1 OK --- Code Snippets --- $iLength1 = 3768 --- Code Snippets --- $sValue1 = Existing user? Sign In   $sValue1 = ? $sValue1 = Sign Up $sValue1 = Browse $sValue1 = Forums $sValue1 = Downloads $sValue1 = Calendar $sValue1 = Forum Rules $sValue1 = Wiki $sValue1 = AutoIt Resources $sValue1 = ? $sValue1 = FAQ $sValue1 = Our Picks $sValue1 = ? $sValue1 = $sValue1 = All Activity $sValue1 = ? $sValue1 = Home $sValue1 = ? $sValue1 = AutoIt v3 Search for SEKOMD in SampleCode2.txt to see all activity of this user. Why is the URL in the address bar not included in the texts? Because the address bar is part of the outer elements of the Chrome window and therefore not included in the web document itself. AllChromeTexts.7z
    1 point
  17. Hi, A quick bump to get this back into view as the prohibition still stands. M23
    1 point
×
×
  • Create New...