Visual Basic Win32 Shell Routines
Undocumented Windows: Format Disk Dialog
The Format Drive Dialog
Posted:   Wednesday August 6, 1997
Updated:   Monday December 26, 2011
Applies to:   VB4-32, VB5, VB6
Developed with:   VB4-32, Windows 95
OS restrictions:   None
Author:   Brad Martinez


SHChangeNotifyRegister: Receive Shell Change Notifications
Undocumented Windows: Overview
Undocumented Windows: Shell Dialogs
Undocumented Windows: Change Icon Dialog
Undocumented Windows: Path Functions

Our second project exploring the undocumented API takes us to SHFormatDrive. Though not listed in Brad's original listings nor an ordinal API like those in Part 1 of this series (and future parts as well), it is nonetheless totally undocumented .. not a trace of it could be located in the July 1997 MSDN.

The caveat still applies: as an undocumented API it is not supported in any way, shape or form by Microsoft. In addition, this API *will* format a drive after prompting, so be careful. The actual call is only one line of code; the bulk of the code is for determination the Windows version since the constant values passed to SHFormatDrive are different for 9x vs. NT, to load the combo box with available drives, and to present a last-ditch message box if the selected drive isn't drive A:

Once again, I've detailed the project form as both it appears with captions in place (the left or top illustration), and as a 'skeleton' form with the control names substituted for captions. There are no hidden controls, so instead of the usual control list, use the right-most form (or bottom, as resolution dictates) to design your project form. The arrangement makes no difference; the names indicated match the code below.

Can you format a drive without showing the dialog? Theoretically yes, but only through interrupt calls or DeviceIOControl on NT boxes. VBnet does not demonstrate this method anywhere on the site.

Finally, the SHFormatDrive code presented here is based on code developed by Joe LeVasseur and published in the Visual Basic Programmer's Journal, errantly attributed to another developer.

 BAS Module Code
Once the form has been designed and saved, paste the following into the general declarations area of a file you name UndocSHFormat.bas:

Option Explicit
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
'Determines if the current OS is WinNT.
'Tested in the form load event only
Public Declare Function GetVersionEx Lib "kernel32" _
   Alias "GetVersionExA" _
  (lpVersionInformation As OSVERSIONINFO) As Long
   dwOSVersionInfoSize As Long
   dwMajorVersion As Long
   dwMinorVersion As Long
   dwBuildNumber As Long
   dwPlatformId As Long
   szCSDVersion As String * 128 
End Type
Public Const VER_PLATFORM_WIN32s = 0
Public Const VER_PLATFORM_WIN32_NT = 2

'APIs declarations for the format function
Public Declare Function SHFormatDrive Lib "shell32" _
  (ByVal hwndOwner As Long, _
   ByVal iDrive As Long, _
   ByVal iCapacity As Long, _
   ByVal iFormatType As Long) As Long
Public Const SHFD_CAPACITY_DEFAULT = 0 'default drive capacity
Public Const SHFD_CAPACITY_360 = 3     '360KB, 5.25" only
Public Const SHFD_CAPACITY_720 = 5     '720KB, 3.5" only
'Normally, these below would be declared as constants,
'if the values between Win95/98 and NT were the same (see
'the commented-out const values below).
'However, because VB lacks a conditional #If variable
'to distinguish between Win95/98 and NT, they are DIMmed
'here and set in the Form_Load routine after GetVersionEx
'has been called.
'Public Const SHFD_FORMAT_QUICK As Long= 0   'quick format
'Public Const SHFD_FORMAT_FULL As Long= 1    'full format
'Public Const SHFD_FORMAT_SYSONLY As Long= 2 'copy sys files only
'Public Const SHFD_FORMAT_FULL As Long= 0   'full format
'Public Const SHFD_FORMAT_QUICK As Long= 1  'quick format
'support APIs to populate the combo box 
'with the available drives
Public Declare Function GetLogicalDriveStrings Lib "kernel32" _
    Alias "GetLogicalDriveStringsA" _
   (ByVal nBufferLength As Long, _
    ByVal lpBuffer As String) As Long
Public Declare Function GetDriveType Lib "kernel32" _
   Alias "GetDriveTypeA" _
  (ByVal nDrive As String) As Long
Public Const DRIVE_REMOVABLE As Long = 2
Public Const DRIVE_FIXED As Long = 3
Public Const DRIVE_REMOTE As Long = 4
Public Const DRIVE_CDROM As Long = 5
Public Const DRIVE_RAMDISK As Long = 6

Public Function IsWinNT() As Boolean

  'Returns True if the current operating 
  'system is WinNT or later
   osvi.dwOSVersionInfoSize = Len(osvi)
   GetVersionEx osvi
   IsWinNT = (osvi.dwPlatformId = VER_PLATFORM_WIN32_NT)
End Function
 Form Code
To the project form illustrated above add the following code:

Option Explicit

Private Sub Form_Load()

   Me.Move (Screen.Width - Me.Width) / 2, (Screen.Height - Me.Height) / 2

  'Load the combo box with the user's 
  'drives & drive types
   LoadAvailableDrives Combo1

  'Pre-select index 1 (typically a user's C drive if 
  'only 1 floppy is installed)
   Combo1.ListIndex = 1

  'Determine if the OS is NT or Win95/98 and assign 
  'the correct format variables
   If IsWinNT Then
      lbOSType = "(NT settings)"
      SHFD_FORMAT_FULL = 0    'full format
      SHFD_FORMAT_QUICK = 1   'quick format
   Else 'it's Win95/98
      lbOSType = "(Win95/98 settings)"
      SHFD_FORMAT_QUICK = 0   'quick format
      SHFD_FORMAT_FULL = 1    'full format
      SHFD_FORMAT_SYSONLY = 2 'copies system files only
   End If
End Sub

Private Sub cmdSHFormat_Click()

  'displays the Format Drive property sheet
   Dim resp As Integer
   Dim drvToFormat As Integer
   Dim prompt As String

   prompt = "Are you sure you want to run the _
             Format dialog against " & Combo1.Text
   resp = MsgBox(prompt, vbCritical Or vbYesNo, "Are you sure")
   If resp = vbYes Then
      lbMessage.Caption = "Checking drive for disk..."
      Call SHFormatDrive(Me.hWnd, _
                         drvToFormat, _
                         SHFD_CAPACITY_DEFAULT, _
      lbMessage.Caption = ""
   End If
End Sub

Private Sub cmdEnd_Click()

   Unload Me
End Sub

Private Function GetDrvStr(currDrive As String) As String

  'from a passed drive string, determines 
  'the type of drive
   Select Case GetDriveType(currDrive)
      Case 0, 1: GetDrvStr= " - Undetermined Drive Type -"
           Select Case Left(currDrive, 1)
              Case "A", "B": GetDrvStr= "Floppy drive"
              Case Else:     GetDrvStr= "Removable drive"
           End Select
      Case DRIVE_FIXED:     GetDrvStr= "Fixed (Hard) drive"
      Case DRIVE_REMOTE:    GetDrvStr= "Remote drive"
      Case DRIVE_CDROM:     GetDrvStr= "CD ROM"
      Case DRIVE_RAMDISK:   GetDrvStr= "Ram disk"
   End Select
End Function

Private Sub LoadAvailableDrives(cmbo As ComboBox)

  Dim lpBuffer As String

  'get list of available drives
   lpBuffer = GetDriveString()

  'Separate the drive strings
  'and add to the combo. StripNulls
  'will continually shorten the
  'string. Loop until a single
  'remaining terminating null is
   Do Until lpBuffer = Chr(0)
   'strip off one drive item
    'and add to the combo
     cmbo.AddItem StripNulls(lpBuffer)
 ' 'alternate method to above for VB6
 '  Dim b() As String
 '  Dim cnt As Long
 '  b() = Split(lpBuffer, vbNullChar)
 ' 'lpBuffer has 2 trailing nulls,
 ' 'that will appear as array entries
 ' 'so skip those
 '  For cnt = LBound(b) To (UBound(b) - 2)
 '     Combo1.AddItem b(cnt)
 '  Next
End Sub

Private Function GetDriveString() As String

  'returns string of available
  'drives each separated by a null
   Dim sBuffer As String
  'possible 26 drives, three characters each + null
   sBuffer = Space$(26 * 4)
  If GetLogicalDriveStrings(Len(sBuffer), sBuffer) Then

     'do not trim off trailing null!
      GetDriveString = Trim$(sBuffer)
   End If

End Function

Private Function StripNulls(startstr As String) As String

 'Take a string separated by chr$(0)
 'and split off 1 item, shortening the
 'string so next item is ready for removal.
  Dim pos As Long

  pos = InStr(startstr$, Chr$(0))
  If pos Then
      StripNulls = Mid$(startstr, 1, pos - 1)
      startstr = Mid$(startstr, pos + 1, Len(startstr))
      Exit Function
  End If

End Function
Save the project before running. If there is no disk in the selected drive, the normal grinding will occur, but the dialog will still appear. Therefore, you'll want to check for the presence of a disk in the drive before calling this on a user's system.

If you select the drive on which Windows is installed, it's self-preserving nature **should** inform you that that drive can not be formatted. However, should the Format dialog appear, selecting Start will format the selected disk. Use caution.


PayPal Link
Make payments with PayPal - it's fast, free and secure!


Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy


Hit Counter