Volumes

BlitzMax Modules Forums/Brucey's Modules/Volumes

Hi Brucey. I've been using the volumes mod in NSS4 and love the simplicity of it. Now it may be totally unrelated to this module but I seem to be getting some problems from users that are running 64-bit Windows or foreign language versions of Windows.

Basically when they first start my game it will create a save folder... GetUserDocumentsDir()+"/New Star Soccer 4/"

For some users the game shuts down immediately and the save folder never gets created. So I'm trying to track down if it crashes before creating save location or after failing to create it. Basically once the save folder is created it stores a Settings.ini file in there. Without said file the game will crash.

So I'm wondering if you or anyone else has successfully used the volumes locale on a 64-bit or a foreign windows machine?

I think "foreign" is more likely to be an issue than 64bit (probably).
Especially if there are non-ascii characters in the path. BlitzMax has failings when it comes to Unicode paths.
I'm not sure how the path will appear if is has non-ascii characters in it, although Volumes should be able to retrieve it okay (it is calling the "W"-wide API, and using FromWString to store it before passing it back).

Your issue may be with the BlitzMax file-handling code, which could be choking on the potential > 127 characters.

Maybe :-)

You are correct, Brucey- I use your Volumes mod too (thank you!) and yes, Cyrillic characters in someone's username will break it. So far I've only seen this break with Windows, but if it's a BlitzMax problem then I guess it would break on any OS.

I would *love* a fix! ;)

It may well be worth looking into this properly - for general file access.

Looks like I may have found my "holiday" project :-)

Hi Brucey,

I also had a look at this mod and I found out that your windows routines to get the volumes are not perfect meaning that they don't get every volume connected to the pc.

If you go to your Control Panel and then to "Administration Tools" (provided that you have the classical control panel style) and then to "Computer Management". An if you go there to the option "Disk Management" there you can remove the device letter and just mount the device in an empty folder (eg. on your desktop) like on linux (or mac?). And if this is the case your volume routines do not find this device.

So I made a little research an quickly found a way to get this too. Besides my little demo shows that it can also handle mutiple mount points like to folders or a letter and a folder.

I made a little demo to show you how it works. Maybe you can implement it in your module.

Before I forget to mention it it uses the unicode winapi functions (ending with W) for all string things.

SuperStrict

Framework brl.linkedlist
Import brl.standardio

Import "-lkernel32"

Extern "win32"
	' volumes
	Function FindFirstVolume:Int(volumeName:Short Ptr, bufferSize:Int) = "FindFirstVolumeW@8"
	Function FindNextVolume:Int(handle:Int, volumeName:Short Ptr, bufferSize:Int) = "FindNextVolumeW@12"
	Function FindVolumeClose:Int(handle:Int) = "FindVolumeClose@4"
	
	' volume paths
	Function GetVolumePathNamesForVolumeName:Int(volumeName:Short Ptr, volumePaths:Short Ptr, bufferSize:Int, copiedSize:Int Ptr) = "GetVolumePathNamesForVolumeNameW@16"
EndExtern

For Local volume:TVolume = EachIn TVolume.Scan()
	Print volume.guid + "~n~t" + "~n~t".join(volume.paths)
Next

Type TVolume
	
	' maximum length of a path
	Const PATH_MAX:Int = $104
	
	' all volumes
	Global list:TList
	
	' scans for volumes
	Function Scan:TList()
		Self.list = New TList
		
		' create buffer
		Local nameBuffer:Short[] = New Short[Self.PATH_MAX]
		
		' get the first volume
		Local handle:Int = FindFirstVolume(nameBuffer, Self.PATH_MAX)
		
		' if this is the case an error has occured or there are no volumes
		If handle < 1 Then Return Self.list
		
		While True
			
			' create new volume
			Local volume:TVolume = New TVolume
			volume.guid = String.FromWString(nameBuffer)
			
			' retrieve the paths
			Local pathsBuffer:Short[] = New Short[Self.PATH_MAX]
			Local bufferSize:Int
			
			' It has worked, let us save it
			If GetVolumePathNamesForVolumeName(nameBuffer, pathsBuffer, Self.PATH_MAX, Varptr bufferSize) Then
				volume.paths = String.FromShorts(pathsBuffer, bufferSize).Trim().split("~0")
			' Some error occured  if the buffer was too small we will set it to the
			' right size and try it again
			ElseIf bufferSize > Self.PATH_MAX
				If GetVolumePathNamesForVolumeName(nameBuffer, pathsBuffer, bufferSize, Varptr bufferSize) Then
					volume.paths = String.FromShorts(pathsBuffer, bufferSize).Trim().split("~0")
				EndIf
			EndIf
			
			' add volume to list
			Self.list.addLast(volume)
			
			' get the next volume or quit the loop if there is none
			If Not FindNextVolume(handle, nameBuffer, Self.PATH_MAX) Then Exit
		Wend
		
		' end the volumes search
		FindVolumeClose(handle)
		
		Return Self.list
	EndFunction
	
	' contains the guid of the volume
	Field guid:String
	
	' contains the paths from which the volume is accessible / which the volume is mounted in
	Field paths:String[]
	
EndType


Thanks Artemis :-)

I'll have a look at fitting into the framework. Much appreciated!

One thing it doesn't find are any of my network drives... (Q -> Z)... it is only showing A, C and D... so I guess I should implement some of what I have now, and some of this...

Okay... this seems to work quite well now :
Volumes :
	  -  A:\ (FAT) -  1mb
	  -  C:\ (NTFS) -  20500mb
	  -  D:\ () -  0mb
	  -  Q:\ () -  0mb
	  -  R:\ () -  0mb
	  -  S:\ () -  0mb
	Shared Folders  -  T:\ (PrlSF) -  12624mb
	Shared Folders  -  U:\ (PrlSF) -  12624mb
	Shared Folders  -  V:\ (PrlSF) -  12624mb
	Shared Folders  -  W:\ (PrlSF) -  12624mb
	Shared Folders  -  X:\ (PrlSF) -  196257mb
	Shared Folders  -  Y:\ (PrlSF) -  12624mb
	Shared Folders  -  Z:\ (PrlSF) -  12624mb

A, C and D and found with your Volume search code, as above, and then I use GetLogicalDrives() to scan for driver letters, and add to the returned list if they aren't already in the list.

This is the same list, but only showing "available" volumes
Volumes :
	  -  A:\ (FAT) -  1mb
	  -  C:\ (NTFS) -  20500mb
	Shared Folders  -  T:\ (PrlSF) -  12624mb
	Shared Folders  -  U:\ (PrlSF) -  12624mb
	Shared Folders  -  V:\ (PrlSF) -  12624mb
	Shared Folders  -  W:\ (PrlSF) -  12624mb
	Shared Folders  -  X:\ (PrlSF) -  196257mb
	Shared Folders  -  Y:\ (PrlSF) -  12624mb
	Shared Folders  -  Z:\ (PrlSF) -  12624mb


While I've been updating it for Unicode friendliness, I've also added three new Custom folder types, for Mac and Windows.

Pictures (My Pictures), Movies (My Videos) and Music (My Music).

Accessible via the GetCustomDir:string(dirType:int) function. See docs for dirType consts.