AutoHotkey Community

It is currently May 27th, 2012, 5:55 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 104 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7
Author Message
 Post subject:
PostPosted: December 14th, 2009, 8:54 pm 
Offline

Joined: August 2nd, 2009, 6:40 am
Posts: 215
Wouldn't it make more sense to use something like TinyFugue (win32) or BeipMU for scripting within a Telnet session?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 10th, 2010, 5:11 pm 
Offline

Joined: June 20th, 2008, 12:40 pm
Posts: 47
I was trying to get Sean's StdoutToVar_CreateProcess working on x64 unicode ahkL. So far I was only successful with 32 bit unicode.
For 64 bit, I tried to change variable types and recalculated the struct positions, but the ReadFile function (step 11) still fails. Anybody has an idea what's wrong?

Script I use for testing:

Code:

sOutput:=StdoutToVar_CreateProcess(A_WinDir "\system32\ipconfig.exe")
Exitapp


StdoutToVar_CreateProcess(sCmd)
   {
   Success:=DllCall("CreatePipe", "Ptr*", hStdInRd
                                , "Ptr*", hStdInWr
                                , "Uint", 0
                                , "Uint", 0)
   if Success=0
      {
      msgbox,Step 1 (CreatePipe)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CreatePipe", "Ptr*", hStdOutRd
                                , "Ptr*", hStdOutWr
                                , "Uint", 0
                                , "Uint", 0)
   if Success=0
      {
      msgbox,Step 2 (CreatePipe)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("SetHandleInformation", "Ptr", hStdInRd
                                         , "Uint", 1
                                         , "Uint", 1)
   if Success=0
      {
      msgbox,Step 3 (SetHandleInformation)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("SetHandleInformation", "Ptr", hStdOutWr
                                         , "Uint", 1
                                         , "Uint", 1)
   if Success=0
      {
      msgbox,Step 4 (SetHandleInformation)`nSuccess=%Success%
      Return
      }

   VarSetCapacity(pi, 24, 0)
   NumPut(VarSetCapacity(si,96,0), si, 0, "UInt")
   NumPut(0x100    , si, 56, "UInt") ; DWORD Flags
   NumPut(hStdInRd , si, 72, "UPtr") ; 64bit HANDLE StdInput
   NumPut(hStdOutWr, si, 80, "UPtr") ; 64bit HANDLE StdOutput
   NumPut(hStdOutWr, si, 88, "UPtr") ; 64bit HANDLE StdError

   Success:=DllCall("CreateProcess", "Uint", 0
                                    , "Ptr", &sCmd
                                   , "Uint", 0
                                   , "Uint", 0
                                    , "int", True
                                   , "Uint", 0x08000000
                                   , "Uint", 0
                                   , "Uint", 0
                                   , "UPtr", &si
                                   , "UPtr", &pi)

   if Success=0
      {
      msgbox,Step 5 (CreateProcess)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",NumGet(pi,0,"UPtr"))
   if Success=0
      {
      msgbox,Step 6 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",NumGet(pi,8,"UPtr"))
   if Success=0
      {
      msgbox,Step 7 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",hStdOutWr)
   if Success=0
      {
      msgbox,Step 8 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",hStdInRd)
   if Success=0
      {
      msgbox,Step 9 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",hStdInWr)
   if Success=0
      {
      msgbox,Step 10 (CloseHandle)`nSuccess=%Success%
      Return
      }

   VarSetCapacity(sTemp,4095)
   nSize:=0
   Success:=DllCall("ReadFile", "Ptr*", hStdOutRd
                              , "Uint", &sTemp
                              , "Uint", 4095
                             , "UintP", nSize
                              , "Uint", 0)
   If Success
      {
      msgbox,Step 11`nSuccess=%Success%
      NumPut(0,sTemp,nSize,"Uchar")
      VarSetCapacity(sTemp,-1)
      sOutput:=StrGet(&sTemp,nSize,"")
      msgbox,%sOutput%
      }
   else
      msgbox,Step 11 (ReadFile) failed

   Success:=DllCall("CloseHandle", "Ptr", hStdOutRd)
   if Success=0
      {
      msgbox,Step 12 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Return   sOutput
   }

I assumed 64 bit STARTUPINFO struct would look like this:

Code:
 0 DWORD  cb;-------------------
 4 LPTSTR lpReserved;           8 Bytes
12 LPTSTR lpDesktop;            8 Bytes
20 LPTSTR lpTitle;              8 Bytes
28 DWORD  dwX;
32 DWORD  dwY;
36 DWORD  dwXSize;
40 DWORD  dwYSize;
44 DWORD  dwXCountChars;
48 DWORD  dwYCountChars;
52 DWORD  dwFillAttribute;
56 DWORD  dwFlags;--------------
60 WORD   wShowWindow;
62 WORD   cbReserved2;
64 LPBYTE lpReserved2;          Lenght 8 bytes?
72 HANDLE hStdInput;------------8 Bytes
80 HANDLE hStdOutput;-----------8 Bytes
88 HANDLE hStdError;------------8 Bytes
96


and PROCESS_INFORMATION struct like this:
Code:
 0 HANDLE hProcess;             8 Bytes
 8 HANDLE hThread;              8 Bytes
16 DWORD  dwProcessId;
20 DWORD  dwThreadId;
24


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 13th, 2010, 9:49 am 
Offline

Joined: October 17th, 2006, 4:15 pm
Posts: 7503
Location: Australia
Structures with 64-bit fields are 64-bit aligned by default. Smaller fields can be packed together, but 64-bit fields must begin at a multiple of 8 bytes. For instance,
Code:
STARTUPINFO:
  0  DWORD  cb;
  4  (padding)

  8  LPTSTR lpReserved;
 16  LPTSTR lpDesktop;
 24  LPTSTR lpTitle;
 32  DWORD  dwX;
 36  DWORD  dwY;

 40  DWORD  dwXSize;
 44  DWORD  dwYSize;
 48  DWORD  dwXCountChars;
 52  DWORD  dwYCountChars; 

 56  DWORD  dwFillAttribute;
 60  DWORD  dwFlags;
 64  WORD   wShowWindow;
 66  WORD   cbReserved2;
 68  (padding)

 72  LPBYTE lpReserved2;
 80  HANDLE hStdInput;
 88  HANDLE hStdOutput;
 96  HANDLE hStdError;
104


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 13th, 2010, 1:27 pm 
Offline

Joined: June 20th, 2008, 12:40 pm
Posts: 47
Lexikos, thank you very much for your help.
I now have a partial version of StdoutToVar_CreateProcess that seems to work well both in x32 and x64 unicode AhkL. The bStream, sDir and sInput parameters are disabled though, since I didn't include the parts of Sean's script that I didn't understand too well or need right away.

I'm not at all sure if the Pointers in CreateProcess and ReadFile are ok the way they are of should remain UInt, but it seems to work alright.

Code:
StdoutToVar_CreateProcess(sCmd, bStream="", sDir="", sInput="")
   {
   bStream=   ; not implemented
   sDir=      ; not implemented
   sInput=    ; not implemented
   
   DllCall("CreatePipe","Ptr*",hStdInRd
                       ,"Ptr*",hStdInWr
                       ,"Uint",0
                       ,"Uint",0)
   DllCall("CreatePipe","Ptr*",hStdOutRd
                       ,"Ptr*",hStdOutWr
                       ,"Uint",0
                       ,"Uint",0)
   DllCall("SetHandleInformation","Ptr",hStdInRd
                                ,"Uint",1
                                ,"Uint",1)
   DllCall("SetHandleInformation","Ptr",hStdOutWr
                                ,"Uint",1
                                ,"Uint",1)

   if A_PtrSize=4
      {
      VarSetCapacity(pi, 16, 0)
      sisize:=VarSetCapacity(si,68,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 44, "UInt")
      NumPut(hStdInRd , si, 56, "Ptr")
      NumPut(hStdOutWr, si, 60, "Ptr")
      NumPut(hStdOutWr, si, 64, "Ptr")
      }
   else if A_PtrSize=8
      {
      VarSetCapacity(pi, 24, 0)
      sisize:=VarSetCapacity(si,96,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 60, "UInt")
      NumPut(hStdInRd , si, 80, "Ptr")
      NumPut(hStdOutWr, si, 88, "Ptr")
      NumPut(hStdOutWr, si, 96, "Ptr")
      }

   DllCall("CreateProcess", "Uint", 0
                           , "Ptr", &sCmd
                          , "Uint", 0
                          , "Uint", 0
                           , "Int", True
                          , "Uint", 0x08000000
                          , "Uint", 0
                          , "Uint", 0
                           , "Ptr", &si
                           , "Ptr", &pi)

   DllCall("CloseHandle","Ptr",NumGet(pi,0))
   DllCall("CloseHandle","Ptr",NumGet(pi,A_PtrSize))
   DllCall("CloseHandle","Ptr",hStdOutWr)
   DllCall("CloseHandle","Ptr",hStdInRd)
   DllCall("CloseHandle","Ptr",hStdInWr)

   VarSetCapacity(sTemp,4095)
   nSize:=0
   loop
      {
      result:=DllCall("Kernel32.dll\ReadFile", "Uint", hStdOutRd
                                             ,  "Ptr", &sTemp
                                             , "Uint", 4095
                                             ,"UintP", nSize
                                              ,"Uint", 0)
      if (result="0")
         break
      else
         sOutput:= sOutput . StrGet(&sTemp,nSize,"CP850")
      }

   DllCall("CloseHandle","Ptr",hStdOutRd)
   Return,sOutput
   }


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 20th, 2011, 3:49 pm 
Offline

Joined: February 6th, 2007, 12:30 am
Posts: 142
Location: Michigan
majkinetor wrote:
Hey Sean if you are still watching.

I modified function to support ExitCode (via ErrorLevel as usual) and made some trivial changes (changed func name and slightly param names and order so its more similar to Run command)

I also made formal documentation.

I will prolly add some more features when time comes to it, like injection of environment variables, and option not to block script (like Run command does).

Cheers and thx again for this awesomeness.

Function
Documentation


This appears to be the best version of calling an external program and trapping the output into a variable.

This function should be included in AHKL.

_________________
http://www.panofish.net


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: September 21st, 2011, 9:29 pm 
Just wanted to post my modified code based on the code by maraskan_user. Supports the sInput and sDir parameters, so only the bStream parameter is left.
Code:
StdoutToVar_CreateProcess(sCmd, bStream="", sDir="", sInput="")
   {
   bStream=   ; not implemented
   
   DllCall("CreatePipe","Ptr*",hStdInRd,"Ptr*",hStdInWr,"Uint",0,"Uint",0)
   DllCall("CreatePipe","Ptr*",hStdOutRd,"Ptr*",hStdOutWr,"Uint",0,"Uint",0)
   DllCall("SetHandleInformation","Ptr",hStdInRd,"Uint",1,"Uint",1)
   DllCall("SetHandleInformation","Ptr",hStdOutWr,"Uint",1,"Uint",1)
   if A_PtrSize=4
      {
      VarSetCapacity(pi, 16, 0)
      sisize:=VarSetCapacity(si,68,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 44, "UInt")
      NumPut(hStdInRd , si, 56, "Ptr")
      NumPut(hStdOutWr, si, 60, "Ptr")
      NumPut(hStdOutWr, si, 64, "Ptr")
      }
   else if A_PtrSize=8
      {
      VarSetCapacity(pi, 24, 0)
      sisize:=VarSetCapacity(si,96,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 60, "UInt")
      NumPut(hStdInRd , si, 80, "Ptr")
      NumPut(hStdOutWr, si, 88, "Ptr")
      NumPut(hStdOutWr, si, 96, "Ptr")
      }

   DllCall("CreateProcess", "Uint", 0, "Ptr", &sCmd, "Uint", 0, "Uint", 0, "Int", True, "Uint", 0x08000000, "Uint", 0, "Ptr", sDir ? &sDir : 0, "Ptr", &si, "Ptr", &pi)
   DllCall("CloseHandle","Ptr",NumGet(pi,0))
   DllCall("CloseHandle","Ptr",NumGet(pi,A_PtrSize))
   DllCall("CloseHandle","Ptr",hStdOutWr)
   DllCall("CloseHandle","Ptr",hStdInRd)
   
   If   sInput <>
      FileOpen(hStdInWr, "h", "UTF-8").Write(sInput)
   
   DllCall("CloseHandle","Ptr",hStdInWr)

   VarSetCapacity(sTemp,4095)
   nSize:=0
   loop
      {
      result:=DllCall("Kernel32.dll\ReadFile", "Uint", hStdOutRd,  "Ptr", &sTemp, "Uint", 4095,"UintP", nSize,"Uint", 0)
      if (result="0")
         break
      else
         sOutput:= sOutput . StrGet(&sTemp,nSize,"UTF-8")
      }

   DllCall("CloseHandle","Ptr",hStdOutRd)
   Return,sOutput
}


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: October 3rd, 2011, 12:15 am 
Offline

Joined: September 8th, 2011, 6:09 pm
Posts: 4
maraskan_user wrote:
Lexikos, thank you very much for your help.
I now have a partial version of StdoutToVar_CreateProcess that seems to work well both in x32 and x64 unicode AhkL. The bStream, sDir and sInput parameters are disabled though, since I didn't include the parts of Sean's script that I didn't understand too well or need right away.

I'm not at all sure if the Pointers in CreateProcess and ReadFile are ok the way they are of should remain UInt, but it seems to work alright.

Code:
StdoutToVar_CreateProcess(sCmd, bStream="", sDir="", sInput="")
   {
   bStream=   ; not implemented
   sDir=      ; not implemented
   sInput=    ; not implemented
   
   DllCall("CreatePipe","Ptr*",hStdInRd
                       ,"Ptr*",hStdInWr
                       ,"Uint",0
                       ,"Uint",0)
   DllCall("CreatePipe","Ptr*",hStdOutRd
                       ,"Ptr*",hStdOutWr
                       ,"Uint",0
                       ,"Uint",0)
   DllCall("SetHandleInformation","Ptr",hStdInRd
                                ,"Uint",1
                                ,"Uint",1)
   DllCall("SetHandleInformation","Ptr",hStdOutWr
                                ,"Uint",1
                                ,"Uint",1)

   if A_PtrSize=4
      {
      VarSetCapacity(pi, 16, 0)
      sisize:=VarSetCapacity(si,68,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 44, "UInt")
      NumPut(hStdInRd , si, 56, "Ptr")
      NumPut(hStdOutWr, si, 60, "Ptr")
      NumPut(hStdOutWr, si, 64, "Ptr")
      }
   else if A_PtrSize=8
      {
      VarSetCapacity(pi, 24, 0)
      sisize:=VarSetCapacity(si,96,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 60, "UInt")
      NumPut(hStdInRd , si, 80, "Ptr")
      NumPut(hStdOutWr, si, 88, "Ptr")
      NumPut(hStdOutWr, si, 96, "Ptr")
      }

   DllCall("CreateProcess", "Uint", 0
                           , "Ptr", &sCmd
                          , "Uint", 0
                          , "Uint", 0
                           , "Int", True
                          , "Uint", 0x08000000
                          , "Uint", 0
                          , "Uint", 0
                           , "Ptr", &si
                           , "Ptr", &pi)

   DllCall("CloseHandle","Ptr",NumGet(pi,0))
   DllCall("CloseHandle","Ptr",NumGet(pi,A_PtrSize))
   DllCall("CloseHandle","Ptr",hStdOutWr)
   DllCall("CloseHandle","Ptr",hStdInRd)
   DllCall("CloseHandle","Ptr",hStdInWr)

   VarSetCapacity(sTemp,4095)
   nSize:=0
   loop
      {
      result:=DllCall("Kernel32.dll\ReadFile", "Uint", hStdOutRd
                                             ,  "Ptr", &sTemp
                                             , "Uint", 4095
                                             ,"UintP", nSize
                                              ,"Uint", 0)
      if (result="0")
         break
      else
         sOutput:= sOutput . StrGet(&sTemp,nSize,"CP850")
      }

   DllCall("CloseHandle","Ptr",hStdOutRd)
   Return,sOutput
   }


Thanks so much!
You just saved my time in doing the same thing, and it seems to work just fine so far.

I wish the original author could merge this into the first post.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 14th, 2011, 3:11 pm 
Great script !

When using the stream or true-flag, the last part of the stdout will not be streamed at all.
The text in Output is complete but the last part of the loop is not displayed.
This is only when there is no carriage return behind the last text. Ping works well, but I have a tool that does not create an addtional line...
What can I do here ? In my case the OutputDebug %sString% misses the last line.

I just have a workaround, to "stream" the output itself instead of the stream value...


Report this post
Top
  
Reply with quote  
 Post subject: Please include this
PostPosted: October 24th, 2011, 2:53 pm 
Offline

Joined: February 2nd, 2011, 9:36 am
Posts: 28
This is a great funtion to make ahk even more great... and I think too it has to be included in ahk_L

Please Lexikos, considere to include this on main code (maybe AHK v2)

Its really a pitty that this jewel of software (StdoutToVar) is so bad supported and forgotten...

- Original Sean has not 64bits, nor utf-8
- Modified Sean has some "expect" aproach
- maraskan_user has 64 bits aproach
- nfl has utf-8 support but no bStream
- None of then has stdin support (I only find COM stuff)...

Please, I think connection with commandline apps its a main priority, and one of worse supported by ahk.

PS. Im harly use ahk and curl and I think together are one of the best tools ever...


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: October 31st, 2011, 9:42 am 
Offline

Joined: July 10th, 2011, 5:03 am
Posts: 272
[remove post stupid q]


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Send key
PostPosted: January 19th, 2012, 12:25 pm 
How could I send CTRC+C when the program or "output" requests this ?

I my case the program waits until the user has connected a device and forces him to press CTRL+C start an action.

I can stream the output text but I have no clue to send the CTRL+C to the waiting programm because there is no console window.

With console windows this no problem of course but I want to hide it completely.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: January 31st, 2012, 5:30 pm 
Offline

Joined: January 31st, 2012, 3:00 pm
Posts: 2
Thank you sean and maraksan! With your improvements from the post above things worked. I took the freedom to reformat and comment it a bit.

Code:
StdoutToVar_CreateProcess(sCmd, bStream="", sDir="", sInput="")
{
   bStream=   ; not implemented
   sDir=      ; not implemented
   sInput=    ; not implemented
   
   DllCall("CreatePipe", "Ptr*", hStdInRd , "Ptr*", hStdInWr , "Uint", 0, "Uint", 0)
   DllCall("CreatePipe", "Ptr*", hStdOutRd, "Ptr*", hStdOutWr, "Uint", 0, "Uint", 0)
   DllCall("SetHandleInformation", "Ptr", hStdInRd , "Uint", 1, "Uint", 1)
   DllCall("SetHandleInformation", "Ptr", hStdOutWr, "Uint", 1, "Uint", 1)

   ; Fill a StartupInfo structure
   if A_PtrSize = 4   ; We're on a 32-bit system.
   {
      VarSetCapacity(pi, 16, 0)
      sisize := VarSetCapacity(si, 68, 0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 44, "UInt")
      NumPut(hStdInRd , si, 56, "Ptr")   ; stdin
      NumPut(hStdOutWr, si, 60, "Ptr")   ; stdout
      NumPut(hStdOutWr, si, 64, "Ptr")   ; stderr
   }
   else if A_PtrSize = 8   ; We're on a 64-bit system.
   {
      VarSetCapacity(pi, 24, 0)
      sisize := VarSetCapacity(si, 96, 0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 60, "UInt")
      NumPut(hStdInRd , si, 80, "Ptr")   ; stdin
      NumPut(hStdOutWr, si, 88, "Ptr")   ; stdout
      NumPut(hStdOutWr, si, 96, "Ptr")   ; stderr
   }

    DllCall("CreateProcess", "Uint", 0          ; Application Name
                           ,  "Ptr", &sCmd      ; Command Line
                           , "Uint", 0          ; Process Attributes
                           , "Uint", 0          ; Thread Attributes
                           ,  "Int", True       ; Inherit Handles
                           , "Uint", 0x08000000 ; Creation Flags (0x08000000 = Suppress console window)
                           , "Uint", 0          ; Environment
                           , "Uint", 0          ; Current Directory
                           ,  "Ptr", &si        ; Startup Info
                           ,  "Ptr", &pi)       ; Process Information

   DllCall("CloseHandle", "Ptr", NumGet(pi, 0))
   DllCall("CloseHandle", "Ptr", NumGet(pi, A_PtrSize))
   DllCall("CloseHandle", "Ptr", hStdOutWr)
   DllCall("CloseHandle", "Ptr", hStdInRd)
   DllCall("CloseHandle", "Ptr", hStdInWr)

   VarSetCapacity(sTemp, 4095)
   nSize := 0
   loop
   {
      result := DllCall("Kernel32.dll\ReadFile", "Uint", hStdOutRd, "Ptr", &sTemp, "Uint", 4095, "UintP", nSize, "Uint", 0)
      if (result = "0")
         break
      else
      sOutput := sOutput . StrGet(&sTemp, nSize, "CP850")
   }

   DllCall("CloseHandle", "Ptr", hStdOutRd)
   return, sOutput
}

Now I am trying to figure out how to reactivate stream support.

P.S.: Sean, your code looks like you were deliberately obfuscating it. There is no price for the most statements per line. ;)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: February 15th, 2012, 7:20 am 
Offline

Joined: July 10th, 2011, 5:03 am
Posts: 272
is there any way to speed up stdouttovar? I'm using it for SQL queries and its taking >1sec to retrieve the output for a query that takes ~32ms in PgAdmin.

(anyone that can possibly help me plz see here: http://www.autohotkey.com/forum/viewtop ... 753#513753)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 15th, 2012, 1:40 am 
Offline

Joined: October 21st, 2008, 2:21 am
Posts: 5
Thanks, Sweeet!

Your modified solution worked just fine on Unicode AHK_L x64


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 104 posts ]  Go to page Previous  1 ... 3, 4, 5, 6, 7

All times are UTC [ DST ]


Who is online

Users browsing this forum: Apollo, Exabot [Bot], Google [Bot], Google Feedfetcher, JamixZol and 22 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group