techiebabel Posted October 2, 2014 Posted October 2, 2014 I've been working on a script to configure the Photo Screensaver in Windows for a bunch of computers at work. I've got it working where I just copy the EncryptedPIDL registry key from a workstation where I manually did the configuration, but part of me is just not happy with that... it just doesn't feel right giving up and not being able to generate that key based on a path that I want to set the screensaver to. I've got a function written to 'decrypt' or decode the value stored in the registry by referencing a whole bunch of work done by a bunch of brilliant folks that were doing similar work, but not quite the same. Here is that (working) function: expandcollapse popupFunc _EncryptedPIDLDecode($sEncryptedPIDL) Local Const $CRYPT_STRING_BASE64 = 0x00000001 ; Determine length of EncryptedPIDL Local $iLength = StringLen($sEncryptedPIDL) ; Create structure to hold the attributes returned and used during decoding Local $tDecodeAttribs = DllStructCreate("int Size; int Skipped;int Flags") If @error Then Return SetError(1,0,'') ; Get pointers to the attributes returned and used during decoding Local $pDecodeSize = DllStructGetPtr($tDecodeAttribs, 'Size') Local $pDecodeSkipped = DllStructGetPtr($tDecodeAttribs, 'Skipped') Local $pDecodeFlags = DllStructGetPtr($tDecodeAttribs, 'Flags') ; Get the values needed for decoding DllCall('Crypt32.dll','int','CryptStringToBinary', _ 'str',$sEncryptedPIDL, _ 'int',$iLength, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',0, _ 'ptr',$pDecodeSize, _ 'ptr',$pDecodeSkipped, _ 'ptr',$pDecodeFlags) If @error Then Return SetError(2,0,'') ; Create structure to hold the PIDL and path Local $tDecodeResults = DllStructCreate("char PIDL[" & DllStructGetData($tDecodeAttribs, 'Size') + 1 & "]; char Path[261]") If @error Then Return SetError(3,0,'') ; Get pointers to the PIDL and path Local $pDecodePIDL = DllStructGetPtr($tDecodeResults, 'PIDL') Local $pDecodePath = DllStructGetPtr($tDecodeResults, 'Path') ; Get the PIDL DllCall('Crypt32.dll','int','CryptStringToBinary', _ 'str',$sEncryptedPIDL, _ 'int',$iLength, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',$pDecodePIDL, _ 'ptr',$pDecodeSize, _ 'ptr',$pDecodeSkipped, _ 'ptr',$pDecodeFlags) If @error Then Return SetError(4,0,'') ; Get the Path DllCall('Shell32.dll','int','SHGetPathFromIDList', _ 'ptr',$pDecodePIDL, _ 'ptr',$pDecodePath) If @error Then Return SetError(5,0,'') ; Return the Path Return DllStructGetData($tDecodeResults, 'Path') EndFunc But I just can't get the encode or 'encrypt' function working. I'm stuck. I believe I know the basic process... take the string of the path, get the PIDL from that string, and then encode the PIDL using BASE64. I believe I'm stuck at getting PIDL or perhaps the size of the PIDL. I can get a memory pointer, but my brain starts to get fuzzy where I try to determine the size of the data contained to provide to the CryptBinaryToString function of Crypt32.dll. If you run the code, you'll see something is getting converted, but the string is far too short. Here is what I have so far (not working): expandcollapse popupFunc _EncryptedPIDLEncode($sPath) Local Const $CRYPT_STRING_BASE64 = 0x00000001 Local Const $IID_ISHELLFOLDER = "{000214E6-0000-0000-C000-000000000046}" Local Const $TAG_ISHELLFOLDER = _ "ParseDisplayName hresult(hwnd;ptr;wstr;dword*;ptr*;dword*);" & _ ; These methods accepts PIDLs that are relative to the parent folder "EnumObjects hresult(hwnd;dword;ptr*);" & _ "BindToObject hresult(ptr;ptr;struct*;ptr*);" & _ "BindToStorage hresult(ptr;ptr;ptr;ptr*);" & _ "CompareIDs hresult(lparam;ptr;ptr);" & _ "CreateViewObject hresult(hwnd;ptr;ptr*);" & _ "GetAttributesOf hresult(uint;struct*;ulong*);" & _ "GetUIObjectOf hresult(hwnd;uint;struct*;struct*;uint*;ptr*);" & _ "GetDisplayNameOf hresult(ptr;uint;struct*);" & _ "SetNameOf hresult(hwnd;ptr;wstr;dword;ptr*);" ; Get the pointer to the root IShelllFolder interface (the Desktop folder) Local $aIShellRoot = DllCall('Shell32.dll', "int", "SHGetDesktopFolder", "ptr*", 0) If @error Or Not $aIShellRoot[1] Then Return SetError(1,0,'') Else Local $pIShellRoot = $aIShellRoot[1] EndIf ; Create an object for the IShellFolder interface Local $oIShellFolder = ObjCreateInterface( $pIShellRoot, $IID_ISHELLFOLDER, $TAG_ISHELLFOLDER ) ; Create a structure to store the pointer to the PIDL Local $tPIDLPtr = DllStructCreate("ptr") If @error Then Return SetError(2,0,'') ; Get the pointer to the PIDL of the specified path Local $pPIDL $oIShellFolder.ParseDisplayName(0, 0, $sPath, 0, $pPIDL, 0) If @error Or Not $pPIDL Then Return SetError(3,0,'') Else DllStructSetData($tPIDLPtr, 1, $pPIDL) Local $iSize = DllStructGetSize($tPIDLPtr) EndIf ; Create a structure to store attributes returned and used during encoding Local $tEncodeAttribs = DllStructCreate("int Size") If @error Then Return SetError(3,0,'') ; Get pointers to the attributes returned and used during encoding Local $pEncodeSize = DllStructGetPtr($tEncodeAttribs, 'Size') ; Get the size for encoding DllCall('Crypt32.dll','int','CryptBinaryToString', _ 'ptr',$pPIDL, _ 'int',$iSize, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',0, _ 'ptr',$pEncodeSize) If @error Then Return SetError(4,0,'') ; Create structure to hold the EncryptedPIDL Local $tEncodeResults = DllStructCreate("char EncryptedPIDL[" & DllStructGetData($tEncodeAttribs, 'Size') + 1 & "]") If @error Then Return SetError(5,0,'') ; Get pointers to the PIDL and path Local $pEncryptedPIDL = DllStructGetPtr($tEncodeResults, 'EncryptedPIDL') ; Get EncrtypedPIDL DllCall('Crypt32.dll','int','CryptBinaryToString', _ 'ptr',$pPIDL, _ 'int',$iSize, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',$pEncryptedPIDL, _ 'ptr',$pEncodeSize) If @error Then Return SetError(6,0,'') ; Return the EncrtypedPIDL Return DllStructGetData($tEncodeResults, 'EncryptedPIDL') EndFunc I have also tried a different variation of the same theme using ILCreateFromPathW, but I get the same results. Here is that variation (also not working). expandcollapse popupFunc _EncryptedPIDLEncode2($sPath) Local Const $CRYPT_STRING_BASE64 = 0x00000001 ; Get the PIDL Local $aPIDL = DllCall('Shell32.dll','ptr','ILCreateFromPathW','wstr',$sPath) If @error Then Return SetError(1,0,'') ; Create a structure to hold the pointer to PIDL so we can get the size Local $tPIDL = DllStructCreate('ptr') If @error Then Return SetError(2,0,'') ; Get the size of the PIDL DllStructSetData($tPIDL, 1, $aPIDL[0]) Local $iSize = DllStructGetSize($tPIDL) ; Create a structure to hold the size of the EncryptedPIDL Local $tEncryptedPIDLSize = DllStructCreate('int') If @error Then Return SetError(3,0,'') ; Get the size of the EncrtypedPIDL Local $aResults = DllCall('Crypt32.dll','int','CryptBinaryToString', _ 'ptr',$aPIDL[0], _ 'int',$iSize, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',0, _ 'ptr',DllStructGetPtr($tEncryptedPIDLSize,1)) If @error Then Return SetError(4,0,'') ; Create a structure to hold the EncryptedPIDL Local $tEncryptedPIDL = DllStructCreate('char[' & DllStructGetData($tEncryptedPIDLSize,1)+1 & ']') If @error Then Return SetError(5,0,'') ; Get the EncryptedPIDL Local $aResults = DllCall('Crypt32.dll','int','CryptBinaryToString', _ 'ptr',$aPIDL[0], _ 'int',$iSize, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',DllStructGetPtr($tEncryptedPIDL,1), _ 'ptr',DllStructGetPtr($tEncryptedPIDLSize,1)) If @error Then Return SetError(6,0,'') ; Return the EncrtypedPIDL Return DllStructGetData($tEncryptedPIDL, 1) EndFunc Any insight?
LarsJ Posted October 4, 2014 Posted October 4, 2014 _EncryptedPIDLEncode2Since CryptBinaryToString is already implemented by trancexx in this post, we can concentrate about the PIDLs.This is the procedure:Func _EncryptedPIDLEncode2( $sPath ) ; Get PIDL pointer from path Local $pPidl = _WinAPI_ShellILCreateFromPath( $sPath ) ; Get size of PIDL structure as the pointer is pointing to Local $iSize = ILGetSize( $pPidl ) ; Create a byte structure from memory location defined by PIDL pointer Local $tPidl = DllStructCreate( "byte[" & $iSize & "]", $pPidl ) ; Get binary string from byte structure Local $sBinStr = DllStructGetData( $tPidl, 1 ) ; Create Base64 encoded string Local $sEncoded = _Base64Encode( $sBinStr ) Return $sEncoded EndFunctechiebabel, In your PIDL size calculations you are calculating the size of the pointer. Not the size of the PIDL structure as the pointer is pointing to.Full code including functions and test:expandcollapse popup#include <WinAPIShellEx.au3> $sTestPath = "C:\WINDOWS\Temp\StdPictures" ; Must be an existing folder ConsoleWrite( @CRLF & "Test path: $sTestPath = " & $sTestPath & @CRLF & @CRLF ) $sEncodedPidl = _EncryptedPIDLEncode2( $sTestPath ) ConsoleWrite( "Base64 encoded PIDL: $sEncodedPidl = " & $sEncodedPidl & @CRLF ) $sDecodedPath = _EncryptedPIDLDecode( $sEncodedPidl ) ConsoleWrite( "Base64 decoded path: $sDecodedPath = " & $sDecodedPath & @CRLF & @CRLF ) Func _EncryptedPIDLEncode2( $sPath ) ; Get PIDL pointer from path Local $pPidl = _WinAPI_ShellILCreateFromPath( $sPath ) ; Get size of PIDL structure as the pointer is pointing to Local $iSize = ILGetSize( $pPidl ) ; Create a byte structure from memory location defined by PIDL pointer Local $tPidl = DllStructCreate( "byte[" & $iSize & "]", $pPidl ) ; Get binary string from byte structure Local $sBinStr = DllStructGetData( $tPidl, 1 ) ; Create Base64 encoded string Local $sEncoded = _Base64Encode( $sBinStr ) Return $sEncoded EndFunc Func ILGetSize( $pidl ) Local $aRet = DllCall( "shell32.dll", "uint", "ILGetSize", "ptr", $pidl ) If @error Then Return SetError(1, 0, 0) Return $aRet[0] EndFunc ;By trancexx: http://www.autoitscript.com/forum/index.php?showtopic=81332 Func _Base64Encode($input) $input = Binary($input) Local $struct = DllStructCreate("byte[" & BinaryLen($input) & "]") DllStructSetData($struct, 1, $input) Local $strc = DllStructCreate("int") Local $a_Call = DllCall("Crypt32.dll", "int", "CryptBinaryToString", _ "ptr", DllStructGetPtr($struct), _ "int", DllStructGetSize($struct), _ "int", 1, _ "ptr", 0, _ "ptr", DllStructGetPtr($strc)) If @error Or Not $a_Call[0] Then Return SetError(1, 0, "") ; error calculating the length of the buffer needed EndIf Local $a = DllStructCreate("char[" & DllStructGetData($strc, 1) & "]") $a_Call = DllCall("Crypt32.dll", "int", "CryptBinaryToString", _ "ptr", DllStructGetPtr($struct), _ "int", DllStructGetSize($struct), _ "int", 1, _ "ptr", DllStructGetPtr($a), _ "ptr", DllStructGetPtr($strc)) If @error Or Not $a_Call[0] Then Return SetError(2, 0, ""); error encoding EndIf Return DllStructGetData($a, 1) EndFunc ;==>_Base64Encode Func _EncryptedPIDLDecode($sEncryptedPIDL) Local Const $CRYPT_STRING_BASE64 = 0x00000001 ; Determine length of EncryptedPIDL Local $iLength = StringLen($sEncryptedPIDL) ; Create structure to hold the attributes returned and used during decoding Local $tDecodeAttribs = DllStructCreate("int Size; int Skipped;int Flags") If @error Then Return SetError(1,0,'') ; Get pointers to the attributes returned and used during decoding Local $pDecodeSize = DllStructGetPtr($tDecodeAttribs, 'Size') Local $pDecodeSkipped = DllStructGetPtr($tDecodeAttribs, 'Skipped') Local $pDecodeFlags = DllStructGetPtr($tDecodeAttribs, 'Flags') ; Get the values needed for decoding DllCall('Crypt32.dll','int','CryptStringToBinary', _ 'str',$sEncryptedPIDL, _ 'int',$iLength, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',0, _ 'ptr',$pDecodeSize, _ 'ptr',$pDecodeSkipped, _ 'ptr',$pDecodeFlags) If @error Then Return SetError(2,0,'') ; Create structure to hold the PIDL and path Local $tDecodeResults = DllStructCreate("char PIDL[" & DllStructGetData($tDecodeAttribs, 'Size') + 1 & "]; char Path[261]") If @error Then Return SetError(3,0,'') ; Get pointers to the PIDL and path Local $pDecodePIDL = DllStructGetPtr($tDecodeResults, 'PIDL') Local $pDecodePath = DllStructGetPtr($tDecodeResults, 'Path') ; Get the PIDL DllCall('Crypt32.dll','int','CryptStringToBinary', _ 'str',$sEncryptedPIDL, _ 'int',$iLength, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',$pDecodePIDL, _ 'ptr',$pDecodeSize, _ 'ptr',$pDecodeSkipped, _ 'ptr',$pDecodeFlags) If @error Then Return SetError(4,0,'') ; Get the Path DllCall('Shell32.dll','int','SHGetPathFromIDList', _ 'ptr',$pDecodePIDL, _ 'ptr',$pDecodePath) If @error Then Return SetError(5,0,'') ; Return the Path Return DllStructGetData($tDecodeResults, 'Path') EndFuncOutput in Scite console:Test path: $sTestPath = C:\WINDOWS\Temp\StdPictures Base64 encoded PIDL: $sEncodedPidl = FAAfUOBP0CDqOmkQotgIACswMJ0ZAC9DOlwAAAAAAAAAAAAAAAAAAAAAAAAAPAAx AAAAAAA6Rbw2EABXSU5ET1dTACYAAwAEAO++JTjxY0RFjCkUAAAAVwBJAE4ARABP AFcAUwAAABYANAAxAAAAAABERRowEABUZW1wAAAgAAMABADvviU48WNERRowFAAA AFQAZQBtAHAAAAAUAEYAMQAAAAAAQ0WSqhAAU1REUElDfjEAAC4AAwAEAO++Q0WS qkRFKCMUAAAAUwB0AGQAUABpAGMAdAB1AHIAZQBzAAAAGAAAAA== Base64 decoded path: $sDecodedPath = C:\WINDOWS\Temp\StdPictures Danyfirex 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions
uranus829 Posted December 27, 2021 Posted December 27, 2021 On 10/4/2014 at 3:07 PM, LarsJ said: _EncryptedPIDLEncode2 Since CryptBinaryToString is already implemented by trancexx in this post, we can concentrate about the PIDLs. This is the procedure: Func _EncryptedPIDLEncode2( $sPath ) ; Get PIDL pointer from path Local $pPidl = _WinAPI_ShellILCreateFromPath( $sPath ) ; Get size of PIDL structure as the pointer is pointing to Local $iSize = ILGetSize( $pPidl ) ; Create a byte structure from memory location defined by PIDL pointer Local $tPidl = DllStructCreate( "byte[" & $iSize & "]", $pPidl ) ; Get binary string from byte structure Local $sBinStr = DllStructGetData( $tPidl, 1 ) ; Create Base64 encoded string Local $sEncoded = _Base64Encode( $sBinStr ) Return $sEncoded EndFunc techiebabel, In your PIDL size calculations you are calculating the size of the pointer. Not the size of the PIDL structure as the pointer is pointing to. Full code including functions and test: expandcollapse popup#include <WinAPIShellEx.au3> $sTestPath = "C:\WINDOWS\Temp\StdPictures" ; Must be an existing folder ConsoleWrite( @CRLF & "Test path: $sTestPath = " & $sTestPath & @CRLF & @CRLF ) $sEncodedPidl = _EncryptedPIDLEncode2( $sTestPath ) ConsoleWrite( "Base64 encoded PIDL: $sEncodedPidl = " & $sEncodedPidl & @CRLF ) $sDecodedPath = _EncryptedPIDLDecode( $sEncodedPidl ) ConsoleWrite( "Base64 decoded path: $sDecodedPath = " & $sDecodedPath & @CRLF & @CRLF ) Func _EncryptedPIDLEncode2( $sPath ) ; Get PIDL pointer from path Local $pPidl = _WinAPI_ShellILCreateFromPath( $sPath ) ; Get size of PIDL structure as the pointer is pointing to Local $iSize = ILGetSize( $pPidl ) ; Create a byte structure from memory location defined by PIDL pointer Local $tPidl = DllStructCreate( "byte[" & $iSize & "]", $pPidl ) ; Get binary string from byte structure Local $sBinStr = DllStructGetData( $tPidl, 1 ) ; Create Base64 encoded string Local $sEncoded = _Base64Encode( $sBinStr ) Return $sEncoded EndFunc Func ILGetSize( $pidl ) Local $aRet = DllCall( "shell32.dll", "uint", "ILGetSize", "ptr", $pidl ) If @error Then Return SetError(1, 0, 0) Return $aRet[0] EndFunc ;By trancexx: http://www.autoitscript.com/forum/index.php?showtopic=81332 Func _Base64Encode($input) $input = Binary($input) Local $struct = DllStructCreate("byte[" & BinaryLen($input) & "]") DllStructSetData($struct, 1, $input) Local $strc = DllStructCreate("int") Local $a_Call = DllCall("Crypt32.dll", "int", "CryptBinaryToString", _ "ptr", DllStructGetPtr($struct), _ "int", DllStructGetSize($struct), _ "int", 1, _ "ptr", 0, _ "ptr", DllStructGetPtr($strc)) If @error Or Not $a_Call[0] Then Return SetError(1, 0, "") ; error calculating the length of the buffer needed EndIf Local $a = DllStructCreate("char[" & DllStructGetData($strc, 1) & "]") $a_Call = DllCall("Crypt32.dll", "int", "CryptBinaryToString", _ "ptr", DllStructGetPtr($struct), _ "int", DllStructGetSize($struct), _ "int", 1, _ "ptr", DllStructGetPtr($a), _ "ptr", DllStructGetPtr($strc)) If @error Or Not $a_Call[0] Then Return SetError(2, 0, ""); error encoding EndIf Return DllStructGetData($a, 1) EndFunc ;==>_Base64Encode Func _EncryptedPIDLDecode($sEncryptedPIDL) Local Const $CRYPT_STRING_BASE64 = 0x00000001 ; Determine length of EncryptedPIDL Local $iLength = StringLen($sEncryptedPIDL) ; Create structure to hold the attributes returned and used during decoding Local $tDecodeAttribs = DllStructCreate("int Size; int Skipped;int Flags") If @error Then Return SetError(1,0,'') ; Get pointers to the attributes returned and used during decoding Local $pDecodeSize = DllStructGetPtr($tDecodeAttribs, 'Size') Local $pDecodeSkipped = DllStructGetPtr($tDecodeAttribs, 'Skipped') Local $pDecodeFlags = DllStructGetPtr($tDecodeAttribs, 'Flags') ; Get the values needed for decoding DllCall('Crypt32.dll','int','CryptStringToBinary', _ 'str',$sEncryptedPIDL, _ 'int',$iLength, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',0, _ 'ptr',$pDecodeSize, _ 'ptr',$pDecodeSkipped, _ 'ptr',$pDecodeFlags) If @error Then Return SetError(2,0,'') ; Create structure to hold the PIDL and path Local $tDecodeResults = DllStructCreate("char PIDL[" & DllStructGetData($tDecodeAttribs, 'Size') + 1 & "]; char Path[261]") If @error Then Return SetError(3,0,'') ; Get pointers to the PIDL and path Local $pDecodePIDL = DllStructGetPtr($tDecodeResults, 'PIDL') Local $pDecodePath = DllStructGetPtr($tDecodeResults, 'Path') ; Get the PIDL DllCall('Crypt32.dll','int','CryptStringToBinary', _ 'str',$sEncryptedPIDL, _ 'int',$iLength, _ 'int',$CRYPT_STRING_BASE64, _ 'ptr',$pDecodePIDL, _ 'ptr',$pDecodeSize, _ 'ptr',$pDecodeSkipped, _ 'ptr',$pDecodeFlags) If @error Then Return SetError(4,0,'') ; Get the Path DllCall('Shell32.dll','int','SHGetPathFromIDList', _ 'ptr',$pDecodePIDL, _ 'ptr',$pDecodePath) If @error Then Return SetError(5,0,'') ; Return the Path Return DllStructGetData($tDecodeResults, 'Path') EndFunc Output in Scite console: Test path: $sTestPath = C:\WINDOWS\Temp\StdPictures Base64 encoded PIDL: $sEncodedPidl = FAAfUOBP0CDqOmkQotgIACswMJ0ZAC9DOlwAAAAAAAAAAAAAAAAAAAAAAAAAPAAx AAAAAAA6Rbw2EABXSU5ET1dTACYAAwAEAO++JTjxY0RFjCkUAAAAVwBJAE4ARABP AFcAUwAAABYANAAxAAAAAABERRowEABUZW1wAAAgAAMABADvviU48WNERRowFAAA AFQAZQBtAHAAAAAUAEYAMQAAAAAAQ0WSqhAAU1REUElDfjEAAC4AAwAEAO++Q0WS qkRFKCMUAAAAUwB0AGQAUABpAGMAdAB1AHIAZQBzAAAAGAAAAA== Base64 decoded path: $sDecodedPath = C:\WINDOWS\Temp\StdPictures Hello, the base64 code generated by “C:\Users\Public\Pictures” does not recognize the path on windows. FAAfUOBP0CDqOmkQotgIACswMJ0ZAC9DOlwAAAAAAAAAAAAAAAAAAAAAAAAAeAAxAAAAAADQUjEDEQBVc2VycwBkAAkABADvvodPd0ibU7gRLgAAAE4GAAAAAAEAAAAAAAAAAAA6AAAAAADrhDoAVQBzAGUAcgBzAAAAQABzAGgAZQBsAGwAMwAyAC4AZABsAGwALAAtADIAMQA4ADEAMwAAABQAfAAxAAAAAACbU2YSEQBQdWJsaWMAAGYACQAEAO++h0/bSZtTZhIuAAAAfwYAAAAAAQAAAAAAAAAAADwAAAAAAL8ifABQAHUAYgBsAGkAYwAAAEAAcwBoAGUAbABsADMAMgAuAGQAbABsACwALQAyADEAOAAxADYAAAAWAIIAMQAAAAAAm1N6EhEAUGljdHVyZXMAAGoACQAEAO++h0/bSZtTehIuAAAAhQYAAAAAAQAAAAAAAAAAAEAAAAAAAMnRBQFQAGkAYwB0AHUAcgBlAHMAAABAAHMAaABlAGwAbAAzADIALgBkAGwAbAAsAC0AMgAxADgAMAAyAAAAGAAAAA==
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