Jump to content

WinNTSetup format helper tool (Is it possible to move the GUI out of this function easily? )


Go to solution Solved by mikell,

Recommended Posts

Posted

That works! Thank you. I tried the string replace but i did not add the 0 or the bitor cmd or your other changes obviously.. i was close but i thought i was wrong.. ok let me see what I can do with this function ;)

Posted (edited)

I have an alternate list method started in the DiskList() function. I am now trying to get the drive letters from the disk and add them to each disk from the original disk list method.. 

#NoTrayIcon
#RequireAdmin
#include <StringConstants.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <ListBoxConstants.au3>
#include <AutoItConstants.au3>
#include <WinAPIFiles.au3>
#include <Constants.au3>
#include <File.au3>
#include <Array.au3>
#include <String.au3>

Global $DiskList = 0
Global $MBR = 0
Global $GPT = 0
Global $bootDrive = ""
Global $mainDrive = ""

Cleanup()

DirCreate(GetCachePath())

Opt("GUIOnEventMode", 1)
MainMenu()

Cleanup()
Exit

Func MainMenu()
    GUICreate('Prep/Format Disk v2.0', 300, 289)
    GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents")
    GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents")
    GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents")

    GUISetIcon(@WorkingDir & '\PrepareDiskNT.ico', 1)
    GUISetBkColor(0x797979)
    GUICtrlCreateLabel('1: Select a disk to prepare for WinNTSetup5', 20, 10, 280)
    $DiskList = GUICtrlCreateList('', 20, 30, 260, 150, BitXOR($GUI_SS_DEFAULT_LIST, $LBS_SORT))
    GUICtrlSetData(-1, DiskList())
    GUICtrlSetOnEvent(-1, "DiskList_Selected")
    $Refresh = GUICtrlCreateButton('Refresh List', 110, 185, 80, 25)
    GUICtrlSetOnEvent(-1, "RefreshPressed")
    GUICtrlSetState(-1, $GUI_FOCUS)

    GUICtrlCreateLabel('2: Select your desired layout...', 20, 214, 280, 30)
    $MBR = GUICtrlCreateButton('BIOS (MBR) Boot', 20, 234, 120, 40)
    GUICtrlSetOnEvent(-1, "MBRPressed")
    GUICtrlSetState(-1, $GUI_DISABLE)
    $GPT = GUICtrlCreateButton('UEFI (GPT) Boot', 160, 234, 120, 40)
    GUICtrlSetOnEvent(-1, "GPTPressed")
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUISetState()

    ; Just idle around
    While 1
        Sleep(10)
    WEnd

EndFunc   ;==>MainMenu

Func RefreshPressed()
    GUICtrlSetData($DiskList, "")
    GUICtrlSetData($DiskList, DiskList())
    DiskList_Selected()
EndFunc   ;==>RefreshPressed

Func MBRPressed()
    Local $s_DiskNumber = StringRegExp(GUICtrlRead($DiskList), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0]

    If @error Then
        MsgBox( _
                $MB_ICONERROR, _
                "Notice: ", _
                "An error occured retrieving the disk number")
    Else
        If MsgBox( _
                BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _
                'This will FORMAT Disk ' & $s_DiskNumber, _
                'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then
            PrepMBR($s_DiskNumber)
            FormatMBR()
            IniWriteMBR()
            MsgBox($MB_ICONINFORMATION, "Redirecting... ", " - WinNTSetup5 will now open - " & @CRLF & @CRLF & 'Boot Drive: ' & $bootDrive & @CRLF & 'Install Drive: ' & $bootDrive)
            LaunchWinNTSetup()
            Cleanup()
            Exit
        EndIf
    EndIf
EndFunc   ;==>MBRPressed

Func GPTPressed()
    Local $s_DiskNumber = StringRegExp(GUICtrlRead($DiskList), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0]

    If @error Then
        MsgBox( _
                $MB_ICONERROR, _
                "Notice: ", _
                "An error occured retrieving the disk number")
    Else
        If MsgBox( _
                BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _
                'This will FORMAT Disk ' & $s_DiskNumber, _
                'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then
            PrepGPT($s_DiskNumber)
            FormatGPT()
            IniWriteGPT()
            MsgBox($MB_ICONINFORMATION, "Redirecting... ", " - WinNTSetup5 will now open - " & @CRLF & @CRLF & 'Boot Drive: ' & $bootDrive & @CRLF & 'Install Drive: ' & $mainDrive)
            LaunchWinNTSetup()
            Cleanup()
            Exit
        EndIf
    EndIf
EndFunc   ;==>GPTPressed

Func SpecialEvents()
    Select
        Case @GUI_CtrlId = $GUI_EVENT_CLOSE
            ; Code below for actions on Close
            Cleanup()
            Exit
        Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE
            ; Code below for actions on Minimize
        Case @GUI_CtrlId = $GUI_EVENT_RESTORE
            ; Code below for actions on Restore
    EndSelect
EndFunc   ;==>SpecialEvents

Func Disk_GetIndexList() ; Get Clean Disk List Index Array
    Local $i_Pid = Run('cmd /c wmic diskdrive get index', @WorkingDir, @SW_HIDE, $STDERR_MERGED)
    ProcessWaitClose($i_Pid)

    Local $as_Indexes = StringSplit(StringStripWS(StringReplace(StdoutRead($i_Pid), 'Index', '', 0, $STR_NOCASESENSE), BitOR($STR_STRIPLEADING, $STR_STRIPTRAILING)), @LF)

    If IsArray($as_Indexes) Then
        If $as_Indexes[0] = 3 And StringInStr($as_Indexes[2], 'ERROR', $STR_NOCASESENSE) Then Return SetError(1, @extended, $as_Indexes[3]) ; assume there's been an error
        Return $as_Indexes
    Else ; an error occured reading the stdout
        Return SetError(2, @extended, 'Unable to read wmic output stream')
    EndIf
EndFunc   ;==>Disk_GetIndexList

Func Disk_GetName($Disk)
    Local $pre_name = ""
    $wmicdata = Run('cmd /c wmic diskdrive ' & $Disk & ' get model', @WorkingDir, @SW_HIDE, 2)
    ProcessWaitClose($wmicdata)
    $pre_name = _StringExplode(StdoutRead($wmicdata), @LF)
    $d_name = StringStripWS($pre_name[1], $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES)
    Return $d_name
EndFunc   ;==>Disk_GetName

Func DiskList()
    Local $Filtered = ""
    Local $aDriveNum = Disk_GetIndexList()
    _ArraySort($aDriveNum, 0, 1)
    For $i = 1 To UBound($aDriveNum) - 1
        $Filtered &= ' Disk ' & StringStripWS($aDriveNum[$i], $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) & " [" & Disk_GetName($aDriveNum[$i]) & "] " & "|"
    Next
    $Filtered = StringRegExpReplace($Filtered, '[\s|]*$', '')
    Return $Filtered
EndFunc   ;==>DiskList

Func GetDiskList()
    Local $aDriveInfo, $iLastDevNumber = -1
    Local $aFixed = DriveGetDrive('FIXED'), $aRemovable = DriveGetDrive('REMOVABLE')
    Local $aDrives[(IsArray($aFixed) ? $aFixed[0] : 0) + (IsArray($aRemovable) ? $aRemovable[0] : 0)][3]

    Local $iDrive = 0
    GUICtrlSetData($DiskList, "") ; clear previous list info
    For $i = 1 To UBound($aFixed) - 1
        $aDrives[$iDrive][0] = $aFixed[$i]
        $aDriveInfo = _WinAPI_GetDriveNumber($aFixed[$i])
        If Not @error Then
            $aDrives[$iDrive][1] = $aDriveInfo[1]
            $aDrives[$iDrive][2] = $aDriveInfo[2]
        EndIf
        $iDrive += 1
    Next
    For $i = 1 To UBound($aRemovable) - 1
        $aDrives[$iDrive][0] = $aRemovable[$i]
        $aDriveInfo = _WinAPI_GetDriveNumber($aRemovable[$i])
        If Not @error Then
            $aDrives[$iDrive][1] = $aDriveInfo[1]
            $aDrives[$iDrive][2] = $aDriveInfo[2]
        EndIf
        $iDrive += 1
    Next

    _ArraySort($aDrives, 0, 0, 0, 1)
    Local $aDisks[UBound($aDrives)][2]
    Local $DiskListOutput = ""

    For $i = 0 To UBound($aDrives) - 1
        If IsNumber($aDrives[$i][1]) Then
            If $aDrives[$i][1] <> $iLastDevNumber Then
                $iLastDevNumber = $aDrives[$i][1]
                $aDisks[$iLastDevNumber][0] = " Disk " & $aDrives[$i][1] & " [" & Disk_GetName($aDrives[$i][1]) & "]" & "|" & @CRLF
            EndIf
            $aDisks[$iLastDevNumber][1] &= ";   └ " & DriveGetLabel($aDrives[$i][0]) & " - " & "(" & StringUpper($aDrives[$i][0]) & "\ )" & "|"
        EndIf
    Next
    ReDim $aDisks[$iLastDevNumber + 1][2]

    For $i = 0 To UBound($aDisks) - 1
        $DiskListOutput &= $aDisks[$i][0]

        $aSplit = StringRegExp($aDisks[$i][1], "[^;]+", 3)
        _ArraySort($aSplit)
        For $j = 0 To UBound($aSplit) - 1
            $DiskListOutput &= $aSplit[$j]
        Next
    Next


    Return $DiskListOutput
EndFunc   ;==>GetDiskList

Func DiskList_Selected() ; action when a list item is selected
    Local $i_State = $GUI_ENABLE

    If GUICtrlRead($DiskList) = '' Or StringInStr(GUICtrlRead($DiskList), "   └ ") Then $i_State = $GUI_DISABLE
    GUICtrlSetState($MBR, $i_State)
    GUICtrlSetState($GPT, $i_State)
EndFunc   ;==>DiskList_Selected

Func GetDriveLetters()
    Local $allDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ", $AvailDriveLetters
    Local $aArray = DriveGetDrive($DT_ALL)
    If @error Then
        ; An error occurred when retrieving the drives.
        MsgBox($MB_SYSTEMMODAL, "", "An Error Occurred! Unable to retrieve " & @CRLF & "available drive letters! Exiting Program...")
        Cleanup()
        Exit
    Else
        For $i = 1 To $aArray[0]
            $driveLetter = StringLeft(StringUpper($aArray[$i]), 1)
            $allDriveLetters = StringReplace($allDriveLetters, $driveLetter, "")
        Next
    EndIf
    $AvailDriveLetters = StringSplit($allDriveLetters, "")
    $bootDrive = $AvailDriveLetters[1] ;Get first available letter
    $mainDrive = $AvailDriveLetters[2] ;Get second available letter
EndFunc   ;==>GetDriveLetters

Func GetWinNTSetupPath()
    Local Static $s_WinNTSetupPath = IniRead(@WorkingDir & '\PrepareDiskNT.ini', "Settings", "WinNTSetupPath", @WorkingDir & '\')
    Return $s_WinNTSetupPath
EndFunc   ;==>GetWinNTSetupPath

Func GetCachePath() ; get the path to the cache folder
    Local Static $s_CachePath = IniRead(@WorkingDir & '\PrepareDiskNT.ini', "Settings", "CachePath", @WorkingDir & '\cache') & '\'
    Return $s_CachePath
EndFunc   ;==>GetCachePath

Func IniWriteMBR()
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT6", "BootDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT6", "TempDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT5", "BootDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT5", "TempDest", $bootDrive & ":")
EndFunc   ;==>IniWriteMBR

Func IniWriteGPT()
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT6", "BootDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT6", "TempDest", $mainDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT5", "BootDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT5", "TempDest", $mainDrive & ":")
EndFunc   ;==>IniWriteGPT

Func LaunchWinNTSetup()
    Run('cmd /c ' & '"' & GetWinNTSetupPath() & 'WinNTSetup_x64.exe' & '"', @WorkingDir, @SW_HIDE)
EndFunc   ;==>LaunchWinNTSetup

Func Cleanup()
    If FileExists(GetCachePath()) Then
        DirRemove(GetCachePath(), $DIR_REMOVE)
    EndIf
EndFunc   ;==>Cleanup

Func PrepMBR($Drive)
    GetDriveLetters()
    createDiskPartScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'scrub.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=MBRscrubber' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'formatmain.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=Windows' & @CRLF & 'Active' & @CRLF & 'Assign letter=' & $bootDrive & @CRLF & 'Exit')
EndFunc   ;==>PrepMBR

Func PrepGPT($Drive)
    GetDriveLetters()
    createDiskPartScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'scrub.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=GPTscrubber' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert gpt' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'formatsystem.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par efi size=100' & @CRLF & 'format quick fs=fat32 label=System' & @CRLF & 'assign letter=' & $bootDrive & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'createmsr.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par msr size=16' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'formatmain.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=450' & @CRLF & 'format quick fs=ntfs label=Windows' & @CRLF & 'assign letter=' & $mainDrive & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'formatwinre.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=ntfs label=WinRE' & @CRLF & 'set id=de94bba4-06d1-4d40-a16a-bfd50179d6ac' & @CRLF & 'Exit')
EndFunc   ;==>PrepGPT

Func createDiskPartScriptFile($fileName, $message)
    $CacheFile = ''
    $CacheFile = FileOpen($fileName, 2)
    FileWrite($CacheFile, $message)
    FileClose($CacheFile)
EndFunc   ;==>createDiskPartScriptFile

Func FormatMBR()
    GUISetState(@SW_HIDE)
    Local $aArray[6][3] = [ _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'scrub.dat' & '"'], _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _
            ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'attrib.dat' & '"'], _
            ["Converting Layout to MBR", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'convert.dat' & '"'], _
            ["Creating Windows Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'formatmain.dat' & '"'] _
            ]

    ProgressOn("Formatting Legacy (MBR)...", "Preparing Disk: ", "0%")

    For $i = 0 To UBound($aArray) - 1
        ProgressSet($i * 17 & "%", $aArray[$i][0])
        ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data
        RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE)
        Sleep(750)
    Next

    ProgressSet(100, "Finished", "Format Completed")
    Sleep(1500)
    ProgressOff()
    GUISetState()
EndFunc   ;==>FormatMBR

Func FormatGPT()
    GUISetState(@SW_HIDE)
    Local $aArray[9][3] = [ _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'scrub.dat' & '"'], _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _
            ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'attrib.dat' & '"'], _
            ["Converting Layout to GPT", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'convert.dat' & '"'], _
            ["Creating System Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'formatsystem.dat' & '"'], _
            ["Creating MSR Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'createmsr.dat' & '"'], _
            ["Creating Windows Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'formatmain.dat' & '"'], _
            ["Creating WinRE Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'formatwinre.dat' & '"'] _
            ]

    ProgressOn("Formatting UEFI (GPT)...", "Preparing Disk: ", "0%")

    For $i = 0 To UBound($aArray) - 1
        ProgressSet($i * 11 & "%", $aArray[$i][0])
        ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data
        RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE)
        Sleep(750)
    Next

    ProgressSet(100, "Finished", "Format Completed")
    Sleep(1500)
    ProgressOff()
    GUISetState()
EndFunc   ;==>FormatGPT

In CMD I can do this to get the letters..

@For /F Delims^=^= %%Z In ('Set Disk 2^>Nul')Do @Set "%%Z="
@For /F Delims^= %%V In ('WMIC DiskDrive Assoc^
 /AssocClass:Win32_DiskDriveToDiskPartition 2^>NUL^|Find /I "Disk #"'
)Do @For /F Tokens^=2Delims^=^" %%W In ("%%V"
)Do @For /F Tokens^=2^,4Delims^=^" %%X In ('WMIC Path^
 Win32_LogicalDiskToPartition 2^>NUL^|Find "%%W" 2^>Nul'
)Do @For /F "Tokens=2Delims=#," %%Z In ("%%X")Do @If Defined Disk%%Z (
    Call Set "Disk%%Z=%%Disk%%Z%% %%Y")Else Set "Disk%%Z=%%Y")
@Set Disk 2>NUL&&Pause

Gives this output

Disk0=D:
Disk1=C:
Disk2=H: G:
Disk3=E: F:

 

Edited by bobomb
Posted (edited)

@Mugen Thank you I did not know JFX added that in..

I am using a lot of these functions for a USB burning tool for PE projects (in another thread on this forum), and WinNTSetup wont be present when the other application is used. Specifically the GetDiskList function..

I think I have a way to work around the issue but I am stuck with StringInStr checking to see if a value exists or not.. maybe someone could tell me what Im doing wrong.. I know this needs to be cleaned up and so do other parts of the getdisklist function but i will worry about that once I get over this hurdle

For $i = 1 To UBound($aDriveNum) - 1
        $iExists = StringInStr($DiskListOutput, "Disk " & $aDriveNum[$i])
        MsgBox($MB_SYSTEMMODAL, "", $iExists)
        If $iExists = -1 Then
            $DiskListOutput &= " Disk " & $aDriveNum[$i] & " [" & Disk_GetName($aDriveNum[$i]) & "]" & "|" & @CRLF
        EndIf
    Next

It is located at the end of the GetDiskList Function in the below complete (unfinished but running script)..

#NoTrayIcon
#RequireAdmin
#include <StringConstants.au3>
#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <ListBoxConstants.au3>
#include <AutoItConstants.au3>
#include <WinAPIFiles.au3>
#include <Constants.au3>
#include <File.au3>
#include <Array.au3>
#include <String.au3>

Global $DiskList = 0
Global $MBR = 0
Global $GPT = 0
Global $bootDrive = ""
Global $mainDrive = ""

Cleanup()

DirCreate(GetCachePath())

Opt("GUIOnEventMode", 1)
MainMenu()

Cleanup()
Exit

Func MainMenu()
    GUICreate('Prep/Format Disk v2.0', 300, 289)
    GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents")
    GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents")
    GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents")

    GUISetIcon(@WorkingDir & '\PrepareDiskNT.ico', 1)
    GUISetBkColor(0x797979)
    GUICtrlCreateLabel('1: Select a disk to prepare for WinNTSetup5', 20, 10, 280)
    $DiskList = GUICtrlCreateList('', 20, 30, 260, 150, BitXOR($GUI_SS_DEFAULT_LIST, $LBS_SORT))
    GUICtrlSetData(-1, GetDiskList())
    GUICtrlSetOnEvent(-1, "DiskList_Selected")
    $Refresh = GUICtrlCreateButton('Refresh List', 110, 185, 80, 25)
    GUICtrlSetOnEvent(-1, "RefreshPressed")
    GUICtrlSetState(-1, $GUI_FOCUS)

    GUICtrlCreateLabel('2: Select your desired layout...', 20, 214, 280, 30)
    $MBR = GUICtrlCreateButton('BIOS (MBR) Boot', 20, 234, 120, 40)
    GUICtrlSetOnEvent(-1, "MBRPressed")
    GUICtrlSetState(-1, $GUI_DISABLE)
    $GPT = GUICtrlCreateButton('UEFI (GPT) Boot', 160, 234, 120, 40)
    GUICtrlSetOnEvent(-1, "GPTPressed")
    GUICtrlSetState(-1, $GUI_DISABLE)
    GUISetState()

    ; Just idle around
    While 1
        Sleep(10)
    WEnd

EndFunc   ;==>MainMenu

Func RefreshPressed()
    GUICtrlSetData($DiskList, "")
    GUICtrlSetData($DiskList, GetDiskList())
    DiskList_Selected()
EndFunc   ;==>RefreshPressed

Func MBRPressed()
    Local $s_DiskNumber = StringRegExp(GUICtrlRead($DiskList), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0]

    If @error Then
        MsgBox( _
                $MB_ICONERROR, _
                "Notice: ", _
                "An error occured retrieving the disk number")
    Else
        If MsgBox( _
                BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _
                'This will FORMAT Disk ' & $s_DiskNumber, _
                'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then
            PrepMBR($s_DiskNumber)
            FormatMBR()
            IniWriteMBR()
            MsgBox($MB_ICONINFORMATION, "Redirecting... ", " - WinNTSetup5 will now open - " & @CRLF & @CRLF & 'Boot Drive: ' & $bootDrive & @CRLF & 'Install Drive: ' & $bootDrive)
            LaunchWinNTSetup()
            Cleanup()
            Exit
        EndIf
    EndIf
EndFunc   ;==>MBRPressed

Func GPTPressed()
    Local $s_DiskNumber = StringRegExp(GUICtrlRead($DiskList), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0]

    If @error Then
        MsgBox( _
                $MB_ICONERROR, _
                "Notice: ", _
                "An error occured retrieving the disk number")
    Else
        If MsgBox( _
                BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _
                'This will FORMAT Disk ' & $s_DiskNumber, _
                'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then
            PrepGPT($s_DiskNumber)
            FormatGPT()
            IniWriteGPT()
            MsgBox($MB_ICONINFORMATION, "Redirecting... ", " - WinNTSetup5 will now open - " & @CRLF & @CRLF & 'Boot Drive: ' & $bootDrive & @CRLF & 'Install Drive: ' & $mainDrive)
            LaunchWinNTSetup()
            Cleanup()
            Exit
        EndIf
    EndIf
EndFunc   ;==>GPTPressed

Func SpecialEvents()
    Select
        Case @GUI_CtrlId = $GUI_EVENT_CLOSE
            ; Code below for actions on Close
            Cleanup()
            Exit
        Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE
            ; Code below for actions on Minimize
        Case @GUI_CtrlId = $GUI_EVENT_RESTORE
            ; Code below for actions on Restore
    EndSelect
EndFunc   ;==>SpecialEvents

Func Disk_GetIndexList() ; Get Clean Disk List Index Array
    Local $i_Pid = Run('cmd /c wmic diskdrive get index', @WorkingDir, @SW_HIDE, $STDERR_MERGED)
    ProcessWaitClose($i_Pid)

    Local $as_Indexes = StringSplit(StringStripWS(StringReplace(StdoutRead($i_Pid), 'Index', '', 0, $STR_NOCASESENSE), BitOR($STR_STRIPLEADING, $STR_STRIPTRAILING)), @LF)

    If IsArray($as_Indexes) Then
        If $as_Indexes[0] = 3 And StringInStr($as_Indexes[2], 'ERROR', $STR_NOCASESENSE) Then Return SetError(1, @extended, $as_Indexes[3]) ; assume there's been an error
        Return $as_Indexes
    Else ; an error occured reading the stdout
        Return SetError(2, @extended, 'Unable to read wmic output stream')
    EndIf
EndFunc   ;==>Disk_GetIndexList

Func Disk_GetName($Disk)
    Local $pre_name = ""
    $wmicdata = Run('cmd /c wmic diskdrive ' & $Disk & ' get model', @WorkingDir, @SW_HIDE, 2)
    ProcessWaitClose($wmicdata)
    $pre_name = _StringExplode(StdoutRead($wmicdata), @LF)
    $d_name = StringStripWS($pre_name[1], $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES)
    Return $d_name
EndFunc   ;==>Disk_GetName

Func DiskList()
    Local $Filtered = ""
    Local $aDriveNum = Disk_GetIndexList()
    _ArraySort($aDriveNum, 0, 1)
    For $i = 1 To UBound($aDriveNum) - 1
        $Filtered &= ' Disk ' & StringStripWS($aDriveNum[$i], $STR_STRIPLEADING + $STR_STRIPTRAILING + $STR_STRIPSPACES) & " - [" & Disk_GetName($aDriveNum[$i]) & "] " & "|"
    Next
    $Filtered = StringRegExpReplace($Filtered, '[\s|]*$', '')
    Return $Filtered
EndFunc   ;==>DiskList

Func GetDiskList()
    Local $aDriveInfo, $iLastDevNumber = -1
    Local $aFixed = DriveGetDrive('FIXED'), $aRemovable = DriveGetDrive('REMOVABLE')
    Local $aDrives[(IsArray($aFixed) ? $aFixed[0] : 0) + (IsArray($aRemovable) ? $aRemovable[0] : 0)][3]
    Local $aDriveNum = Disk_GetIndexList()
    Local $iDrive = 0

    _ArraySort($aDriveNum, 0, 1)

    GUICtrlSetData($DiskList, "") ; clear previous list info
    For $i = 1 To UBound($aFixed) - 1
        $aDrives[$iDrive][0] = $aFixed[$i]
        $aDriveInfo = _WinAPI_GetDriveNumber($aFixed[$i])
        If Not @error Then
            $aDrives[$iDrive][1] = $aDriveInfo[1]
            $aDrives[$iDrive][2] = $aDriveInfo[2]
        EndIf
        $iDrive += 1
    Next
    For $i = 1 To UBound($aRemovable) - 1
        $aDrives[$iDrive][0] = $aRemovable[$i]
        $aDriveInfo = _WinAPI_GetDriveNumber($aRemovable[$i])
        If Not @error Then
            $aDrives[$iDrive][1] = $aDriveInfo[1]
            $aDrives[$iDrive][2] = $aDriveInfo[2]
        EndIf
        $iDrive += 1
    Next

    _ArraySort($aDrives, 0, 0, 0, 1)
    Local $aDisks[UBound($aDrives)][2]
    Local $DiskListOutput = ""

    For $i = 0 To UBound($aDrives) - 1
        If IsNumber($aDrives[$i][1]) Then
            If $aDrives[$i][1] <> $iLastDevNumber Then
                $iLastDevNumber = $aDrives[$i][1]
                $aDisks[$iLastDevNumber][0] = " Disk " & $aDrives[$i][1] & " [" & Disk_GetName($aDrives[$i][1]) & "]" & "|" & @CRLF
            EndIf
            $aDisks[$iLastDevNumber][1] &= ";   └ " & DriveGetLabel($aDrives[$i][0]) & " - " & "(" & StringUpper($aDrives[$i][0]) & "\ )" & "|"
        EndIf
    Next

    ReDim $aDisks[$iLastDevNumber + 1][2]

    For $i = 0 To UBound($aDisks) - 1
        ;_ArrayDisplay($aDisks)
        $DiskListOutput &= $aDisks[$i][0]
        $aSplit = StringRegExp($aDisks[$i][1], "[^;]+", 3)
        _ArraySort($aSplit)
        ;_ArrayDisplay($aSplit)
        For $j = 0 To UBound($aSplit) - 1
            $DiskListOutput &= $aSplit[$j]
        Next
    Next

    For $i = 1 To UBound($aDriveNum) - 1
        $iExists = StringInStr($DiskListOutput, "Disk " & $aDriveNum[$i])
        MsgBox($MB_SYSTEMMODAL, "", $iExists)
        If $iExists = -1 Then
            $DiskListOutput &= " Disk " & $aDriveNum[$i] & " [" & Disk_GetName($aDriveNum[$i]) & "]" & "|" & @CRLF
        EndIf
    Next
    ;MsgBox($MB_SYSTEMMODAL, "", $DiskListOutput)

    Return $DiskListOutput
EndFunc   ;==>GetDiskList

Func DiskList_Selected() ; action when a list item is selected
    Local $i_State = $GUI_ENABLE

    If GUICtrlRead($DiskList) = '' Or StringInStr(GUICtrlRead($DiskList), "   └ ") Then $i_State = $GUI_DISABLE
    GUICtrlSetState($MBR, $i_State)
    GUICtrlSetState($GPT, $i_State)
EndFunc   ;==>DiskList_Selected

Func GetDriveLetters()
    Local $allDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ", $AvailDriveLetters
    Local $aArray = DriveGetDrive($DT_ALL)
    If @error Then
        ; An error occurred when retrieving the drives.
        MsgBox($MB_SYSTEMMODAL, "", "An Error Occurred! Unable to retrieve " & @CRLF & "available drive letters! Exiting Program...")
        Cleanup()
        Exit
    Else
        For $i = 1 To $aArray[0]
            $driveLetter = StringLeft(StringUpper($aArray[$i]), 1)
            $allDriveLetters = StringReplace($allDriveLetters, $driveLetter, "")
        Next
    EndIf
    $AvailDriveLetters = StringSplit($allDriveLetters, "")
    $bootDrive = $AvailDriveLetters[1] ;Get first available letter
    $mainDrive = $AvailDriveLetters[2] ;Get second available letter
EndFunc   ;==>GetDriveLetters

Func GetWinNTSetupPath()
    Local Static $s_WinNTSetupPath = IniRead(@WorkingDir & '\PrepareDiskNT.ini', "Settings", "WinNTSetupPath", @WorkingDir & '\')
    Return $s_WinNTSetupPath
EndFunc   ;==>GetWinNTSetupPath

Func GetCachePath() ; get the path to the cache folder
    Local Static $s_CachePath = IniRead(@WorkingDir & '\PrepareDiskNT.ini', "Settings", "CachePath", @WorkingDir & '\cache') & '\'
    Return $s_CachePath
EndFunc   ;==>GetCachePath

Func IniWriteMBR()
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT6", "BootDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT6", "TempDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT5", "BootDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT5", "TempDest", $bootDrive & ":")
EndFunc   ;==>IniWriteMBR

Func IniWriteGPT()
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT6", "BootDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT6", "TempDest", $mainDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT5", "BootDest", $bootDrive & ":")
    IniWrite(GetWinNTSetupPath() & "WinNTSetup.ini", "WinNT5", "TempDest", $mainDrive & ":")
EndFunc   ;==>IniWriteGPT

Func LaunchWinNTSetup()
    Run('cmd /c ' & '"' & GetWinNTSetupPath() & 'WinNTSetup_x64.exe' & '"', @WorkingDir, @SW_HIDE)
EndFunc   ;==>LaunchWinNTSetup

Func Cleanup()
    If FileExists(GetCachePath()) Then
        DirRemove(GetCachePath(), $DIR_REMOVE)
    EndIf
EndFunc   ;==>Cleanup

Func PrepMBR($Drive)
    GetDriveLetters()
    createDiskPartScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'scrub.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=MBRscrubber' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'formatmain.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=Windows' & @CRLF & 'Active' & @CRLF & 'Assign letter=' & $bootDrive & @CRLF & 'Exit')
EndFunc   ;==>PrepMBR

Func PrepGPT($Drive)
    GetDriveLetters()
    createDiskPartScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $Drive & @CRLF & 'clean' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'scrub.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=GPTscrubber' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $Drive & @CRLF & 'convert gpt' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'formatsystem.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par efi size=100' & @CRLF & 'format quick fs=fat32 label=System' & @CRLF & 'assign letter=' & $bootDrive & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'createmsr.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par msr size=16' & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'formatmain.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=450' & @CRLF & 'format quick fs=ntfs label=Windows' & @CRLF & 'assign letter=' & $mainDrive & @CRLF & 'Exit')
    createDiskPartScriptFile(GetCachePath() & 'formatwinre.dat', 'Sel Dis ' & $Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=ntfs label=WinRE' & @CRLF & 'set id=de94bba4-06d1-4d40-a16a-bfd50179d6ac' & @CRLF & 'Exit')
EndFunc   ;==>PrepGPT

Func createDiskPartScriptFile($fileName, $message)
    $CacheFile = ''
    $CacheFile = FileOpen($fileName, 2)
    FileWrite($CacheFile, $message)
    FileClose($CacheFile)
EndFunc   ;==>createDiskPartScriptFile

Func FormatMBR()
    GUISetState(@SW_HIDE)
    Local $aArray[6][3] = [ _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'scrub.dat' & '"'], _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _
            ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'attrib.dat' & '"'], _
            ["Converting Layout to MBR", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'convert.dat' & '"'], _
            ["Creating Windows Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'formatmain.dat' & '"'] _
            ]

    ProgressOn("Formatting Legacy (MBR)...", "Preparing Disk: ", "0%")

    For $i = 0 To UBound($aArray) - 1
        ProgressSet($i * 17 & "%", $aArray[$i][0])
        ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data
        RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE)
        Sleep(750)
    Next

    ProgressSet(100, "Finished", "Format Completed")
    Sleep(1500)
    ProgressOff()
    GUISetState()
EndFunc   ;==>FormatMBR

Func FormatGPT()
    GUISetState(@SW_HIDE)
    Local $aArray[9][3] = [ _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'scrub.dat' & '"'], _
            ["Cleaning Drive", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'clean.dat' & '"'], _
            ["Resetting Disk Attributes", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'attrib.dat' & '"'], _
            ["Converting Layout to GPT", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'convert.dat' & '"'], _
            ["Creating System Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'formatsystem.dat' & '"'], _
            ["Creating MSR Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'createmsr.dat' & '"'], _
            ["Creating Windows Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'formatmain.dat' & '"'], _
            ["Creating WinRE Partition", 'cmd /c diskpart /s ' & '"' & GetCachePath() & 'formatwinre.dat' & '"'] _
            ]

    ProgressOn("Formatting UEFI (GPT)...", "Preparing Disk: ", "0%")

    For $i = 0 To UBound($aArray) - 1
        ProgressSet($i * 11 & "%", $aArray[$i][0])
        ;MsgBox($MB_ICONINFORMATION, "Troubleshooting.. ", $aArray[$i][1]) ;Troubleshoot Array Data
        RunWait($aArray[$i][1], @WorkingDir, @SW_HIDE)
        Sleep(750)
    Next

    ProgressSet(100, "Finished", "Format Completed")
    Sleep(1500)
    ProgressOff()
    GUISetState()
EndFunc   ;==>FormatGPT

 

Edited by bobomb
Posted

Here's another way to do it

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <TreeViewConstants.au3>
#include <WindowsConstants.au3>
#include <GuiTreeView.au3>

GUICreate("bobomb", 400, 288, 722, 322)
Global $c_Treeview = GUICtrlCreateTreeView(16, 8, 369, 217)
Disk_GetList()
_GUICtrlTreeView_Sort($c_Treeview)
$Button1 = GUICtrlCreateButton("Button1", 96, 240, 75, 25)
$Button2 = GUICtrlCreateButton("Button2", 184, 240, 75, 25)
GUISetState(@SW_SHOW)


While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit

    EndSwitch
WEnd

Func Disk_GetList()
    Local Const $WBEMFLAGRETURNIMMEDIATELY = 0x10

    Local Enum _
            $UNKNOWN, _
            $NOROOTDIRECTORY, _
            $REMOVABLEDISK, _
            $LOCALDISK, _
            $NETWORKDRIVE, _
            $COMPACTDISK, _
            $RAMDISK

    Local $o_WMIService = ObjGet("winmgmts:\\" & @ComputerName & "\root\cimv2")

    If IsObj($o_WMIService) Then
        Local $s_Query = "SELECT * FROM Win32_DiskDrive"
        Local $o_DiskDrives = $o_WMIService.ExecQuery($s_Query, "WQL", $WBEMFLAGRETURNIMMEDIATELY)

        If IsObj($o_DiskDrives) Then
            Local $o_Partitions = 0
            Local $o_LogicalDisks = 0

            For $o_DiskDrive In $o_DiskDrives
                $h_Parent = GUICtrlCreateTreeViewItem("Disk " & $o_DiskDrive.Index & " [" & $o_DiskDrive.Model & "]", $c_Treeview)

                $s_Query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" & $o_DiskDrive.DeviceId & "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
                $o_Partitions = $o_WMIService.ExecQuery($s_Query)

                If IsObj($o_Partitions) Then
                    For $o_Partition In $o_Partitions
                        $s_Query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & $o_Partition.DeviceId & "'} WHERE AssocClass = Win32_LogicalDiskToPartition"
                        $o_LogicalDisks = $o_WMIService.ExecQuery($s_Query)

                        For $o_LogicalDisk In $o_LogicalDisks
                            If $o_LogicalDisk.drivetype = $REMOVABLEDISK Or $o_LogicalDisk.drivetype = $LOCALDISK Then
                                GUICtrlCreateTreeViewItem('(' & $o_LogicalDisk.DeviceId & '\) ' & $o_LogicalDisk.Volumename, $h_Parent)
                            EndIf
                        Next
                    Next
                Else
                    ; add error info here
                EndIf
            Next
        Else
            ; add error info here
        EndIf
    Else
        ; add error info here
    EndIf
EndFunc   ;==>Disk_GetList

 

  • bobomb changed the title to WinNTSetup format helper tool (Is it possible to move the GUI out of this function easily? )
Posted (edited)

That disk function works perfectly. Very awesome @benners!  Below is the updated script. This and the BurnTool in the other thread share functions and basic gui but both do useful things that will make PE users lives easier.. They arent meant to be beautiful but to replace old cmd scripts.. this is much safer than looking at a disk 0 disk 1 disk 2 list in diskpart ;)

Also thank you @junkew for helping teach me

#NoTrayIcon
#RequireAdmin
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=PrepareDiskNT.ico
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Res_Comment=Prepare / Format Disks for WinNTSetup
#AutoIt3Wrapper_Res_Description=PrepareDiskNT.exe
#AutoIt3Wrapper_Res_Fileversion=2.0.0.6
#AutoIt3Wrapper_Add_Constants=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

;~ #Tidy_Parameters=/sf

#include <AutoItConstants.au3>
#include <MsgBoxConstants.au3>
#include <GUIConstantsEx.au3>
#include <GuiTreeView.au3>
#include <StringConstants.au3>

Global $c_DiskList = 0
Global $c_MBR_btn = 0
Global $c_GPT_btn = 0
Global $s_BootDrive = ""
Global $s_MainDrive = ""

Cleanup(False)

DirCreate(GetCachePath())

Opt("GUIOnEventMode", 1)

GUI_Create()

Func Buttons_Disable()
    GUICtrlSetState($c_MBR_btn, $GUI_DISABLE)
    GUICtrlSetState($c_GPT_btn, $GUI_DISABLE)
EndFunc   ;==>Buttons_Disable

Func Buttons_Enable()
    GUICtrlSetState($c_MBR_btn, $GUI_ENABLE)
    GUICtrlSetState($c_GPT_btn, $GUI_ENABLE)
EndFunc   ;==>Buttons_Enable

Func Cleanup($b_Exit = True)
    If FileExists(GetCachePath()) Then DirRemove(GetCachePath(), $DIR_REMOVE)
    If $b_Exit Then Exit
EndFunc   ;==>Cleanup

Func DiskList_GetDrives()
    Local Const $WBEMFLAGRETURNIMMEDIATELY = 0x10

    Local Enum _
            $Unknown, _
            $NoRootDirectory, _
            $RemovableDisk, _
            $LocalDisk, _
            $NetworkDrive, _
            $CompactDisk, _
            $RAMDisk

    Local $o_WMIService = ObjGet("winmgmts:\\" & @ComputerName & "\root\cimv2")

    If IsObj($o_WMIService) Then
        Local $s_Query = "SELECT * FROM Win32_DiskDrive"
        Local $o_DiskDrives = $o_WMIService.ExecQuery($s_Query, "WQL", $WBEMFLAGRETURNIMMEDIATELY)

        If IsObj($o_DiskDrives) Then
            Local $o_Partitions = 0
            Local $o_LogicalDisks = 0

            For $o_DiskDrive In $o_DiskDrives
                $h_Parent = GUICtrlCreateTreeViewItem("Disk " & $o_DiskDrive.Index & " [" & $o_DiskDrive.Model & "]", $c_DiskList)
                GUICtrlSetOnEvent(-1, 'Buttons_Enable')
                _GUICtrlTreeView_SetIcon($c_DiskList, $h_Parent, "shell32.dll", 15)

                $s_Query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" & $o_DiskDrive.DeviceId & "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition"
                $o_Partitions = $o_WMIService.ExecQuery($s_Query)

                If IsObj($o_Partitions) Then
                    For $o_Partition In $o_Partitions
                        $s_Query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" & $o_Partition.DeviceId & "'} WHERE AssocClass = Win32_LogicalDiskToPartition"
                        $o_LogicalDisks = $o_WMIService.ExecQuery($s_Query)

                        For $o_LogicalDisk In $o_LogicalDisks
                            If $o_LogicalDisk.drivetype = $RemovableDisk Or $o_LogicalDisk.drivetype = $LocalDisk Then
                                GUICtrlCreateTreeViewItem('(' & $o_LogicalDisk.DeviceId & '\) ' & $o_LogicalDisk.Volumename, $h_Parent)
                                GUICtrlSetOnEvent(-1, 'Buttons_Disable')
                                _GUICtrlTreeView_SetIcon($c_DiskList, -1, "shell32.dll", 7)
                            EndIf
                        Next
                    Next
                Else
                    ; add error info here
                EndIf
            Next
        Else
            ; add error info here
        EndIf
    Else
        ; add error info here
    EndIf
EndFunc   ;==>DiskList_GetDrives

Func DiskList_Load()
    _GUICtrlTreeView_BeginUpdate($c_DiskList)
    _GUICtrlTreeView_DeleteAll($c_DiskList)
    DiskList_GetDrives()
    If _GUICtrlTreeView_GetCount($c_DiskList) > 2 Then _GUICtrlTreeView_Sort($c_DiskList)
    _GUICtrlTreeView_Expand($c_DiskList)
    _GUICtrlTreeView_EndUpdate($c_DiskList)
    Buttons_Disable()
EndFunc   ;==>DiskList_Load

Func DiskPart_CreateScriptFile($s_FileName, $s_Message)
    Local $h_File = FileOpen($s_FileName, 2)

    FileWrite($h_File, $s_Message)
    FileClose($h_File)
EndFunc   ;==>DiskPart_CreateScriptFile

Func GetCachePath()
    Local Static $s_CachePath = IniRead(@WorkingDir & '\PrepareDiskNT.ini', "Settings", "CachePath", @WorkingDir & '\cache') & '\'
    Return $s_CachePath
EndFunc   ;==>GetCachePath

Func GetDriveLetters()
    Local $s_AllDriveLetters = "CDEFGHIJKLMNOPQRSTUVWXYZ"
    Local $as_Drives = DriveGetDrive($DT_ALL)

    If @error Then
        ; An error occurred when retrieving the drives.
        MsgBox( _
                BitOR($MB_ICONERROR, $MB_SYSTEMMODAL), _
                "Drive Letters", _
                "Unable to retrieve available drive letters! Exiting Program...")
        Cleanup()
    Else
        Local $s_DriveLetter

        For $i = 1 To $as_Drives[0]
            $s_DriveLetter = StringLeft(StringUpper($as_Drives[$i]), 1)
            $s_AllDriveLetters = StringReplace($s_AllDriveLetters, $s_DriveLetter, "")
        Next
    EndIf

    Local $as_AvailDriveLetters = StringSplit($s_AllDriveLetters, "")

    $s_BootDrive = $as_AvailDriveLetters[1] ; Get first available letter
    $s_MainDrive = $as_AvailDriveLetters[2] ; Get second available letter
EndFunc   ;==>GetDriveLetters

Func GPT_Format()
    GUISetState(@SW_HIDE)

    Local $as_DiskPart[10][2] = [ _
            [9, 0], _
            ["Cleaning Drive", 'clean.dat'], _
            ["Cleaning Drive", 'scrub.dat'], _
            ["Cleaning Drive", 'clean.dat'], _
            ["Resetting Disk Attributes", 'attrib.dat'], _
            ["Converting Layout to GPT", 'convert.dat'], _
            ["Creating System Partition", 'formatsystem.dat'], _
            ["Creating MSR Partition", 'createmsr.dat'], _
            ["Creating Windows Partition", 'formatmain.dat'], _
            ["Creating WinRE Partition", 'formatwinre.dat'] _
            ]

    ProgressOn("Formatting GPT (UEFI)...", "Preparing Disk: ", "0%")

    For $i = 1 To $as_DiskPart[0][0]
        ProgressSet($i * 11 & "%", $as_DiskPart[$i][0])
        RunWait(@ComSpec & ' /c diskpart /s ' & '"' & GetCachePath() & $as_DiskPart[$i][1] & '"', @WorkingDir, @SW_HIDE)
        Sleep(750)
    Next

    ProgressSet(100, "Finished", "Format Completed")
    Sleep(1500)
    ProgressOff()
    GUISetState()
EndFunc   ;==>GPT_Format

Func GPT_Pressed()
    Local $s_DiskNumber = StringRegExp(GUICtrlRead($c_DiskList, $GUI_READ_EXTENDED), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)
    If $s_DiskNumber = "" Then
        MsgBox( _
                $MB_ICONERROR, _ ; it is possible to bug the GUI and make the buttons appear by pressing + or - on tree then refresh
                "Attention: ", _
                "No disk is selected!")
        Buttons_Disable()
    Else

        $s_DiskNumber = StringRegExp(GUICtrlRead($c_DiskList, $GUI_READ_EXTENDED), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0]

        If @error Then
            MsgBox( _
                    $MB_ICONERROR, _
                    "Attention: ", _
                    "An error occured retrieving the disk number")
        Else
            If MsgBox( _
                    BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _
                    'This will FORMAT Disk ' & $s_DiskNumber, _
                    'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then
                GPT_Prepare($s_DiskNumber)
                GPT_Format()
                GPT_WriteIni()

                MsgBox( _
                        $MB_ICONINFORMATION, _
                        "Redirecting... ", _
                        " - WinNTSetup will now open - " & @CRLF & @CRLF & 'Boot Drive: ' & $s_BootDrive & @CRLF & 'Install Drive: ' & $s_MainDrive)

                WinNTSetup_Launch()
                Cleanup()
            EndIf
        EndIf
    EndIf
EndFunc   ;==>GPT_Pressed

Func GPT_WriteIni()
    Local $s_IniFile = WinNTSetup_GetPath() & "WinNTSetup.ini"

    IniWrite($s_IniFile, "WinNT6", "BootDest", $s_BootDrive & ":")
    IniWrite($s_IniFile, "WinNT6", "TempDest", $s_MainDrive & ":")
    IniWrite($s_IniFile, "WinNT5", "BootDest", $s_BootDrive & ":")
    IniWrite($s_IniFile, "WinNT5", "TempDest", $s_MainDrive & ":")
EndFunc   ;==>GPT_WriteIni

Func GPT_Prepare($s_DiskNumber)
    GetDriveLetters()
    DiskPart_CreateScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $s_DiskNumber & @CRLF & 'clean' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'scrub.dat', 'Sel Dis ' & $s_DiskNumber & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=GPTscrubber' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $s_DiskNumber & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $s_DiskNumber & @CRLF & 'convert gpt' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'formatsystem.dat', 'Sel Dis ' & $s_DiskNumber & @CRLF & 'cre par efi size=100' & @CRLF & 'format quick fs=fat32 label=System' & @CRLF & 'assign letter=' & $s_BootDrive & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'createmsr.dat', 'Sel Dis ' & $s_DiskNumber & @CRLF & 'cre par msr size=16' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'formatmain.dat', 'Sel Dis ' & $s_DiskNumber & @CRLF & 'cre par pri' & @CRLF & 'shrink minimum=450' & @CRLF & 'format quick fs=ntfs label=Windows' & @CRLF & 'assign letter=' & $s_MainDrive & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'formatwinre.dat', 'Sel Dis ' & $s_DiskNumber & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=ntfs label=WinRE' & @CRLF & 'set id=de94bba4-06d1-4d40-a16a-bfd50179d6ac' & @CRLF & 'Exit')
EndFunc   ;==>GPT_Prepare

Func GUI_Create()
    GUICreate('Prep/Format Disk v2.0', 300, 289)
    GUISetOnEvent($GUI_EVENT_CLOSE, "GUI_Close")

    GUISetIcon(@WorkingDir & '\PrepareDiskNT.ico', 1)
    GUISetBkColor(0x898989)

    GUICtrlCreateLabel('1: Select a disk to prepare for WinNTSetup', 20, 10, 280)

    $c_DiskList = GUICtrlCreateTreeView(10, 30, 280, 150)
    DiskList_Load()

    GUICtrlCreateButton('Refresh List', 110, 185, 80, 25)
    GUICtrlSetOnEvent(-1, "DiskList_Load")
    GUICtrlSetState(-1, $GUI_FOCUS)

    GUICtrlCreateLabel('2: Select your desired layout...', 20, 214, 280, 30)
    $c_MBR_btn = GUICtrlCreateButton('MBR (BIOS) Boot', 20, 234, 120, 40)
    GUICtrlSetOnEvent(-1, "MBR_Pressed")
    GUICtrlSetState(-1, $GUI_DISABLE)

    $c_GPT_btn = GUICtrlCreateButton('GPT (UEFI) Boot', 160, 234, 120, 40)
    GUICtrlSetOnEvent(-1, "GPT_Pressed")
    GUICtrlSetState(-1, $GUI_DISABLE)

    GUISetState()

    ; Just idle around
    While 1
        Sleep(10)
    WEnd
EndFunc   ;==>GUI_Create

Func GUI_Close()
    Cleanup()
EndFunc   ;==>GUI_Close

Func MBR_Format()
    GUISetState(@SW_HIDE)

    Local $as_DiskPart[7][2] = [ _
            [6, 0], _
            ["Cleaning Drive", 'clean.dat'], _
            ["Cleaning Drive", 'scrub.dat'], _
            ["Cleaning Drive", 'clean.dat'], _
            ["Resetting Disk Attributes", 'attrib.dat'], _
            ["Converting Layout to MBR", 'convert.dat'], _
            ["Creating Windows Partition", 'formatmain.dat'] _
            ]

    ProgressOn("Formatting MBR (BIOS)...", "Preparing Disk: ", "0%")

    For $i = 1 To $as_DiskPart[0][0]
        ProgressSet($i * 17 & "%", $as_DiskPart[$i][0])
        RunWait(@ComSpec & ' /c diskpart /s ' & '"' & GetCachePath() & $as_DiskPart[$i][1] & '"', @WorkingDir, @SW_HIDE)
        Sleep(750)
    Next

    ProgressSet(100, "Finished", "Format Completed")
    Sleep(1500)
    ProgressOff()
    GUISetState()
EndFunc   ;==>MBR_Format

Func MBR_Prepare($s_Drive)
    GetDriveLetters()
    DiskPart_CreateScriptFile(GetCachePath() & 'clean.dat', 'Sel Dis ' & $s_Drive & @CRLF & 'clean' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'scrub.dat', 'Sel Dis ' & $s_Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=MBRscrubber' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'attrib.dat', 'Sel Dis ' & $s_Drive & @CRLF & 'attribute disk clear readonly' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'convert.dat', 'Sel Dis ' & $s_Drive & @CRLF & 'convert mbr' & @CRLF & 'Exit')
    DiskPart_CreateScriptFile(GetCachePath() & 'formatmain.dat', 'Sel Dis ' & $s_Drive & @CRLF & 'cre par pri' & @CRLF & 'format quick fs=NTFS label=Windows' & @CRLF & 'Active' & @CRLF & 'Assign letter=' & $s_BootDrive & @CRLF & 'Exit')
EndFunc   ;==>MBR_Prepare

Func MBR_Pressed()
    Local $s_DiskNumber = StringRegExp(GUICtrlRead($c_DiskList, $GUI_READ_EXTENDED), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)
    If $s_DiskNumber = "" Then
        MsgBox( _
                $MB_ICONERROR, _ ; it is possible to bug the GUI and make the buttons appear by pressing + or - on tree then refresh
                "Attention: ", _
                "No disk is selected!")
        Buttons_Disable()
    Else

        $s_DiskNumber = StringRegExp(GUICtrlRead($c_DiskList, $GUI_READ_EXTENDED), '(?<=Disk\s)[0-9]+', $STR_REGEXPARRAYMATCH)[0]

        If @error Then
            MsgBox( _
                    $MB_ICONERROR, _
                    "Attention: ", _
                    "An error occured retrieving the disk number")
        Else
            If MsgBox( _
                    BitOR($MB_TOPMOST, $MB_ICONWARNING, $MB_YESNO, $MB_DEFBUTTON2), _
                    'This will FORMAT Disk ' & $s_DiskNumber, _
                    'ALL DATA WILL BE ERASED FROM DISK ' & $s_DiskNumber & @CRLF & 'Are you sure you want to proceed?') = $IDYES Then
                MBR_Prepare($s_DiskNumber)
                MBR_Format()
                MBR_WriteIni()
                MsgBox($MB_ICONINFORMATION, "Redirecting... ", " - WinNTSetup will now open - " & @CRLF & @CRLF & 'Boot Drive: ' & $s_BootDrive & @CRLF & 'Install Drive: ' & $s_BootDrive)
                WinNTSetup_Launch()
                Cleanup()
            EndIf
        EndIf

    EndIf
EndFunc   ;==>MBR_Pressed

Func MBR_WriteIni()
    Local $s_IniFile = WinNTSetup_GetPath() & "WinNTSetup.ini"
    IniWrite($s_IniFile, "WinNT6", "BootDest", $s_BootDrive & ":")
    IniWrite($s_IniFile, "WinNT6", "TempDest", $s_BootDrive & ":")
    IniWrite($s_IniFile, "WinNT5", "BootDest", $s_BootDrive & ":")
    IniWrite($s_IniFile, "WinNT5", "TempDest", $s_BootDrive & ":")
EndFunc   ;==>MBR_WriteIni

Func WinNTSetup_GetPath()
    Local Static $s_WinNTSetupPath = IniRead(@WorkingDir & '\PrepareDiskNT.ini', "Settings", "WinNTSetupPath", @WorkingDir) & '\'
    If $s_WinNTSetupPath = '\' Then $s_WinNTSetupPath = ''
    Return $s_WinNTSetupPath
EndFunc   ;==>WinNTSetup_GetPath

Func WinNTSetup_Launch()
    Run(@ComSpec & ' /c ""' & WinNTSetup_GetPath() & 'WinNTSetup_x64.exe""', @WorkingDir, @SW_HIDE)
EndFunc   ;==>WinNTSetup_Launch

PrepareDiskNT.ini (PrepareDiskNT.exe can be used in the same folder as WinNTSetup.exe, If PrepareDiskNT.ini exists, it can be used to set the relative path to WinNTSetup.exe)

[Settings]
WinNTSetupPath=

Screenshot 2021-12-17 234520.png

Edited by bobomb

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...