Jump to content

Weird problem when $DBT_DEVICECOMPLETEREMOVAL is triggered?


 Share

Recommended Posts

I am trying to make gui to automate saving selected files and folders from CD, but for some reason when CD is ejected, then button disappears from gui and treeview items dont get removed. I think that problem is with GuiRegisterMsg. Anyone can help me how to fix it?

#NoTrayIcon
#RequireAdmin
#include <GUIConstants.au3>
#include <GUIConstantsEx.au3>
#include <TreeViewConstants.au3>
#include <WindowsConstants.au3>
#Include <GuiTreeView.au3>
#Include <File.au3>
#include <WinAPIFiles.au3>
#include <WinAPI.au3>

Opt("WinWaitDelay", 0)
Opt("MouseClickDelay", 0)
Opt("MouseClickDownDelay", 0)
Opt("MouseClickDragDelay", 0)
Opt("SendKeyDelay", 0)
Opt("SendKeyDownDelay", 0)
Opt("WinTitleMatchMode", 3)
Opt('GUIOnEventMode', 1)
Opt('GUICloseOnEsc' , 1)

FileDelete (@ScriptDir & "\Unstoppable.ucb")
Global $CheckBoxCount = 0
Global $CheckedItems = ''
Global Const $DBT_DEVICEARRIVAL = 0x00008000
Global Const $DBT_DEVICECOMPLETEREMOVAL = 0x00008004
Global Const $DBT_DEVTYP_VOLUME = 0x00000002

Global $hGUI = GUICreate("Waiting for disc...", 530, 400, -1, -1)
Global $hTreeView = _GUICtrlTreeView_Create($hGUI, 0, 0, 530, 370, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_CHECKBOXES))
Global $recover = GUICtrlCreateButton("Recover", 0, 370, 80, 30, $SS_Center)
GUISetBkColor(0xCECECE)
GUICtrlSetOnEvent($recover, '_Recover')
GUISetOnEvent($GUI_EVENT_CLOSE, '_AllExit')
$hImage = _GUIImageList_Create(16, 16, 5, 2)
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 4)
_GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", 54)
_GUICtrlTreeView_SetNormalImageList($hTreeView, $hImage)
GUIRegisterMsg($WM_DEVICECHANGE, "DeviceChange")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState(@SW_SHOW, $hGUI)

$Temp = DriveGetDrive("CDROM")
If IsArray($Temp) Then
   For $j = 1 to $Temp[0]
      If DriveStatus($Temp[$j]) = 'READY' Then
         $hItem = _GUICtrlTreeView_AddChild($hTreeView, '', StringUpper($Temp[$j]), 0)
         _GUICtrlTreeView_SetChildren($hTreeView, $hItem, True)
         WinSetTitle($hGUI, WinGetTitle($hGUI), 'Select files and folders to recover:')
      EndIf
   Next
EndIf

While 1
   Sleep(1000)
WEnd

Func _AllExit()
   GUIDelete($hGUI)
   Exit
EndFunc

Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
   #forceref $hWnd, $iMsg, $wParam
   Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR
   $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
   $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
   $iCode = DllStructGetData($tNMHDR, "Code")
   Switch $hWndFrom
   Case $hTreeView
      Switch $iCode
      Case $NM_CLICK
         $aPos = GUIGetCursorInfo($hGUI)
         $ObjectClicked = _GUICtrlTreeView_HitTest($hTreeView, $aPos[0], $aPos[1])
         $cItem = _GUICtrlTreeView_HitTestItem($hTreeView, $aPos[0], $aPos[1])
         If $ObjectClicked = '16' Then
            If _GUICtrlTreeView_GetExpanded($hTreeView, $cItem) = True Then
               ControlTreeView($hGUI, "", $hTreeView, "Collapse", $cItem)
            Else
               $sSelectedPath = StringReplace(_GUICtrlTreeView_GetTree($hTreeView, $cItem), "|", "\")
               If _GUICtrlTreeView_GetChildCount($hTreeView, $cItem) <= 0 Then
                  _SearchFolder($cItem, $sSelectedPath)
               EndIf
            EndIf
         ElseIf $ObjectClicked = '64' Then
            If _GUICtrlTreeView_GetChecked($hTreeView, $cItem) = False Then
               ; checked
               $CheckBoxCount = $CheckBoxCount + 1
               $sSelectedPath = StringReplace(_GUICtrlTreeView_GetTree($hTreeView, $cItem), "|", "\")
               If not StringInStr($sSelectedPath, '\') Then $sSelectedPath = $sSelectedPath & '\'
               $CheckedItems = $CheckedItems & $sSelectedPath & @CRLF
            Else
               ; unchecked
               $CheckBoxCount = $CheckBoxCount - 1
               $sSelectedPath = StringReplace(_GUICtrlTreeView_GetTree($hTreeView, $cItem), "|", "\")
               If not StringInStr($sSelectedPath, '\') Then $sSelectedPath = $sSelectedPath & '\'
               $CheckedItems = StringReplace($CheckedItems, $sSelectedPath & @CRLF, '')
            EndIf
         EndIf
      Case $NM_DBLCLK
         $aPos = GUIGetCursorInfo($hGUI)
         $ObjectClicked = _GUICtrlTreeView_HitTest($hTreeView, $aPos[0], $aPos[1])
         $cItem = _GUICtrlTreeView_HitTestItem($hTreeView, $aPos[0], $aPos[1])
         If $ObjectClicked = '2' or $ObjectClicked = '4' Then
            If _GUICtrlTreeView_GetExpanded($hTreeView, $cItem) = True Then
               ControlTreeView($hGUI, "", $hTreeView, "Collapse", $cItem)
            Else
               $sSelectedPath = StringReplace(_GUICtrlTreeView_GetTree($hTreeView, $cItem), "|", "\")
               If _GUICtrlTreeView_GetChildCount($hTreeView, $cItem) <= 0 Then
                  _SearchFolder($cItem, $sSelectedPath)
               EndIf
            EndIf
         EndIf
      Case $TVN_SELCHANGINGA, $TVN_SELCHANGINGW
         Return 1
      Case $NM_SETFOCUS
         Return 1
      EndSwitch
   EndSwitch
   Return $GUI_RUNDEFMSG
EndFunc

Func _SearchFolder($cParent, $sPath)
   $aFolderList = _FileListToArray($sPath, "*", $FLTA_FOLDERS)
   If IsArray($aFolderList) Then
      For $i = 1 To $aFolderList[0]
         $hItem = _GUICtrlTreeView_AddChild($hTreeView, $cParent, $aFolderList[$i], 0)
         _GUICtrlTreeView_SetChildren($hTreeView, $hItem, True)
      Next
   EndIf
   $aFileList = _FileListToArray($sPath, "*", $FLTA_FILES)
   If IsArray($aFileList) Then
      For $i = 1 To $aFileList[0]
         _GUICtrlTreeView_AddChild($hTreeView, $cParent, $aFileList[$i], 1, 1)
      Next
   EndIf
   If _GUICtrlTreeView_GetChildCount($hTreeView, $cParent) <= 0 Then
      _GUICtrlTreeView_SetChildren($hTreeView, $cParent, False)
   EndIf
EndFunc

Func DeviceChange($hWndGUI, $msg, $wParam, $lParam)
   Local $DriveLetter
   Local Const $DeviceType = GetDeviceType($lParam)
   If $DeviceType = $DBT_DEVTYP_VOLUME Then
      Local Const $UnitMask = GetUnitMask($lParam)
      $DriveLetter = GetDriveLetterFromUnitMask($UnitMask) & ":"
   EndIf
   Switch $wParam
   Case $DBT_DEVICECOMPLETEREMOVAL
      If DriveGetType($DriveLetter) = "CDROM" Then
         $hItem = _GUICtrlTreeView_FindItem($hTreeView, $DriveLetter)
         If $hItem <> '0' Then _GUICtrlTreeView_Delete($hTreeView, $hItem)
         $Temp = DriveGetDrive("CDROM")
         If IsArray($Temp) Then
            $ready = 'no'
            For $j = 1 to $Temp[0]
               If DriveStatus($Temp[$j]) = 'READY' Then
                  $ready = 'yes'
                  ExitLoop
               EndIf
            Next
         EndIf
         If $ready = 'yes' Then
            $RecoverList = StringSplit($CheckedItems, @LF)
            If IsArray($RecoverList) Then
               For $i = 1 to $RecoverList[0] - 1
                  If StringInStr($RecoverList[$i], $DriveLetter & '\') Then
                     $CheckBoxCount = $CheckBoxCount - 1
                     $CheckedItems = StringReplace($CheckedItems, $RecoverList[$i] & @LF, '')
                  EndIf
               Next
            EndIf
         Else
            $CheckBoxCount = 0
            $CheckedItems = ''
            WinSetTitle($hGUI, WinGetTitle($hGUI), 'Waiting for disc...')
         EndIf
      EndIf
   Case $DBT_DEVICEARRIVAL
      If DriveGetType($DriveLetter) = "CDROM" Then
         $hItem = _GUICtrlTreeView_FindItem($hTreeView, $DriveLetter)
         If $hItem <> '0' Then _GUICtrlTreeView_Delete($hTreeView, $hItem)
         $hItem = _GUICtrlTreeView_AddChild($hTreeView, '', $DriveLetter, 0)
         _GUICtrlTreeView_SetChildren($hTreeView, $hItem, True)
         WinSetTitle($hGUI, WinGetTitle($hGUI), 'Select files and folders to recover:')
      EndIf
   EndSwitch
   Return
EndFunc;==DeviceChange

Func GetUnitMask($lParam)
   ; Create a struct from $lParam which contains a pointer to a Windows-created struct.
   Local Const $tagDEV_BROADCAST_VOLUME = "dword dbcv_size; dword dbcv_devicetype; dword dbcv_reserved; dword dbcv_unitmask; word dbcv_flags"
   Local Const $DEV_BROADCAST_VOLUME = DllStructCreate($tagDEV_BROADCAST_VOLUME, $lParam)
   Local Const $UnitMask = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcv_unitmask")
   Return $UnitMask
EndFunc ;==>GetUnitMask

Func GetDeviceType($lParam)
   ; Create a struct from $lParam which contains a pointer to a Windows-created struct.
   Local Const $tagDEV_BROADCAST_VOLUME = "dword dbcv_size; dword dbcv_devicetype; dword dbcv_reserved; dword dbcv_unitmask; word dbcv_flags"
   Local Const $DEV_BROADCAST_VOLUME = DllStructCreate($tagDEV_BROADCAST_VOLUME, $lParam)
   Local Const $DeviceType = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcv_devicetype")
   Return $DeviceType
EndFunc ;==>GetDeviceType

Func GetDriveLetterFromUnitMask($UnitMask)
   Local Const $Drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   Local $Count = 0
   Local $Pom = $UnitMask
   While $Pom <> 0
      $Pom = BitShift($Pom, 1)
      $Count += 1
   WEnd
   If $Count >= 1 And $Count <= 26 Then
      Return StringMid($Drives, $Count, 1)
   Else
      Return SetError(1, 0, '?')
   EndIf
EndFunc ;==>GetDriveLetterFromUnitMask

Func _Recover()
   Local $sRetFolder, $sRetFile, $path, $sDrive, $sDir, $sFolderName, $sExtension, $CDROM
   If $CheckBoxCount = '0' Then
      MsgBox(0, '', 'You have to check at least 1 file or folder before clicking Recover.')
      Return
   Else
      Local $ProgressGui = GUICreate('', 220, 39, (@DesktopWidth-220)/2-35, 0, $WS_CAPTION)
      Local $CurrentActivity = GUICtrlCreateLabel('', 3, 1, 213, 35, $SS_CENTER)
      GUICtrlSetFont($CurrentActivity, 11, 0, 0, "Verdana")
      GUISetState(@SW_HIDE, $hGUI)
      GUISetState(@SW_SHOW, $ProgressGui)
      GUICtrlSetData($CurrentActivity, "Recovering files and folders...")
      $sRetFile = ''
      $sRetFolder = ''
      $RecoverList = StringSplit($CheckedItems, @LF)
      _PathSplit(StringStripCR($RecoverList[1]), $sDrive, $sDir, $sFolderName, $sExtension)
      $CDROM = $sDrive
      For $i = 1 to $RecoverList[0] - 1
         $path = StringStripCR($RecoverList[$i])
         If StringInStr(FileGetAttrib($path), "D") = 0 Then
            ; File
            $sRetFile = $sRetFile & $path & '|' & @DesktopDir & '\Recovered' & @CRLF
         Else
            ; Folder
            _PathSplit($path, $sDrive, $sDir, $sFolderName, $sExtension)
            $sRetFolder = $sRetFolder & $path & '|' & @DesktopDir & '\Recovered\' & $sFolderName & $sExtension & @CRLF
         EndIf
      Next
      FileOpen(@ScriptDir & "\Unstoppable.ucb", $FO_UTF8 + $FO_APPEND)
      FileWrite(@ScriptDir & "\Unstoppable.ucb", @CRLF)
      FileWrite(@ScriptDir & "\Unstoppable.ucb", $sRetFolder)
      FileWrite(@ScriptDir & "\Unstoppable.ucb", $sRetFile)
      RegDelete('HKCU\Software\Roadkil')
      RegWrite('HKCU\Software\Roadkil', 'Lic_Unstp','REG_BINARY', Binary('0x31'))
      RegWrite('HKCU\Software\Roadkil', 'Settings_Unstp', 'REG_BINARY', Binary('0x0f27050000000000'))
      RunWait(@ScriptDir & '\UnstoppableCopier.exe' & ' +urateiwfz "' & @ScriptDir & '\Unstoppable.ucb' & '"')
      GUICtrlSetData($CurrentActivity, "Recovering finished. Ejecting disc...")
      FileDelete (@ScriptDir & "\Unstoppable.ucb")
      $hItem = _GUICtrlTreeView_FindItem($hTreeView, $CDROM)
      _GUICtrlTreeView_Delete($hTreeView, $hItem)
      WinSetTitle($hGUI, WinGetTitle($hGUI), 'Waiting for disc...')
      $CheckBoxCount = 0
      $CheckedItems = ''
      $hVolume = _WinAPI_CreateFile('\\.\' & $CDROM, 2, 2, 6)
      _WinAPI_DeviceIoControl($hVolume, $FSCTL_DISMOUNT_VOLUME)
      _WinAPI_DeviceIoControl($hVolume, $IOCTL_STORAGE_EJECT_MEDIA)
      _WinAPI_CloseHandle($hVolume)
      GUISetState(@SW_HIDE, $ProgressGui)
      GUISetState(@SW_SHOW, $hGUI)
      GUIDelete($ProgressGui)
      Return
   EndIf
EndFunc

 

Edited by Nikolas92
Link to comment
Share on other sites

Well i dont have a cdrom so i had to test with

DriveGetDrive("FIXED")

but its really an external hd, and after i eject it, the only thing that happens is the tree no longer can go recursive/show more files or folders (for this Hdd but for the others works as normal)

Button stays there anyway. As i couldn't reproduce the problem, im not going to be of much help.

Edited by careca
Spoiler

Renamer - Rename files and folders, remove portions of text from the filename etc.

GPO Tool - Export/Import Group policy settings.

MirrorDir - Synchronize/Backup/Mirror Folders

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

String Trigger - Triggers pasting text or applications or internet links on specific strings.

Inconspicuous - Hide files in plain sight, not fully encrypted.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

IUIAutomation - Topic with framework and examples

Au3Record.exe

Link to comment
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
 Share

  • Recently Browsing   0 members

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