wtarkan

Change Status of a Disk to Offline or Online Without Diskpart

9 posts in this topic

Hi , I Need to Change the Status of a Disk to Offline or Online Without Diskpart

I have tried all possibilities but no success , Finally find a C++ code but not sure if it is possible to convert it Autoit format , Or maybe somenone can help me to do it with autoit 

Here is the code 

BOOL disk_offline(HANDLE h_file, bool enable){
DWORD bytes_returned = 0;
BOOL b_offline = 0;
if(get_size_volume_disk(h_file)){
    SET_DISK_ATTRIBUTES disk_attr;
    ZeroMemory(&disk_attr, sizeof(disk_attr));
    disk_attr.Version = sizeof(SET_DISK_ATTRIBUTES);
    disk_attr.Attributes = enable? DISK_ATTRIBUTE_OFFLINE: 0;
    disk_attr.AttributesMask = DISK_ATTRIBUTE_OFFLINE;
    b_offline = DeviceIoControl(h_file, IOCTL_DISK_SET_DISK_ATTRIBUTES, &disk_attr, disk_attr.Version, NULL, 0, &bytes_returned, NULL);
    // Invalidates the cached partition table and re-enumerates the device.
    if(!enable) BOOL b_update = DeviceIoControl(h_file, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &bytes_returned, NULL);
}
return b_offline;
}

Source

http://tiku.io/questions/502405/take-disks-online-offline

Share this post


Link to post
Share on other sites



Use _WinAPI_DeviceIoControl

 

Saludos

Share this post


Link to post
Share on other sites
#RequireAdmin
Opt("MustDeclareVars", 1)

MsgBox(64, "", _SET_DISK_ONLINE("\\.\PHYSICALDRIVE1"))

Func _SET_DISK_ONLINE($SourceDisk)
    ;Writede By BlueLife
    Local Const $OPEN_EXISTING = 3
    Local Const $GENERIC_WRITE = 0x40000000
    Local Const $GENERIC_READ = 0x80000000

    Local Const $FILE_SHARE_READ = 0x00000001
    Local Const $FILE_SHARE_WRITE = 0x00000002
    Local Const $FILE_ATTRIBUTE_NORMAL = 0x00000080

    Local Const $IOCTL_DISK_GET_DISK_ATTRIBUTES = 0x000700f0
    Local Const $IOCTL_DISK_SET_DISK_ATTRIBUTES = 0x0007c0f4
    Local Const $IOCTL_DISK_UPDATE_PROPERTIES = 459072

    ;https://msdn.microsoft.com/en-us/library/windows/desktop/hh706680%28v=vs.85%29.aspx
    Local $tag_GET_DISK_ATTRIBUTES = 'DWORD Version;int64 Reserved1;DWORD Attributes;'

    ;Error !!!!!!!!!!!!
    ;https://msdn.microsoft.com/en-us/library/windows/desktop/hh706683%28v=vs.85%29.aspx
    Local $tag_SET_DISK_ATTRIBUTES = DllStructCreate('DWORD Version;BOOLEAN Persist;BOOLEAN RelinquishOwnership;int64 Reserved1[2];INT64 Attributes; INT64 AttributesMask;DWORD Owner;')

    Local $hFile = _WinAPI_CreateFileEx($SourceDisk, $OPEN_EXISTING, BitOR($GENERIC_READ, $GENERIC_WRITE), BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE), $FILE_ATTRIBUTE_NORMAL)
    If $hFile = 0 Then Return SetError(1, 0, 0)

    Local $tStrunct = DllStructCreate($tag_GET_DISK_ATTRIBUTES)
    DllStructSetData($tStrunct, 'Attributes', 1)
    DllStructSetData($tStrunct, 'Version', DllStructGetSize($tStrunct))

    Local $Error = 0
    ;https://msdn.microsoft.com/en-us/library/windows/desktop/hh706681%28v=vs.85%29.aspx
    If _WinAPI_DeviceIoControl($hFile, $IOCTL_DISK_GET_DISK_ATTRIBUTES, 0, 0, DllStructGetPtr($tStrunct), DllStructGetSize($tStrunct)) = 1 Then
        If BitAND(DllStructGetData($tStrunct, 2), 1) = 1 Then ;Offline
            MsgBox(64, "Info:", $SourceDisk & " Ofline Disk")

            ;!!!!!!!!!!!! Error !!!!!!!!!!!!
            Local $tStrunct = DllStructCreate($tag_SET_DISK_ATTRIBUTES) ;
            DllStructSetData($tStrunct, 'Attributes', 0) ;
            DllStructSetData($tStrunct, 'AttributesMask', 0)
            DllStructSetData($tStrunct, 'Version', DllStructGetSize($tStrunct))

            ;https://msdn.microsoft.com/en-us/library/windows/desktop/hh706682%28v=vs.85%29.aspx
            If _WinAPI_DeviceIoControl($hFile, $IOCTL_DISK_SET_DISK_ATTRIBUTES, 0, 0, DllStructGetPtr($tStrunct), DllStructGetSize($tStrunct)) = 1 Then
                _WinAPI_DeviceIoControl($hFile, $IOCTL_DISK_UPDATE_PROPERTIES)
            Else
                $Error = 2
            EndIf
        EndIf
    Else
        $Error = 1
    EndIf
    If $hFile Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hFile)
    Return SetError($Error, 0, $Error = 0)
EndFunc   ;==>_SET_DISK_ONLINE

Func _WinAPI_DeviceIoControl($hDevice, $iControlCode, $pInBuffer = 0, $iInBufferSize = 0, $pOutBuffer = 0, $iOutBufferSize = 0)
    Local $Ret = DllCall("kernel32.dll", 'int', 'DeviceIoControl', 'ptr', $hDevice, 'dword', $iControlCode, 'ptr', $pInBuffer, 'dword', $iInBufferSize, 'ptr', $pOutBuffer, 'dword', $iOutBufferSize, 'dword*', 0, 'ptr', 0)
    If (@error) Or (Not $Ret[0]) Then Return SetError(1, 0, 0)
    Return SetError(0, $Ret[7], 1)
EndFunc   ;==>_WinAPI_DeviceIoControl

Func _WinAPI_CreateFileEx($sFile, $iCreation, $iAccess = 0, $iShare = 0, $iFlagsAndAttributes = 0, $tSecurity = 0, $hTemplate = 0)
    Local $Ret = DllCall("kernel32.dll", 'ptr', 'CreateFileW', 'wstr', $sFile, 'dword', $iAccess, 'dword', $iShare, 'ptr', DllStructGetPtr($tSecurity), 'dword', $iCreation, 'dword', $iFlagsAndAttributes, 'ptr', $hTemplate)

    If (@error) Or ($Ret[0] = Ptr(-1)) Then
        Return SetError(1, 0, 0)
    EndIf
    Return $Ret[0]
EndFunc   ;==>_WinAPI_CreateFileEx

I have tried something but the "$IOCTL_DISK_SET_DISK_ATTRIBUTES " part is problematic , I hope some experienced forum members can help to fix it.

Good luck...

Share this post


Link to post
Share on other sites

As far I see your Structure is wrong.

Should be.

 

Global Const $sTag_SET_DISK_ATTRIBUTES = 'DWORD Version;BOOLEAN Persist;BOOLEAN Reserved1[3];INT64 Attributes;INT64 AttributesMask;DWORD Reserved2[4];'

Saludos

Share this post


Link to post
Share on other sites

Thank you but I have already tried it

disk 1 was Offline

The code give me \\.\PHYSICALDRIVE1 Offline message 
but It can not be capable  to make the Disk Online

I could not find the error , Thank you

Share this post


Link to post
Share on other sites

Does diskpart work?

(I have just one disk I can't try your example...)

Saludos

Share this post


Link to post
Share on other sites

yes , diskpart work but I don't want to use it , the Above codes identify the disk status as Offline but can not change it to online and that is exactly my problem

Thanks

Share this post


Link to post
Share on other sites

You were using DeviceIoControl Wrong. I wrote my own...

 

#include <WinAPIFiles.au3>
#include <WinAPI.au3>

#RequireAdmin

Global Const $DISK_ATTRIBUTE_OFFLINE = 0x0000000000000001
Global Const $IOCTL_DISK_SET_DISK_ATTRIBUTES = 0x0007c0f4
Global Const $sTag_SET_DISK_ATTRIBUTES = 'DWORD Version;BOOLEAN Persist;BOOLEAN Reserved1[3];INT64 Attributes;INT64 AttributesMask;DWORD Reserved2[4];'


_SetDiskoffline("\\.\PHYSICALDRIVE1")

Func _SetDiskoffline($sSourceDisk, $bEnable = True);true=set offilne (defalut)  ;false set online

    Local $hFile = _WinAPI_CreateFileEx($sSourceDisk, $OPEN_EXISTING, BitOR($GENERIC_READ, $GENERIC_WRITE), BitOR($FILE_SHARE_READ, $FILE_SHARE_WRITE), 0)
    If @error Then Return
    ConsoleWrite($hFile & @CRLF)
    Local $tSetAttributes = DllStructCreate($sTag_SET_DISK_ATTRIBUTES)
    $tSetAttributes.Version = DllStructGetSize($tSetAttributes)
    $tSetAttributes.Attributes = $bEnable
    $tSetAttributes.AttributesMask = $DISK_ATTRIBUTE_OFFLINE

    If _WinAPI_DeviceIoControl($hFile, $IOCTL_DISK_SET_DISK_ATTRIBUTES, DllStructGetPtr($tSetAttributes), DllStructGetSize($tSetAttributes)) Then
        Return _WinAPI_DeviceIoControl($hFile, $IOCTL_DISK_UPDATE_PROPERTIES)
    Else
        Return False
    EndIf

EndFunc   ;==>_SetDiskoffline

Saludos

Share this post


Link to post
Share on other sites

Ah , thank you very much , Problem solved :)

Share this post


Link to post
Share on other sites

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