Jump to content
Sign in to follow this  
tonyxp

Auto GeForce Experience Install

Recommended Posts

Hello,
I wish to perform a GeForce Experience installation with driver download and install, the script works until the function _RunFromSubfolder it works half !

it works if the setup.exe is in the folder which makes me say that "while not fileexists" does not fulfill its function :(

the script must wait until the file has been downloaded to the $aItems[1]

Do you have a good idea? :)

Many thanks 
 

_ScreenSetting(1600, 900, 32, 60)

;====================================================================================
;
;Function Name:     _ScreenSetting()
;Description:       Changes the screen resolution, color dept and refresh rate
;Version:           1.0
;Parameters:        $iWidth   - Width of the desktop screen in pixels. (horizontal resolution)
;                   $iHeight  - Height of the desktop screen in pixels. (vertical resolution)
;                   $iDepth   - Depth of the desktop screen in bits per pixel.
;                   $iRefresh - Refresh rate of the desktop screen in hertz.
;Return Value(s):   On Success - Screen is adjusted
;                   On failure - Message with error description
;Requirement(s):    Tested on AutoIt 3.2.10.0
;Autor(s):          R.Gilman (a.k.a rasim); special thanks to amel27
;
;====================================================================================
Func _ScreenSetting($iWidth = @DesktopWidth, $iHeight = @DesktopHeight, $iDepth = @DesktopDepth, $iRefresh = @DesktopRefresh)
    Local Const $DISP_CHANGE_SUCCESSFUL = 0
    Local Const $DISP_CHANGE_RESTART    = 1
    Local Const $DISP_CHANGE_FAILED     = -1
    Local Const $DISP_CHANGE_BADMODE    = -2
    Local Const $DISP_CHANGE_NOTUPDATED = -3
    Local Const $DISP_CHANGE_BADFLAGS   = -4
    Local Const $DISP_CHANGE_BADPARAM   = -5

    Local Const $CDS_TEST           = 0x4
    Local Const $CDS_UPDATEREGISTRY = 0x1

    Local Const $DM_PELSWIDTH        = 0x80000
    Local Const $DM_PELSHEIGHT       = 0x100000
    Local Const $DM_BITSPERPEL       = 0x40000
    Local Const $DM_DISPLAYFREQUENCY = 0x400000

    Local Const $ENUM_CURRENT_SETTINGS   = -1
    Local Const $WM_DISPLAYCHANGE        = 0x007E
    Local Const $HWND_BROADCAST          = 0xFFFF
    Local Const $SPI_SETNONCLIENTMETRICS = 0x2A

    Local $DEVMODE, $DllRet

    $DEVMODE = DllStructCreate("char dmDeviceName[32];ushort dmSpecVersion;ushort dmDriverVersion;short dmSize;" & _
                               "ushort dmDriverExtra;dword dmFields;short dmOrientation;short dmPaperSize;short dmPaperLength;" & _
                               "short dmPaperWidth;short dmScale;short dmCopies;short dmDefaultSource;short dmPrintQuality;" & _
                               "short dmColor;short dmDuplex;short dmYResolution;short dmTTOption;short dmCollate;" & _
                               "byte dmFormName[32];dword dmBitsPerPel;int dmPelsWidth;dword dmPelsHeight;" & _
                               "dword dmDisplayFlags;dword dmDisplayFrequency")

    $DllRet = DllCall("user32.dll", "int", "EnumDisplaySettings", "ptr", 0, "dword", $ENUM_CURRENT_SETTINGS, _
                      "ptr", DllStructGetPtr($DEVMODE))
    $DllRet = $DllRet[0]

    If $DllRet = 0 Then
        MsgBox(16, "Error", "Unable to get graphic mode")
        Return False
    EndIf

    $VGA_MAP_KEY = RegRead("HKLM\HARDWARE\DEVICEMAP\VIDEO", "\Device\Video0")
    $VGA_KEY = StringReplace($VGA_MAP_KEY, "\Registry\Machine", "HKLM")

    RegWrite($VGA_KEY, "PruningMode", "REG_DWORD", 0)

    DllStructSetData($DEVMODE, "dmSize", DllStructGetSize($DEVMODE))
    DllStructSetData($DEVMODE, "dmPelsWidth", $iWidth)
    DllStructSetData($DEVMODE, "dmPelsHeight", $iHeight)
    DllStructSetData($DEVMODE, "dmBitsPerPel", $iDepth)
    DllStructSetData($DEVMODE, "dmDisplayFrequency", $iRefresh)
    DllStructSetData($DEVMODE, "dmFields", BitOR($DM_PELSWIDTH, $DM_PELSHEIGHT, $DM_BITSPERPEL, $DM_DISPLAYFREQUENCY))

    $DllRet = DllCall("user32.dll", "int", "ChangeDisplaySettings", "ptr", DllStructGetPtr($DEVMODE), "int", $CDS_TEST)
    $DllRet = $DllRet[0]

    If $DllRet <> $DISP_CHANGE_SUCCESSFUL Then
        Switch $DllRet
            Case $DISP_CHANGE_RESTART
                MsgBox(48, "Warning", "Restart your computer for change display settings")
            Case $DISP_CHANGE_FAILED
                MsgBox(16, "Error", "The video driver not set a new mode")
                Return False
            Case $DISP_CHANGE_BADMODE
                MsgBox(16, "Error", "Video mode not supported")
                Return False
            Case $DISP_CHANGE_NOTUPDATED
                MsgBox(16, "Error", "Unable to write in registry")
                Return False
            Case $DISP_CHANGE_BADFLAGS
                MsgBox(16, "Error", "Bad flags")
                Return False
            Case $DISP_CHANGE_BADPARAM
                MsgBox(16, "Error", "Bad parameters")
                Return False
        EndSwitch
    EndIf

    $DllRet = DllCall("user32.dll", "int", "ChangeDisplaySettings", "ptr", DllStructGetPtr($DEVMODE), "int", $CDS_UPDATEREGISTRY)
    $DllRet = $DllRet[0]

    DllCall("user32.dll", "int", "SendMessage", "hwnd", $HWND_BROADCAST, "int", $WM_DISPLAYCHANGE, _
            "int", $SPI_SETNONCLIENTMETRICS, "int", 0)

    RegWrite($VGA_KEY, "PruningMode", "REG_DWORD", 1)

    $DEVMODE = ""
    $DllRet  = ""
EndFunc
Sleep(5000)

; Affichage d'une infobulle d'information
TrayTip("Installation de GeForce Experience","Début d'installation de GeForce Experience",100000)

;Pause de 5 secondes
Sleep(5000)

;lance le porgramme d'installation
ShellExecuteWait("setup.exe","-noreboot -passive -noeula -nofinish")

;lance l'exe Geforce après installation
Run("C:\Program Files\NVIDIA Corporation\NVIDIA GeForce Experience\NVIDIA GeForce Experience.exe")
Sleep(10000)

;Attendre la fênetre Geforce CLUF
WinActive("GeForce Experience")

;auto installation clavier
Send("{ENTER}")
sleep(2000)
Send("{TAB}")
sleep(2000)
Send("{ENTER}")
sleep(5000)
MouseClick("left", 913, 598, 1)
sleep(5000)
send("blabla")
Send("{ENTER}")
sleep(5000)
send("P@sswOrd")
Send("{ENTER}")
sleep(5000)
MouseClick("left", 992, 678, 1)
sleep(5000)
MouseClick("left", 394, 84, 1)
sleep(5000)
MouseClick("left", 1333, 275, 1)
sleep(5000)
MouseClick("left", 1237, 214, 1)

;Installation du pilote téléchargé dans programdata
#include <File.au3>

Global Enum  $RFS_ERROR_RUN = 2

Global Const $g_sFileName = 'setup.exe', _
             $g_sFilePath = 'C:\ProgramData\NVIDIA Corporation\Downloader\', _
             $g_sFileMsg  = 'file         : "%s"\n(sub-)folder : "%s"\nlocated at   : "%s"\n'

_RunFromSubfolder($g_sFileName, $g_sFilePath)

Func _RunFromSubfolder(Const $sFile, Const $sFolder)
    Local       $sMessage = ''
    Local       $iError   = 0, _
                $iExtd    = 0, _
                $iPID     = 0
    Local Const $aItems   = _FileListToArrayRec($sFolder, $sFile, $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
    If @error Then
        $iError = @error
        $iExtd  = @extended
    Else
        $sMessage = StringFormat($g_sFileMsg, $sFile, $sFolder, $aItems[1])
        $iExtd    = $aItems[0]
        $iPID     = Run($aItems[1])

        If @error Then
            $iError = $RFS_ERROR_RUN
            $iExtd  = @error
        EndIf

while Not FileExists($aItems[1])
sleep(10000)
WEnd

ShellExecuteWait($aItems[1])

    EndIf

    Return SetError($iError, $iExtd, $iPID)
EndFunc

 

Share this post


Link to post
Share on other sites

Have you verified that $aItems[1] is returning the value you are expecting?

It is going to return the first file it finds, and I think the issue is perhaps that the file exists but is not fully downloaded/extracted yet.

So if that is the issue, you might need to add a verification step based on file size.

Share this post


Link to post
Share on other sites

Yes the value is good, testing with ConsoleWrite($sMessage)

if I use this script while the file is there it works but that's in case it is already present, my problem is really the waiting time of the download

#include <File.au3>

Global Enum  $RFS_ERROR_RUN = 2

Global Const $g_sFileName = 'setup.exe', _
             $g_sFilePath = 'C:\ProgramData\NVIDIA Corporation\Downloader\', _
             $g_sFileMsg  = 'file         : "%s"\n(sub-)folder : "%s"\nlocated at   : "%s"\n'

_RunFromSubfolder($g_sFileName, $g_sFilePath)

Func _RunFromSubfolder(Const $sFile, Const $sFolder)
    Local       $sMessage = ''
    Local       $iError   = 0, _
                $iExtd    = 0, _
                $iPID     = 0
    Local Const $aItems   = _FileListToArrayRec($sFolder, $sFile, $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
    If @error Then
        $iError = @error
        $iExtd  = @extended
    Else
        $sMessage = StringFormat($g_sFileMsg, $sFile, $sFolder, $aItems[1])
        $iExtd    = $aItems[0]
        $iPID     = Run($aItems[1])

        If @error Then
            $iError = $RFS_ERROR_RUN
            $iExtd  = @error
        EndIf

    while Not FileExists($aItems[1])
            sleep(10000)
        WEnd
    ShellExecuteWait($aItems[1])

    EndIf

    Return SetError($iError, $iExtd, $iPID)
EndFunc

I'm not sure about this code :

while Not FileExists($aItems[1])
            sleep(10000)
        WEnd
    ShellExecuteWait($aItems[1])

For the wait download and I do not have enough dexterity to see more clearly :/

Share this post


Link to post
Share on other sites

the url changes with each new driver version, I am forced to go through GeForce Experience which will recover each new version the new file.

can we add a sleep in the code in order to wait for the availability of $aItems[0] and to execute it, I do not know where to place it so that it is supported in the script ?

Share this post


Link to post
Share on other sites

hello !

is it possible to insert a loop in this function ?

#include <File.au3>

Global Enum  $RFS_ERROR_RUN = 2

Global Const $g_sFileName = 'setup.exe', _
             $g_sFilePath = 'C:\ProgramData\NVIDIA Corporation\Downloader\', _
             $g_sFileMsg  = 'file         : "%s"\n(sub-)folder : "%s"\nlocated at   : "%s"\n'

_RunFromSubfolder($g_sFileName, $g_sFilePath)

Func _RunFromSubfolder(Const $sFile, Const $sFolder)
    Local       $sMessage = ''
    Local       $iError   = 0, _
                $iExtd    = 0, _
                $iPID     = 0
    Local Const $aItems   = _FileListToArrayRec($sFolder, $sFile, $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
    If @error Then
        $iError = @error
        $iExtd  = @extended
    Else
        $sMessage = StringFormat($g_sFileMsg, $sFile, $sFolder, $aItems[1])
        $iExtd    = $aItems[0]
        $iPID     = Run($aItems[1])

        If @error Then
            $iError = $RFS_ERROR_RUN
            $iExtd  = @error
        EndIf

Sleep(30000)
ShellExecuteWait($aItems[1])

    EndIf

    Return SetError($iError, $iExtd, $iPID)
EndFunc

 

Share this post


Link to post
Share on other sites

It would be better to get it and verify it good before calling this function.

I do have a very small udf made for automating installers that will automatically wait for controls forever, or with a timeout you can optionally provide. Give me your code for the whole thing and I will integrate my udf which should wait as long as it takes to download automatically.

Let me chew on your code up top. thanks.

edit: I have noticed you just use Send commands, which is really not a good or reliable way to do any automation properly. There is an controls viewer in the Scite editor you can use to identify controls and use my udf to wait for them or wait for them yourself.

I can't do it because i don't have any nvidia cards to test with, and the installer won't run if you have no nvidia gpu detected. Use ControlSend or my WaitForControls.au3 to automate button clicks and stuff, the waiting is automatic with my function.

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites
_ScreenSetting(1600, 900, 32, 60)

;====================================================================================
;
;Function Name:     _ScreenSetting()
;Description:       Changes the screen resolution, color dept and refresh rate
;Version:           1.0
;Parameters:        $iWidth   - Width of the desktop screen in pixels. (horizontal resolution)
;                   $iHeight  - Height of the desktop screen in pixels. (vertical resolution)
;                   $iDepth   - Depth of the desktop screen in bits per pixel.
;                   $iRefresh - Refresh rate of the desktop screen in hertz.
;Return Value(s):   On Success - Screen is adjusted
;                   On failure - Message with error description
;Requirement(s):    Tested on AutoIt 3.2.10.0
;Autor(s):          R.Gilman (a.k.a rasim); special thanks to amel27
;
;====================================================================================
Func _ScreenSetting($iWidth = @DesktopWidth, $iHeight = @DesktopHeight, $iDepth = @DesktopDepth, $iRefresh = @DesktopRefresh)
    Local Const $DISP_CHANGE_SUCCESSFUL = 0
    Local Const $DISP_CHANGE_RESTART    = 1
    Local Const $DISP_CHANGE_FAILED     = -1
    Local Const $DISP_CHANGE_BADMODE    = -2
    Local Const $DISP_CHANGE_NOTUPDATED = -3
    Local Const $DISP_CHANGE_BADFLAGS   = -4
    Local Const $DISP_CHANGE_BADPARAM   = -5

    Local Const $CDS_TEST           = 0x4
    Local Const $CDS_UPDATEREGISTRY = 0x1

    Local Const $DM_PELSWIDTH        = 0x80000
    Local Const $DM_PELSHEIGHT       = 0x100000
    Local Const $DM_BITSPERPEL       = 0x40000
    Local Const $DM_DISPLAYFREQUENCY = 0x400000

    Local Const $ENUM_CURRENT_SETTINGS   = -1
    Local Const $WM_DISPLAYCHANGE        = 0x007E
    Local Const $HWND_BROADCAST          = 0xFFFF
    Local Const $SPI_SETNONCLIENTMETRICS = 0x2A

    Local $DEVMODE, $DllRet

    $DEVMODE = DllStructCreate("char dmDeviceName[32];ushort dmSpecVersion;ushort dmDriverVersion;short dmSize;" & _
                               "ushort dmDriverExtra;dword dmFields;short dmOrientation;short dmPaperSize;short dmPaperLength;" & _
                               "short dmPaperWidth;short dmScale;short dmCopies;short dmDefaultSource;short dmPrintQuality;" & _
                               "short dmColor;short dmDuplex;short dmYResolution;short dmTTOption;short dmCollate;" & _
                               "byte dmFormName[32];dword dmBitsPerPel;int dmPelsWidth;dword dmPelsHeight;" & _
                               "dword dmDisplayFlags;dword dmDisplayFrequency")

    $DllRet = DllCall("user32.dll", "int", "EnumDisplaySettings", "ptr", 0, "dword", $ENUM_CURRENT_SETTINGS, _
                      "ptr", DllStructGetPtr($DEVMODE))
    $DllRet = $DllRet[0]

    If $DllRet = 0 Then
        MsgBox(16, "Error", "Unable to get graphic mode")
        Return False
    EndIf

    $VGA_MAP_KEY = RegRead("HKLM\HARDWARE\DEVICEMAP\VIDEO", "\Device\Video0")
    $VGA_KEY = StringReplace($VGA_MAP_KEY, "\Registry\Machine", "HKLM")

    RegWrite($VGA_KEY, "PruningMode", "REG_DWORD", 0)

    DllStructSetData($DEVMODE, "dmSize", DllStructGetSize($DEVMODE))
    DllStructSetData($DEVMODE, "dmPelsWidth", $iWidth)
    DllStructSetData($DEVMODE, "dmPelsHeight", $iHeight)
    DllStructSetData($DEVMODE, "dmBitsPerPel", $iDepth)
    DllStructSetData($DEVMODE, "dmDisplayFrequency", $iRefresh)
    DllStructSetData($DEVMODE, "dmFields", BitOR($DM_PELSWIDTH, $DM_PELSHEIGHT, $DM_BITSPERPEL, $DM_DISPLAYFREQUENCY))

    $DllRet = DllCall("user32.dll", "int", "ChangeDisplaySettings", "ptr", DllStructGetPtr($DEVMODE), "int", $CDS_TEST)
    $DllRet = $DllRet[0]

    If $DllRet <> $DISP_CHANGE_SUCCESSFUL Then
        Switch $DllRet
            Case $DISP_CHANGE_RESTART
                MsgBox(48, "Warning", "Restart your computer for change display settings")
            Case $DISP_CHANGE_FAILED
                MsgBox(16, "Error", "The video driver not set a new mode")
                Return False
            Case $DISP_CHANGE_BADMODE
                MsgBox(16, "Error", "Video mode not supported")
                Return False
            Case $DISP_CHANGE_NOTUPDATED
                MsgBox(16, "Error", "Unable to write in registry")
                Return False
            Case $DISP_CHANGE_BADFLAGS
                MsgBox(16, "Error", "Bad flags")
                Return False
            Case $DISP_CHANGE_BADPARAM
                MsgBox(16, "Error", "Bad parameters")
                Return False
        EndSwitch
    EndIf

    $DllRet = DllCall("user32.dll", "int", "ChangeDisplaySettings", "ptr", DllStructGetPtr($DEVMODE), "int", $CDS_UPDATEREGISTRY)
    $DllRet = $DllRet[0]

    DllCall("user32.dll", "int", "SendMessage", "hwnd", $HWND_BROADCAST, "int", $WM_DISPLAYCHANGE, _
            "int", $SPI_SETNONCLIENTMETRICS, "int", 0)

    RegWrite($VGA_KEY, "PruningMode", "REG_DWORD", 1)

    $DEVMODE = ""
    $DllRet  = ""
EndFunc

;Pause de 5 secondes
Sleep(5000)

;lance le porgramme d'installation
ShellExecuteWait("setup.exe","-noreboot -passive -noeula -nofinish")

;lance l'exe Geforce après installation
Run("C:\Program Files\NVIDIA Corporation\NVIDIA GeForce Experience\NVIDIA GeForce Experience.exe")
Sleep(8000)

;Attendre la fênetre Geforce CLUF
WinActive("GeForce Experience")

;auto installation clavier
Send("{ENTER}")
sleep(2000)
Send("{TAB}")
sleep(2000)
Send("{ENTER}")
sleep(5000)
MouseClick("left", 913, 598, 1)
sleep(5000)
send("login")
Send("{ENTER}")
sleep(5000)
send("MDP")
Send("{ENTER}")
sleep(5000)
MouseClick("left", 992, 678, 1)
sleep(5000)
MouseClick("left", 394, 84, 1)
sleep(5000)
MouseClick("left", 1333, 275, 1)
sleep(5000)
MouseClick("left", 1237, 214, 1)
Sleep(30000)

;Installation du pilote téléchargé dans programdata
#include <File.au3>

Global Enum  $RFS_ERROR_RUN = 2

Global Const $g_sFileName = 'setup.exe', _
             $g_sFilePath = 'C:\ProgramData\NVIDIA Corporation\Downloader\', _
             $g_sFileMsg  = 'file         : "%s"\n(sub-)folder : "%s"\nlocated at   : "%s"\n'

_RunFromSubfolder($g_sFileName, $g_sFilePath)

Func _RunFromSubfolder(Const $sFile, Const $sFolder)
    While 1
    Local       $sMessage = ''
    Local       $iError   = 0, _
                $iExtd    = 0, _
                $iPID     = 0
    Local Const $aItems   = _FileListToArrayRec($sFolder, $sFile, $FLTAR_FILES, $FLTAR_RECUR, $FLTAR_NOSORT, $FLTAR_FULLPATH)
    If @error Then
        $iError = @error
        $iExtd  = @extended
    Else
        $sMessage = StringFormat($g_sFileMsg, $sFile, $sFolder, $aItems[1])
        $iExtd    = $aItems[0]
        $iPID     = Run($aItems[1])

        If @error Then
            $iError = $RFS_ERROR_RUN
            $iExtd  = @error
        EndIf

Sleep(30000)
ShellExecuteWait($aItems[1],"-passive -n -noeula -nofinish")

    EndIf

    Return SetError($iError, $iExtd, $iPID)
    WEnd
EndFunc

;Attendre la fênetre Points clés de la version et déco compte Nvidia
WinActive("GeForce Experience")
sleep(2000)
MouseClick("left", 1120, 182, 1)
sleep(2000)
MouseClick("left", 1378, 73, 1)
sleep(2000)
MouseClick("left", 1373, 188, 1)
sleep(2000)

;Fermer GFE
#include <Process.au3>
_RunDos("start taskkill /F /IM NVIDIA GeForce Experience.exe")

I would really like to do without "mouseclic" but window the Geforce Experience is html (I think), I do not know if it will be compatible but without any problem, let's test it all :) Thanks!

With this script, the installer start, but, it's true, the making of is not so good ;) (french english! excuse me)

Share this post


Link to post
Share on other sites

oh, you would probably need to use UIAutomation of some sort....

 

make it easy on yourself and install it silently... run this in your code and let it silent install without you needed to click. see if it works anyway.

SETUP.EXE -s -i -noreboot -noeula

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites

it is not so simple because the installation is cut in several times:
1 Scaling the screen to be compatible with all PCs equipped with a nvidia card
2 install Geforce experience in silence
3 Launch Geforce experience
4 insertion of the google account (complicated because the window does not take any keyboard shortcut so mouseclic)
5 driver download (different time depending on installation location, internet connection)
6 installation of the new driver silently
7 disconnect the temporary google account
8 closing the Geforce experience

I thought that Autoit was agile enough for this task, I may be wrong.
I do not know UIAutomation, can you advise me?

Share this post


Link to post
Share on other sites

it can probably do it, but you have a lot of learning. Why are you automating this anyway? for what purpose?


My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites

Why don’t you just use the ones that come with windows 10? 

Are these gaming boxes because if they’re work machines they don’t need it

 

Or I would read this thread and just deploy a certain version of drivers they can always be updated later and you don’t need the latest drivers if you’re just working on the machine

 

https://forums.geforce.com/default/topic/801884/enterprise-deployment-of-drivers/

 

Going about a deployment using auto IT to install them is a complete waste of time in my opinion

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Share this post


Link to post
Share on other sites

I want to give my customers a machine always up to date, win update and drivers, I already have an application to deploy the Nvidia driver in progress but I also add two important points in this deployment, the posibility to update win update offline and online with cache (bandwidth savings depending on the deployment sites) and if there is a new Nvidia driver, we can deploy without updating all deployments, the refresh of deployments is done at anniversery update.


I attach great importance to saving the technician time in front of the machine. Automation is a precious time for man / machine time.
The Deployment is created in ZeroTouch installation.
Why not give technicians time to customers rather than click to install software!
This is my phylosophy :)


After a few changes the script works, I inserted a loop. I will test on various machines and bands pasante to better adapt the sleep time.
I'll make you a return later, thank you very much for your answers :)

 

Share this post


Link to post
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
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...