Search This Blog

Monday, April 28, 2008

Invisible USB Flash drives due to network drives in Windows XP.

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=Flasher.ico
#AutoIt3Wrapper_outfile=Flasher.exe
#AutoIt3Wrapper_UseAnsi=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
AutoItSetOption ("RunErrorsFatal", 0)
AutoItSetOption ("TrayIconHide",1)
#include <array.au3>
#include <Date.au3>
#include <ServiceControl.au3>
 
Dim $ADrv[26], $RDrv[26], $NDrv[26], $Available[23]
dim $i
Dim $InstallPath
if $CmdLine[0] = "" then Exit
 
$InstallPath = "C:\Program Files\NYITSUPPORT\Flasher\"
 
Select
    case @OSVersion = "WIN_XP"
        Call ("StartSequence")
    case @OSVersion = "WIN_2000"
        $ver = RegRead("HKLM\SYSTEM\CurrentControlSet\Control\ProductOptions", "ProductType")
        If $ver = "ServerNT" then Exit
        Call ("StartSequence")
    case Else
        Exit
EndSelect    
    
Func StartSequence()
    Select
        case $CmdLine [1] = "/uninstall"
            if not IsAdmin() then Exit
            call ("Uninstall")
            
        case $CmdLine [1] = "/install" 
            if not IsAdmin() then Exit
            if FileExists($InstallPath) then Exit
            Call ("Install")
            Exit
            
        case $CmdLine [1] = "/client"
            call ("Client")
            Exit
            
        case $CmdLine [1] = "/service"
            if not IsAdmin() then Exit
            call ("Service")
 
        case Else
            Exit
            
    EndSelect
EndFunc
 
Func Install()
    FileCopy (@ScriptFullPath, $InstallPath,8)
    FileCopy (@ScriptDir & "\RunAsSvc.exe", $InstallPath, 8)
    ShellExecute("cacls.exe", '"' & StringLeft($InstallPath, StringLen($InstallPath)-1) & '" /e /c /g BUILTIN\Users:F')
    $args = ' -i --displayname "NYITSUPPORT Flasher" --description "NYITSUPPORT Flasher SERVICE" --exe "' & $InstallPath & "flasher.exe" & '" --params "/service" --quiet'
    FileCreateShortcut($InstallPath & "Flasher.exe", @StartupCommonDir & "\NYITSUPPORT Flasher.lnk", $InstallPath, "/client", "NYITSUPPORT Flasher CLIENT")
    RunWait ($InstallPath & "RunAsSvc.exe" & $args)
EndFunc
 
Func Uninstall()
    FileDelete (@StartupCommonDir & "\NYITSUPPORT Flasher.lnk")
    ;Kill the Flasher SERVICE
    $objWMIService = ObjGet("winmgmts:" & "{impersonationLevel=impersonate}!\\" & "." & "\root\cimv2")
    $colListOfServices = $objWMIService.ExecQuery ("Select * from Win32_Service Where DisplayName = 'NYITSUPPORT Flasher'")
    For $objService in $colListOfServices
        $objService.StopService()
        $objService.Delete()
    Next
    ;Kill running Flasher CLIENT and delete the Flasher folder
    Dim $objWMIService, $objProcess, $colProcess
    $objWMIService =ObjGet("winmgmts:" & "{impersonationLevel=impersonate}!\\" & "." & "\root\cimv2") 
    $colProcess = $objWMIService.ExecQuery ("Select * from Win32_Process Where Name = " & "'flasher.exe'")
    For $objProcess in $colProcess
        DirRemove($InstallPath,1)
        $objProcess.Terminate()
    Next 
 
EndFunc
 
Func Client()
    While 1=1
        Sleep(30000)
        Call("Available")
    WEnd
EndFunc
 
Func Available()     ;collect D:-Z: into the $Available array
    for $p = 1 to 23
        _ArrayDelete($Available,$p)
    Next
    For $i = 68 To 90
        _ArrayInsert($Available, $i - 68, Chr($i) & ":")
    Next
    Call("Existing")
EndFunc
 
Func Existing() ;delete any existing drives from the $Available array
    $ADrv = DriveGetDrive("ALL")
    For $a = 1 To UBound($ADrv) - 1
        $b = _ArraySearch($Available, $ADrv[$a], 0, 0, 0)
        If $b <> -1 Then _ArrayDelete($Available, $b)
    Next
    If $Available[1] = "" Then
        sleep(120000)
    Else
        _ArraySort($Available, 1)
        Call("REMAP")
    EndIf    
EndFunc   ;==>Existing
 
Func REMAP()
    $NDrv = DriveGetDrive("NETWORK")
    If $NDrv <> 0 Then
        For $i = 1 To UBound($NDrv) - 1
            $j = RegRead("HKLM\SYSTEM\MountedDevices", "\DosDevices\" & $NDrv[$i]) ;check for presense of HKLM\SYSTEM\MountedDevices\DosDevices\(n): Drive
            If $j <> "" Then
                    $ChangeFile = FileOpen($InstallPath & "Flasher.Change", 2)
                    $fwl = FileWriteLine ($ChangeFile, $NDrv[$i] & "-" & $Available[1])
                    FileClose($ChangeFile)
            EndIf
        Next
    EndIf
EndFunc
 
Func Service()
    while 1 = 1
    sleep(30000)
    $ChangeFile = $InstallPath & "Flasher.Change"
        if FileExists ($ChangeFile) Then
            $ChangeFile = FileOpen($InstallPath & "Flasher.Change",0)
            $Flasher_Change = FileReadLine ($ChangeFile)
            $Before = StringMid ($Flasher_Change, 1, 2)
            $After = StringMid ($Flasher_Change, 4, 2)
            $Data = RegRead("HKLM\SYSTEM\MountedDevices", "\DosDevices\" & $Before)
            $rd = RegDelete("HKLM\SYSTEM\MountedDevices", "\DosDevices\" & $Before)
                if $rd = 1 then 
                    RegWrite("HKLM\SYSTEM\MountedDevices", "\DosDevices\" & $After, "REG_BINARY", $Data)
                    FileClose($ChangeFile)
                    FileDelete($ChangeFile)
                EndIf
        EndIf
        FileClose($ChangeFile)
        FileDelete($ChangeFile)
    WEnd
EndFunc

This application was written to address a known issue in Microsoft Windows XP/2000 with drive letter usage. 

If a user logs in and has drives mapped starting at F and higher, and connects a flash drive, Windows will assign the next available system drive ignoring the user's mapped drive letters. 

Now since the user has a drive mapped at the letter already, he will not see the flash drive. 

You can correct this by going into compmgmt.msc - drive manager, and change the physical letter there. 

The only problem is if the user does not have admin rights, he would not be able to change anything. 

There is a hotfix that Microsoft has released for XP 

http://support.microsoft.com/kb/297694 

If you cannot acquire the hotfix, or have some other issues for not installing it, you can use flasher.exe. It has a small footprint while running and is hardly noticeable. 

I created this application before the hotfix became available. 

It has worked great in our parent company deployment for many months. 

I originally saw another application that was available for free for personal use, but you have to buy for a corporate environment. 

It worked in a test environment, and is probably better written; I needed my own solution that i can troubleshoot programmatically, not to mention it was free (minus my time). 

http://www.uwe-sieber.de/usbdlm_e.html 

My approach is very different though as you can tell in the code. In any case, you're free to use and reuse the code any way you please as long as you don't hold me responsible for any damage. 

I also rely on a ServiceControl.au3 

http://www.autoitscript.com/forum/index.php?showtopic=6487

Global $STANDARD_RIGHTS_REQUIRED = 0x000F0000
 
; Service Control Manager access types
Global $SC_MANAGER_CONNECT = 0x0001
Global $SC_MANAGER_CREATE_SERVICE = 0x0002
Global $SC_MANAGER_ENUMERATE_SERVICE = 0x0004
Global $SC_MANAGER_LOCK = 0x0008
Global $SC_MANAGER_QUERY_LOCK_STATUS = 0x0010
Global $SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020
 
Global $SC_MANAGER_ALL_ACCESS = BitOR($STANDARD_RIGHTS_REQUIRED, _
                                      $SC_MANAGER_CONNECT, _
                                      $SC_MANAGER_CREATE_SERVICE, _
                                      $SC_MANAGER_ENUMERATE_SERVICE, _
                                      $SC_MANAGER_LOCK, _
                                      $SC_MANAGER_QUERY_LOCK_STATUS, _
                                      $SC_MANAGER_MODIFY_BOOT_CONFIG)
 
; Service access types
Global $SERVICE_QUERY_CONFIG = 0x0001
Global $SERVICE_CHANGE_CONFIG = 0x0002
Global $SERVICE_QUERY_STATUS = 0x0004
Global $SERVICE_ENUMERATE_DEPENDENTS = 0x0008
Global $SERVICE_START = 0x0010
Global $SERVICE_STOP = 0x0020
Global $SERVICE_PAUSE_CONTINUE = 0x0040
Global $SERVICE_INTERROGATE = 0x0080
Global $SERVICE_USER_DEFINED_CONTROL = 0x0100
 
Global $SERVICE_ALL_ACCESS = BitOR($STANDARD_RIGHTS_REQUIRED, _
                                   $SERVICE_QUERY_CONFIG, _
                                   $SERVICE_CHANGE_CONFIG, _
                                   $SERVICE_QUERY_STATUS, _
                                   $SERVICE_ENUMERATE_DEPENDENTS, _
                                   $SERVICE_START, _
                                   $SERVICE_STOP, _
                                   $SERVICE_PAUSE_CONTINUE, _
                                   $SERVICE_INTERROGATE, _
                                   $SERVICE_USER_DEFINED_CONTROL)
 
; Service controls
Global $SERVICE_CONTROL_STOP = 0x00000001
Global $SERVICE_CONTROL_PAUSE = 0x00000002
Global $SERVICE_CONTROL_CONTINUE = 0x00000003
Global $SERVICE_CONTROL_INTERROGATE = 0x00000004
Global $SERVICE_CONTROL_SHUTDOWN = 0x00000005
Global $SERVICE_CONTROL_PARAMCHANGE = 0x00000006
Global $SERVICE_CONTROL_NETBINDADD = 0x00000007
Global $SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
Global $SERVICE_CONTROL_NETBINDENABLE = 0x00000009
Global $SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
Global $SERVICE_CONTROL_DEVICEEVENT = 0x0000000B
Global $SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0x0000000C
Global $SERVICE_CONTROL_POWEREVENT = 0x0000000D
Global $SERVICE_CONTROL_SESSIONCHANGE = 0x0000000E
 
; Service types
Global $SERVICE_KERNEL_DRIVER = 0x00000001
Global $SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
Global $SERVICE_ADAPTER = 0x00000004
Global $SERVICE_RECOGNIZER_DRIVER = 0x00000008
Global $SERVICE_DRIVER = BitOR($SERVICE_KERNEL_DRIVER, _
                               $SERVICE_FILE_SYSTEM_DRIVER, _
                               $SERVICE_RECOGNIZER_DRIVER)
Global $SERVICE_WIN32_OWN_PROCESS = 0x00000010
Global $SERVICE_WIN32_SHARE_PROCESS = 0x00000020
Global $SERVICE_WIN32 = BitOR($SERVICE_WIN32_OWN_PROCESS, _
                              $SERVICE_WIN32_SHARE_PROCESS)
Global $SERVICE_INTERACTIVE_PROCESS = 0x00000100
Global $SERVICE_TYPE_ALL = BitOR($SERVICE_WIN32, _
                                 $SERVICE_ADAPTER, _
                                 $SERVICE_DRIVER, _
                                 $SERVICE_INTERACTIVE_PROCESS)
 
; Service start types
Global $SERVICE_BOOT_START = 0x00000000
Global $SERVICE_SYSTEM_START = 0x00000001
Global $SERVICE_AUTO_START = 0x00000002
Global $SERVICE_DEMAND_START = 0x00000003
Global $SERVICE_DISABLED = 0x00000004
 
; Service error control
Global $SERVICE_ERROR_IGNORE = 0x00000000
Global $SERVICE_ERROR_NORMAL = 0x00000001
Global $SERVICE_ERROR_SEVERE = 0x00000002
Global $SERVICE_ERROR_CRITICAL = 0x00000003
 
;===============================================================================
; Description:   Starts a service on a computer
; Parameters:    $sComputerName - name of the target computer. If empty, the local computer name is used
;                $sServiceName - name of the service to start
; Requirements:  None
; Return Values: On Success - 1
;                On Failure - 0 and @error is set to extended Windows error code
; Note:          This function does not check to see if the service has started successfully
;===============================================================================
Func _StartService($sComputerName, $sServiceName)
   Local $hAdvapi32
   Local $hKernel32
   Local $arRet
   Local $hSC
   Local $hService
   Local $lError = -1
 
   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $hKernel32 = DllOpen("kernel32.dll")
   If $hKernel32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
                    "str", $sComputerName, _
                    "str", "ServicesActive", _ 
                    "long", $SC_MANAGER_CONNECT)
   If $arRet[0] = 0 Then
      $arRet = DllCall($hKernel32, "long", "GetLastError")
      $lError = $arRet[0]
   Else
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "long", "OpenService", _
                       "long", $hSC, _
                       "str", $sServiceName, _
                       "long", $SERVICE_START)
      If $arRet[0] = 0 Then
         $arRet = DllCall($hKernel32, "long", "GetLastError")
         $lError = $arRet[0]
      Else
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "int", "StartService", _
                          "long", $hService, _
                          "long", 0, _
                          "str", "")
         If $arRet[0] = 0 Then
            $arRet = DllCall($hKernel32, "long", "GetLastError")
            $lError = $arRet[0]
         EndIf
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hService)         
      EndIf
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)
   DllClose($hKernel32)
   If $lError <> -1 Then 
      SetError($lError)
      Return 0
   EndIf
   Return 1
EndFunc
 
;===============================================================================
; Description:   Stops a service on a computer
; Parameters:    $sComputerName - name of the target computer. If empty, the local computer name is used
;                $sServiceName - name of the service to stop
; Requirements:  None
; Return Values: On Success - 1
;                On Failure - 0 and @error is set to extended Windows error code
; Note:          This function does not check to see if the service has stopped successfully
;===============================================================================
Func _StopService($sComputerName, $sServiceName)
   Local $hAdvapi32
   Local $hKernel32
   Local $arRet
   Local $hSC
   Local $hService
   Local $lError = -1
 
   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $hKernel32 = DllOpen("kernel32.dll")
   If $hKernel32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
                    "str", $sComputerName, _
                    "str", "ServicesActive", _
                    "long", $SC_MANAGER_CONNECT)
   If $arRet[0] = 0 Then
      $arRet = DllCall($hKernel32, "long", "GetLastError")
      $lError = $arRet[0]
   Else
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "long", "OpenService", _
                       "long", $hSC, _
                       "str", $sServiceName, _
                       "long", $SERVICE_STOP)
      If $arRet[0] = 0 Then
         $arRet = DllCall($hKernel32, "long", "GetLastError")
         $lError = $arRet[0]
      Else
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "int", "ControlService", _
                          "long", $hService, _
                          "long", $SERVICE_CONTROL_STOP, _
                          "str", "")
         If $arRet[0] = 0 Then
            $arRet = DllCall($hKernel32, "long", "GetLastError")
            $lError = $arRet[0]
         EndIf
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hService)         
      EndIf
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)
   DllClose($hKernel32)   
   If $lError <> -1 Then 
      SetError($lError)
      Return 0
   EndIf
   Return 1
EndFunc
 
;===============================================================================
; Description:   Checks if a service exists on a computer
; Parameters:    $sComputerName - name of the target computer. If empty, the local computer name is used
;                $sServiceName - name of the service to check
; Requirements:  None
; Return Values: On Success - 1
;                On Failure - 0
;===============================================================================
Func _ServiceExists($sComputerName, $sServiceName)
   Local $hAdvapi32
   Local $arRet
   Local $hSC
   Local $bExist = 0
 
   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
                    "str", $sComputerName, _
                    "str", "ServicesActive", _
                    "long", $SC_MANAGER_CONNECT)
   If $arRet[0] <> 0 Then
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "long", "OpenService", _
                       "long", $hSC, _
                       "str", $sServiceName, _
                       "long", $SERVICE_INTERROGATE)
      If $arRet[0] <> 0 Then
         $bExist = 1
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $arRet[0])
      EndIf
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)
   Return $bExist
EndFunc
 
;===============================================================================
; Description:   Checks if a service is running on a computer
; Parameters:    $sComputerName - name of the target computer. If empty, the local computer name is used
;                $sServiceName - name of the service to check
; Requirements:  None
; Return Values: On Success - 1
;                On Failure - 0
; Note:          This function relies on the fact that only a running service responds
;                to a SERVICE_CONTROL_INTERROGATE control code. Check the ControlService
;                page on MSDN for limitations with using this method.
;===============================================================================
Func _ServiceRunning($sComputerName, $sServiceName)
   Local $hAdvapi32
   Local $arRet
   Local $hSC
   Local $hService   
   Local $bRunning = 0
 
   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
                    "str", $sComputerName, _
                    "str", "ServicesActive", _
                    "long", $SC_MANAGER_CONNECT)
   If $arRet[0] <> 0 Then
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "long", "OpenService", _
                       "long", $hSC, _
                       "str", $sServiceName, _
                       "long", $SERVICE_INTERROGATE)
      If $arRet[0] <> 0 Then
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "int", "ControlService", _
                          "long", $hService, _
                          "long", $SERVICE_CONTROL_INTERROGATE, _
                          "str", "")
         $bRunning = $arRet[0]
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hService)
      EndIf
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)   
   Return $bRunning
EndFunc
 
;===============================================================================
; Description:   Creates a service on a computer
; Parameters:    $sComputerName - name of the target computer. If empty, the local computer name is used
;                $sServiceName - name of the service to create
;                $sDisplayName - display name of the service
;                $sBinaryPath - fully qualified path to the service binary file
;                               The path can also include arguments for an auto-start service
;                $sServiceUser - [optional] default is LocalSystem
;                                name of the account under which the service should run
;                $sPassword - [optional] default is empty
;                             password to the account name specified by $sServiceUser
;                             Specify an empty string if the account has no password or if the service 
;                             runs in the LocalService, NetworkService, or LocalSystem account
;                 $nServiceType - [optional] default is $SERVICE_WIN32_OWN_PROCESS
;                 $nStartType - [optional] default is $SERVICE_AUTO_START
;                 $nErrorType - [optional] default is $SERVICE_ERROR_NORMAL
;                 $nDesiredAccess - [optional] default is $SERVICE_ALL_ACCESS
;                 $sLoadOrderGroup - [optional] default is empty
;                                    names the load ordering group of which this service is a member
; Requirements:  Administrative rights on the computer
; Return Values: On Success - 1
;                On Failure - 0 and @error is set to extended Windows error code
; Note:          Dependencies cannot be specified using this function
;                Refer to the CreateService page on MSDN for more information
;===============================================================================
Func _CreateService($sComputerName, _
                    $sServiceName, _
                    $sDisplayName, _
                    $sBinaryPath, _
                    $sServiceUser = "LocalSystem", _
                    $sPassword = "", _
                    $nServiceType = 0x00000010, _
                    $nStartType = 0x00000002, _
                    $nErrorType = 0x00000001, _
                    $nDesiredAccess = 0x000f01ff, _
                    $sLoadOrderGroup = "")
   Local $hAdvapi32
   Local $hKernel32
   Local $arRet
   Local $hSC
   Local $lError = -1   
 
   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $hKernel32 = DllOpen("kernel32.dll")
   If $hKernel32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
                    "str", $sComputerName, _
                    "str", "ServicesActive", _
                    "long", $SC_MANAGER_ALL_ACCESS)
   If $arRet[0] = 0 Then
      $arRet = DllCall($hKernel32, "long", "GetLastError")
      $lError = $arRet[0]
   Else
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "long", "OpenService", _
                       "long", $hSC, _
                       "str", $sServiceName, _
                       "long", $SERVICE_INTERROGATE)
      If $arRet[0] = 0 Then
         $arRet = DllCall($hAdvapi32, "long", "CreateService", _
                          "long", $hSC, _
                          "str", $sServiceName, _
                          "str", $sDisplayName, _
                          "long", $nDesiredAccess, _
                          "long", $nServiceType, _
                          "long", $nStartType, _
                          "long", $nErrorType, _
                          "str", $sBinaryPath, _
                          "str", $sLoadOrderGroup, _
                          "ptr", 0, _
                          "str", "", _
                          "str", $sServiceUser, _
                          "str", $sPassword)
         If $arRet[0] = 0 Then            
            $arRet = DllCall($hKernel32, "long", "GetLastError")
            $lError = $arRet[0]
         Else
            DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $arRet[0])
         EndIf
      Else
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $arRet[0])
      EndIf      
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)
   DllClose($hKernel32)   
   If $lError <> -1 Then 
      SetError($lError)
      Return 0
   EndIf
   Return 1
EndFunc
 
;===============================================================================
; Description:   Deletes a service on a computer
; Parameters:    $sComputerName - name of the target computer. If empty, the local computer name is used
;                $sServiceName - name of the service to delete
; Requirements:  Administrative rights on the computer
; Return Values: On Success - 1
;                On Failure - 0 and @error is set to extended Windows error code
;===============================================================================
Func _DeleteService($sComputerName, $sServiceName)
   Local $hAdvapi32
   Local $hKernel32
   Local $arRet
   Local $hSC
   Local $hService
   Local $lError = -1   
 
   $hAdvapi32 = DllOpen("advapi32.dll")
   If $hAdvapi32 = -1 Then Return 0
   $hKernel32 = DllOpen("kernel32.dll")
   If $hKernel32 = -1 Then Return 0
   $arRet = DllCall($hAdvapi32, "long", "OpenSCManager", _
                    "str", $sComputerName, _
                    "str", "ServicesActive", _
                    "long", $SC_MANAGER_ALL_ACCESS)
   If $arRet[0] = 0 Then
      $arRet = DllCall($hKernel32, "long", "GetLastError")
      $lError = $arRet[0]
   Else
      $hSC = $arRet[0]
      $arRet = DllCall($hAdvapi32, "long", "OpenService", _
                       "long", $hSC, _
                       "str", $sServiceName, _
                       "long", $SERVICE_ALL_ACCESS)
      If $arRet[0] = 0 Then
         $arRet = DllCall($hKernel32, "long", "GetLastError")
         $lError = $arRet[0]
      Else
         $hService = $arRet[0]
         $arRet = DllCall($hAdvapi32, "int", "DeleteService", _
                          "long", $hService)
         If $arRet[0] = 0 Then
            $arRet = DllCall($hKernel32, "long", "GetLastError")
            $lError = $arRet[0]
         EndIf
         DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hService)
      EndIf
      DllCall($hAdvapi32, "int", "CloseServiceHandle", "long", $hSC)
   EndIf
   DllClose($hAdvapi32)
   DllClose($hKernel32)   
   If $lError <> -1 Then 
      SetError($lError)
      Return 0
   EndIf
   Return 1
EndFunc
Install info: Two exe files need to be placed in the same folder in an install directory. 
1: flasher.exe - The actual application 
2: RunAsSvc.exe - A file used for setting the exe as a Windows Service. It will set the flasher to run in the SYSTEM context as a service. 

The flasher.exe has 4 modes of operation called by switches following the command.
It will exit unless a switch is included. 

/install 
  •     Checks and exits if it was executed on a server. Otherwise installs on a workstation 2000/XP only. Did not test with 2000. 
  •     Copies itself and RunAsSvc.exe to c:\program files\NYITSUPPORT\Flasher folder. 
  •     Registers itself as a service using RunAsSvc by calling itself with a /service switch.
  •     Creates a shortcut to itself with a /client switch, and places it into c:\documents and settings\all users\start menu\startup. 
  •     Changes NTFS permissions on c:\program files\NYITSUPPORT\Flasher to users Allow-Full rights. 

/client 
  •     Runs in the user context and checks for any drive letter conflicts. 
  •     If a conflict is detected, a value with the "existing letter-new letter" is written to c:\program files\NYITSUPPORT\Flasher\drive.change file. 
  •     Example: F:-Z:Checks every 30 seconds 

/service 
  •     Runs in the SYSTEM context and checks for any entries in the drive.change file.
  •     If an entry is present, it will remap the physical drives based on the letters the client instance provided in the file. 
  •     Using the example given above will change the F drive to Z.
  •     The change is performed by changing letters in HKLM\system\MountedDevices\DosDevices\x instances.
  •     Deletes the change file.Checks every 30 seconds. 

/uninstall 
  •     Stops/deletes it's own service instance.
  •     Kills/deletes the client instance.
  •     Deletes the shortcut created in the All Users startup.Deletes the Flasher folder. 
   
The application has to be rolled out in administrative context for the setup to complete. 
Computer Startup has to be used as a means for deployment with Group Policy.


Blackberry Contacts not syncing from Outlook contact subfolders

Just ran across an interesting issue with a client's blackberry. 
After his desktop was upgraded to Office 2007, the contact sub-folders stopped syncing randomly. 
Most folders still synced, some however did not. 
The user has all his contacts sorted by subfolders inside of the main Contacts folder in Outlook. 
Tried creating test contacts and folders, and could not find a relation between syncing and non syncing folders/contacts. 

Solution: Deleted the user from the Blackberry Enterprise Server, cleared all Blackberry related data (one of the prompts when deleting). 
Wiped the handheld. 
Created the account on the server not using the old stats (prompt). 
Reactivated and everything worked perfectly.

Monday, April 14, 2008

DST2008 script - could be used for other things

Basically i wrote this script to address an issue our parent company was having with incompletely patched machines. By opening the clock and unchecking and then checking back the Automatically adjust clock for daylight saving changes the issue is resolved as the time zone gets reapplied properly. The problem is that if a user has no admin rights, youre pretty much screwed. This script will also run the Outlook mailbox TZMove tool. Yes you could run it centrally. But how do you know which user's were patched before the existing appointments got created?

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_outfile=DST2008.exe
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
AutoItSetOption ("RunErrorsFatal", 0)
AutoItSetOption ("TrayIconHide",1)
call ("StartSequence")
 
Func StartSequence()
    if $CmdLine[$CmdLine[0]] = "" then 
        Exit
    Else
        Select
            case $CmdLine [1] = "/uninstall"
                if not IsAdmin() then Exit
                call("uninstall")
                
            case $CmdLine [1] = "/install" 
                $DS = RegRead ("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation", "DaylightStart")
                if $DS = "00000300020002000000000000000000" then
                    $log = FileOpen("\\NYITSUPPORT\DST2008\LOGS\" & @ComputerName & ".log",9)
                    FileWriteLine($log, @CRLF & "DaylightStart is proper. Nothing done " & @MON & "/" & @MDAY & "/" & @YEAR & " - " & @HOUR & ":" & @MIN)
                    FileClose($log)
                    Exit
                Else
                    if not IsAdmin() then Exit
                    Call ("Install")
                EndIf
 
            case $CmdLine [1] = "/tzmove"
                call ("tzmove")
            case Else
                Exit
                
        EndSelect
    EndIf
EndFunc
 
func tzmove()
    RunWait('"C:\Program Files\Microsoft Office\Office12\Office Outlook Time Zone Data Update Tool\tzmove.exe" /quiet',"",@SW_HIDE)
    $log = FileOpen("\\NYITSUPPORT\DST2008\LOGS\" & @UserName & "\" & @ComputerName & ".log",9)
    FileWriteLine($log, @CRLF & "TZMove executed " & @MON & "/" & @MDAY & "/" & @YEAR & " - " & @HOUR & ":" & @MIN)
    FileClose($log)
    FileCopy(@TempDir & "\Outlook Time Zone Update.log", "\\NYITSUPPORT\DST2008\LOGS\" & @UserName,9)
EndFunc
 
Func Install()
    $StandardName = RegRead("HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation", "StandardName")
    RunWait('"control.exe" timedate.cpl,,/Z ' & $StandardName)
    FileCopy(@ScriptDir & "\tzmove.exe", "C:\Program Files\NYITSUPPORT\DST2008\", 9)
    RunWait('"C:\Program Files\NYITSUPPORT\DST2008\tzmove.exe" /passive /quiet /extract:"c:\program files\NYITSUPPORT\dst2008"',"c:\program files\NYITSUPPORT\dst2008")
    RunWait('msiexec /i "C:\Program Files\NYITSUPPORT\DST2008\tzmove.msi" /q', "C:\Program Files\NYITSUPPORT\DST2008")
    FileCopy(@ScriptFullPath, "C:\program files\NYITSUPPORT\DST2008\",9)
    FileCreateShortcut("C:\Program Files\NYITSUPPORT\DST2008\DST2008.exe", "C:\Documents and settings\all users\start menu\programs\startup\DST2008.lnk", "", "/tzmove")
    $log = FileOpen("\\NYITSUPPORT\DST2008\LOGS\" & @ComputerName & ".log",9)
    FileWriteLine($log, @CRLF & "Installed " & @MON & "/" & @MDAY & "/" & @YEAR & " - " & @HOUR & ":" & @MIN)
    FileClose($log)
EndFunc
 
Func Uninstall()
    FileDelete("c:\documents and settings\all users\start menu\programs\startup\dst2008.lnk")
    FileDelete("c:\documents and settings\all users\start menu\programs\startup\dst2008.exe.lnk")
    DirRemove("c:\program files\NYITSUPPORT\DST2008",1)
    $log = FileOpen("\\NYITSUPPORT\DST2008\LOGS\" & @ComputerName & ".log",9)
    FileWriteLine($log, @CRLF & "Uninstalled " & @MON & "/" & @MDAY & "/" & @YEAR & " - " & @HOUR & ":" & @MIN)
    FileClose($log)
EndFunc

I believe you will find the switches useful. You can customize this for anything you want. I used AutoItScript as the development environment. 

Ever since i started using it for a DST rollout in 2007 where i wrote a much larger script, i have never looked back at vbscript ot writing batch files. The price is unbeatable at $0.00. It lets you compiles. 

TZMove.exe and DST2008.exe need to be in the same folder. 

/install This option will check if the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\DaylightStart value is correctly set as 00000300020002000000000000000000

If it is proper the application will exit. 

Else it will check for admin rights and run the check/uncheck of the “Automatically adjust clock for daylight saving changes” by toggling the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\DisableAutoDaylightTimeSet value. 

It will also manually enter the 00000300020002000000000000000000 value as a precaution. 

Run TZMove.exe /passive /quiet /extract:c:\program files\NYITSUPPORT\dst2008, which will extract the tzmove.msi and the catalog folder. 

Run tzmove.msi /q, which will install the application to the default C:\Program Files\Microsoft Office\Office12\Office Outlook Time Zone Data Update Tool folder. 

Create a shortcut to c:\Program Files\NYITSUPPORT\DST2008.exe /tzmove under c:\Documents and Settings\All Users\Start Menu\Programs\StartUp Create a ComputerName.log file under \\NYITSUPPORT\DST2008\LOGS and enter Installed MM/DD/YYYY – 00:00 into the file. 

/uninstall Delete c:\documents and settings\all users\start menu\programs\startup\dst2008.lnk and the c:\program files\NYITSUPPORT\DST2008 folder.

Enter a log in ComputerName.log file under \\NYITSUPPORT\DST2008\LOGS and append Uninstalled MM/DD/YYYY – 00:00 into the file. 

/tzmove This option is only initiated by the shortcut set using the /install switch at next logon of the user. 

Run C:\Program Files\Microsoft Office\Office12\Office Outlook Time Zone Data Update Tool\tzmove.exe /quiet Create a log under \\NYITSUPPORT\DST2008\LOGS\username\computername.log and enter TZMove executed MM/DD/YYYY – 00:00 into the file. 

Copy %temp%\Outlook Time Zone Update.log to the \\NYITSUPPORT\DST2008\LOGS\username folder.

Thursday, April 10, 2008

Vista SP1 missing right click context menu search

Here is how to get it back based on the link below.

Open regedit and navigate to HKEY_CLASSES_ROOT\Directory\shell\find

delete the LegacyDisable entry