Jump to content

Resources UDF


Zedna
 Share

Recommended Posts

Can you implement ResourceWrite, so that the .exe can update the resource data for the next time the .exe runs?

I will not do that in this my UDF - it's beyond my experiences/free time now.

But as far as I know Jos made exactly this in his latest Autoit3Wrapper - he made updating EXE resources by API calls instead of previous using of rc.exe & resourcehacker.

So maybe Jos can help you with that.

If there will be released AutoIt sources of ResourceUpdate API solution I can put it into my UDF.

EDIT: Here is the link to post with such complete AutoIt code examples

Edited by Zedna
Link to comment
Share on other sites

  • Developers

I will not do that in this my UDF - it's beyond my experiences/free time now.

But as far as I know Jos made exactly this in his latest Autoit3Wrapper - he made updating EXE resources by API calls instead of previous using of rc.exe & resourcehacker.

So maybe Jos can help you with that.

If there will be released AutoIt sources of ResourceUpdate API solution I can put it into my UDF.

I have looked at it for a bit but these are the challenges at this moment that needs to be resolved first:

- Resource update Functions I wrote use the standard windows dllcalls but for some reason mess up the embedded script in compiled exe's, so AUtoIt3Wrapper is updating the resources of a copy of the appropriate BIN file to work around it. I have no idea why Reshacker is able to update compiled scripts and what it is doing extra to avoid embedded script corruption.

- UPXed programs/scripts: probably need to do a "UPX -d" before updating the resources.

Other than that, its quite easy to modify the functions from AutoIt3Wrapper to update the Resources. :)

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • 3 weeks later...

ok, so i use the latest scite with all tools, and the new compilere puts the bmp's in a rc header, instaed of the bmp header, this breaks the resource function, it cant find it.

but it works if i integrate the bmp myself with reshacker.

so is there a way to tell the resource function to get the bmp out of the rc data, instead of the bmp one?

i hope you can clarify for me man, this function is to good to let go :)

damian666

and proud of it!!!
Link to comment
Share on other sites

I received this problem report:

I will look at it.

Now I instaled latest Scite4AutoIt3 (2008-03-08) and tested my examples with my UDF from first post.

There is realy problem. All resources added by #AutoIt3Wrapper_Res_File_Add directive are now put into RCData section and named by number 1,2,3,... instead of put them into right section with right name (based on values given from directive)

;#AutoIt3Wrapper_Res_File_Add=Filename[,Section [,ResName]] 
#AutoIt3Wrapper_Res_File_Add=image1.bmp, bitmap, TEST_BMP_1

So I think #AutoIt3Wrapper_Res_File_Add directive is broken and doesn't preserve Section,Name values.

Jos can you please confirm this problem?

Edited by Zedna
Link to comment
Share on other sites

ok, so i use the latest scite with all tools, and the new compilere puts the bmp's in a rc header, instaed of the bmp header, this breaks the resource function, it cant find it.

but it works if i integrate the bmp myself with reshacker.

so is there a way to tell the resource function to get the bmp out of the rc data, instead of the bmp one?

i hope you can clarify for me man, this function is to good to let go :)

damian666

See my previous post. I think it's problem you are talking about.

Link to comment
Share on other sites

  • Developers

I will look at it.

Now I instaled latest Scite4AutoIt3 (2008-03-08) and tested my examples with my UDF from first post.

There is realy problem. All resources added by #AutoIt3Wrapper_Res_File_Add directive are now put into RCData section and named by number 1,2,3,... instead of put them into right section with right name (based on values given from directive)

;#AutoIt3Wrapper_Res_File_Add=Filename[,Section [,ResName]] 
#AutoIt3Wrapper_Res_File_Add=image1.bmp, bitmap, TEST_BMP_1

So I think #AutoIt3Wrapper_Res_File_Add directive is broken and doesn't preserve Section,Name values.

Jos can you please confirm this problem?

You are correct and thought I mentioned that (here but omitted to update the helpfile.. sorry ). I couldn't get that to work like ResHacker does and started to use the standard approach I saw in the example code I studied which is using RCDATA and a sequence number.

I have not revisited that anymore and nobody complained about it in the "beta" period. :)

Edited by Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

You are correct and thought I mentioned that (here but omitted to update the helpfile.. sorry ). I couldn't get that to work like ResHacker does and started to use the standard approach I saw in the example code I studied which is using RCDATA and a sequence number.

I have not revisited that anymore and nobody complained about it in the "beta" period. :)

OK.

Will you fix this or this behaviour will stay as it is now?

If it will stay this way I will return back to my old resource add syntax in my UDF examples:

#AutoIt3Wrapper_useupx=n
#AutoIt3Wrapper_run_after=ResHacker.exe -add %out%, %out%, image1.bmp, bitmap, TEST_BMP_1, 0
#AutoIt3Wrapper_run_after=upx.exe --compress-resources=0 "%out%"

Because your new behaviour is useless for my UDF.

Link to comment
Share on other sites

  • Developers

OK.

Will you fix this or this behaviour will stay as it is now?

If it will stay this way I will return back to my old resource add syntax in my UDF examples:

Because your new behaviour is useless for my UDF.

Just so I understand properly: You need it to also support RT_BITMAP which is currently missing .. right ?

Does it matter when it uses a sequence number ?

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Just so I understand properly: You need it to also support RT_BITMAP which is currently missing .. right ?

Does it matter when it uses a sequence number ?

Jos

Yes. RT_BITMAP and RT_HTML and also "SOUND" for WAV sound.

But also name of resource must be known and not somehow generated - this is BIG problem for me.

EDIT: added RT_HTML (23) used in my second example - resource_test_ie.au3

#AutoIt3Wrapper_Res_File_Add=test_1.htm, 23, TEST_HTML_1; Filename,Section,ResName
#AutoIt3Wrapper_Res_File_Add=test_1.gif, 23, TEST_GIF_1
Edited by Zedna
Link to comment
Share on other sites

  • Developers

Sorry Jos, I haven't been very active on AutoIt forum for last few months ;)

Hey, no problem.. same counts for me lately since I am on a full time assignment again.

When writing the internal resource functions, I was focused on building the proper RT_Version structures and making the standard Resource updates working.

I haven't been using your Resource functions really and never looked at what was needed since ResHacker took care of it all.

Don't mind looking at other supported Resource sections, just need some time to see what it takes to make it work. Maybe its very simple like the RT_DATA section.

Will get back to you on this one. :)

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

  • Developers

Yes. RT_BITMAP and RT_HTML and also "SOUND" for WAV sound.

But also name of resource must be known and not somehow generated - this is BIG problem for me.

EDIT: added RT_HTML (23) used in my second example - resource_test_ie.au3

#AutoIt3Wrapper_Res_File_Add=test_1.htm, 23, TEST_HTML_1; Filename,Section,ResName
#AutoIt3Wrapper_Res_File_Add=test_1.gif, 23, TEST_GIF_1
I am not sure if I can easily support none standard sections names like "SOUNDS" in stead of the standard numbers like RT_HTML (23). If my memory serves me right the standard DLL calls didn't allow me to use Strings in stead of Numbers. (need to test that again now things are working)

Jos

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

Hey, no problem.. same counts for me lately since I am on a full time assignment again.

When writing the internal resource functions, I was focused on building the proper RT_Version structures and making the standard Resource updates working.

I haven't been using your Resource functions really and never looked at what was needed since ResHacker took care of it all.

Don't mind looking at other supported Resource sections, just need some time to see what it takes to make it work. Maybe its very simple like the RT_DATA section.

Will get back to you on this one. :)

OK. Thanks for taking care about it  ;)

I will make temporary info in first post about workaround for the time being.

EDIT: updated first post.

Edited by Zedna
Link to comment
Share on other sites

  • 1 month later...

I made the Function to use JPG as a resource:

#include <GDIPlus.au3>
#include <Memory.au3>
#include <Resources.au3>
; Convertet from AHK To AutoIT by Prog@ndy
Func _ResourceSetJpgToCtrl($CtrlId,$ResName)
    Local $buffer = _ResourceGet($ResName)
; Converting Image data to hBITMAP ; Thanks Sean
; http://www.autohotkey.com/forum/viewtopic.php?t=22999
Local $nSize = @extended
Local $hData = _MemGlobalAlloc($nSize,2)
;~ hData := DllCall("GlobalAlloc", "UInt",2, "UInt", @extended )
;~ pData := DllCall("GlobalLock",  UInt,hData )
Local $pData = _MemGlobalLock($hData)
_MemMoveMemory($buffer,$pData,$nSize)
;~ DllCall( "RtlMoveMemory", UInt,pData, UInt,Buffer, UInt,nSize )
;~ DllCall( "GlobalUnlock", UInt,hData )
_MemGlobalUnlock($hData)
Local $ret = DllCall( "ole32.dll","int","CreateStreamOnHGlobal", "int",$hData, "long",1, "Int*",0 )
Local $pStream = $ret[3]
_GDIPlus_Startup()
;~ DllCall( "LoadLibrary", Str,"gdiplus" )
;~ VarSetCapacity(si, 16, 0), si := Chr(1)
;~ DllCall( "gdiplus\GdiplusStartup", UIntP,pToken, UInt,&si, UInt,0 )

Local $pBitmap = DllCall( $ghGDIPDll,"int","GdipCreateBitmapFromStream", "ptr",$pStream, "int*",0 )
$pBitmap = $pBitmap[2]
;~ DllCall( "gdiplus\GdipCreateHBITMAPFromBitmap", UInt,pBitmap, UIntP,hBitmap, UInt,0 )
$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($pBitmap)
_SetBitmapToCtrl($CtrlId,$hBitmap) ;SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %Pic1%
_GDIPlus_BitmapDispose($pBitmap)
_GDIPlus_Shutdown()
$dll = DllStructCreate("Uint",$pStream)
$dll2 = DllStructCreate("uInt",DllStructGetData($dll,1)+8)
;~ MsgBox(0, '', DllStructGetData($dll2,1))
DllCall("","UInt",DllStructGetData($dll2,1),"UInt",$pStream)
_WinAPI_DeleteObject($pStream)
$pStream = 0
;~ DllCall( NumGet(NumGet(1*pStream)+8 ), UInt,pStream )
_MemGlobalFree($hData)
EndFuncoÝ÷ ØLZ^jëh×6#AutoIt3Wrapper_Res_File_Add=D:\Dokumente\Dateien von Andreas\Eigene Bilder\banner.jpg, rcdata, TEST_JPG_1
#include <GUIConstants.au3>
#include <JPGResource.au3>

#region - GUI Create
GUICreate('test')
$pic = GUICtrlCreatePic("",10,10,100,100)
_ResourceSetJpgToCtrl($pic,"#1") ; DidN#t work with TEST_JPG_1, but why? This way it uses the first RCDATA-Resource
GUISetState()
#endregion

#region - GUI SelectLoop
While 1
    $msg = GUIGetMsg()
    Select
        Case $msg = $GUI_EVENT_CLOSE
            Exit

    EndSelect
WEnd
#endregion

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

I made the Function to use JPG as a resource:

SUPER!!

I couldn't get to work CreateStreamOnHGlobal and GdipCreateBitmapFromStream API functions.

Now I see where was problem: You used MemMoveMemory API to copy memory from EXE to alocated memory and you created stream on this copy.

That's great! It works fine. I will include this into my UDF quickly.

Many thanks ProgAndy!!! :D

DidN#t work with TEST_JPG_1, but why? This way it uses the first RCDATA-Resource

See my first post I added EDIT: 2008-03-10 section at end where is described this problem and also temporary workaround (It's bug in Scite4AutoIt3 -> AutoIt3Wrapper)

Edited by Zedna
Link to comment
Share on other sites

would it be possible to use a dll file as a resource file and then have it act upon another resource file?

Yes. Tha't possible but this my UDF is not created for this purpose.

Read carefully whole first post:

Notes:

* this UDF is for loading resources only from currently running AutoIt EXE and not from another EXE/DLL files (for use with external EXE/DLL must be used LoadLibrary & GetModuleHandle).

You may easily accomodate it to your wishes...

Link to comment
Share on other sites

For using external Resource DLLs, you need to do some other DLL-Calls:

LoadLibrary

and FreeLibrary

Here is the UDF with an extra Parameter for External Librarys:

#include <GDIPlus.au3>
#include <Memory.au3>
#include-once

Global Const $RT_CURSOR = 1
Global Const $RT_BITMAP = 2
Global Const $RT_ICON = 3
Global Const $RT_MENU = 4
Global Const $RT_DIALOG = 5
Global Const $RT_STRING = 6
Global Const $RT_FONTDIR = 7
Global Const $RT_FONT = 8
Global Const $RT_ACCELERATORS = 9
Global Const $RT_RCDATA = 10
Global Const $RT_MESSAGETABLE = 11
Global Const $RT_GROUP_CURSOR = 12
Global Const $RT_GROUP_ICON = 14
Global Const $RT_VERSION = 16

Global Const $RT_ANICURSOR = 21
Global Const $RT_ANIICON = 22
Global Const $RT_HTML = 23
Global Const $RT_MANIFEST = 24

Global Const $SND_RESOURCE = 0x00040004
Global Const $SND_SYNC = 0x0
Global Const $SND_ASYNC = 0x1
Global Const $SND_LOOP = 0x8
Global Const $SND_NOSTOP = 0x10
Global Const $SND_NOWAIT = 0x2000
Global Const $SND_PURGE = 0x40

Func _ResourceGet($ResName, $ResType = 10, $ResLang = 0,$DLL=-1) ; $RT_RCDATA = 10
    Local Const $IMAGE_BITMAP = 0
    Local $hInstance, $hBitmap, $InfoBlock, $GlobalMemoryBlock, $MemoryPointer, $ResSize
    If $DLL = -1 Then
        $hInstance = DllCall("kernel32.dll", "int", "GetModuleHandleA", "int", 0)
    Else
        $hInstance = DllCall("kernel32.dll","int","LoadLibrary","str",$DLL)
    EndIf
    $hInstance = $hInstance[0]

    If $ResType = $RT_BITMAP Then
        $hBitmap = DllCall("user32.dll", "hwnd", "LoadImage", "hwnd", $hInstance, "str", $ResName, _
                "int", $IMAGE_BITMAP, "int", 0, "int", 0, "int", 0)
        If @error Then Return SetError(1, 0, 0)
        $hBitmap = $hBitmap[0]
        Return $hBitmap ; returns handle to Bitmap
    EndIf

    If $ResLang <> 0 Then
        $InfoBlock = DllCall("kernel32.dll", "int", "FindResourceExA", "int", $hInstance, "str", $ResName, "long", $ResType, "short", $ResLang)
    Else
        $InfoBlock = DllCall("kernel32.dll", "int", "FindResourceA", "int", $hInstance, "str", $ResName, "long", $ResType)
    EndIf

    If @error Then Return SetError(2, 0, 0)
    $InfoBlock = $InfoBlock[0]
    If $InfoBlock = 0 Then Return SetError(3, 0, 0)
   
    $ResSize = DllCall("kernel32.dll", "dword", "SizeofResource", "int", $hInstance, "int", $InfoBlock)
    If @error Then Return SetError(4, 0, 0)
    $ResSize = $ResSize[0]
    If $ResSize = 0 Then Return SetError(5, 0, 0)
   
    $GlobalMemoryBlock = DllCall("kernel32.dll", "int", "LoadResource", "int", $hInstance, "int", $InfoBlock)
    If @error Then Return SetError(6, 0, 0)
    $GlobalMemoryBlock = $GlobalMemoryBlock[0]
    If $GlobalMemoryBlock = 0 Then Return SetError(7, 0, 0)
   
    $MemoryPointer = DllCall("kernel32.dll", "int", "LockResource", "int", $GlobalMemoryBlock)
    If @error Then Return SetError(8, 0, 0)
    $MemoryPointer = $MemoryPointer[0]
    If $MemoryPointer = 0 Then Return SetError(9, 0, 0)
   If $DLL <> -1 Then DllCall("Kernel32.dll","int","FreeLibrary","str",$hInstance)
    SetExtended($ResSize)
    Return $MemoryPointer
EndFunc


Func _ResourceSetJpgToCtrl($CtrlId,$ResName,$DLL=-1)
    Local $buffer = _ResourceGet($ResName,10,0,$DLL)
; Converting Image data to hBITMAP ; Thanks Sean
; http://www.autohotkey.com/forum/viewtopic.php?t=22999
Local $nSize = @extended
Local $hData = _MemGlobalAlloc($nSize,2)
;~ hData := DllCall("GlobalAlloc", "UInt",2, "UInt", @extended )
;~ pData := DllCall("GlobalLock",  UInt,hData )
Local $pData = _MemGlobalLock($hData)
_MemMoveMemory($buffer,$pData,$nSize)
;~ DllCall( "RtlMoveMemory", UInt,pData, UInt,Buffer, UInt,nSize )
;~ DllCall( "GlobalUnlock", UInt,hData )
_MemGlobalUnlock($hData)
Local $ret = DllCall( "ole32.dll","int","CreateStreamOnHGlobal", "int",$hData, "long",1, "Int*",0 )
Local $pStream = $ret[3]
_GDIPlus_Startup()
;~ DllCall( "LoadLibrary", Str,"gdiplus" )
;~ VarSetCapacity(si, 16, 0), si := Chr(1)
;~ DllCall( "gdiplus\GdiplusStartup", UIntP,pToken, UInt,&si, UInt,0 )

Local $pBitmap = DllCall( $ghGDIPDll,"int","GdipCreateBitmapFromStream", "ptr",$pStream, "int*",0 )
$pBitmap = $pBitmap[2]
;~ DllCall( "gdiplus\GdipCreateHBITMAPFromBitmap", UInt,pBitmap, UIntP,hBitmap, UInt,0 )
$hBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($pBitmap)
_SetBitmapToCtrl($CtrlId,$hBitmap) ;SendMessage, (STM_SETIMAGE:=0x172), (IMAGE_BITMAP:=0x0), hBitmap,, ahk_id %Pic1%
_GDIPlus_BitmapDispose($pBitmap)
_GDIPlus_Shutdown()
$dll = DllStructCreate("Uint",$pStream)
$dll2 = DllStructCreate("uInt",DllStructGetData($dll,1)+8)
;~ MsgBox(0, '', DllStructGetData($dll2,1))
DllCall("","UInt",DllStructGetData($dll2,1),"UInt",$pStream)
_WinAPI_DeleteObject($pStream)
$pStream = 0
;~ DllCall( NumGet(NumGet(1*pStream)+8 ), UInt,pStream )
_MemGlobalFree($hData)
EndFunc


Func _ResourceGetAsString($ResName, $ResType = 10, $ResLang = 0,$DLL=-1) ; $RT_RCDATA = 10
    Local $ResPointer, $ResSize, $struct

    $ResPointer = _ResourceGet($ResName, $ResType, $ResLang,$DLL)
    If @error Then
        SetError(1, 0, 0)
        Return ''
    EndIf
    $ResSize = @extended
    $struct = DllStructCreate("char[" & $ResSize & "]", $ResPointer)
    Return DllStructGetData($struct, 1) ; returns string
EndFunc

Func _ResourceGetAsBytes($ResName, $ResType = 10, $ResLang = 0,,$DLL=-1) ; $RT_RCDATA = 10
    Local $ResPointer, $ResSize

    $ResPointer = _ResourceGet($ResName, $ResType, $ResLang,$DLL)
    If @error Then Return SetError(1, 0, 0)
    $ResSize = @extended
    Return DllStructCreate("byte[" & $ResSize & "]", $ResPointer) ; returns struct with bytes
EndFunc

Func _ResourceSaveToFile($FileName, $ResName, $ResType = 10, $ResLang = 0, $CreatePath = 0,$DLL=-1) ; $RT_RCDATA = 10
    Local $ResStruct, $ResSize, $FileHandle

    $ResStruct = _ResourceGetAsBytes($ResName, $ResType, $ResLang,$DLL)
    If @error Then Return SetError(1, 0, 0)
    $ResSize = DllStructGetSize($ResStruct)
   
    If $CreatePath Then $CreatePath = 8 ; mode 8 = Create directory structure if it doesn't exist
    $FileHandle = FileOpen($FileName, 2+16+$CreatePath)
    If @error Then Return SetError(2, 0, 0)
    FileWrite($FileHandle, DllStructGetData($ResStruct, 1))
    If @error Then Return SetError(3, 0, 0)
    FileClose($FileHandle)
    If @error Then Return SetError(4, 0, 0)

    Return $ResSize
EndFunc

Func _ResourceSetImageToCtrl($CtrlId, $ResName, $ResType = 10,,$DLL=-1) ; $RT_RCDATA = 10
    Local $ResData = _ResourceGet($ResName, $ResType,$DLL)
    If @error Then Return SetError(1, 0, 0)
   
    If $ResType = $RT_BITMAP Then
        _SetBitmapToCtrl($CtrlId, $ResData)
        If @error Then Return SetError(2, 0, 0)
        Return 1
    EndIf
   
    ; for other types then BITMAP not implemented yet (must be used GDI+) ...
    ; ...
    Return SetError(-1, 0, 0)
EndFunc

; internal helper function
Func _SetBitmapToCtrl($CtrlId, $hBitmap)
    Local Const $STM_SETIMAGE = 0x0172
    Local Const $IMAGE_BITMAP = 0

    Local $hWnd = GUICtrlGetHandle($CtrlId)
    If $hWnd = 0 Then Return SetError(1, 0, 0)
    DllCall("user32.dll", "hwnd", "SendMessage", "hwnd", $hWnd, "int", $STM_SETIMAGE, "int", $IMAGE_BITMAP, "int", $hBitmap)
    If @error Then Return SetError(2, 0, 0)
    Return 1
EndFunc

; thanks Larry
; MSDN: http://msdn2.microsoft.com/en-us/library/ms712879.aspx
; default flag is $SND_SYNC = 0
Func _ResourcePlaySound($ResName, $Flag = 0)
    Local $ret = DllCall("winmm.dll", "int", "PlaySound", "str", $ResName, "hwnd", 0, "int", BitOr($SND_RESOURCE,$Flag))
    If @error Then Return SetError(1, 0, 0)
    Return $ret[0]
EndFunc

Just the _REsourcePlaySound is not changed, don't know how :D

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

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