Testing drives

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by fweil.

Hello,

Here is a sample program for checking available drives and further information. Because some topics related to file system stuff last days, I went deeper to API functions.

I commented source code enough I suppose, but if I missed some explanations, feel free to ask more.

I give the code as it is, but I would like confirmation about one thing : the sGetDriveType() procedure. For interested people, would you like to check if you agree about values I used here for type identification of drives, because I found MSDN information unclear about. Do values depend on the OS version ?

Anyway this code is free and may give some more ideas to anybody.

;=================================================================
;
;
;
Procedure DisplayHelp()
OpenConsole()
PrintN("The application has To possible usage :")
PrintN("CheckDrives x:\ will switch to console mode just giving back the drives status")
PrintN("CheckDrives [IntegerValue] will switch to window mode and display the drives list with details and refresh")
PrintN("")
PrintN("When using window mode, passing a null value will set refresh timer to 2500ms. A 0 value will display one")
PrintN("time only the information and wait for closing the window.")
PrintN("Any other integer value will set the delay to the given value in ms. In case of a bad value (making a result of 0")
PrintN("the refresh is set to 2500ms.")
PrintN("")
PrintN("Closing the window if window mode is selected can be done by the close gadget or Escape key.")
PrintN("Console mode closes with Escape key.")
PrintN("")
PrintN("Press any key to close.")

While Inkey() = ""
Wend

CloseConsole()

EndProcedure

;
;
;
Procedure.s sGetDriveType(Parameter.s)
Result.s
Select GetDriveType_(Parameter)
Case 2
Result = "Floppy"
Case 3
Result = "Drive Fixed"
Case 4
Result = "Remote"
Case 5
Result = "Removable"
Case 6
Result = "Ram disk"
Default
Result = "Unknown"
EndSelect
ProcedureReturn Result
EndProcedure

;
; UpdateDrives tests the identified drives and checks for further details
;
Procedure UpdateDrives(Delay.l)
*Buffer = AllocateMemory(0, 255, 0)
Quit.l
ipt.l
i.l
C.l
Serial.l
LogicalDriveType.s
VName.s
FSName.s
Text.s
EOL.s
Dim LogicalDrives.s(100)
VName = Space(255)
FSName = Space(255)
EOL = Chr(13) + Chr(10)
If Delay 0
Quit = #FALSE
Else
Quit = #TRUE
EndIf
;
; A repeat / forever loop allows to scan drives all the time
;
Repeat
;
; Erase the list of items
;
ClearGadgetItemList(10)
;
; Set the first table entry to null
;
LogicalDrives(1) = ""
;
; Initialize the items counter to 1
;
ipt = 1
;
; Get the drives names in *Buffer and split it into a table
;
; GetLogicalDriveStrings writes the list of drives names
; in a buffer, each name being Chr(0) separated.
; The end of the buffer contains a double Chr(0).
;
For i = 0 To GetLogicalDriveStrings_(255, *Buffer)
C = PeekB(*Buffer + i)
If C 0
LogicalDrives(ipt) = LogicalDrives(ipt) + Chr(C)
Else
ipt = ipt + 1
LogicalDrives(ipt) = ""
EndIf
Next
;
; Decrease the last entry number until no null item is found
;
While LogicalDrives(ipt) = ""
ipt = ipt - 1
Wend
;
; Loop to give further information about found drives
;
; Values I found in different documents are not so clear. This has to be checked.
;
For i = 1 To ipt
LogicalDriveType = sGetDriveType(LogicalDrives(i))
;
; Items are displayed using found parameters or filling status for not available drives
;
If GetVolumeInformation_(LogicalDrives(i), VName, 255, Serial, 0, 0, FSName, 255)
Text = LogicalDrives(i) + Chr(10) + VName + Chr(10) + Str(Serial) + Chr(10) + FSName + Chr(10) + LogicalDriveType + Chr(10) + " "
Else
Text = LogicalDrives(i) + Chr(10) + Chr(10) + Chr(10) + Chr(10) + LogicalDriveType
If GetLastError_() = 21
Text = Text + Chr(10) + "Device not ready"
Else
Text = Text + Chr(10) + "LastError=" + Str(GetLastError_())
EndIf
EndIf
AddGadgetItem(10, -1, Text)
Next
Delay(Delay)
Until Quit
EndProcedure

;
; Get drives
;
; Got this API code from freaks post to PureBasic forum and just transformed it to a function.
; Not used in this application sample
;
Procedure.s GetDrives()
bitmask.l = GetLogicalDrives_()
drives.s = ""
one.l = 1
For i = 0 To 31
If bitmask & one 0
Quit = #TRUE
Else
If Parameter = ""
Delay = 2500
ElseIf Parameter = "?"
Else
If Parameter " "
Delay = Val(Parameter)
Parameter = ""
If Delay < 1
Delay = 2500
EndIf
Else
Delay = 2500
Parameter = ""
EndIf
EndIf
EndIf

If Parameter = ""
;
; Window mode call UpdateDrives() as a thread
;
errmode = SetErrorMode_(#SEM_FAILCRITICALERRORS)
If OpenWindow(0, 0, 0, 434, 250, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_TitleBar, "")
AddKeyboardShortcut(0, #PB_Shortcut_F1, 20)
AddKeyboardShortcut(0, #PB_Shortcut_Escape, 99)
If CreateGadgetList(WindowID())
ListIconGadget(10, 10, 10, 414, 220, "Drives", 50)
AddGadgetColumn(10, 1, "Virtual", 80)
AddGadgetColumn(10, 2, "Serial", 50)
AddGadgetColumn(10, 3, "FS", 50)
AddGadgetColumn(10, 4, "Type", 80)
AddGadgetColumn(10, 5, "Status", 100)
EndIf
If CreateStatusBar(0, WindowID())
StatusBarText(0, 0, "F1 - Help | Esc - Quit", 0)
EndIf
ThreadID = CreateThread(@UpdateDrives(), Delay)
Repeat
WEvent = WaitWindowEvent()
Select WEvent
Case #PB_EventCloseWindow
Quit = #TRUE
Case #PB_EventMenu
EventMenu = EventMenuID()
Select EventMenu
Case 20
DisplayHelp()
Case 99
Quit = #TRUE
Default
EndSelect
Default
EndSelect
Until Quit
EndIf
ElseIf Mid(LTrim(RTrim(Parameter)), 1, 1) = "?"
DisplayHelp()
Else
;
; Simplified version of UpdateDrives() for just one drive check using the console mode.
;
OpenConsole()
LogicalDriveType = sGetDriveType(Parameter)
;
; Items are displayed using found parameters or filling status for not available drives
;
If GetVolumeInformation_(Parameter, VName, 255, Serial, 0, 0, FSName.s, 255)
Text = Parameter + " " + VName + " " + Str(Serial) + " " + FSName + " " + LogicalDriveType
Else
Text = Parameter + " " + LogicalDriveType
If GetLastError_() = 21
Text = Text + " " + "Device Not ready"
Else
Text = Text + " " + "LastError=" + Str(GetLastError_())
EndIf
EndIf
PrintN(Text)

While Inkey() = ""
Wend

CloseConsole()
EndIf
End
;=================================================================

Francois Weil
14, rue Douer
F64100 Bayonne
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by freak.

Program works fine, good work.

Some suggestions about GetDriveType_():

The Platform SDK says nothing about differences in OS Versions.

Note that the return value 1 means that the given string is no root dir and
the value 0 means that the type is unknown.

You should add this, becourse 0 means that there is a drive, of any type, where
1 means, that you can't use that drive (or given string), becourse it is no drive. (which can be important for the programmer)
Your code returns 'Unknown' both times.


Some more small changes:

5 specifies a CDROM-drive, not just any kind of removable device.
2 specifies a removable device, it doesn't have to be a Floppy (could also be
a ZIP-drive, ore something like this)

That's what the Platform SDK says...
Hope it helped,

Timo

--

A debugged program is one for which you have not yet found the conditions that make it fail.

Edited by - freak on 29 July 2002 19:20:39
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by fweil.

Thanx freak.

I am adding some more things to this application example and will post part of it in some days probably.

I was also trying to know if there is a possibility to check the floppy drive for example to know if there is a floppy inside, without to activate heads retry (!). This is also available for any removable device, but I could not find the right way to detect my floppy without that small noise.

When checking peripherals (and of course remote removables makes sense)it would be interesting to have silent detection to not activate hardware but just check if the device is ready for working.

Rgrds

Francois Weil
14, rue Douer
F64100 Bayonne
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by freak.

Hi again,

I think detecting the Floppy without the noise is not possible, sorry.
Remember, when you click on the Floppy in Windows Explorer, it also makes this noise. So If the guys at MS couldn't make it without the noise, I think there's no way of doing it.

Timo
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by fweil.

...,

Sure MS people are the best ?

Ok I am trying to find Nessy in the Loch !

Thnx again.

Francois Weil
14, rue Douer
F64100 Bayonne
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by freak.

> Sure MS people are the best ?

I didn't say that. But it's their OS, and how would you do something using
a OS's API that even the developer of the OS couldn't do?

I think, if there's some way, it is a little more lower level.

Anyway, if you want to add the drive's size, here's some
code i wrote some time ago:

http://www.reelmediaproductions.com/pb/ ... ace_31.zip

If you're done, you could send your stuff to the Recource Site as well, so
people could include it in their projects easily.

That's it...

Timo
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by fweil.

I will post one or two things on Paul's site soon ... this week.

Thnx

Francois Weil
14, rue Douer
F64100 Bayonne
Post Reply