259-char path limit workarounds Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
LogicDaemon
Posts: 21
Joined: 21 Feb 2014, 01:22

259-char path limit workarounds

27 Dec 2016, 12:32

Hi all.

I need to work with long paths, and I hoped AutoHotkey is appropriate tool for almost anything. Unfortunately, Loop operator betrayed me, since it intentionally ignores files with paths longer than 259 char, even if I prefix the path with \\?\

Seriously, most programs nowadays don't stick to that limit and work well with long paths! (not the explorer, though it shows them and appropriately passes as arguments to other programs)

Can we please lift that artificial limit? Maybe with some #LongFilenames or when \\?\ prefix is explicitly used.

And meanwhile, can anyone feed me workaround for Loop, Files please? Maybe using dllcall FindFirstFile, FindNextFile, and FindClose (without practice, it's time consuming to figure out how to correctly prepare memory and put arguments for DllCall).

Otherwise, I'll rely on %comspec% /C DIR /B, which is very crutchy.
Last edited by LogicDaemon on 27 Dec 2016, 12:41, edited 3 times in total.
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: 259-char path limit workarounds

27 Dec 2016, 12:36

I wrote a script for this I'll try and post it in a moment. For dealing with long filenames if you somehow acquire the short-form path, you can use that in AutoHotkey.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: 259-char path limit workarounds

27 Dec 2016, 12:42

Apologies, the script isn't up to my usual standards, I was planning to perfect it in the next few months.
I'm not really an expert programmer, so it really takes it out of me every time I do something like this.
I think it would be great if AutoHotkey could add long filename support, and alphabetical order registry loop.
I have had to create some fiendish complicated functions for Sort command to correctly alphabetise registry entries after a loop.
Checking for long filenames was one of the first things I hoped to do with AutoHotkey.

EDIT: It may be that this script does not currently retrieve files from within folders with long paths.

Code: Select all

;z list all files (file loop + custom file loop) (FindFirstFile).ahk

;note: it may be that this script does not currently retrieve files from within folders with long paths

#SingleInstance force
ListLines, Off
#KeyHistory 0
Menu, Tray, Click, 1
#NoEnv
AutoTrim, Off
#UseHook

;note: doesn't get files from root of c

if A_Is64bitOS
DllCall("Wow64DisableWow64FsRedirection", "uint*", OldValue)

vOutput3 := ""
VarSetCapacity(vOutput3, 10000000*2)
vOutput4 := ""
VarSetCapacity(vOutput4, 10000000*2)
vOutput5 := ""
VarSetCapacity(vOutput5, 10000000*2)

vIndex := 0

Loop, C:\*.*, 2, 1 ;(0/1/2=files/both/folders, 0/1=subfolders no/subfolders yes)
{
vDirX := A_LoopFileFullPath
;vDirX = %A_ScriptDir%

;==================================================

;FILE LOOP

vOutput := ""
Loop, %vDirX%\*.*, 1, 0 ;(0/1/2=files/both/folders, 0/1=subfolders no/subfolders yes)
{
vPath := A_LoopFileFullPath
vName := A_LoopFileName ;filename (minus path)

vAttrib := DllCall("GetFileAttributes", "str", vPath)
;vOutput .= vAttrib "`t" vName "`r`n"
vOutput .= vAttrib "`t" vPath "`r`n"
}

;===============

;FILE LOOP CUSTOM

vDirX2 =  \\?\%vDirX%\*

VarSetCapacity(filedata, 2000,0)
hFile := DllCall("Kernel32.dll\FindFirstFile", "str", vDirX2, "ptr", &filedata)
vOutput2 := ""

;=====
if !(hFile = -1)
{
vAttrib := NumGet(&filedata)
vName := strget(&filedata+44)
vPath = %vDirX%\%vName%
if vName not in .,..
;vOutput2 .= vAttrib "`t" vName "`r`n"
vOutput2 .= vAttrib "`t" vPath "`r`n"

while DllCall("Kernel32.dll\FindNextFile", "ptr", hFile, "ptr", &filedata)
{
vAttrib := NumGet(&filedata)
vName := strget(&filedata+44)
vPath = %vDirX%\%vName%
if vName not in .,..
;vOutput2 .= vAttrib "`t" vName "`r`n"
vOutput2 .= vAttrib "`t" vPath "`r`n"
}
DllCall("Kernel32.dll\FindClose", "ptr", hFile)
}
;=====

;===============

if 0
if (vOutput = vOutput2)
Sleep 0 ;MsgBox y (%vDirX%)
else
{
Clipboard := "[METHOD 1] " vDirX "`r`n" vOutput "[METHOD 2] " vDirX "`r`n" vOutput2 "`r`n"
MsgBox n (%vDirX%)
}

;Clipboard := vOutput "`r`n`r`n" vOutput2
;MsgBox done

if !(vOutput = vOutput2)
{
vIndex := vIndex+1
vOutput3 .= "[METHOD 1] " vDirX "`r`n" vOutput "[METHOD 2] " vDirX "`r`n" vOutput2 "`r`n"
vOutput4 .= "[METHOD 1] " vDirX "`r`n" vOutput "`r`n"
vOutput5 .= "[METHOD 2] " vDirX "`r`n" vOutput2 "`r`n"
}

;==================================================
}

vDate := A_Now
vPath3 = %A_Desktop%\z compare folders %vDate%.txt
vPath4 = %A_Desktop%\z compare folders %vDate% 1.txt
vPath5 = %A_Desktop%\z compare folders %vDate% 2.txt
FileAppend, %vOutput3%, *%vPath3%, UTF-8
FileAppend, %vOutput4%, *%vPath4%, UTF-8
FileAppend, %vOutput5%, *%vPath5%, UTF-8
MsgBox done
Return
Last edited by jeeswg on 31 Jan 2017, 05:08, edited 3 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: 259-char path limit workarounds

27 Dec 2016, 13:05

OK it appears shift+right click, Copy Path, on a long filename, returns blank.
And Edit, Copy, and retrieve %Clipboard%, returns blank.
Anyhow, in the FindFirstFile filename loop above you can retrieve
the short paths as well as the full paths.

EDIT: it may be that this script does not currently retrieve files from within folders with long paths.
Last edited by jeeswg on 27 Dec 2016, 14:22, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
LogicDaemon
Posts: 21
Joined: 21 Feb 2014, 01:22

Re: 259-char path limit workarounds

27 Dec 2016, 13:29

OK it appears shift+right click, Copy Path, on a long filename, returns blank.
Windows 10 release has same problem for me, but on "slow" Insider Preview (build 14986), it returns double-quoted \\?\-prefixed path.
But I use Total Commander most of the time anyway.
And Edit, Copy, and retrieve %Clipboard%, returns blank.
Works for me on both Windows 10 machines (release and Insider Preview)

Thanks for the script anyhow!
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: 259-char path limit workarounds  Topic is solved

27 Dec 2016, 14:41

OK, turns out I did do the full folder loop too, yes, that was properly fiendish, especially as I have to make up programming paradigms as I go along, for not knowing them, for dealing with the hierarchies in memory.
I can't vouch 100% for the accuracy of this script, and it was due to be checked over also in the next few months.

Code: Select all

;z list files 1 jee.ahk

#SingleInstance force
ListLines, Off
#KeyHistory 0
Menu, Tray, Click, 1
#NoEnv
AutoTrim, Off
#UseHook

SplitPath, A_ScriptName,,,, vScriptNameNoExt
Menu, Tray, Tip, % vScriptNameNoExt

;==================================================

#MaxMem 500

if A_Is64bitOS
	DllCall("kernel32.dll\Wow64DisableWow64FsRedirection", "UInt*", 0)

;01:02 22/04/2016
;q:: ;test - list all files + folders (custom file loop) (recurse)
vSearchDir := A_Desktop "\new fol\! txt\test list files 1"
vSearchDir := A_Desktop
vSearchDir := "C:\"
vSearchDir := A_Desktop "\new fol"
MsgBox, % vSearchDir

vSearchDir := RTrim(vSearchDir, "\")

vOutput := ""
VarSetCapacity(vOutput, 200*1000000*2)
VarSetCapacity(vFINDDATA, 2000, 0)
vLevelLast := 0
vLevelCurrent := 1
vLevelDir1 := vSearchDir

Loop
{
	vSearchDir := vLevelDir%vLevelCurrent%
	vSearchDir2 := "\\?\" vSearchDir "\*"
	;if (A_Index = 5)
	;	break

	;has this folder been seen before? (if last level < current level then no)
	if (vLevelLast < vLevelCurrent)
	{
		vLevelSub%vLevelCurrent% := ""
		;===============
		Loop
		{
			if (A_Index = 1)
			{
				hFile := DllCall("kernel32.dll\FindFirstFile", "Str", vSearchDir2, "Ptr", &vFINDDATA, "Ptr")
				if (hFile = -1)
					break
			}
			if (A_Index > 1)
				if !DllCall("kernel32.dll\FindNextFile", "Ptr", hFile, "Ptr", &vFINDDATA)
				{
					DllCall("kernel32.dll\FindClose", "Ptr", hFile)
					break
				}
			vAttrib := NumGet(&vFINDDATA, 0, "UInt")
			vName := StrGet(&vFINDDATA+44)
			vPath := vSearchDir "\" vName
			if vName not in .,..
				if (StrLen(vPath) <= 259) ;to make it the same as AutoHotkey
					vOutput .= vPath "`r`n"
			;vOutput .= vAttrib "`t" vPath "`r`n"
			if (vAttrib & 0x10) ;FILE_ATTRIBUTE_DIRECTORY := 0x10
				if vName not in .,..
					vLevelSub%vLevelCurrent% .= vName "|"
		}
		;===============
		vLevelPoint%vLevelCurrent% := 1
		vLevelLen%vLevelCurrent% := StrLen(vLevelSub%vLevelCurrent%)
	}

	;does this folder have unseen subfolders? (is pointer position greater than length of subfolders list)
	if (vLevelPoint%vLevelCurrent% > vLevelLen%vLevelCurrent%)
	{
		if (vLevelCurrent = 1)
			break
		else
			vLevelLast := vLevelCurrent, vLevelCurrent -= 1
	}
	else
	{
		;remove first unseen subfolder from list (move pointer for current level onwards), go to first unseen subfolder (set last level = current level, and increase 'current level')
		vPos := InStr(vLevelSub%vLevelCurrent%, "|", 0, vLevelPoint%vLevelCurrent%)
		vNameNext := SubStr(vLevelSub%vLevelCurrent%, vLevelPoint%vLevelCurrent%, (vPos-1)-vLevelPoint%vLevelCurrent%+1)

		vLevelPoint%vLevelCurrent% := vPos+1
		vDirNext := vLevelDir%vLevelCurrent% "\" vNameNext

		vLevelLast := vLevelCurrent, vLevelCurrent += 1
		vLevelDir%vLevelCurrent% := vDirNext
	}
}

;Clipboard := vOutput
vPath := A_Desktop "\z list files " A_Now " jee.txt"
FileAppend, % vOutput, % "*" vPath, UTF-8
MsgBox, % "done"
return

;==================================================
Last edited by jeeswg on 04 Oct 2018, 16:55, edited 2 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
LogicDaemon
Posts: 21
Joined: 21 Feb 2014, 01:22

Re: 259-char path limit workarounds

17 Jun 2017, 23:59

I know that's old topic, still I want to share what I've asked it for :)

In file zpaq.ahk, look the function "LongPathsInDir". It can be easily adopted to return directory contents (with subdirectories).
I've tweaked _WIN32_FIND_DATA struct size to be exact (not to waste any memory), and added comments for parsing of the attributes.

Why I needed it:
There is archiver called zpaq. Its command line is not that Intricate as 7-zip's one, and also there are weird caveats. For example, when adding to an archive without specifying \\?\ prefix for source paths (including cases when adding relative path), any files with full path length > 259 chars won't be added to the archive, they'll be skipped with a warning. Also, there is no way of feeding it a separate file list, all paths must be given on command line.

But I'm using total commander with usercmd.ini for dealing with zpaq archives, which only supports long paths in unicode file lists, and not on command line.

This is what zpaq.ahk saves from. First, it reads file lists and puts them right on command line for zpaq; second, it checks if there are any long paths,
and if there are, expands them to full paths with \\?\ prefix (otherwise, I get a warning in separate console window which closes once archiving is done, which is often split-second for whole operation if no files get added because they all had long paths).
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: 259-char path limit workarounds

16 Sep 2017, 05:01

I've gone back to the script and improved it somewhat.

Code: Select all

#SingleInstance force
ListLines, Off
#KeyHistory 0
Menu, Tray, Click, 1
#NoEnv
AutoTrim, Off
#UseHook

SplitPath, A_ScriptName,,,, vScriptNameNoExt
Menu, Tray, Tip, % vScriptNameNoExt

;==================================================

#MaxMem 600

if A_Is64bitOS
	DllCall("kernel32\Wow64DisableWow64FsRedirection", PtrP,0)

;q:: ;list all files + folders (custom file loop) (recurse)
vSearchDir := "C:\"
vSearchDir := A_Desktop "\MyDir"

vOutput := ""
VarSetCapacity(vOutput, 260*1000000*2)
VarSetCapacity(WIN32_FIND_DATA, 592, 0)
vSearchDir := RTrim(vSearchDir, "\")
vLevelLast := 0
vLevelCurrent := 1
vLevelDir1 := vSearchDir
MAX_PATH := 260
;vInfo := "vAttrib"
;vInfo := "vDateC"
;vInfo := "vDateA"
;vInfo := "vDateM"
;vInfo := "vSize"
;vInfo := "vNameShort"
vInfo := "vLen"

;==================================================

vOutput2 := ""
VarSetCapacity(vOutput2, 260*1000000*2)
Loop, Files, % vSearchDir "\*", FDR
{
	vPath := A_LoopFileFullPath
	vAttrib := A_LoopFileAttrib
	vDateC := A_LoopFileTimeCreated
	vDateA := A_LoopFileTimeAccessed
	vDateM := A_LoopFileTimeModified
	vSize := A_LoopFileSize
	vNameShort := A_LoopFileShortName
	vLen := StrLen(vPath)
	vOutput2 .= %vInfo% "`t" vPath "`r`n"
}
Clipboard := vOutput2
;MsgBox, % "done (AHK File loop)"

;==================================================

Loop
{
	vSearchDir := vLevelDir%vLevelCurrent%
	vSearchDir2 := "\\?\" vSearchDir "\*"

	;has this folder been seen before? (if last level < current level then no)
	if (vLevelLast < vLevelCurrent)
	{
		vLevelSub%vLevelCurrent% := ""
		;===============
		Loop
		{
			if (A_Index = 1)
			&& ((hFile := DllCall("kernel32\FindFirstFile", Str,vSearchDir2, Ptr,&WIN32_FIND_DATA)) = -1)
				break
			if (A_Index > 1)
			&& !DllCall("kernel32\FindNextFile", Ptr,hFile, Ptr,&WIN32_FIND_DATA)
			{
				DllCall("kernel32\FindClose", Ptr,hFile)
				break
			}

			vAttribNum := NumGet(&WIN32_FIND_DATA, 0, "UInt") ;dwFileAttributes
			vAttrib := JEE_AhkNumToAttrib(vAttribNum)
			vDateC := JEE_DateFileTimeToDate(&WIN32_FIND_DATA+4) ;ftCreationTime
			vDateA := JEE_DateFileTimeToDate(&WIN32_FIND_DATA+12) ;ftLastAccessTime
			vDateM := JEE_DateFileTimeToDate(&WIN32_FIND_DATA+20) ;ftLastWriteTime
			vSize := NumGet(&WIN32_FIND_DATA, 32, "UInt") ;nFileSizeLow
			vName := StrGet(&WIN32_FIND_DATA+44, MAX_PATH) ;cFileName[MAX_PATH]
			vName := StrGet(&WIN32_FIND_DATA+44) ;cFileName[MAX_PATH]
			vNameShort := StrGet(&WIN32_FIND_DATA+564, 14) ;cAlternateFileName[14]
			if (vNameShort = "")
				vNameShort := vName
			vPath := vSearchDir "\" vName
			vLen := StrLen(vPath)

			if !(vName = ".") && !(vName = "..")
			;&& (StrLen(vPath) <= 259) ;to make it the same as AutoHotkey (ignore long filenames)
			;&& (StrLen(vPath) > 259) ;to only list long filenames
				;vOutput .= vPath "`r`n"
				vOutput .= %vInfo% "`t" vPath "`r`n"

			if (vAttribNum & 0x10) ;FILE_ATTRIBUTE_DIRECTORY := 0x10
			&& !(vName = ".") && !(vName = "..")
				vLevelSub%vLevelCurrent% .= vName "|"
		}
		;===============
		vLevelPoint%vLevelCurrent% := 1
		vLevelLen%vLevelCurrent% := StrLen(vLevelSub%vLevelCurrent%)
	}

	;does this folder have unseen subfolders? (is pointer position greater than length of subfolders list)
	if (vLevelPoint%vLevelCurrent% > vLevelLen%vLevelCurrent%)
	{
		if (vLevelCurrent = 1)
			break
		else
			vLevelLast := vLevelCurrent, vLevelCurrent -= 1
	}
	else
	{
		;remove first unseen subfolder from list (move pointer for current level onwards), go to first unseen subfolder (set last level = current level, and increase 'current level')
		vPos := InStr(vLevelSub%vLevelCurrent%, "|", 0, vLevelPoint%vLevelCurrent%)
		vNameNext := SubStr(vLevelSub%vLevelCurrent%, vLevelPoint%vLevelCurrent%, (vPos-1)-vLevelPoint%vLevelCurrent%+1)

		vLevelPoint%vLevelCurrent% := vPos+1
		vDirNext := vLevelDir%vLevelCurrent% "\" vNameNext

		vLevelLast := vLevelCurrent, vLevelCurrent += 1
		vLevelDir%vLevelCurrent% := vDirNext
	}
}

;Clipboard := vOutput
vPath := A_Desktop "\z list files " A_Now " jee.txt"
FileAppend, % vOutput, % "*" vPath, UTF-8
MsgBox, % "done"

;JEE_WinMergeCompareStrings("CUSTOM`r`n" vOutput, "AHK`r`n" vOutput2)
return

;==================================================

;note: this converts a number from GetFileAttributes or WIN32_FIND_DATA (dwFileAttributes) to match AutoHotkey's FileGetAttrib command
;note: this assumes the file exists
JEE_AhkNumToAttrib(vNum)
{
	static oArray := {"R":0x1,"H":0x2,"S":0x4,"D":0x10,"A":0x20,"N":0x80,"T":0x100,"O":0x800,"E":0x1000,"C":0x4000,"V":0x10000}
	static vList := "RASHNDOCT" ;RASHNDOCTEV
	local vAttrib
	Loop, Parse, vList
		if (vNum & oArray[A_LoopField])
			vAttrib .= A_LoopField
	return (vAttrib = "") ? "X" : vAttrib
}

;==================================================

JEE_DateFileTimeToDate(vAddr, vLocal:=1, vLen:=14)
{
	local vIntervals, vIntervals2, vDate
	vIntervals := NumGet(vAddr+0, 0, "UInt64")
	if vLocal
	{
		DllCall("kernel32\FileTimeToLocalFileTime", Int64P,vIntervals, Int64P,vIntervals2)
		vIntervals := vIntervals2
	}
	vDate := 1601
	vDate += vIntervals//10000000, S
	if (vLen > 14)
		vDate .= Format("{:03}", Mod(vIntervals//10000,1000)) ;milliseconds
	return SubStr(vDate, 1, vLen)
}

;==================================================
@LogicDaemon: Thanks for your latest comment, interesting.
Last edited by jeeswg on 17 Feb 2019, 17:26, edited 2 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: 259-char path limit workarounds

24 Nov 2017, 23:17

Here's another approach using objects:

Code: Select all

q:: ;list files in folder
vDir1 := A_ScriptDir
oShell := ComObjCreate("Shell.Application")
vCount := oShell.Namespace(vDir1).Items.Count
VarSetCapacity(vOutput, vCount*261 << !!A_IsUnicode)
for oItem in oShell.Namespace(vDir1).Items
	;if !oItem.IsFolder
		vOutput .= oItem.Path "`r`n"
oShell := oItem := ""
Clipboard := vOutput
MsgBox, % "done"
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
LogicDaemon
Posts: 21
Joined: 21 Feb 2014, 01:22

Re: 259-char path limit workarounds

25 Nov 2017, 02:22

Thanks :) I would certainly prefer DllCall over COM because of performance. COM is really, really slow, it's noticeable with large directories. And AutoHotkey is fairly fast if used properly, I'd say it's on par with php and maybe even python; much faster than batch files and wscript at least.

P.S. Just noticed there's "mark correct answer" button :) Pressed it on the response which helped me with my script ;)
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: 259-char path limit workarounds

21 Apr 2018, 02:31

I found that oItem.Path sometimes didn't work, it returned blanks, however, oItem.Name did appear to work consistently, although it matches what you see in the folder window, so extensions might be omitted.

Links:
Shell object (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
Shell.NameSpace method (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
Folder object (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
FolderItems object (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
FolderItem object (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6469
Joined: 19 Dec 2016, 01:58
Location: UK

Re: 259-char path limit workarounds

08 May 2018, 10:31

Here's an attempt at listing the selected files in an Explorer window (including long paths), using objects.

Code: Select all

q:: ;list selected files (attempts to handle long paths)
WinGet, hWnd, ID, A
oWin := ""
for oWin2 in ComObjCreate("Shell.Application").Windows
	if (oWin2.HWND = hWnd)
	{
		oWin := oWin2
		break
	}
oWin2 := ""
if !oWin
	return

vDir := oWin.Document.Folder.Self.Path
vOutput := ""
for oItem in oWin.Document.SelectedItems
{
	;if !oItem.IsFolder
	;	continue
	vPath := oItem.Path ;sometimes fails
	if (vPath = "")
		vPfx := "[Dir+Name/NameNoExt] ", vPath := vDir "\" oItem.Name ;can omit extension
	else
		vPfx := ""

	if FileExist("\\?\" vPath)
	{
		vSize := DllCall("kernel32\GetLongPathName", Str,"\\?\" vPath, Ptr,0, UInt,0, UInt)
		VarSetCapacity(vPath2, vSize*2, 0)
		if DllCall("kernel32\GetLongPathName", Str,"\\?\" vPath, Str,vPath2, UInt,vSize, UInt)
			vPath := (SubStr(vPath2, 1, 4) = "\\?\") ? SubStr(vPath2, 5) : vPath2
	}

	vOutput .= vPfx vPath "`r`n"
}

oWin := oItem := ""
Clipboard := vOutput
MsgBox, % vOutput
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], cahek0404, flyingDman, kludgeofthegods, marin87, Rohwedder, tmplinshi, Xtra and 138 guests