Jump to content



Photo

USB drive Monitor Example


  • Please log in to reply
42 replies to this topic

#1 ptrex

ptrex

    Universalist

  • MVPs
  • 2,399 posts

Posted 13 March 2007 - 08:51 AM

USB Monitor - using WMI Event notification

Some one in the Support Section asked if it was possible to have a notification if a USB drive was Connected / Disconnected.

Well here is an example using the WMI Event notification :

$strComputer = "." $objWMIService = ObjGet("winmgmts:" & $strComputer & "rootcimv2") $colEvents = $objWMIService.ExecNotificationQuery _ ("Select * From __InstanceOperationEvent Within 5 Where " _ & "TargetInstance isa 'Win32_LogicalDisk'") While 1 $objEvent = $colEvents.NextEvent If $objEvent.TargetInstance.DriveType = 2 Then Select Case $objEvent.Path_.Class()="__InstanceCreationEvent" Consolewrite("Drive " & $objEvent.TargetInstance.DeviceId & "has been added." & @CR) Case $objEvent.Path_.Class()="__InstanceDeletionEvent" Consolewrite("Drive " & $objEvent.TargetInstance.DeviceId & "has been removed."& @CR) EndSelect EndIf WEnd


Enjoy !!

ptrex

Edited by ptrex, 14 September 2012 - 09:13 AM.








#2 Irongeek

Irongeek

    Seeker

  • Active Members
  • 35 posts

Posted 15 March 2007 - 02:18 PM

I just wanted to say thanks. This will really help me on one of my projects. I'll be sure to mention you in the credits.

#3 ptrex

ptrex

    Universalist

  • MVPs
  • 2,399 posts

Posted 15 March 2007 - 02:34 PM

@Irongeek

Thanks

You are welcome :whistle:

If it is an interesting project you can share it with rest of us.

regards

ptrex

#4 Irongeek

Irongeek

    Seeker

  • Active Members
  • 35 posts

Posted 15 March 2007 - 02:41 PM

I plan to. All the stuff I've done from my site in Autoit I've put the source code out for.

#5 sshrum

sshrum

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 538 posts

Posted 09 April 2007 - 09:24 PM

I think I like your way...I've been doing mine like this: run through all the drive letters and check for changes in drivestatus...just make sure to skip floppy drives :-)

for $i = 1 to 25     $aDriveStatus[$i] = DriveStatus(chr($i+65) & ":\") Next while 1     for $i = 1 to 25         $sDriveStatus = DriveStatus(chr($i+65) & ":\")         if $aDriveStatus[$i] <> $sDriveStatus then             $aDriveStatus[$i] = $sDriveStatus             if $sDriveStatus = "READY" Then             ;CODE TO RUN             EndIf         EndIf     Next WEnd


I'll give yours a try tonight

Edited by sshrum, 09 April 2007 - 09:24 PM.

Sean Shrum :: Shrum Consultingsean[at]shrum[dot]net :: http://www.shrum.net---------------Skinner: 'Oh, brandishing your buttocks is only making me angrier!'Me: 'Make it idiot-proof, and someone will make a better idiot'Me (sort of): 'Give a man a fish and you feed him for a day. Teach a man to fish and he'll snag some part of his body with a rusty hook, get tetanus, and surely die'---------------All my published AU3-based apps and utilities

#6 alwaysZeroHour

alwaysZeroHour

    Seeker

  • Active Members
  • 8 posts

Posted 25 June 2007 - 08:46 AM

Hey,
It seems to work well but its grinding my floppy drive all the time.
Any ideas for a fix?

Cheers
Z Posted Image

#7 arcker

arcker

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 556 posts

Posted 25 June 2007 - 10:15 AM

it's because the current query ask for all the drives
so if you want to just monitor the removable drive, try this

$strComputer = "."  $objWMIService = ObjGet("winmÛ]ΉˆÌLŽÉˆÌLŽÉœ][ÝÈ ˜[È  ˆÌ ͎ÜݐÛÛ]ˆ   ˜[È  œ][ÝɈÌLŽÜ›ÛÝ   ˆÌLŽ6–×c"gV÷C² ¢b33c¶6öÄWfVçG2Òb33c¶ö&¥tԕ6W'f–6RäW†V4æ÷F–f–6F–öåVW'’(€€€€ ™ÅÕ½ÐíM•±•Ð€¨ɽ´}}%¹Íх¹•=Á•É…Ñ¥½¹ٕ¹Ð]¥Ñ¡¥¸€Ô]¡•É”€™ÅÕ½Ðì|(       & "TargetInstance isa 'Win32_LogicalDisk' and &quotÈȈ ˜[È  œ][ÝÕ™Ù][œÝ[˜ÙK‘š]™UHH ‰œ][ÝÈ B‚•Ú[H Bˆb33c¶ö&¤WfVçBÒb33c¶6öÄWfVçG2äæW‡DWfVç@¢–bb33c¶ö&¤WfVçBåF&vWD–Íх¹”¹ɥٕQåÁ”€ô€ÈQ¡•¸€(€€€€€€€M•±•Ð€(€€€€€€€€€€€ …Í”€˜ŒÀÌØí½‰©ٕ¹Ð¹ath_.Class()="__InstanceCreationEvent"                 ConsolewriJ    œ][ÝÑš]™H    œ][ÝÈ   ˜[È  ˆÌ ÍŽÛØš‘]™[ •™Ù][œÝ[˜ÙK‘]šXÙRY   ˜[È  œ]÷C¶†2&VVâFFVBâgV÷C²fײ5"¢66Rb33c¶ö&¤WfVçBåF…òä6…ÍÌ ¤ô™ÅÕ½Ðí}}%¹Íх¹••±•Ñ¥½¹ٕ¹Ð™ÅÕ½Ðì(€€€€€€€€€€€€€€€ ½¹Í½±•Ýɥє ™ÅÕ½;Drive " & $objEvent.TargetInstance.DeviceId & "has ™Y[ˆ™[[ݙY ‰œ][Ýɘ[ÈԊBˆ[™Ù[X݈[™Y‚•Ñ[™


the drivetype = 2 is the removable drive
for more information take a look at this :
http://msdn2.microsoft.com/en-us/library/aa394173.aspx
-- Arck System _ Soon --Ideas make everything"La critique est facile, l'art est difficile"Projects :Au3Service = Run your exe as service / Updated 27/05/2011 Get it Here

#8 Elkie

Elkie

    Seeker

  • Active Members
  • 47 posts

Posted 03 August 2007 - 07:12 AM

Thank you very much now i can implement this to secure my computer from unwanted UFD activity. I hope this will help, thanks again! :).
Say why is my floppy drive still grinding even using the latest script?

Edited by Elkie, 03 August 2007 - 07:53 AM.


#9 arcker

arcker

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 556 posts

Posted 03 August 2007 - 08:21 AM

simple : you ask the logical drive class, so it queries all the disk before filter it, wherever you place this filter, i think. your floppy is usb connected ?
-- Arck System _ Soon --Ideas make everything"La critique est facile, l'art est difficile"Projects :Au3Service = Run your exe as service / Updated 27/05/2011 Get it Here

#10 Elkie

Elkie

    Seeker

  • Active Members
  • 47 posts

Posted 03 August 2007 - 10:32 AM

simple : you ask the logical drive class, so it queries all the disk before filter it, wherever you place this filter, i think. your floppy is usb connected ?


Nope, that's the problem i use coventional floppy controller, but when i run the script it keep running the floppy drive every 5 sec

#11 UglyBob

UglyBob

    Seeker

  • Active Members
  • 26 posts

Posted 06 August 2007 - 03:57 PM

Nope, that's the problem i use coventional floppy controller, but when i run the script it keep running the floppy drive every 5 sec


cheers ptrex
I too had this problem with the script. However, I've found a fix.

Instead of the initial query searching within the 'Win32_LogicalDisk' WMI I've created a different query which checks 'Win32_PnPEntity'

$colEvents = $objWMIService.ExecNotificationQuery _
("Select * From __InstanceOperationEvent Within 5 Where " _
& "TargetInstance isa 'Win32_PnPEntity' and " _
& "(TargetInstance.Description = 'USB FloppyDisk Drive' or " _
& "TargetInstance.Description = 'CD-ROM Drive' or " _
& "TargetInstance.Description = 'Disk Drive')" )

You could also check for 'Generic Volume'. The description filters completely depend on what you wish to search on.

-----------------------

I've expanded on the original script to automatically disconnect the USB device if the logged on user is not a member of a particular Active Directory group.
This amalgamates this script and another script created by 'arcker':

http://www.autoitscript.com/forum/index.ph...=disconnect+USB

with some additional tweaking to suit my needs:

When the:

Case $objEvent.Path_.Class()="__InstanceCreationEvent"

occurs I then run :

$objWMIService.ExecQuery("Select * From Win32_LogicalDisk Where DriveType = 2" )

(this will of course still cause the Floppy disk to trigger, but this will only occur once. I was hopping to find a WMI query other than win32_logicaldisk that would give me the drive letter for the particular USB device, so far I can't find it).

a FOR...NEXT loops through the results and checks if the user is allowed to use the device.


So far, so good. I've tested quite a few USB drives and all have been detected and disconnected.

The reference material used to create the queries are:
Microsoft Script Guy: http://www.microsoft.com/technet/scriptcen...06/hey0213.mspx
WMI queries: http://msdn2.microsoft.com/en-us/library/aa394173.aspx

and, if you ever want to find out what the 'descriptions' are to other USB devices that are connected which the script misses you can use the Microsoft vb script: http://www.microsoft.com/technet/scriptcen...05/hey0315.mspx

If anyone is interested (once I've completed the script and improved my lousy coding :) ) I'll post the complete script.

Edited by UglyBob, 06 August 2007 - 03:58 PM.

"My God, you're looking hideously ugly today, Ugly Bob."

#12 arcker

arcker

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 556 posts

Posted 06 August 2007 - 09:19 PM

hehe excellent for a first try !
i don't understand understand pnpentity but i will take a look for sure !
i've provide a script that continuosly monitor the usb drive but... there is more simple
you can just :
- verify AD group membership
- unload possible connected key by my script provided (eject key)
- block by registry
- block by ntfs (calc or better, win32_logicalfilesetsecuritydescriptor)

please post your script either, it sounds really interesting.
-- Arck System _ Soon --Ideas make everything"La critique est facile, l'art est difficile"Projects :Au3Service = Run your exe as service / Updated 27/05/2011 Get it Here

#13 Elkie

Elkie

    Seeker

  • Active Members
  • 47 posts

Posted 07 August 2007 - 12:24 AM

Hmmh, interesting indeed, at first i thought i could use CMI_USBDisk or something for the WMI script but it's not working at all. I'll try it thanks,

#14 ptrex

ptrex

    Universalist

  • MVPs
  • 2,399 posts

Posted 07 August 2007 - 06:52 AM

@UglyBob

Good job !!

You did quit some investigation on this matter.

When you have some code running please post it in this thread, so others can benifit of it as well.

Good to see you get inspired by this !! :)

; <a href='http://www.microsoft.com/technet/scriptcenter/resources/qanda/mar05/hey0315.mspx' class='bbc_url' title='External link' rel='nofollow external'>http://www.microsoft.com/technet/scriptcenter/resources/qanda/mar05/hey0315.mspx</a> $strComputer = "." $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2") $colDevices = $objWMIService.ExecQuery ("Select * From Win32_USBControllerDevice") For $objDevice in $colDevices     $strDeviceName = $objDevice.Dependent     $strQuotes = Chr(34)     $strDeviceName = StringReplace($strDeviceName, $strQuotes, "")     $arrDeviceNames = StringSplit($strDeviceName, "=")     $strDeviceName = $arrDeviceNames[2]     $colUSBDevices = $objWMIService.ExecQuery ("Select * From Win32_PnPEntity Where DeviceID = '" & $strDeviceName & "'")     For $objUSBDevice in $colUSBDevices         MsgBox(0,"USB Description",$objUSBDevice.Description)     Next     MsgBox(0,"USB Devices",$strDeviceName) Next


PS: added the USB device descriptions script.

regards,

ptrex

Edited by ptrex, 07 August 2007 - 07:29 AM.


#15 Elkie

Elkie

    Seeker

  • Active Members
  • 47 posts

Posted 07 August 2007 - 11:55 AM

@UglyBob

Good job !!

You did quit some investigation on this matter.

When you have some code running please post it in this thread, so others can benifit of it as well.

Good to see you get inspired by this !! :)

; [url="http://www.microsoft.com/technet/scriptcenter/resources/qanda/mar05/hey0315.mspx"]http://www.microsoft.com/technet/scriptcen...05/hey0315.mspx[/url] $strComputer = "." $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2") $colDevices = $objWMIService.ExecQuery ("Select * From Win32_USBControllerDevice") For $objDevice in $colDevices     $strDeviceName = $objDevice.Dependent     $strQuotes = Chr(34)     $strDeviceName = StringReplace($strDeviceName, $strQuotes, "")     $arrDeviceNames = StringSplit($strDeviceName, "=")     $strDeviceName = $arrDeviceNames[2]     $colUSBDevices = $objWMIService.ExecQuery ("Select * From Win32_PnPEntity Where DeviceID = '" & $strDeviceName & "'")     For $objUSBDevice in $colUSBDevices         MsgBox(0,"USB Description",$objUSBDevice.Description)     Next     MsgBox(0,"USB Devices",$strDeviceName) Next

PS: added the USB device descriptions script.

regards,

ptrex

Sorry for my noob question, is this mean i have to combine this script with the first post to create the USB insert detection (monitoring) script?

#16 ptrex

ptrex

    Universalist

  • MVPs
  • 2,399 posts

Posted 07 August 2007 - 03:17 PM

@Elkie

Yes indead.

But I am hoping the Mr. UglyBob is doing that for you. :)

Regards,

ptrex

#17 UglyBob

UglyBob

    Seeker

  • Active Members
  • 26 posts

Posted 07 August 2007 - 03:35 PM

thanks for the au3 version of the USB list ptrex.

Right, here's my script so far. As mentioned previously this amalgamates a couple scripts and functions together (with the odd tweak here and there to suit). Apologies for any incorrect command useage you may find, I'm still learning.


Plain Text         
; ==================================================================================================== ====================================== ; Created by UglyBob - 03/08/2007 ; Thanks to: ;           Yoan Roblet (Arcker) (AutoIT member) - For the code (functions) which disconnect the detected USB device from the workstation ;           ptrex (AutoIT member) - For the initial USB detection code) ;           Johny Clelland (AutoIT member) - For the initial AD code to query group membership ; Reference Material - ;                       <a href='http://support.microsoft.com/kb/165721' class='bbc_url' title='External link' rel='nofollow external'>http://support.microsoft.com/kb/165721</a> ;                       Microsoft Script Guy USB Monitor - <a href='http://www.microsoft.com/technet/scriptcen...06/hey0213.mspx' class='bbc_url' title='External link' rel='nofollow external'>http://www.microsoft.com/technet/scriptcen...06/hey0213.mspx</a> ;                       WMI queries -  <a href='http://msdn2.microsoft.com/en-us/library/aa394173.aspx' class='bbc_url' title='External link' rel='nofollow external'>http://msdn2.microsoft.com/en-us/library/aa394173.aspx</a> ;                       Microsoft Script Guy ID USB Devices - <a href='http://www.microsoft.com/technet/scriptcen...05/hey0315.mspx' class='bbc_url' title='External link' rel='nofollow external'>http://www.microsoft.com/technet/scriptcen...05/hey0315.mspx</a> ; Version Control ; --------------- ; Updated - 06/08/2007 - Added filters to the initial SELECT query for USB devices that also create floppy & CD-ROM drives ; Updated - 07/08/2007 - Added filters to the win32_logicaldisk query to ignore already disconnected USB devices ; ==================================================================================================== ====================================== #include <A3LWinApi.au3> #include <Constants.au3> ; ------------------------------------------------------------------------------------------------------------ ; Variables $AllowUser = False $objWMIService = ObjGet("winmgmts:\\.\root\cimv2") $Offline = False $OpenVolume = ""    $szVolumeFormat = "\\\\.\\%s" $szRootFormat = "%s\\" $szErrorFormat = "Error %d: %s\n" $USB_Allow_Group = "USB storage Users" $colEvents = $objWMIService.ExecNotificationQuery _     ("Select * From __InstanceOperationEvent Within 5 Where " _         & "TargetInstance isa 'Win32_PnPEntity' and  " _         & "(TargetInstance.Description = 'USB FloppyDisk Drive' or " _         & "TargetInstance.Description = 'CD-ROM Drive' or " _         & "TargetInstance.Description = 'Disk Drive')" )     ; Additional filter = TargetInstance.Description = 'Generic Volume' ;------------------------------------------ ;Arbitrary variables Global Const $INVALID_HANDLE_VALUE = 0 ;------------------------------------------ ;DeviceIoControl Contants Global Const $FSCTL_LOCK_VOLUME = int(0x090018) Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020) Global Const $IOCTL_STORAGE_EJECT_MEDIA  = int(0x002D4808) Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804) ;------------------------------------------ ;Retry Constants Global Const $LOCK_TIMEOUT = 10000    ; 10 Seconds Global Const $LOCK_RETRIES = 3 ;------------------------------------------ ; AD LDAP variables Dim $objConnection, $oUsr, $objRootDSE $objConnection = ObjCreate("ADODB.Connection") ; Create COM object to AD $objConnection.Provider = "ADsDSOObject" $objConnection.Open ("Active Directory Provider") ; Open connection to AD $objRootDSE = ObjGet("LDAP://RootDSE") ; If there is no response from LDAP then the script will treat the computer running the script as 'offline'. ; Ideal when a laptop is not connected to the network. If @Error then     $Offline = True Else     ConsoleWrite ( "Domain = " & $objRootDSE.Get ("defaultNamingContext") & @CRLF )     ConsoleWrite ( "Offline = " & $Offline & @CRLF )     $strDNSDomain = $objRootDSE.Get ("defaultNamingContext") ;Retrieve the current AD domain name (DN) EndIf ; ------------------------------------------------------------------------------------------------------------ While 1     $objEvent = $colEvents.NextEvent     Select     Case $objEvent.Path_.Class()="__InstanceCreationEvent"         ConsoleWrite ( "Detected Device = " & $objEvent.TargetInstance.DeviceID & " - " & $objEvent.TargetInstance.Description & @CRLF )         $Event = $objWMIService.ExecQuery("Select * From Win32_LogicalDisk Where (DriveType = 2 and MediaType != 5 and (FileSystem = 'FAT' or FileSystem = 'FAT32'))" )         For $objItem in $Event             $OpenVolume = $objItem.DeviceID             ConsoleWrite ( $objItem.DeviceID & " - " & $objItem.VolumeName & " - " & $objItem.FileSystem & @CRLF )             If $Offline = False Then                 If memberof($AllowUser) = False Then                 EjectVolume($OpenVolume)                 MsgBox (16, "USB Drive Detected", "Drive " & $OpenVolume & " has been added to your PC." & @CRLF & @CRLF & "You are not authorised to use such portable media." & @CRLF & @CRLF & "Please contact the ICT dept. for further assistance.")                 EndIf             Else                 MsgBox (64, "USB Drive Notification", "Drive " & $OpenVolume & " has been added to your PC.")             EndIf         Next         $OpenVolume = ""         ; The 'case' statement below is no longer required for this particular script but is useful for reporting successful USB disconnections ;Case $objEvent.Path_.Class()="__InstanceDeletionEvent" ;   MsgBox (64, "USB Drive", "Drive " & $OpenVolume & " has been Removed.")         EndSelect WEnd ; --------------------------------- ; ;          FUNCTIONS ; ; --------------------------------- Func ReportError($szMsg)     ConsoleWrite(StringFormat($szErrorFormat, _API_GetLastErrorMessage (), $szMsg) & @CRLF)     Exit EndFunc  ;==>ReportError Func OpenVolume($cDriveLetter)    ;HANDLE hVolume    ;UINT uDriveType    ;TCHAR szVolumeName[8]    ;TCHAR szRootName[5]    ;DWORD dwAccessFlags     $szRootName = StringFormat($szRootFormat, $cDriveLetter)     $uDriveType = DriveGetType($szRootName);     ConsoleWrite($szRootName & @tab & $uDriveType & @crlf)     Switch $uDriveType         Case "Removable"             $dwAccessFlags = 6         Case "CDROM"             $dwAccessFlags = 2         Case Else             ConsoleWrite("Cannot eject.  Drive type is incorrect." & @CRLF)             Return $INVALID_HANDLE_VALUE     EndSwitch     $szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter)    ;$szVolumeName = $szVolumeFormat & $cDriveLetter     ConsoleWrite($szVolumeName & @crlf )     $hVolume = _API_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6)         #cs         hVolume = CreateFile(   szVolumeName,         dwAccessFlags,         FILE_SHARE_READ | FILE_SHARE_WRITE,         NULL,         OPEN_EXISTING,         0,         NULL );     #ce     If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile");     Return $hVolume; EndFunc  ;==>OpenVolume Func CloseVolume($hVolume)     Return _API_CloseHandle ($hVolume); EndFunc  ;==>CloseVolume Func LockVolume($hVolume)     Local $dwBytesReturned     Local $dwSleepAmount     Local $nTryCount     local $iRead     $dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES;    ; Do this in a loop until a timeout period has expired     For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES         If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then             Return True         Else             Sleep($dwSleepAmount);         EndIf     Next     Return False; EndFunc  ;==>LockVolume Func DismountVolume($hVolume)     ConsoleWrite("Dismount " & $hVolume & @crlf)     Local $dwBytesReturned, $iRead     local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead)    ;msgbox(0,"",$aResult)     Return $aResult    ;Return $dwBytesReturned EndFunc  ;==>DismountVolume Func PreventRemovalOfVolume($hVolume, $fPreventRemoval)     Local $dwBytesReturned     Local $aResult     Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped         $PMRBUFFER = DllStructCreate("bool PreventMediaRemoval")         DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval)         $lpBytesReturned    = DllStructCreate("int Read")     $pRead   = DllStructGetPtr($lpBytesReturned, "Read")     $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _     "ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped)     if $aResult = 0 then msgbox(0,"",_API_GetLastErrorMessage())     Return $aResult <> 0         ;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL),    ;NULL, 0,    ; & dwBytesReturned,    ;NULL); EndFunc  ;==>PreventRemovalOfVolume Func AutoEjectVolume($hVolume)     Local $aResult, $iRead;     $aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead)     Return $aResult EndFunc  ;==>AutoEjectVolume Func EjectVolume($cDriveLetter)     Local $hVolume;     Local $fRemoveSafely = False;     Local $fAutoEject = False;    ; Open the volume.     $hVolume = OpenVolume($cDriveLetter);     If $hVolume == $INVALID_HANDLE_VALUE Then Return False    ; Lock and dismount the volume.     If LockVolume($hVolume) And DismountVolume($hVolume) Then         $fRemoveSafely = True;         ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf)        ; Set prevent removal to false and eject the volume.         If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then             $fAutoEject = True;         EndIf     Else         ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf)     EndIf        ; Close the volume so other processes can use the drive.     If CloseVolume($hVolume) = False Then         Return False;     EndIf         If $fAutoEject Then         ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.\n", $cDriveLetter))     Else         If $fRemoveSafely Then             ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.\n", $cDriveLetter))         EndIf     EndIf         Return True; EndFunc  ;==>EjectVolume Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead)     Local $aResult     Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped     $tRead   = DllStructCreate("int Data")         $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _     "ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped)         $iRead   = DllStructGetData($tRead, "Data")         ConsoleWrite("Device Control " & $iRead & @CRLF)     Return $aResult<>0 EndFunc  ;==>_Device_Control Func Memberof($AllowUser)     Dim $usergroups[1], $i = 1     Local $groups     $strQuery = "<LDAP://" & $strDNSDomain & ">;( samAccountName=" & @UserName & ");ADsPath;subtree"     $objRecordSet = $objConnection.Execute ($strQuery) ; Retrieve the FQDN for the logged on user     If $objRecordSet.RecordCount = 1 Then         $ldap_entry = $objRecordSet.fields (0).value         $oUsr = ObjGet($ldap_entry) ; Retrieve the COM Object for the logged on user         $groups = $oUsr.groups ; Get the list of group objects from the user         For $groupname In $groups             ReDim $usergroups[UBound($usergroups) + 1]             $usergroups[0] += 1 ; Increment the count of groups             $usergroups[$i] = StringTrimLeft($groupname.name, 3)             If $usergroups[$i] = $USB_Allow_Group Then                 $AllowUser = True                 Return $AllowUser                 ConsoleWrite ( "Allow = " & $AllowUser & @CRLF )                 ExitLoop             EndIf         $i += 1         Next     EndIf     ConsoleWrite ( "Allow = " & $AllowUser & @CRLF ) EndFunc  ;==>memberof




The reason why I have the filter:

(DriveType = 2 and MediaType != 5 and (FileSystem = 'FAT' or FileSystem = 'FAT32')) when checking the drives is to filter the floppy disk drive and to ignore a USB device that has already been disconnected by the script but the drive is still physically attached to the PC. There may be a slightly better WMI field to query, but so far this works, you may want to add 'NTFS' should you wish to disconnect any such devices too.

I did spot a simpler script somewhere on this forum regarding the listing of a user's groups, but the AD function works so hey why change it. :)
"My God, you're looking hideously ugly today, Ugly Bob."

#18 Rozek

Rozek

    Seeker

  • Active Members
  • 19 posts

Posted 16 August 2007 - 08:42 AM

Incredible, incredible!

I still can't believe what's possible with AutoIt (and the proper knowledge of Windows, of course)

Just to give a little bit back of what I got from AutoIt and this forum:

I had to integrate the check for removable volumes into a message event loop which controls an AutoIt GUI. After a little bit of research and some experiments I found the following solution (presented as a skeleton - you may add your own code where necessary)

AutoIt         
; **** add a COM error handler (see below) **** global $ErrorHandler = ObjEvent("AutoIt.Error","handleCOMError") func handleCOMError ()   if ($ErrorHandler.number = -2147352567) then        ; i.e. if timeout occurred     sleep(100)                             ; just wait a moment (then try again)     return                                                 ; continue processing   endif   with $ErrorHandler     ConsoleWriteError("COMError.number         = " & string(.number)         & @LF)     ConsoleWriteError("COMError.windescription = " & string(.windescription) & @LF)     ConsoleWriteError("COMError.source         = " & string(.source)         & @LF)     ConsoleWriteError("COMError.description    = " & string(.description)    & @LF)     ConsoleWriteError("COMError.helpfile       = " & string(.helpfile)       & @LF)     ConsoleWriteError("COMError.helpcontext    = " & string(.helpcontext)    & @LF)     ConsoleWriteError("COMError.lastdllerror   = " & string(.lastdllerror)   & @LF)     ConsoleWriteError("COMError.scriptline     = " & string(.scriptline)     & @LF)   endwith   exit                                   ; abort program in case of a real error endfunc ; **** set-up the WMIService object and register a query **** ; ... <= create WMIService and ExecNotificationQuery as required ; **** now continously check for WMI "events" **** while true   $objEvent = $colEvents.NextEvent(1)           ; do not wait longer than 1 msec   if ($objEvent <> 0) then                         ; did we get a *real* result? ;   ... <= process the WMI "event" as required   endif wend


The basic "trick" to provide a "timeout" (given in milliseconds) when calling ".NextEvent" and to catch the "timeout" (which is an error from the WMIService' point of view)

Hope this is of any help!

Kind regards,

Andreas Rozek

#19 BullGates

BullGates

    Wayfarer

  • Active Members
  • Pip
  • 77 posts

Posted 17 August 2007 - 11:44 PM

This is giving me some ideas to improve my concept as posted before in here:
http://www.autoitscript.com/forum/index.ph...st&p=366233

But the big problem I find in using COM is that the script can break easily if the error processing doesn't predict all the situations.
The posted script by UgglyBob looks interesting, but offline mode does not work and crashes easilly if you disconnect the network - if a user knows that, it will crash the script and he can then use the USB storage device. With my initial script, if it crashes at least he might be protected... It's a nice idea to use USB events to trigger some checks and avoid traffic to the domain controllers I guess. :)

Oh by the way, how would you implement such script? As a service? As normal user I guess it won't have permissions to work right...

Edited by BullGates, 17 August 2007 - 11:46 PM.


#20 UglyBob

UglyBob

    Seeker

  • Active Members
  • 26 posts

Posted 18 August 2007 - 06:45 PM

well, it was (and still is) of course work in progress. One of the other fundamental flaws in the script is the fact that you can plug the USB device prior to script actually running (such as booting up). This would not be picked up by '__InstanceCreationEvent '.

I'm working on an improved script. I've ditched the above WMI query, and instead am using Win32_DiskDrive as the initial check, which will query every 5 seconds for any USB drives (regardless of whether they have been plugged in before the script has started).
As for the AD issue, well this all depends on how you want to control USB devices. My main thought is to prevent users connecting USB devices allowing them to copy data from network servers or try to use software stored on said devices. That subject has many other issues and ways of circumvention, I guess you gotta start somewhere....

so...
1) Do you block ALL USB drives?
2) Do you allow authorised domain/local users to plug in USB devices?
If so, do you query AD or local workstation groups?
3) Do you allow offline connectivity when laptops are not connected to the network?

So far, my latest version is working (it doesn't fall over, or hang when offline). The script now dismounts drives unless it can confirm that the logged on user is a member of a specific AD group. As for how to run the script, that's still up for debate, but I think a service may be the option (I guess this all depends on the environment and situations that the script will be used).

More testing to do.... :)
"My God, you're looking hideously ugly today, Ugly Bob."




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users