OffScrubC2R Vbs
OffScrubC2R Vbs
Option Explicit
'-------------------------------------------------------------------------------
'
' Declaration of constants
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
'
' Declaration of variables
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
' Main
'
' Main section of script
'-------------------------------------------------------------------------------
'-----------------------------
' Stage # 0 - Basic detection |
'-----------------------------
LogH "Stage # 0 " & chr(34) & "Basic detection" & chr(34)
' ensure integrity of WI metadata which could fail used APIs otherwise
'---------------------------------------------------------------------
LogH1 "Ensure Windows Installer metadata integrity " & " (" & Time & ")"
EnsureValidWIMetadata HKCU,"Software\Classes\Installer\Products", COMPRESSED
EnsureValidWIMetadata HKCR,"Installer\Products", COMPRESSED
EnsureValidWIMetadata HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\
UserData\S-1-5-18\Products", COMPRESSED
EnsureValidWIMetadata HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\
UserData\S-1-5-18\Components", COMPRESSED
EnsureValidWIMetadata HKCR,"Installer\Components", COMPRESSED
sPackageGuid = ""
If RegReadValue(HKLM, "SOFTWARE\Microsoft\Office\15.0\ClickToRun", "PackageGUID",
sValue, "REG_SZ") Then
sPackageGuid = sValue
ElseIf RegReadValue(HKLM, "SOFTWARE\Microsoft\Office\16.0\ClickToRun",
"PackageGUID", sValue, "REG_SZ") Then
sPackageGuid = sValue
ElseIf RegReadValue(HKLM, "SOFTWARE\Microsoft\Office\ClickToRun", "PackageGUID",
sValue, "REG_SZ") Then
sPackageGuid = sValue
End If
'-----------------------
' Stage # 1 - Uninstall |
'-----------------------
' uninstall
'----------
LogH1 "Remove " & ONAME
Uninstall
'---------------------
' Stage # 2 - CleanUp |
'---------------------
LogH "Stage # 2 " & chr(34) & "CleanUp" & chr(34)
' Exit
ExitScript
'------------------
' Stage # 3 - Exit |
'------------------
'-------------------------------------------------------------------------------
' ExitScript
'
' Returncode and reboot handler
'-------------------------------------------------------------------------------
Sub ExitScript
Dim sPrompt
sTmp = "ReturnErrorOrSuccess switch has been set. The current value return
code translates to: "
If fOverallSuccess Then
iError = ERROR_SUCCESS
Log sTmp & "SUCCESS"
Else
Log sTmp & "ERROR"
End If
End If
wscript.quit iError
End Sub 'ExitScript
'-------------------------------------------------------------------------------
' End Main
'
' End of Main section
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
' Initialize
'
' Configure defaults and initialize all required objects
'-------------------------------------------------------------------------------
Sub Initialize ()
Dim iCnt
'-------------------------------------------------------------------------------
' ParseCmdLine
'
' Command line parser
'-------------------------------------------------------------------------------
Sub ParseCmdLine
iArgCnt = Wscript.Arguments.Count
If iArgCnt > 0 Then
If wscript.Arguments(0) = "UAC" Then
If wscript.arguments.count = 1 Then iArgCnt = 0
End If
End If
If iArgCnt = 0 Then
Select Case UCase(wscript.ScriptName)
Case Else
'Create the log
CreateLog
FindInstalledOProducts
sDefault = "ALL"
arrArguments = Split(Trim(sDefault), " ")
If UBound(arrArguments) = -1 Then ReDim arrArguments(0)
End Select
Else
ReDim arrArguments(iArgCnt-1)
For iCnt = 0 To (iArgCnt-1)
arrArguments(iCnt) = UCase(Wscript.Arguments(iCnt))
sArguments = sArguments & arrArguments(iCnt) & " "
Next 'iCnt
End If 'iArgCnt = 0
'-------------------------------------------------------------------------------
' ShowSyntax
'
' Show the expected syntax for the script usage
'-------------------------------------------------------------------------------
Sub ShowSyntax
Wscript.Echo vbCrLf & _
SCRIPTFILE & " V " & SCRIPTVERSION & vbCrLf & _
"Copyright (c) Microsoft Corporation. All Rights Reserved" & vbCrLf &
vbCrLf & _
SCRIPTFILE & " - Remove " & ONAME & vbCrLf & _
"when a regular uninstall is no longer possible" & vbCrLf & vbCrLf & _
"Usage:" & vbTab & SCRIPTFILE & vbCrLf & vbCrLf & _
vbTab & "/? ' Displays this help"& vbCrLf & _
vbTab & "/Log [LogfolderPath] ' Custom folder for log files" &
vbCrLf & _
vbTab & "/SkipSD ' Skips the ShortcutDetection in
local profiles" & vbCrLf & _
vbTab & "/NoCancel ' Setup.exe and Msiexec.exe have
no Cancel button" & vbCrLf &_
vbTab & "/Quiet ' Script, Setup.exe and
Msiexec.exe run quiet with no UI" & vbCrLf &_
vbTab & "/ReturnErorOrSuccess ' Returns 0 for a successful
removal. Non-Zero if not." & vbCrLf
Wscript.Quit
End Sub 'ShowSyntax
'-------------------------------------------------------------------------------
' FindInstalledOProducts
'
' Office configuration products are listed with their configuration product
' name in the "Uninstall" key.
'-------------------------------------------------------------------------------
Sub FindInstalledOProducts
Dim ArpItem, prod, cult
Dim sCurKey, sValue, sConfigName, sCulture, sDisplayVersion, sVersionFallback
Dim sUninstallString, sProd
Dim iLeft, iRight
Dim arrKeys, arrProducts, arrCultures
Dim fSystemComponent0, fDisplayVersion, fUninstallString
If dicInstalledSku.Count > 0 Then Exit Sub 'Already done from command line
parser
fDisplayVersion = False
'O16 section
LogOnly "Check for Office C2R products (>=QR8)"
' Check Office Configuration key
If RegReadValue(HKLM, REG_C2RPRODUCTIDS, "ActiveConfiguration",
sActiveConfiguration, "REG_SZ") Then
' Get DisplayVersion
'Try QR8 logic first
fDisplayVersion = RegReadValue(HKLM, REG_C2RPRODUCTIDS &
sActiveConfiguration & "\culture", "x-none", sVersionFallback, "REG_SZ")
If RegEnumKey(HKLM, REG_C2RPRODUCTIDS & sActiveConfiguration & "\culture",
arrCultures) Then
For Each cult In arrCultures
If InStr(LCase(cult), "x-none") > 0 Then
fDisplayVersion = RegReadValue(HKLM, REG_C2RPRODUCTIDS &
sActiveConfiguration & "\culture\" & cult, "Version", sVersionFallback, "REG_SZ")
End If
Next 'cult
End If
' Update product dic
If RegEnumKey(HKLM, REG_C2RPRODUCTIDS & sActiveConfiguration, arrProducts)
Then
For Each prod In arrProducts
sProd = LCase(prod)
If InStr(sProd, ".") > 0 Then sProd = Left(sProd, InStr(sProd,
".") - 1)
Select Case LCase(sProd)
Case "culture", "stream"
Case Else
LogOnly "Found Office C2R product in Configuration: " & prod
' update product dictionary
If NOT dicInstalledSku.Exists(sProd) Then
LogOnly "add new product to dictionary: " & sProd
If RegReadValue(HKLM, REG_C2RPRODUCTIDS &
sActiveConfiguration & "\" & prod & "\x-none", "Version", sDisplayVersion,
"REG_SZ") Then
dicInstalledSku.Add sProd, sDisplayVersion
Else
dicInstalledSku.Add sProd, sVersionFallback
End If
End If
End Select
Next 'prod
End If 'arrProducts
End If 'ActiveConfiguration
End If
Next 'ArpItem
End If
'-------------------------------------------------------------------------------
' EnsureValidWIMetadata
'
' Ensures that only valid metadata entries exist to avoid API failures.
' Invalid entries will be removed
'-------------------------------------------------------------------------------
Sub EnsureValidWIMetadata(hDefKey, sKey, iValidLength)
Dim arrKeys
Dim SubKey
'-------------------------------------------------------------------------------
' CleanOSPP
'
' Clean out licenses from the Office Software Protection Platform
'-------------------------------------------------------------------------------
Sub CleanOSPP
Dim oProductInstances, pi
Dim sCleanOSPP, sCmd, sRetVal
sCleanOSPP = "x64\CleanOSPP.exe"
If Not f64 Then sCleanOSPP = "x86\CleanOSPP.exe"
If oFso.FileExists(sScriptDir & sCleanOSPP) Then
sCmd = sScriptDir & sCleanOSPP
Log " Running: " & sCmd
On Error Resume Next
sRetVal = oWShell.Run(sCmd, 0, True)
Log " Return value: " & sRetVal
On Error Goto 0
Exit Sub
End If
' Initialize the software protection platform object with a filter on Office
2013 products
If iVersionNT > 601 Then
Set oProductInstances = oWmiLocal.ExecQuery("SELECT ID, ApplicationId,
PartialProductKey, Name, ProductKeyID FROM SoftwareLicensingProduct WHERE
ApplicationId = '" & OfficeAppId & "' " & "AND PartialProductKey <> NULL")
Else
Set oProductInstances = oWmiLocal.ExecQuery("SELECT ID, ApplicationId,
PartialProductKey, Name, ProductKeyID FROM OfficeSoftwareProtectionProduct WHERE
ApplicationId = '" & OfficeAppId & "' " & "AND PartialProductKey <> NULL")
End If
'-------------------------------------------------------------------------------
' DelSchtasks
'
' Delete know scheduled tasks.
'-------------------------------------------------------------------------------
Sub DelSchtasks ()
Dim sCmd
LogOnly "FF_INTEGRATEDstreamSchedule"
oWShell.Run "SCHTASKS /Delete /TN FF_INTEGRATEDstreamSchedule /F", 0, False
wscript.sleep 500
LogOnly "FF_INTEGRATEDUPDATEDETECTION"
oWShell.Run "SCHTASKS /Delete /TN FF_INTEGRATEDUPDATEDETECTION /F", 0, False
wscript.sleep 500
LogOnly "C2RAppVLoggingStart"
oWShell.Run "SCHTASKS /Delete /TN C2RAppVLoggingStart /F", 0, False
wscript.sleep 500
LogOnly "OfficeInventoryAgentFallBack"
sCmd = "SCHTASKS /Delete /TN " & Chr(34) & "\Microsoft\Office\
OfficeInventoryAgentFallBack" & Chr(34) & " /F"
oWShell.Run sCmd, 0, False
wscript.sleep 500
LogOnly "OfficeTelemetryAgentFallBack"
sCmd = "SCHTASKS /Delete /TN " & Chr(34) & "\Microsoft\Office\
OfficeTelemetryAgentFallBack" & Chr(34) & " /F"
oWShell.Run sCmd, 0, False
wscript.sleep 500
LogOnly "OfficeInventoryAgentLogOn"
sCmd = "SCHTASKS /Delete /TN " & Chr(34) & "\Microsoft\Office\
OfficeInventoryAgentLogOn" & Chr(34) & " /F"
oWShell.Run sCmd, 0, False
LogOnly "OfficeTelemetryAgentLogOn"
sCmd = "SCHTASKS /Delete /TN " & Chr(34) & "\Microsoft\Office\
OfficeTelemetryAgentLogOn" & Chr(34) & " /F"
oWShell.Run sCmd, 0, False
End Sub
'-------------------------------------------------------------------------------
' CloseOfficeApps
'
' End all running instances of applications that will be removed.
'-------------------------------------------------------------------------------
Sub CloseOfficeApps
Dim Processes, Process, app, prop
Dim sAppName, sOut, sUserWarn
Dim fWait
Dim iRet
'-------------------------------------------------------------------------------
' Uninstall
'
' Identify and invoke default uninstall command for a regular uninstall.
'-------------------------------------------------------------------------------
Sub Uninstall
Dim OseService, srvc
Dim hDefKey, sSubKeyName, sValue, Name, arrNames, arrTypes
Dim sku, prod, sUninstallCmd, sReturn, sMsiProp, sCmd
Dim sPkgFld, sPkgGuid
Dim i
' check if OSE service is *installed, *not disabled, *running under System
context.
LogH2 "Check state of OSE service"
Set OseService = oWmiLocal.Execquery("Select * From Win32_Service Where Name
like 'ose%'")
For Each srvc in OseService
If (srvc.StartMode = "Disabled") AND (Not srvc.ChangeStartMode("Manual") =
0) Then _
Log "Conflict detected: OSE service is disabled"
If (Not srvc.StartName = "LocalSystem") AND (srvc.Change( , , , , , ,
"LocalSystem", "")) Then _
Log "Conflict detected: OSE service not running as LocalSystem"
Next 'srvc
' delete potential blocking registry keys for msiexec based tasks
LogH2 "Remove C2R and App-V registry data"
For Each sku in dicC2RSuite.Keys
' remove the ARP entry
RegDeleteKey HKLM, REG_ARP & sku
Next 'sku
RegDeleteKey HKCU, "SOFTWARE\Microsoft\Office\15.0\ClickToRun"
RegDeleteKey HKLM, "SOFTWARE\Microsoft\Office\15.0\ClickToRun"
RegDeleteKey HKCU, "SOFTWARE\Microsoft\Office\16.0\ClickToRun"
RegDeleteKey HKLM, "SOFTWARE\Microsoft\Office\16.0\ClickToRun"
RegDeleteKey HKCU, "SOFTWARE\Microsoft\Office\ClickToRun"
RegDeleteKey HKLM, "SOFTWARE\Microsoft\Office\ClickToRun"
'-------------------------------------------------------------------------------
' RegWipe
'
' Removal of left behind registry data
'-------------------------------------------------------------------------------
Sub Regwipe
Dim hDefKey, item, name, value, RetVal
Dim sGuid, sSubKeyName, sValue, sCmd
Dim i, iLoopCnt
Dim arrKeys, arrNames, arrTypes, arrTestNames, arrTestTypes
Dim arrMultiSzValues, arrMultiSzNewValues
Dim fDelReg
CloseOfficeApps
' Note: ARP entries have already been cleared in uninstall stage
' HKCU Registration
RegDeleteKey HKCU, "Software\Microsoft\Office\15.0\Registration"
RegDeleteKey HKCU, "Software\Microsoft\Office\16.0\Registration"
RegDeleteKey HKCU, "Software\Microsoft\Office\Registration"
' ARP
' Note: configuration entries have already been removed
' as part of the 'Uninstall' stage
If RegEnumKey(HKLM, REG_ARP, arrKeys) Then
For Each item in arrKeys
If Len(item) > 37 Then
sGuid = UCase(Left(item, 38))
If CheckDelete(sGuid) Then RegDeleteKey HKLM, REG_ARP & item & "\"
End If 'Len(Item)>37
Next 'Item
End If
'-------------------------------------------------------------------------------
' ClearShellIntegrationReg
'
' Delete registry items that may cause Explorer / Windows Shell to have a lock
' on files
'-------------------------------------------------------------------------------
Sub ClearShellIntegrationReg
Dim Processes, Process
Dim sOut
Dim iRet
' BHO
RegDeleteKey HKLM, "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser
Helper Objects\{31D09BA0-12F5-4CCE-BE8A-2923E76605DA}"
RegDeleteKey HKLM, "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser
Helper Objects\{B4F3A835-0E21-4959-BA22-42B3008E02FF}"
RegDeleteKey HKLM, "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser
Helper Objects\{D0498E0A-45B7-42AE-A9AA-ABA463DBD3BF}"
RegDeleteKey HKLM, "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\
Explorer\Browser Helper Objects\{31D09BA0-12F5-4CCE-BE8A-2923E76605DA}"
RegDeleteKey HKLM, "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\
Explorer\Browser Helper Objects\{B4F3A835-0E21-4959-BA22-42B3008E02FF}"
RegDeleteKey HKLM, "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\
Explorer\Browser Helper Objects\{D0498E0A-45B7-42AE-A9AA-ABA463DBD3BF}"
' VolumeCaches
RegDeleteKey HKLM, "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\
VolumeCaches\Microsoft Office Temp Files"
'-------------------------------------------------------------------------------
' FileWipe
'
' Removal of left behind services, files and shortcuts
'-------------------------------------------------------------------------------
Sub FileWipe
Dim scRoot
Dim fDelFolders
fDelFolders = False
CloseOfficeApps
DelSchtasks
If fC2R Then
LogH1 "Delete Files and Folders"
' delete C2R package files
LogH2 "Delete C2R package files"
If oFso.FolderExists(sProgramFiles & "\Microsoft Office 15") _
Or oFso.FolderExists(sProgramFiles & "\Microsoft Office 16") _
Or oFso.FolderExists(oWShell.ExpandEnvironmentStrings("%programfiles%") &
"\Microsoft Office\PackageManifests") _
Or
oFso.FolderExists(oWShell.ExpandEnvironmentStrings("%programfiles(x86)%") & "\
Microsoft Office\PackageManifests") Then
fDelFolders = True
'Log " Attention: Now closing Explorer.exe for file delete
operations"
'Log " Explorer will automatically restart."
wscript.sleep 2000
CloseOfficeApps
End If
' delete Office folders
LogH2 "Delete Office folders"
DeleteFolder sProgramFiles & "\Microsoft Office 15"
DeleteFolder sProgramFiles & "\Microsoft Office 16"
If f64 Then
DeleteFolder sCommonProgramFilesX86 & "\Microsoft Office 15"
DeleteFolder sCommonProgramFilesX86 & "\Microsoft Office 16"
End If
If fDelFolders Then
DeleteFolder sProgramFiles & "\Microsoft Office\PackageManifests"
DeleteFolder sProgramFiles & "\Microsoft Office\PackageSunrisePolicies"
DeleteFolder sProgramFiles & "\Microsoft Office\root"
DeleteFile sProgramFiles & "\Microsoft Office\AppXManifest.xml"
DeleteFile sProgramFiles & "\Microsoft Office\FileSystemMetadata.xml"
If Not dicKeepSku.Count > 0 Then
DeleteFolder sProgramFiles & "\Microsoft Office\Office16"
DeleteFolder sProgramFiles & "\Microsoft Office\Office15"
End If
If f64 Then
DeleteFolder sProgramFilesX86 & "\Microsoft Office\
PackageManifests"
DeleteFolder sProgramFilesX86 & "\Microsoft Office\
PackageSunrisePolicies"
DeleteFolder sProgramFilesX86 & "\Microsoft Office\root"
DeleteFile sProgramFilesX86 & "\Microsoft Office\
AppXManifest.xml"
DeleteFile sProgramFilesX86 & "\Microsoft Office\
FileSystemMetadata.xml"
If Not dicKeepSku.Count > 0 Then
DeleteFolder sProgramFilesX86 & "\Microsoft Office\
Office16"
DeleteFolder sProgramFilesX86 & "\Microsoft Office\
Office15"
End If
End If
End If
'-------------------------------------------------------------------------------
' CleanShortcuts
'
' Recursively search all profile folders for Office shortcuts in scope
'-------------------------------------------------------------------------------
Sub CleanShortcuts (sFolder, fDelete, fUnPin)
Dim oFolder, fld, file, sc, item
Dim fDeleteSC
'-------------------------------------------------------------------------------
' ClearTaskBand
'
' Clears contents from the users taskband to get rid of pinned items
'-------------------------------------------------------------------------------
Sub ClearTaskBand ()
Dim sid
Dim sTaskBand, sHKUTaskBand
Dim arrSid
sTaskBand = "Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband\"
RegDeleteValue HKCU, sTaskBand, "Favorites", False
RegDeleteValue HKCU, sTaskBand, "FavoritesRemovedChanges", False
RegDeleteValue HKCU, sTaskBand, "FavoritesChanges", False
RegDeleteValue HKCU, sTaskBand, "FavoritesResolve", False
RegDeleteValue HKCU, sTaskBand, "FavoritesVersion", False
'-------------------------------------------------------------------------------
' LoadUsersReg
'
' Loads the HKCU for all local users
'-------------------------------------------------------------------------------
Sub LoadUsersReg ()
Dim profilefolder
Dim sValue
'-------------------------------------------------------------------------------
' ClearOfficeHKLM
'
' Recursively search and clear the HKLM Office key from references in scope
'-------------------------------------------------------------------------------
Sub ClearOfficeHKLM (sSubKeyName)
Dim key, name
Dim sValue
Dim arrKeys, arrNames, arrTypes
Dim arrTestNames, arrTestTypes, arrTestKeys
' recursion
If RegEnumKey(HKLM, sSubKeyName, arrKeys) Then
For Each key in arrKeys
ClearOfficeHKLM sSubKeyName & "\" & key
Next 'key
End If
'-------------------------------------------------------------------------------
'
' Helper Functions
'
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------
' IsC2R
'
' Check if the passed in string is related to C2R
' Returns TRUE if in C2R scope
'-------------------------------------------------------------------------------
Function IsC2R (sValue)
Dim fReturn
fReturn = False
IsC2R = fReturn
End Function
'-------------------------------------------------------------------------------
' CheckRegPermissions
'
' Test the permissions on some key registry locations to determine if
' sufficient permissions are given.
'-------------------------------------------------------------------------------
Function CheckRegPermissions
Const KEY_QUERY_VALUE = &H0001
Const KEY_SET_VALUE = &H0002
Const KEY_CREATE_SUB_KEY = &H0004
Const DELETE = &H00010000
Dim sSubKeyName
Dim fReturn
CheckRegPermissions = True
sSubKeyName = "Software\Microsoft\Windows\"
oReg.CheckAccess HKLM, sSubKeyName, KEY_QUERY_VALUE, fReturn
If Not fReturn Then CheckRegPermissions = False
oReg.CheckAccess HKLM, sSubKeyName, KEY_SET_VALUE, fReturn
If Not fReturn Then CheckRegPermissions = False
oReg.CheckAccess HKLM, sSubKeyName, KEY_CREATE_SUB_KEY, fReturn
If Not fReturn Then CheckRegPermissions = False
oReg.CheckAccess HKLM, sSubKeyName, DELETE, fReturn
If Not fReturn Then CheckRegPermissions = False
'-------------------------------------------------------------------------------
' GetMyProcessId
'
' Returns the process id of the own process
'-------------------------------------------------------------------------------
Function GetMyProcessId()
Dim iParentProcessId
iParentProcessId = 0
' try to obtain from creating a new cscript instance
On Error Resume Next
iParentProcessId = GetObject("winmgmts:root\
cimv2").Get("Win32_Process.Handle='" & oWShell.Exec("cscript.exe").ProcessId &
"'").ParentProcessId
On Error Goto 0
If iParentProcessId > 0 Then
' succeeded to obtain the process id
GetMyProcessId = iParentProcessId
Exit Function
End If
'-------------------------------------------------------------------------------
' Delimiter
'
' Returns the delimiter for a passed in string
'-------------------------------------------------------------------------------
Function Delimiter (sVersion)
Dim iCnt, iAsc
'-------------------------------------------------------------------------------
' GetExpandedGuid
'
' Returns the expanded string from a compressed GUID
'-------------------------------------------------------------------------------
Function GetExpandedGuid (sGuid)
Dim i
'-------------------------------------------------------------------------------
' GetCompressedGuid
'
' Returns the compressed string for a GUID
'-------------------------------------------------------------------------------
Function GetCompressedGuid (sGuid)
Dim sCompGUID
Dim i
'-------------------------------------------------------------------------------
' GetDecodedGuid
'
' Returns the GUID from a squished format
'-------------------------------------------------------------------------------
Function GetDecodedGuid(sEncGuid, sGuid)
fFailed = False
sTable =
"0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,"
& _
"0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,"
& _
"0xff,0x00,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,"
& _
"0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0xff,0xff,0xff,0x16,0xff,0x17,"
& _
"0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,"
& _
"0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0xff,0x34,0x35,0x36,"
& _
"0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,"
& _
"0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0xff,0x53,0x54,0xff"
arrTable = Split(sTable,",")
lTotal = 0 : pow85 = 1
For i = 0 To 19
fFailed = True
If i Mod 5 = 0 Then
lTotal = 0 : pow85 = 1
End If ' i Mod 5 = 0
iAsc = Asc(Mid(sEncGuid,i+1,1))
sHex = arrTable(iAsc)
If iAsc >=128 Then Exit For
If sHex = "0xff" Then Exit For
iChr = CInt("&h"&Right(sHex,2))
lTotal = lTotal + (iChr * pow85)
If i Mod 5 = 4 Then sDecode = sDecode & DecToHex(lTotal)
pow85 = pow85 * 85
fFailed = False
Next 'i
If NOT fFailed Then sGuid = "{"&Mid(sDecode,1,8)&"-"& _
Mid(sDecode,13,4)&"-"& _
Mid(sDecode,9,4)&"-"& _
Mid(sDecode,23,2) & Mid(sDecode,21,2)&"-"& _
Mid(sDecode,19,2) & Mid(sDecode,17,2) &
Mid(sDecode,31,2) & Mid(sDecode,29,2) & Mid(sDecode,27,2) & Mid(sDecode,25,2) &"}"
'-------------------------------------------------------------------------------
' DecToHex
'
' Convert a long decimal to hex
'-------------------------------------------------------------------------------
Function DecToHex(lDec)
Dim sHex
Dim iLen
Dim lVal, lExp
Dim arrChr
arrChr = Array("0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F")
sHex = ""
lVal = lDec
lExp = 16^10
While lExp >= 1
If lVal >= lExp Then
sHex = sHex & arrChr(Int(lVal / lExp))
lVal = lVal - lExp * Int(lVal / lExp)
Else
sHex = sHex & "0"
If sHex = "0" Then sHex = ""
End If
lExp = lExp / 16
Wend
iLen = 8 - Len(sHex)
If iLen > 0 Then sHex = String(iLen, "0") & sHex
DecToHex = sHex
End Function
'-------------------------------------------------------------------------------
' RelaunchAs64Host
'
' Relaunch self with 64 bit CScript host
'-------------------------------------------------------------------------------
Sub RelaunchAs64Host
Dim Argument, sCmd
Dim fQuietRelaunch
fQuietRelaunch = False
sCmd = Replace(LCase(wscript.Path), "syswow64", "sysnative") & "\cscript.exe "
& Chr(34) & WScript.scriptFullName & Chr(34)
If fQuiet Then fQuietRelaunch = True
If Wscript.Arguments.Count > 0 Then
For Each Argument in Wscript.Arguments
sCmd = sCmd & " " & chr(34) & Argument & chr(34)
Select Case UCase(Argument)
Case "/Q", "/QUIET"
fQuietRelaunch = True
End Select
Next 'Argument
End If
sCmd = sCmd & " /ChangedHostBitness"
If fQuietRelaunch Then
sCmd = Replace (sCmd, "\cscript.exe", "\wscript.exe")
Wscript.Quit CLng(oWShell.Run (sCmd, 0, True))
Else
Wscript.Quit CLng(oWShell.Run (sCmd, 1, True))
End If
'-------------------------------------------------------------------------------
' RelaunchElevated
'
' Relaunch the script with elevated permissions
'-------------------------------------------------------------------------------
Sub RelaunchElevated
Dim Argument, Process, Processes
Dim iParentProcessId, iSpawnedProcessId
Dim sCmdLine, sRetValFile, sValue
Dim oShell
SetError ERROR_RELAUNCH
' Shell object for relaunch
Set oShell = CreateObject("Shell.Application")
' Note: Command line has not been parsed at this point
' build command line for relaunch
sCmdLine = Chr(34) & WScript.ScriptFullName & Chr(34)
If Wscript.Arguments.Count > 0 Then
For Each Argument in Wscript.Arguments
Select Case UCase(Argument)
Case "/Q","/QUIET"
'Don't try to relaunch in quiet mode
Exit Sub
SetError ERROR_ELEVATION_FAILED
Case "UAC"
'Already tried elevated relaunch
SetError ERROR_ELEVATION_FAILED
Exit Sub
Case Else
sCmdLine = sCmdLine & " " & chr(34) & Argument & chr(34)
End Select
Next 'Argument
End If
' prep work to get the return value from the elevated process
iParentProcessId = GetMyProcessId
'-------------------------------------------------------------------------------
' RelaunchAsCScript
'
' Relaunch self with Cscript as host
'-------------------------------------------------------------------------------
Sub RelaunchAsCScript
Dim Argument
Dim sCmdLine
Dim fQuietNoCScript
fQuietNoCScript = False
SetError ERROR_RELAUNCH
sCmdLine = "cmd.exe /c " & WScript.Path & "\cscript.exe //NOLOGO " & Chr(34) &
WScript.scriptFullName & Chr(34)
If Wscript.Arguments.Count > 0 Then
For Each Argument in Wscript.Arguments
sCmdLine = sCmdLine & " " & chr(34) & Argument & chr(34)
Select Case UCase(Argument)
Case "/Q","/QUIET"
fQuietNoCScript = True
ClearError ERROR_RELAUNCH
End Select
Next 'Argument
End If
sCmdLine = sCmdLine & " " & chr(34) & "/ChangedScriptHost" & chr(34)
'-------------------------------------------------------------------------------
' SetError
'
' Set error bit(s)
'-------------------------------------------------------------------------------
Sub SetError(ErrorBit)
iError = iError OR ErrorBit
Select Case ErrorBit
Case ERROR_DCAF_FAILURE, ERROR_STAGE2, ERROR_ELEVATION_USERDECLINED,
ERROR_ELEVATION, ERROR_SCRIPTINIT
iError = iError OR ERROR_FAIL
End Select
End Sub
'-------------------------------------------------------------------------------
' ClearError
'
' Unset error bit(s)
'-------------------------------------------------------------------------------
Sub ClearError(ErrorBit)
iError = iError AND (ERROR_ALL - ErrorBit)
Select Case ErrorBit
Case ERROR_ELEVATION_USERDECLINED, ERROR_ELEVATION, ERROR_SCRIPTINIT
iError = iError AND (ERROR_ALL - ERROR_FAIL)
End Select
End Sub
'-------------------------------------------------------------------------------
' SetRetVal
'
' Write return value to file
'-------------------------------------------------------------------------------
Sub SetRetVal(iError)
Dim RetValFileStream
'don't fail script execution if writing the return value to file fails
On Error Resume Next
'-------------------------------------------------------------------------------
' GetRetValFromFile
'
' Read return value from file.
' Used to ensure return value can get obtained from an elevated process
'-------------------------------------------------------------------------------
Function GetRetValFromFile ()
Dim RetValFileStream
Dim iRetValFromFile
On Error Resume Next 'don't fail script execution when getting the return value
from file fails
'-------------------------------------------------------------------------------
' CreateLog
'
' Create the removal log file
'-------------------------------------------------------------------------------
Sub CreateLog
Dim DateTime
Dim sLogName
LogH2 "Microsoft Customer Support Services - " & ONAME & " Removal Utility" &
vbCrLf & vbCrLf & _
"Version: " & vbTab & SCRIPTVERSION & vbCrLf & _
"64 bit OS: " & vbTab & f64 & vbCrLf & _
"Removal start: " & vbTab & Time
LogH2 "OS Details: " & sOSinfo & vbCrLf
fLogInitialized = True
End Sub 'CreateLog
'-------------------------------------------------------------------------------
' HiveString
'
' Translates the numeric constant into the human readable registry hive string
'-------------------------------------------------------------------------------
Function HiveString(hDefKey)
Select Case hDefKey
Case HKCR : HiveString = "HKEY_CLASSES_ROOT"
Case HKCU : HiveString = "HKEY_CURRENT_USER"
Case HKLM : HiveString = "HKEY_LOCAL_MACHINE"
Case HKU : HiveString = "HKEY_USERS"
Case Else : HiveString = hDefKey
End Select
End Function
'-------------------------------------------------------------------------------
' RegKeyExists
'
' Returns a boolean for the test on existence of a given registry key
'-------------------------------------------------------------------------------
Function RegKeyExists(hDefKey, sSubKeyName)
Dim arrKeys
RegKeyExists = False
If oReg.EnumKey(hDefKey, sSubKeyName, arrKeys) = 0 Then RegKeyExists = True
End Function
'-------------------------------------------------------------------------------
' RegValExists
'
' Returns a boolean for the test on existence of a given registry value
'-------------------------------------------------------------------------------
Function RegValExists(hDefKey,sSubKeyName,sName)
Dim arrValueTypes, arrValueNames
Dim i
RegValExists = False
If Not RegKeyExists(hDefKey,sSubKeyName) Then Exit Function
If oReg.EnumValues(hDefKey,sSubKeyName,arrValueNames,arrValueTypes) = 0 AND
IsArray(arrValueNames) Then
For i = 0 To UBound(arrValueNames)
If LCase(arrValueNames(i)) = Trim(LCase(sName)) Then RegValExists =
True
Next
End If 'oReg.EnumValues
End Function
'-------------------------------------------------------------------------------
' RegReadValue
'
' Read the value of a given registry entry
' The correct type has to be passed in as argument
'-------------------------------------------------------------------------------
Function RegReadValue(hDefKey, sSubKeyName, sName, sValue, sType)
Dim RetVal
Dim Item
Dim arrValues
RegReadValue = (RetVal = 0)
End Function 'RegReadValue
'-------------------------------------------------------------------------------
' RegEnumValues
'
' Enumerate a registry key to return all values
'-------------------------------------------------------------------------------
Function RegEnumValues(hDefKey, sSubKeyName, arrNames, arrTypes)
Dim RetVal, RetVal64
Dim arrNames32, arrNames64, arrTypes32, arrTypes64
If f64 Then
RetVal = oReg.EnumValues(hDefKey, sSubKeyName, arrNames32, arrTypes32)
RetVal64 = oReg.EnumValues(hDefKey, Wow64Key(hDefKey, sSubKeyName),
arrNames64, arrTypes64)
If (RetVal = 0) AND (NOT RetVal64 = 0) AND IsArray(arrNames32) AND
IsArray(arrTypes32) Then
arrNames = arrNames32
arrTypes = arrTypes32
End If
If (NOT RetVal = 0) AND (RetVal64 = 0) AND IsArray(arrNames64) AND
IsArray(arrTypes64) Then
arrNames = arrNames64
arrTypes = arrTypes64
End If
If (RetVal = 0) AND (RetVal64 = 0) AND IsArray(arrNames32) AND
IsArray(arrNames64) AND IsArray(arrTypes32) AND IsArray(arrTypes64) Then
arrNames = RemoveDuplicates(Split((Join(arrNames32, "\") & "\" &
Join(arrNames64, "\")), "\"))
arrTypes = RemoveDuplicates(Split((Join(arrTypes32, "\") & "\" &
Join(arrTypes64, "\")), "\"))
End If
Else
RetVal = oReg.EnumValues(hDefKey, sSubKeyName, arrNames, arrTypes)
End If 'f64
RegEnumValues = ((RetVal = 0) OR (RetVal64 = 0)) AND IsArray(arrNames) AND
IsArray(arrTypes)
End Function 'RegEnumValues
'-------------------------------------------------------------------------------
' RegEnumKey
'
' Enumerate a registry key to return all subkeys
'-------------------------------------------------------------------------------
Function RegEnumKey(hDefKey, sSubKeyName, arrKeys)
Dim RetVal, RetVal64
Dim arrKeys32, arrKeys64
If f64 Then
RetVal = oReg.EnumKey(hDefKey, sSubKeyName, arrKeys32)
RetVal64 = oReg.EnumKey(hDefKey, Wow64Key(hDefKey, sSubKeyName), arrKeys64)
If (RetVal = 0) AND (NOT RetVal64 = 0) AND IsArray(arrKeys32) Then arrKeys
= arrKeys32
If (Not RetVal = 0) AND (RetVal64 = 0) AND IsArray(arrKeys64) Then arrKeys
= arrKeys64
If (RetVal = 0) AND (RetVal64 = 0) Then
If IsArray(arrKeys32) AND IsArray (arrKeys64) Then
arrKeys = RemoveDuplicates(Split((Join(arrKeys32, "\") & "\" &
Join(arrKeys64, "\")), "\"))
ElseIf IsArray(arrKeys64) Then
arrKeys = arrKeys64
Else
arrKeys = arrKeys32
End If
End If
Else
RetVal = oReg.EnumKey(hDefKey, sSubKeyName, arrKeys)
End If 'f64
RegEnumKey = ((RetVal = 0) OR (RetVal64 = 0)) AND IsArray(arrKeys)
End Function 'RegEnumKey
'-------------------------------------------------------------------------------
' RegDeleteValue
'
' Wrapper around oReg.DeleteValue to handle 64 bit
'-------------------------------------------------------------------------------
Sub RegDeleteValue(hDefKey, sSubKeyName, sName, fRegMultiSZ)
Dim sDelKeyName, sValue
Dim iRetVal
Dim fKeep
'-------------------------------------------------------------------------------
' RegDeleteKey
'
' Wrappper around RegDeleteKeyEx to handle 64bit
'-------------------------------------------------------------------------------
Sub RegDeleteKey(hDefKey, sSubKeyName)
Dim sDelKeyName
Dim fKeep
fKeep = dicKeepReg.Exists(LCase(sSubKeyName))
If (NOT fKeep AND f64) Then fKeep = dicKeepReg.Exists(LCase(Wow64Key(hDefKey,
sSubKeyName)))
If fKeep Then
LogOnly "Disallowing the delete of still required keypath element: " &
HiveString(hDefKey) & "\" & sSubKeyName
If NOT fForce Then Exit Sub
End If
'-------------------------------------------------------------------------------
' RegDeleteKeyEx
'
' Recursively delete a registry structure
'-------------------------------------------------------------------------------
Sub RegDeleteKeyEx(hDefKey, sSubKeyName)
Dim arrSubkeys
Dim sSubkey
Dim iRetVal
'-------------------------------------------------------------------------------
' Wow64Key
'
' Return the 32bit regkey location on a 64bit environment
'-------------------------------------------------------------------------------
Function Wow64Key(hDefKey, sSubKeyName)
Dim iPos
'-------------------------------------------------------------------------------
' RemoveDuplicates
'
' Remove duplicate entries from a one dimensional array
'-------------------------------------------------------------------------------
Function RemoveDuplicates(Array)
Dim Item
Dim dicNoDupes
'-------------------------------------------------------------------------------
' CheckError
'
' Checks the status of 'Err' and logs the error details if <> 0
'-------------------------------------------------------------------------------
Sub CheckError(sModule)
If Err <> 0 Then
LogOnly " Error: " & sModule & " - Source: " & Err.Source & "; Err#
(Hex): " & Hex( Err ) & _
"; Err# (Dec): " & Err & "; Description : " & Err.Description
End If 'Err = 0
Err.Clear
End Sub
'-------------------------------------------------------------------------------
' LogH
'
' Write a header log string to the log file
'-------------------------------------------------------------------------------
Sub LogH (sLog)
LogStream.WriteLine ""
sLog = sLog & vbCrLf & String(Len(sLog), "=")
If NOT fQuiet AND fCScript Then wscript.echo ""
If NOT fQuiet AND fCScript Then wscript.echo sLog
LogStream.WriteLine sLog
End Sub 'Logh
'-------------------------------------------------------------------------------
' LogH1
'
' Write a header log string to the log file
'-------------------------------------------------------------------------------
Sub LogH1 (sLog)
LogStream.WriteLine ""
sLog = sLog & vbCrLf & String(Len(sLog), "-")
If NOT fQuiet AND fCScript Then wscript.echo ""
If NOT fQuiet AND fCScript Then wscript.echo sLog
LogStream.WriteLine sLog
End Sub 'LogH1
'-------------------------------------------------------------------------------
' LogH2
'
' Write w/o indent Cmd window and the log file
'-------------------------------------------------------------------------------
Sub LogH2 (sLog)
If NOT fQuiet AND fCScript Then wscript.echo sLog
LogStream.WriteLine ""
LogStream.WriteLine sLog
End Sub 'LogH2
'-------------------------------------------------------------------------------
' Log
'
' Echos the log string to the Cmd window and the log file
'-------------------------------------------------------------------------------
Sub Log (sLog)
If NOT fQuiet AND fCScript Then wscript.echo sLog
If sLog = "" Then
LogStream.WriteLine
Else
LogStream.WriteLine " " & Time & ": " & sLog
End If
End Sub 'Log
'-------------------------------------------------------------------------------
' LogOnly
'
' Commits the log string to the log file
'-------------------------------------------------------------------------------
Sub LogOnly (sLog)
If sLog = "" Then
LogStream.WriteLine
Else
LogStream.WriteLine " " & Time & ": " & sLog
End If
End Sub 'Log
'-------------------------------------------------------------------------------
' InScope
'
' Check if ProductCode is in scope for removal
'-------------------------------------------------------------------------------
'Check if ProductCode is in scope
Function InScope(sProductCode)
Dim fInScope
Dim sProd
fInScope = False
'LogOnly "Now checking scope of: " & sProductCode
If Len(sProductCode) = 38 Then
'LogOnly "GUID length validated to be 38 characters"
sProd = UCase(sProductCode)
If Right(sProd, PRODLEN) = OFFICEID Then
'LogOnly "Pattern matches " & OFFICEID
If CInt(Mid(sProd, 4, 2)) > 14 Then
If Err <> 0 Then
Err.Clear
Exit Function
End If
'LogOnly "VersionMajor confirmed to be > 14"
Select Case Mid(sProd, 11, 4)
Case "007E", "008F", "008C", "24E1", "237A", "00DD"
'LogOnly "SKUFilter matches scope"
fInScope = True
Case Else
'LogOnly "SKU " & Mid(sProd, 11, 4) & " doesn't match known
integration products scope"
End Select
End If
End If
' Microsoft Online Services Sign-in Assistant (x64 ship and x86 ship)
If sProd = "{6C1ADE97-24E1-4AE4-AEDD-86D3A209CE60}" Then fInScope = True
If sProd = "{9520DDEB-237A-41DB-AA20-F2EF2360DCEB}" Then fInScope = True
If sProd = UCase(sPackageGuid) Then fInScope = True
If sProd = UCase("{9AC08E99-230B-47e8-9721-4577B7F124EA}") Then fInScope =
True
End If '38
InScope = fInScope
End Function 'InScope
'-------------------------------------------------------------------------------
' CheckDelete
'
' Check a ProductCode is known to stay installed
'-------------------------------------------------------------------------------
Function CheckDelete(sProductCode)
CheckDelete = False
' ensure valid GUID length
If NOT Len(sProductCode) = 38 Then Exit Function
' only care if it's in the expected ProductCode pattern
If NOT InScope(sProductCode) Then Exit Function
' check if it's a known product that should be kept
If dicKeepSku.Exists(UCase(sProductCode)) Then Exit Function
CheckDelete = True
End Function 'CheckDelete
'-------------------------------------------------------------------------------
' DeleteService
'
' Delete a service
'-------------------------------------------------------------------------------
'Delete a service
Sub DeleteService(sName)
Dim Services, srvc, Processes, process
Dim sQuery, sStates, sProcessName, sCmd
Dim iRet
sStates = "STARTED;RUNNING"
sQuery = "Select * From Win32_Service Where Name='" & sName & "'"
Set Services = oWmiLocal.Execquery(sQuery)
'-------------------------------------------------------------------------------
' SetupRetVal
'
' Translation for known uninstall return values
'-------------------------------------------------------------------------------
Function SetupRetVal(RetVal)
Select Case RetVal
Case 0 : SetupRetVal = "Success"
'msiexec return values
Case 1259 : SetupRetVal = "APPHELP_BLOCK"
Case 1601 : SetupRetVal = "INSTALL_SERVICE_FAILURE"
Case 1602 : SetupRetVal = "INSTALL_USEREXIT"
Case 1603 : SetupRetVal = "INSTALL_FAILURE"
Case 1604 : SetupRetVal = "INSTALL_SUSPEND"
Case 1605 : SetupRetVal = "UNKNOWN_PRODUCT"
Case 1606 : SetupRetVal = "UNKNOWN_FEATURE"
Case 1607 : SetupRetVal = "UNKNOWN_COMPONENT"
Case 1608 : SetupRetVal = "UNKNOWN_PROPERTY"
Case 1609 : SetupRetVal = "INVALID_HANDLE_STATE"
Case 1610 : SetupRetVal = "BAD_CONFIGURATION"
Case 1611 : SetupRetVal = "INDEX_ABSENT"
Case 1612 : SetupRetVal = "INSTALL_SOURCE_ABSENT"
Case 1613 : SetupRetVal = "INSTALL_PACKAGE_VERSION"
Case 1614 : SetupRetVal = "PRODUCT_UNINSTALLED"
Case 1615 : SetupRetVal = "BAD_QUERY_SYNTAX"
Case 1616 : SetupRetVal = "INVALID_FIELD"
Case 1618 : SetupRetVal = "INSTALL_ALREADY_RUNNING"
Case 1619 : SetupRetVal = "INSTALL_PACKAGE_OPEN_FAILED"
Case 1620 : SetupRetVal = "INSTALL_PACKAGE_INVALID"
Case 1621 : SetupRetVal = "INSTALL_UI_FAILURE"
Case 1622 : SetupRetVal = "INSTALL_LOG_FAILURE"
Case 1623 : SetupRetVal = "INSTALL_LANGUAGE_UNSUPPORTED"
Case 1624 : SetupRetVal = "INSTALL_TRANSFORM_FAILURE"
Case 1625 : SetupRetVal = "INSTALL_PACKAGE_REJECTED"
Case 1626 : SetupRetVal = "FUNCTION_NOT_CALLED"
Case 1627 : SetupRetVal = "FUNCTION_FAILED"
Case 1628 : SetupRetVal = "INVALID_TABLE"
Case 1629 : SetupRetVal = "DATATYPE_MISMATCH"
Case 1630 : SetupRetVal = "UNSUPPORTED_TYPE"
Case 1631 : SetupRetVal = "CREATE_FAILED"
Case 1632 : SetupRetVal = "INSTALL_TEMP_UNWRITABLE"
Case 1633 : SetupRetVal = "INSTALL_PLATFORM_UNSUPPORTED"
Case 1634 : SetupRetVal = "INSTALL_NOTUSED"
Case 1635 : SetupRetVal = "PATCH_PACKAGE_OPEN_FAILED"
Case 1636 : SetupRetVal = "PATCH_PACKAGE_INVALID"
Case 1637 : SetupRetVal = "PATCH_PACKAGE_UNSUPPORTED"
Case 1638 : SetupRetVal = "PRODUCT_VERSION"
Case 1639 : SetupRetVal = "INVALID_COMMAND_LINE"
Case 1640 : SetupRetVal = "INSTALL_REMOTE_DISALLOWED"
Case 1641 : SetupRetVal = "SUCCESS_REBOOT_INITIATED"
Case 1642 : SetupRetVal = "PATCH_TARGET_NOT_FOUND"
Case 1643 : SetupRetVal = "PATCH_PACKAGE_REJECTED"
Case 1644 : SetupRetVal = "INSTALL_TRANSFORM_REJECTED"
Case 1645 : SetupRetVal = "INSTALL_REMOTE_PROHIBITED"
Case 1646 : SetupRetVal = "PATCH_REMOVAL_UNSUPPORTED"
Case 1647 : SetupRetVal = "UNKNOWN_PATCH"
Case 1648 : SetupRetVal = "PATCH_NO_SEQUENCE"
Case 1649 : SetupRetVal = "PATCH_REMOVAL_DISALLOWED"
Case 1650 : SetupRetVal = "INVALID_PATCH_XML"
Case 3010 : SetupRetVal = "SUCCESS_REBOOT_REQUIRED"
Case Else : SetupRetVal = "Unknown Return Value"
End Select
End Function 'SetupRetVal
'-------------------------------------------------------------------------------
' DeleteFile
'
' Wrapper to delete a file
'-------------------------------------------------------------------------------
Sub DeleteFile(sFile)
Dim File, attr
Dim sDelFile, sFileName, sNewPath
Dim fKeep
fKeep = dicKeepFolder.Exists(LCase(sFile))
If (NOT fKeep AND f64) Then fKeep =
dicKeepFolder.Exists(LCase(Wow64Folder(sFile)))
If fKeep Then
LogOnly "Disallowing the delete of still required keypath element: " &
sFile
If NOT fForce Then Exit Sub
End If
If oFso.FileExists(sFile) Then
sDelFile = sFile
ElseIf f64 AND oFso.FileExists(Wow64Folder(sFile)) Then
sDelFile = Wow64Folder(sFile)
Else
LogOnly "Path not found. Cannot not delete folder: " & sFile
Exit Sub
End If
If Not fDetectOnly Then
LogOnly "Delete file: " & sDelFile
Set File = oFso.GetFile(sDelFile)
' ensure read-only flag is not set
attr = File.Attributes
If CBool(attr AND 1) Then File.Attributes = attr AND (attr - 1)
' add folder to empty folder cleanup list
If NOT dicDelFolder.Exists(File.ParentFolder.Path) Then dicDelFolder.Add
File.ParentFolder.Path, File.ParentFolder.Path
' delete the file
sFile = File.Path
File.Delete True
Set File = Nothing
If Err <> 0 Then
CheckError "DeleteFile"
' schedule file for delete on next reboot
ScheduleDeleteFile sFile
End If 'Err <> 0
Else
LogOnly "Preview mode. Disallowing delete for folder: " & sDelFile
End If
On Error Goto 0
End Sub 'DeleteFile
'-------------------------------------------------------------------------------
' DeleteFolder
'
' Wrapper to delete a folder
'-------------------------------------------------------------------------------
Sub DeleteFolder(sFolder)
Dim Folder, fld, attr
Dim sDelFolder, sFolderName, sNewPath, sCmd
Dim fKeep
Case 76
' check on invalid path lengt issues Err 76 (0x4C) "Path not found"
' attempt 'rd' command
CheckError "DeleteFolder"
LogOnly " Attempt to remove with 'rd' command"
sCmd = "cmd.exe /c rd /s " & chr(34) & sDelFolder & chr(34) & " /q"
oWShell.Run sCmd, 0, True
If NOT oFso.FolderExists(sDelFolder) Then Exit Sub
End Select
'-------------------------------------------------------------------------------
' Wow64Folder
'
' Returns the WOW folder structure to handle folder-path operations on
' 64 bit environments
'-------------------------------------------------------------------------------
Function Wow64Folder(sFolder)
If LCase(Left(sFolder, Len(sWinDir & "\System32"))) = LCase(sWinDir & "\
System32") Then
Wow64Folder = sWinDir & "\syswow64" & Right(sFolder, Len(sFolder) -
Len(sWinDir & "\System32"))
ElseIf LCase(Left(sFolder, Len(sProgramFiles))) = LCase(sProgramFiles) Then
Wow64Folder = sProgramFilesX86 & Right(sFolder, Len(sFolder) -
Len(sProgramFiles))
Else
Wow64Folder = "?" 'Return invalid string to ensure the folder cannot exist
End If
End Function 'Wow64Folder
'-------------------------------------------------------------------------------
' ScheduleDeleteFile
'
' Adds a file to the list of items to delete on reboot
'-------------------------------------------------------------------------------
Sub ScheduleDeleteFile (sFile)
If NOT dicDelInUse.Exists(sFile) Then dicDelInUse.Add sFile, sFile Else Exit
Sub
LogOnly "Add file in use for delete on reboot: " & sFile
fRebootRequired = True
SetError ERROR_REBOOT_REQUIRED
End Sub 'ScheduleDeleteFile
'-------------------------------------------------------------------------------
' ScheduleDeleteFolder
'
' Recursively adds a folder and its contents to the list of
' items to delete on reboot
'-------------------------------------------------------------------------------
Sub ScheduleDeleteFolder (sFolder)
Dim oFolder, fld, file, attr
Set oFolder = oFso.GetFolder(sFolder)
' exclude hidden system folders
attr = oFolder.Attributes
If CBool(attr AND 6) Then Exit Sub
'-------------------------------------------------------------------------------
' ScheduleDeleteEx
'
' Schedules the delete of files/folders in use on next reboot by adding
' affected files/folders to the PendingFileRenameOperations registry entry
'-------------------------------------------------------------------------------
Sub ScheduleDeleteEx ()
Dim key, hDefKey, sKeyName, sValueName
Dim i
Dim arrData
hDefKey = HKLM
sKeyName = "SYSTEM\CurrentControlSet\Control\Session Manager"
sValueName = "PendingFileRenameOperations"
'-------------------------------------------------------------------------------
' DeleteEmptyFolders
'
' Deletes an individual folder structure if empty
'-------------------------------------------------------------------------------
Sub DeleteEmptyFolder (sFolder)
Dim Folder
' cosmetic' task don't fail on error
On Error Resume Next
If oFso.FolderExists(sFolder) Then
Set Folder = oFso.GetFolder(sFolder)
If (Folder.Subfolders.Count = 0) AND (Folder.Files.Count = 0) Then
Set Folder = Nothing
SmartDeleteFolder sFolder
End If
End If
CheckError "DeleteEmptyFolder"
On Error Goto 0
End Sub 'DeleteEmptyFolders
'-------------------------------------------------------------------------------
' DeleteEmptyFolders
'
' Delete an empty folder structure
'-------------------------------------------------------------------------------
Sub DeleteEmptyFolders
Dim Folder
Dim sFolder
'-------------------------------------------------------------------------------
' SmartDeleteFolder
'
' Wrapper to delete a folder and the empty parent folder structure
'-------------------------------------------------------------------------------
Sub SmartDeleteFolder(sFolder)
Dim sDelFolder
If oFso.FolderExists(sFolder) Then
sDelFolder = sFolder
ElseIf f64 AND oFso.FolderExists(Wow64Folder(sFolder)) Then
sDelFolder = Wow64Folder(sFolder)
Else
Exit Sub
End If
If Not fDetectOnly Then
LogOnly "Request SmartDelete for folder: " & sDelFolder
SmartDeleteFolderEx sDelFolder
Else
LogOnly "Preview mode. Disallowing SmartDelete request for folder: " &
sDelFolder
End If
End Sub 'SmartDeleteFolder
'-------------------------------------------------------------------------------
' SmartDeleteFolderEx
'
' Executes the folder delete operation(s)
'-------------------------------------------------------------------------------
Sub SmartDeleteFolderEx(sFolder)
Dim Folder
'-------------------------------------------------------------------------------
' RestoreExplorer
'
' Ensure Windows Explorer is restarted if needed
'-------------------------------------------------------------------------------
Sub RestoreExplorer
Dim Processes, Result, oAT, DateTime, JobID
Dim sCmd
'-------------------------------------------------------------------------------
' MyJoin
'
' Replacement function to the internal Join function to prevent failures
' that were seen in some instances
'-------------------------------------------------------------------------------
Function MyJoin(arrToJoin, sSeparator)
Dim sJoined
Dim i
sJoined = ""
If IsArray(arrToJoin) Then
For i = 0 To UBound(arrToJoin)
sJoined = sJoined & arrToJoin(i) & sSeparator
Next 'i
End If
If Len(sJoined) > 1 Then sJoined = Left(sJoined, Len(sJoined) - 1)
MyJoin = sJoined
End Function
'-------------------------------------------------------------------------------
' Rerun
'
' Flag need for reboot and schedule autorun to run the tool again on reboot.
'-------------------------------------------------------------------------------
Sub Rerun ()
Dim sValue
fRebootRequired = True
SetError ERROR_REBOOT_REQUIRED
SetError ERROR_INCOMPLETE
fSetRunOnce = True
' oReg.CreateKey HKCU, "SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce"
' oReg.SetStringValue HKCU, "SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce",
"CleanC2R", "cscript.exe " & chr(34) & sScrubDir & "\" & SCRIPTFILE & chr(34)
End Sub
'-------------------------------------------------------------------------------
' SetRunOnce
'
' Create a RunOnce entry to resume setup after a reboot
'-------------------------------------------------------------------------------
Sub SetRunOnce
Dim sValue