By
zorphnog
I needed a tool that would allow me to edit local group policy files. Registry policy files contain registry information used by the local group policy. Editing these files, followed by a `gpupdate /force` command allows you to enforce the modified local group policy. To my surprise, there aren't many editors out there for this type of file. I found a few implementations across the net, but none of them did everything I wanted or they were not free. Mainly I wanted a tool that provided read/write capabilities for the registry policy file format (.pol) via GUI and command line interface.
So I created 'GPO Registry Editor' to solve this problem and I thought I would share it with the community. The script provides read/write access .pol file through GUI and CLI. I created the editor to be compliant with the Registry Policy File Format. However, in my testing the special values **DeleteKeys and **SecureKey do not conform the the format specification (at least not on Windows XP). Although I did implement these features, they do not perform the expected results when updated via gpupdate.
The CLI has the following usage:
GPO Registry Editor
v1.0.0.0
Provides read and write capabilities for registry policy files.
Usage:
-a --add Add the entry specified by the key, value, type, and data parameters.
-r --remove Remove the entry specified by the key and value parameters.
-d --data Specifies the data of the registry entry.
-f --file Specifies the registry file to load or modify. Use `computer` or `user` to specify the system policy files.
-k --key Specifies the key of the registry entry.
-s --silent Perform the operation silently (no GUI).
-t --type Specifies the type of the registry entry.
-v --value Specifies the value of the registry entry.
-h --help Display this message.
-? --? Display this message.
Example: Add a value to the system Computer/Machine registry file.
gre --add -f=computer -k=Software\Policies\Microsoft\MyTestKey -v="My Test Value" -t REG_SZ -d="Registry Policy File editing"
Example: Remove a value from the system User registry file and suppress GUI error messages.
gre --remove -f user -k Software\Policies\Microsoft\MyTestKey -v "My Test Value" -s
Example: Delete all values of a key from a local file.
gre --add -f=C:\Registry.pol -k=Software\Policies\Microsoft\MyTestKey -v=**DelValsSource code:
#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Compile_Both=y
#AutoIt3Wrapper_UseX64=y
#AutoIt3Wrapper_Res_Description=Provides read and write capabilities for registry policy files.
#AutoIt3Wrapper_Res_Fileversion=1.0.0.0
#AutoIt3Wrapper_Res_Language=1033
#AutoIt3Wrapper_Res_requestedExecutionLevel=asInvoker
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#cs ----------------------------------------------------------------------------
Title: GPO Registry Editor
AutoIt Version: 3.3.8.1
Author: Michael Mims (zorphnog)
Script Function:
Provides read/write capabilities for the registry policy file format (.pol) via GUI or command line interface.
Registry policy files contain registry information used by the local group policy. Editing these files, followed
by a `gpupdate /force` command will update the local group policy.
**Note: On Windows Vista and above, administrator rights are required to save to the system group policy folder.
Compile with the requestedExecutionLevel=requireAdministrator directive to ensure administrator access.
Reference(s):
Registry Policy File Format - http://msdn.microsoft.com/en-us/library/windows/desktop/aa374407(v=vs.85).aspx
#ce ----------------------------------------------------------------------------
#include <EditConstants.au3>
#include <File.au3>
#include <GuiComboBox.au3>
#include <GuiConstants.au3>
#include <GuiListView.au3>
#include <Misc.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include "_OptParse.au3"
; Set Options
Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)
Opt("MustDeclareVars", 1)
; Create mutex
If @AutoItX64 And @Compiled Then
_Singleton("GPO64_RE")
Else
_Singleton("GPO_RE")
EndIf
; Application globals
Global Const $GRE_TITLE = "GPO Registry Editor"
Global Const $GRE_VERSION = "1.0.0.0"
Global Const $GRE_DESC = "Provides read and write capabilities for registry policy files."
; File globals
Global Const $GRE_LOG_FILE = @ScriptDir & "gre.log"
Global Const $USER_REGISTRY_FILE = @SystemDir & "GroupPolicyUserRegistry.pol"
Global Const $MACHINE_REGISTRY_FILE = @SystemDir & "GroupPolicyMachineRegistry.pol"
; Policy file format globals
Global Const $REGISTRY_FILE_SIGNATURE = 0x67655250
Global Const $REGISTRY_FILE_VERSION = 0x00000001
Global Const $REGISTRY_FILE_ENCODING = 2 ; 1 - ANSI, 2 - UTF16 LE, 3 - UTF16 BE, 4 - UTF8
; $g_aEntries array indices
Global Enum $POLENTRY_KEY, $POLENTRY_VALUE, $POLENTRY_TYPE, $POLENTRY_SIZE, $POLENTRY_DATA
; Registry globals
Global Enum $REG_NONE,$REG_SZ,$REG_EXPAND_SZ,$REG_BINARY,$REG_DWORD,$REG_DWORD_BIG_ENDIAN,$REG_LINK,$REG_MULTI_SZ, _
$REG_RESOURCE_LIST,$REG_FULL_RESOURCE_DESCRIPTOR,$REG_RESOURCE_REQUIREMENTS_LIST,$REG_QWORD
Global Const $g_REGTYPES[12] = [ "REG_NONE", "REG_SZ", "REG_EXPAND_SZ", "REG_BINARY", _
"REG_DWORD", "REG_DWORD_BIG_ENDIAN", "REG_LINK", "REG_MULTI_SZ", "REG_RESOURCE_LIST", _
"REG_FULL_RESOURCE_DESCRIPTOR", "REG_RESOURCE_REQUIREMENTS_LIST", "REG_QWORD"]
Global Const $g_ENTRYREGTYPE_CONV[4] = [$REG_SZ,$REG_EXPAND_SZ,$REG_BINARY,$REG_DWORD]
Global Const $g_ENTRYREGTYPES[4] = [$g_REGTYPES[$g_ENTRYREGTYPE_CONV[0]],$g_REGTYPES[$g_ENTRYREGTYPE_CONV[1]], _
$g_REGTYPES[$g_ENTRYREGTYPE_CONV[2]], $g_REGTYPES[$g_ENTRYREGTYPE_CONV[3]]]
; Policy entry type globals
Global Enum $ENTRY_TYPE_NORM,$ENTRY_TYPE_DEL,$ENTRY_TYPE_DELMULVALS,$ENTRY_TYPE_DELALLVALS,$ENTRY_TYPE_DELKEYS, _
$ENTRY_TYPE_SECKEY,$_ENTRY_TYPE_SIZE
Global Const $g_ENTRYTYPES[$_ENTRY_TYPE_SIZE] = ["Normal Entry", "Delete Value", "Delete Multiple Values", _
"Delete All Values", "Delete Subkeys", "Secure Key"]
; $g_MainCtrl array indices
Global Enum $ENT_GUI,$ENT_CBENTR,$ENT_LBKEY,$ENT_INKEY,$ENT_LBVALU,$ENT_INVALU,$ENT_LBTYPE,$ENT_CBTYPE,$ENT_LBDATA, _
$ENT_INDATA,$ENT_LBDESC,$ENT_ILASTENTR,$_ENT_SIZE
; $g_EntryCtrl array indices
Global Enum $MAIN_GUI,$MAIN_LVENTR,$MAIN_BTNEW,$MAIN_BTEDIT,$MAIN_BTDEL,$MAIN_MIMPOL,$MAIN_MIUPOL,$MAIN_MISAVE, _
$MAIN_MISAVA,$_MAIN_SIZE
; Command line option array indices
Global Enum $GRE_OPT_ACTION,$GRE_OPT_FILE,$GRE_OPT_KEY,$GRE_OPT_VALUE,$GRE_OPT_TYPE,$GRE_OPT_DATA,$_GRE_OPT_SIZE
Global Enum $GRE_ACTION_ADD,$GRE_ACTION_REMOVE
; Error code globals
Global Enum Step *2 $GRE_ERROR_NONE=0,$GRE_ERROR_NOFILE=1,$GRE_ERROR_NOACTION,$GRE_ERROR_NOKEY,$GRE_ERROR_NOVALUE, _
$GRE_ERROR_NOTYPE,$GRE_ERROR_INVALIDTYPE,$GRE_ERROR_NODATA,$GRE_ERROR_FILENOTEXIST,$GRE_ERROR_INVALIDARG, _
$GRE_ERROR_DUPLICATEARG,$GRE_ERROR_INVALIDSWITCH,$GRE_ERROR_FILEWRITE,$GRE_ERROR_INVALIDREGISTRYSIG, _
$GRE_ERROR_INVALIDREGISTRYVERSION,$GRE_ERROR_ENTRYNOTFOUND,$GRE_ERROR_DELETEENTRY,$GRE_ERROR_INVALIDSPECVAL
Global $g_aEntries[1][5], $g_MainCtrl[$_MAIN_SIZE], $g_EntryCtrl[$_ENT_SIZE]
Global $g_sRegFile, $g_iEditLVIndex = -1, $g_bOpen = False, $g_bChanged = False, $g_bDebug = False, $g_bSilent = False
_Main()
Func _AddEntry($sKey, $sValue, $iType = 1, $vData = "")
Local $iIndex = _FindEntry($sKey, $sValue)
If @error Then
$iIndex = UBound($g_aEntries)
ReDim $g_aEntries[$iIndex + 1][5]
$g_aEntries[$iIndex][$POLENTRY_KEY] = $sKey & ChrW(0)
$g_aEntries[$iIndex][$POLENTRY_VALUE] = $sValue & ChrW(0)
EndIf
; Force type for special values
If StringLeft($sValue, 2) == "**" Then
__DebugPrint("Special value; forcing REG_SZ", "_AddEntry")
$iType = $REG_SZ
EndIf
$g_aEntries[$iIndex][$POLENTRY_TYPE] = Binary(Int($iType))
; Determine if value is string data and convert properly
Switch $iType
Case $REG_SZ, $REG_EXPAND_SZ
; Check for special values
If StringLeft($sValue, 2) == "**" Then
Select
Case StringMid($sValue, 3, 12) = "DeleteValues" Or StringMid($sValue, 3, 10) = "DeleteKeys"
$vData = StringToBinary(StringRegExpReplace(StringStripWS($vData, 3), "(s*;s*)", ";") & _
ChrW(0), $REGISTRY_FILE_ENCODING)
Case Else
$vData = StringToBinary(ChrW(0x20) & ChrW(0), $REGISTRY_FILE_ENCODING)
EndSelect
Else
$vData = StringToBinary($vData & ChrW(0), $REGISTRY_FILE_ENCODING)
EndIf
Case $REG_DWORD
$vData = Binary(Int($vData))
Case Else
$vData = Binary($vData)
EndSwitch
$g_aEntries[$iIndex][$POLENTRY_SIZE] = BinaryLen($vData)
$g_aEntries[$iIndex][$POLENTRY_DATA] = $vData
Return $iIndex
EndFunc ;==>_AddEntry
Func _CloseFile()
If Not $g_bOpen Then Return True
If $g_bOpen And $g_bChanged Then
Local $iRet = MsgBox(0x1033, $GRE_TITLE, "The current registry file has been modified. Would you like to save the changes?", 0, $g_MainCtrl[$MAIN_GUI])
If $iRet = 2 Then ; CANCEL
Return False
ElseIf $iRet = 6 Then ; YES
_SaveFile()
EndIf
EndIf
_GUICtrlListView_DeleteAllItems($g_MainCtrl[$MAIN_LVENTR])
_ModifyFile(False, False)
$g_aEntries = 0
Dim $g_aEntries[1][5]
$g_sRegFile = ""
Return True
EndFunc ;==>_CloseFile
Func _CreateEntryGUI($bIsNew = True)
Local $sTitle = "Add"
If Not $bIsNew Then $sTitle = "Edit"
$g_EntryCtrl[$ENT_GUI] = GUICreate($sTitle & " Registry Entry", 520, 240, -1, -1, BitOR($WS_POPUP, $WS_CAPTION), $WS_EX_TOOLWINDOW, $g_MainCtrl[$MAIN_GUI])
GUICtrlCreateGroup("", 10, 10, 500, 185)
$g_EntryCtrl[$ENT_CBENTR] = GUICtrlCreateCombo("", 20, 6, 135, 25, BitOR($CBS_DROPDOWNLIST,$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, _ArrayToString($g_ENTRYTYPES), $g_ENTRYTYPES[0])
GUICtrlSetOnEvent(-1, "_Ev_cbEntryType")
$g_EntryCtrl[$ENT_ILASTENTR] = 0
$g_EntryCtrl[$ENT_LBKEY] = GUICtrlCreateLabel("Key:", 20, 44, 45, 17, $SS_RIGHT)
$g_EntryCtrl[$ENT_INKEY] = GUICtrlCreateInput("", 70, 41, 430, 21)
$g_EntryCtrl[$ENT_LBVALU] = GUICtrlCreateLabel("Value:", 20, 76, 45, 17, $SS_RIGHT)
$g_EntryCtrl[$ENT_INVALU] = GUICtrlCreateInput("", 70, 73, 430, 21)
$g_EntryCtrl[$ENT_LBTYPE] = GUICtrlCreateLabel("Type:", 20, 108, 45, 17, $SS_RIGHT)
$g_EntryCtrl[$ENT_CBTYPE] = GUICtrlCreateCombo("", 70, 105, 240, 25, BitOR($CBS_DROPDOWNLIST,$CBS_AUTOHSCROLL))
GUICtrlSetData(-1, _ArrayToString($g_ENTRYREGTYPES), $g_ENTRYREGTYPES[0])
$g_EntryCtrl[$ENT_LBDATA] = GUICtrlCreateLabel("Data:", 20, 140, 45, 17, $SS_RIGHT)
$g_EntryCtrl[$ENT_INDATA] = GUICtrlCreateInput("", 70, 137, 430, 42, $ES_MULTILINE)
$g_EntryCtrl[$ENT_LBDESC] = GUICtrlCreateLabel("", 70, 100, 430, 68)
GUICtrlSetFont(-1, Default, Default, 2)
GUICtrlSetState(-1, $GUI_HIDE)
GUICtrlCreateGroup("", -99, -99, 1, 1)
GUICtrlCreateButton("OK", 350, 205, 75, 25)
GUICtrlSetOnEvent(-1, "_Ev_btEntryOk")
GUICtrlCreateButton("Cancel", 435, 205, 75, 25)
GUICtrlSetOnEvent(-1, "_Ev_btEntryCancel")
EndFunc ;==>_CreateEntryGUI
Func _CreateGUI()
$g_MainCtrl[$MAIN_GUI] = GUICreate($GRE_TITLE, 770, 475, -1, -1, BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU, $WS_MAXIMIZEBOX, $WS_SIZEBOX))
GUISetOnEvent($GUI_EVENT_CLOSE, "_Ev_miFileClose")
GUICtrlCreateListView("Registry Key|Value|Type|Data", 10, 10, 750, 400)
$g_MainCtrl[$MAIN_LVENTR] = GUICtrlGetHandle(-1)
GUICtrlSendMsg(-1, 0x101E, 0, 350)
GUICtrlSendMsg(-1, 0x101E, 1, 150)
GUICtrlSendMsg(-1, 0x101E, 2, 100)
GUICtrlSendMsg(-1, 0x101E, 3, 100)
GUICtrlSetResizing(-1, $GUI_DOCKBORDERS)
$g_MainCtrl[$MAIN_BTNEW] = GUICtrlCreateButton("New...", 10, 420, 75, 25, 0)
GUICtrlSetState(-1, $GUI_DISABLE)
GUICtrlSetOnEvent(-1, "_Ev_btNew")
GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT,$GUI_DOCKBOTTOM,$GUI_DOCKSIZE))
$g_MainCtrl[$MAIN_BTEDIT] = GUICtrlCreateButton("Edit...", 95, 420, 75, 25, 0)
GUICtrlSetState(-1, $GUI_DISABLE)
GUICtrlSetOnEvent(-1, "_Ev_btEdit")
GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT,$GUI_DOCKBOTTOM,$GUI_DOCKSIZE))
$g_MainCtrl[$MAIN_BTDEL] = GUICtrlCreateButton("Delete", 180, 420, 75, 25, 0)
GUICtrlSetState(-1, $GUI_DISABLE)
GUICtrlSetOnEvent(-1, "_Ev_btDelete")
GUICtrlSetResizing(-1, BitOR($GUI_DOCKLEFT,$GUI_DOCKBOTTOM,$GUI_DOCKSIZE))
; Menu items
Local $muFile, $muOpen
$muFile = GUICtrlCreateMenu("File")
GUICtrlCreateMenuItem("New", $muFile)
GUICtrlSetOnEvent(-1, "_Ev_miFileNew")
$muOpen = GUICtrlCreateMenu("Open", $muFile)
$g_MainCtrl[$MAIN_MIMPOL] = GUICtrlCreateMenuItem("Machine Policy", $muOpen)
GUICtrlSetOnEvent(-1, "_Ev_miFileOpenSystem")
$g_MainCtrl[$MAIN_MIUPOL] = GUICtrlCreateMenuItem("User Policy", $muOpen)
GUICtrlSetOnEvent(-1, "_Ev_miFileOpenSystem")
GUICtrlCreateMenuItem("", $muOpen)
GUICtrlCreateMenuItem("File...", $muOpen)
GUICtrlSetOnEvent(-1, "_Ev_miFileOpenFile")
$g_MainCtrl[$MAIN_MISAVE] = GUICtrlCreateMenuItem("Save", $muFile)
GUICtrlSetState(-1, $GUI_DISABLE)
GUICtrlSetOnEvent(-1, "_Ev_miFileSave")
$g_MainCtrl[$MAIN_MISAVA] = GUICtrlCreateMenuItem("Save As...", $muFile)
GUICtrlSetState(-1, $GUI_DISABLE)
GUICtrlSetOnEvent(-1, "_Ev_miFileSave")
GUICtrlCreateMenuItem("", $muFile)
GUICtrlCreateMenuItem("Exit", $muFile)
GUICtrlSetOnEvent(-1, "_Ev_miFileClose")
GUIRegisterMsg($WM_NOTIFY, "_WM_NOTIFY")
GUISetState(@SW_SHOW)
EndFunc ;==>_CreateGUI
Func _DeleteEntry($sKey, $sValue)
Local $iIndex = _FindEntry($sKey, $sValue)
If @error Then Return SetError(@error, 0, -1)
__DebugPrint("--key=" & $sKey & " --value=" & $sValue, "_DeleteEntry")
_ArrayDelete($g_aEntries, $iIndex)
If @error Then Return SetError($GRE_ERROR_DELETEENTRY, 0, -1)
Return 1
EndFunc ;==>_DeleteEntry
Func _EditEntry($iEntry = -1)
If $iEntry == -1 Then
$g_iEditLVIndex = $iEntry
_CreateEntryGUI()
Else
_CreateEntryGUI(False)
_LoadEntryValues($iEntry)
EndIf
GUISetState(@SW_DISABLE, $g_MainCtrl[$MAIN_GUI])
GUISetState(@SW_SHOW, $g_EntryCtrl[$ENT_GUI])
EndFunc ;==>_EditEntry
Func _FindEntry($sKey, $sValue)
Local $iCurrent, $iIndex, $iSize
$iCurrent = 0
$iSize = UBound($g_aEntries)
While $iCurrent < $iSize
$iIndex = _ArraySearch($g_aEntries, $sValue, $iCurrent, 0, 0, 0, 1, $POLENTRY_VALUE)
If @error Then ExitLoop
If $g_aEntries[$iIndex][$POLENTRY_KEY] = $sKey Then
__DebugPrint($iIndex & " " & $g_aEntries[$iIndex][$POLENTRY_KEY], "_FindEntry")
Return $iIndex
EndIf
$iCurrent = $iIndex + 1
WEnd
Return SetError($GRE_ERROR_ENTRYNOTFOUND, 0, -1)
EndFunc ;==>_FindEntry
Func _GetFormattedData($iIndex, $bHex = True)
Switch $g_aEntries[$iIndex][$POLENTRY_TYPE]
Case $REG_SZ, $REG_EXPAND_SZ
Return BinaryToString($g_aEntries[$iIndex][$POLENTRY_DATA], $REGISTRY_FILE_ENCODING)
Case $REG_BINARY
Return "0x" & Hex(Int($g_aEntries[$iIndex][$POLENTRY_DATA]), 8)
Case $REG_DWORD
If $bHex Then Return "0x" & Hex(Int($g_aEntries[$iIndex][$POLENTRY_DATA]), 8)
Return Int($g_aEntries[$iIndex][$POLENTRY_DATA])
Case Else
Return $g_aEntries[$iIndex][4]
EndSwitch
EndFunc ;==>_GetFormattedData
Func _LoadEntryValues($iEntry)
Local $iEntryType, $sKey, $sValue, $iRegType, $sValue
$iEntryType = 0
$sKey = $g_aEntries[$iEntry][$POLENTRY_KEY]
$sValue = $g_aEntries[$iEntry][$POLENTRY_VALUE]
If StringLeft($sValue, 2) == "**" Then
Select
Case StringMid($sValue, 3, 12) = "DeleteValues"
$iEntryType = $ENTRY_TYPE_DELMULVALS
$sValue = BinaryToString($g_aEntries[$iEntry][$POLENTRY_DATA], $REGISTRY_FILE_ENCODING)
$iRegType = 0
Case StringMid($sValue, 3, 4) = "Del."
$iEntryType = $ENTRY_TYPE_DEL
$sValue = StringMid($sValue, 7)
$iRegType = 0
Case StringMid($sValue, 3, 7) = "DelVals"
$iEntryType = $ENTRY_TYPE_DELALLVALS
$sValue = ""
$iRegType = 0
Case StringMid($sValue, 3, 10) = "DeleteKeys"
$iEntryType = $ENTRY_TYPE_DELKEYS
$sValue = BinaryToString($g_aEntries[$iEntry][$POLENTRY_DATA], $REGISTRY_FILE_ENCODING)
$iRegType = 0
Case StringMid($sValue, 3, 9) = "SecureKey"
$iEntryType = $ENTRY_TYPE_SECKEY
$iRegType = Int(StringMid($sValue, 13, 1))
$sValue = ""
EndSelect
_GUICtrlComboBox_SetCurSel($g_EntryCtrl[$ENT_CBENTR], $iEntryType)
_Ev_cbEntryType()
GUICtrlSetData($g_EntryCtrl[$ENT_INKEY], $sKey)
GUICtrlSetData($g_EntryCtrl[$ENT_INVALU], $sValue)
_GUICtrlComboBox_SetCurSel($g_EntryCtrl[$ENT_CBTYPE], $iRegType)
Else
$iRegType = _ArraySearch($g_ENTRYREGTYPE_CONV, $g_aEntries[$iEntry][$POLENTRY_TYPE])
GUICtrlSetData($g_EntryCtrl[$ENT_INKEY], $sKey)
GUICtrlSetData($g_EntryCtrl[$ENT_INVALU], $sValue)
_GUICtrlComboBox_SetCurSel($g_EntryCtrl[$ENT_CBTYPE], $iRegType)
GUICtrlSetData($g_EntryCtrl[$ENT_INDATA], _GetFormattedData($iEntry, False))
EndIf
EndFunc ;==>_LoadEntryValues
Func _Main()
Local $aValidOpts, $aOptions, $sFilename = ""
If @CPUArch = "X64" And Not @AutoItX64 Then
;~ __DebugPrint("X64 architecture detected.", "_Main", True)
Local $sDrive, $sDir, $sFile, $sExt, $sExec
_PathSplit(@ScriptFullPath, $sDrive, $sDir, $sFile, $sExt)
$sExec = @ScriptDir & "" & $sFile & "_x64" & $sExt
;~ __DebugPrint("Attempting 64 bit launch: " & $sExec, "_Main", True)
If FileExists($sExec) Then Exit(RunWait($sExec & " " & _ArrayToString($CmdLine, " ", 1), @WorkingDir))
EndIf
If _ParseOptions($aValidOpts, $aOptions) Then
Local $iOption, $iMatches = 0
If _OptParse_MatchOption("h,help,?", $aOptions, $iOption) Then
_OptParse_ShowUsage($aValidOpts, 1)
Exit($GRE_ERROR_NONE)
EndIf
If _OptParse_MatchOption("D,debug", $aOptions, $iOption) Then
$iMatches += 1
$g_bDebug = True
__PrintEnvironment()
EndIf
If _OptParse_MatchOption("s,silent", $aOptions, $iOption) Then
__DebugPrint("Silent mode set", "_Main")
$iMatches += 1
$g_bSilent = True
_OptParse_SetDisplay(0)
EndIf
If _OptParse_MatchOption("f,file", $aOptions, $iOption) Then
$iMatches += 1
Switch StringLower($aOptions[$iOption][1])
Case "c","comp","computer","m","machine"
$sFilename = $MACHINE_REGISTRY_FILE
Case "u","user"
$sFilename = $USER_REGISTRY_FILE
Case Else
$sFilename = _PathFull($aOptions[$iOption][1])
EndSwitch
__DebugPrint("[file] " & $sFilename, "_Main")
EndIf
; Some command line parameters for testing
; --add -f Registry.pol -k SoftwareMyTestKey -v TestMe -t REG_SZ -d "test, test, test"
; --remove -f Registry.pol -k SoftwareMyTestKey -v TestMe
If _OptParse_MatchOption("a,add,r,remove", $aOptions, $iOption) Then
Local $iReturn, $aValidated = _ValidateOptions($aOptions)
_ReadPolFile($sFilename)
If @error Then Exit(@error)
If $aValidated[$GRE_OPT_ACTION] == $GRE_ACTION_ADD Then
_AddEntry($aValidated[$GRE_OPT_KEY], $aValidated[$GRE_OPT_VALUE], $aValidated[$GRE_OPT_TYPE], _
$aValidated[$GRE_OPT_DATA])
ElseIf $aValidated[$GRE_OPT_ACTION] == $GRE_ACTION_REMOVE Then
_DeleteEntry($aValidated[$GRE_OPT_KEY], $aValidated[$GRE_OPT_VALUE])
If @error Then Exit(@error)
EndIf
_WritePolFile($sFilename)
If @error Then Exit(@error)
Exit($GRE_ERROR_NONE)
ElseIf $iMatches < $aOptions[0][0] Then
_OptParse_Display("No action specified. Use --add or --remove to modify a policy file.", "Error")
Exit($GRE_ERROR_NOACTION)
EndIf
EndIf
_CreateGUI()
If $sFilename <> "" Then _OpenFile($sFilename)
While 1
Sleep(10)
WEnd
EndFunc ;==>_Main
Func _ModifyFile($bNewOpen, $bNewChanged)
Local $sTitle, $aClientSize, $a_iCall
__DebugPrint(StringFormat("[%s, %s] => [%s, %s]", $g_bOpen, $g_bChanged, $bNewOpen, $bNewChanged), "_ModifyFile")
If $bNewOpen <> $g_bOpen Then
If $bNewOpen Then
If $g_sRegFile == "" Then
$sTitle = "New Policy File - " & $GRE_TITLE
Else
$sTitle = $g_sRegFile & " - " & $GRE_TITLE
EndIf
$aClientSize = WinGetClientSize($g_MainCtrl[$MAIN_GUI])
$a_iCall = DllCall("shlwapi.dll", "int", "PathCompactPathW", _
"hwnd", 0, _
"wstr", $sTitle, _
"dword", $aClientSize[0] - 100)
If Not @error Then $sTitle = $a_iCall[2]
WinSetTitle($g_MainCtrl[$MAIN_GUI], 0, $sTitle)
GUICtrlSetState($g_MainCtrl[$MAIN_MISAVA], $GUI_ENABLE)
GUICtrlSetState($g_MainCtrl[$MAIN_BTNEW], $GUI_ENABLE)
GUICtrlSetState($g_MainCtrl[$MAIN_BTEDIT], $GUI_ENABLE)
GUICtrlSetState($g_MainCtrl[$MAIN_BTDEL], $GUI_ENABLE)
Else
WinSetTitle($g_MainCtrl[$MAIN_GUI], 0, $GRE_TITLE)
GUICtrlSetState($g_MainCtrl[$MAIN_MISAVE], $GUI_DISABLE)
GUICtrlSetState($g_MainCtrl[$MAIN_MISAVA], $GUI_DISABLE)
GUICtrlSetState($g_MainCtrl[$MAIN_BTNEW], $GUI_DISABLE)
GUICtrlSetState($g_MainCtrl[$MAIN_BTEDIT], $GUI_DISABLE)
GUICtrlSetState($g_MainCtrl[$MAIN_BTDEL], $GUI_DISABLE)
$g_bChanged = False
EndIf
$g_bOpen = $bNewOpen
Return
EndIf
If $bNewChanged <> $g_bChanged And $g_bOpen Then
If $bNewChanged Then
If $g_sRegFile == "" Then
$sTitle = "New Policy File* - " & $GRE_TITLE
Else
$sTitle = $g_sRegFile & "* - " & $GRE_TITLE
EndIf
$aClientSize = WinGetClientSize($g_MainCtrl[$MAIN_GUI])
$a_iCall = DllCall("shlwapi.dll", "int", "PathCompactPathW", _
"hwnd", 0, _
"wstr", $sTitle, _
"dword", $aClientSize[0] - 100)
If Not @error Then $sTitle = $a_iCall[2]
WinSetTitle($g_MainCtrl[$MAIN_GUI], 0, $sTitle)
GUICtrlSetState($g_MainCtrl[$MAIN_MISAVE], $GUI_ENABLE)
Else
If $g_sRegFile == "" Then
$sTitle = "New Policy File - " & $GRE_TITLE
Else
$sTitle = $g_sRegFile & " - " & $GRE_TITLE
EndIf
$aClientSize = WinGetClientSize($g_MainCtrl[$MAIN_GUI])
$a_iCall = DllCall("shlwapi.dll", "int", "PathCompactPathW", _
"hwnd", 0, _
"wstr", $sTitle, _
"dword", $aClientSize[0] - 100)
If Not @error Then $sTitle = $a_iCall[2]
WinSetTitle($g_MainCtrl[$MAIN_GUI], 0, $sTitle)
GUICtrlSetState($g_MainCtrl[$MAIN_MISAVE], $GUI_DISABLE)
EndIf
EndIf
$g_bChanged = $bNewChanged
EndFunc ;==>_ModifyFile
Func _OpenFile($sFilename = "")
If Not _CloseFile() Then Return
If $sFilename <> "" Then
GUISetCursor(15, 1, $g_MainCtrl[$MAIN_GUI])
_ReadPolFile($sFilename)
If @error Then
GUISetCursor()
Return
EndIf
_UpdateListView()
GUISetCursor()
EndIf
$g_sRegFile = $sFilename
_ModifyFile(True, False)
EndFunc ;==>_OpenFile
Func _ParseOptions(ByRef $aValidOpts, ByRef $aOptions)
Local $local_CmdLine = $CmdLine
$aValidOpts = 0
$aOptions = 0
; Create the valid options list
_OptParse_Init($aValidOpts, $GRE_TITLE & "n", "v" & $GRE_VERSION & "n", $GRE_DESC & "n")
_OptParse_Add($aValidOpts, "a", "add", $OPT_ARG_NONE, "Add the entry specified by the key, value, type, and data parameters.")
_OptParse_Add($aValidOpts, "r", "remove", $OPT_ARG_NONE, "Remove the entry specified by the key and value parameters.")
_OptParse_Add($aValidOpts, "D", "debug", BitOR($OPT_ARG_NONE,$OPT_ARG_HIDDEN), "Record debugging information.")
_OptParse_Add($aValidOpts, "d", "data", $OPT_ARG_REQ, "Specifies the data of the registry entry.")
_OptParse_Add($aValidOpts, "f", "file", $OPT_ARG_REQ, "Specifies the registry file to load or modify. Use `computer` or `user` to specify the system policy files.")
_OptParse_Add($aValidOpts, "k", "key", $OPT_ARG_REQ, "Specifies the key of the registry entry.")
_OptParse_Add($aValidOpts, "s", "silent", $OPT_ARG_NONE, "Perform the operation silently (no GUI).")
_OptParse_Add($aValidOpts, "t", "type", $OPT_ARG_REQ, "Specifies the type of the registry entry.")
_OptParse_Add($aValidOpts, "v", "value", $OPT_ARG_REQ, "Specifies the value of the registry entry.")
_OptParse_Add($aValidOpts, "h", "help", $OPT_ARG_NONE, "Display this message.")
_OptParse_Add($aValidOpts, "?", "?", $OPT_ARG_NONE, "Display this message.")
$aOptions = _OptParse_GetOpts($local_CmdLine, $aValidOpts)
Switch @error
Case 0
_OptParse_SetDisplay(1) ; Display via MsgBox
Return True
Case 1
_OptParse_SetDisplay(1) ; Display via MsgBox
Return False
Case 2
Exit($GRE_ERROR_INVALIDARG)
Case 3
Exit($GRE_ERROR_DUPLICATEARG)
Case 4
Exit($GRE_ERROR_INVALIDSWITCH)
EndSwitch
EndFunc ;==>_ParseOptions
Func _ReadPolFile($sFilename)
Local $hInfile, $bBuffer, $iStart, $iCurrent, $iLength, $iColon, $iNumEntries, $bTemp
If Not FileExists($sFilename) Then
If Not $g_bSilent Then MsgBox(0x1010, $GRE_TITLE, "ERROR: File not found: " & $sFilename)
Return SetError($GRE_ERROR_FILENOTEXIST, 0, -1)
EndIf
$hInfile = FileOpen($sFilename, 16)
$bBuffer = FileRead($hInfile)
FileClose($hInfile)
$iLength = BinaryLen($bBuffer)
If BinaryMid($bBuffer, 1, 4) <> Binary($REGISTRY_FILE_SIGNATURE) Then
If Not $g_bSilent Then MsgBox(0x1010, $GRE_TITLE, "ERROR: Invalid file signature. File will not be processed.")
Return SetError($GRE_ERROR_INVALIDREGISTRYSIG, 0, -1)
EndIf
If BinaryMid($bBuffer, 5, 4) <> Binary($REGISTRY_FILE_VERSION) Then
If Not $g_bSilent Then MsgBox(0x1010, $GRE_TITLE, "ERROR: Invalid registry file version. File will not be processed.")
Return SetError($GRE_ERROR_INVALIDREGISTRYVERSION, 0, -1)
EndIf
$iStart = 9
$iCurrent = 9
$iColon = 0
$iNumEntries = 0
$g_aEntries = 0
Dim $g_aEntries[1][5]
; The body consists of registry values in the following format.
; [key;value;type;size;data]
While $iCurrent < $iLength
$bTemp = BinaryMid($bBuffer, $iCurrent, 2)
Switch $bTemp
Case 0x005B ; Unicode => [
ReDim $g_aEntries[$iNumEntries+1][5]
$iColon = 0
$iStart = $iCurrent + 2
Case 0x005D ; Unicode => ]
$iStart = $iCurrent + 2
$iNumEntries += 1
Case 0x003B ; Unicode => ;
Switch $iColon
Case 0
$g_aEntries[$iNumEntries][$POLENTRY_KEY] = BinaryToString(BinaryMid($bBuffer, $iStart, $iCurrent - $iStart), $REGISTRY_FILE_ENCODING)
$iColon += 1
$iStart = $iCurrent + 2
Case 1
$g_aEntries[$iNumEntries][$POLENTRY_VALUE] = BinaryToString(BinaryMid($bBuffer, $iStart, $iCurrent - $iStart), $REGISTRY_FILE_ENCODING)
$iColon += 1
$iStart = $iCurrent + 2
Case 2
;~ _ArrayDisplay($g_aEntries)
$g_aEntries[$iNumEntries][$POLENTRY_TYPE] = Int(BinaryMid($bBuffer, $iStart, $iCurrent - $iStart))
$iColon += 1
$iStart = $iCurrent + 2
Case 3
$g_aEntries[$iNumEntries][$POLENTRY_SIZE] = Int(BinaryMid($bBuffer, $iStart, $iCurrent - $iStart))
$iColon += 1
$iStart = $iCurrent + 2
$g_aEntries[$iNumEntries][$POLENTRY_DATA] = BinaryMid($bBuffer, $iStart, $g_aEntries[$iNumEntries][$POLENTRY_SIZE])
$iCurrent = $iStart + $g_aEntries[$iNumEntries][$POLENTRY_SIZE] - 2
Case Else
$iColon += 1
$iStart = $iCurrent + 2
EndSwitch
EndSwitch
$iCurrent += 2
WEnd
EndFunc ;==>_ReadPolFile
Func _SaveFile($bSaveAs = False)
If $bSaveAs Or Not FileExists($g_sRegFile) Then
Local $sFilename = FileSaveDialog("Save GPO Registry File...", "", "GPO Registry Files (*.pol)", 18, "", $g_MainCtrl[$MAIN_GUI])
If @error Then Return False
If StringRight($sFilename, 4) <> ".pol" Then $sFilename &= ".pol"
$g_sRegFile = $sFilename
EndIf
_WritePolFile($g_sRegFile)
If @error Then Return False
_ModifyFile($g_bOpen, False)
EndFunc ;==>_SaveFile
Func _UpdateListView()
Local $i, $iMax
_GUICtrlListView_BeginUpdate($g_MainCtrl[$MAIN_LVENTR])
_GUICtrlListView_DeleteAllItems($g_MainCtrl[$MAIN_LVENTR])
$iMax = UBound($g_aEntries) - 1
For $i=0 To $iMax
_GUICtrlListView_AddItem($g_MainCtrl[$MAIN_LVENTR], $g_aEntries[$i][$POLENTRY_KEY])
_GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $i, $g_aEntries[$i][$POLENTRY_VALUE], 1)
_GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $i, $g_REGTYPES[$g_aEntries[$i][$POLENTRY_TYPE]], 2)
_GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $i, _GetFormattedData($i), 3)
Next
_GUICtrlListView_EndUpdate($g_MainCtrl[$MAIN_LVENTR])
EndFunc ;==>_UpdateListView
Func _ValidateOptions($aOptions)
Local $aReturn[$_GRE_OPT_SIZE], $iOption
; Check for policy file definition
If Not _OptParse_MatchOption("f,file", $aOptions, $iOption) Then
_OptParse_Display("File required. Use --file to specify the policy file to modify.", "Error")
Exit($GRE_ERROR_NOFILE)
EndIf
; Check for key definition
If _OptParse_MatchOption("k,key", $aOptions, $iOption) Then
__DebugPrint("[key] " & $aOptions[$iOption][1], "_ValidateOptions")
$aReturn[$GRE_OPT_KEY] = $aOptions[$iOption][1]
Else
_OptParse_Display("Key required. Use --key to specify the registry key to modify.", "Error")
Exit($GRE_ERROR_NOKEY)
EndIf
; Check for value definition
If _OptParse_MatchOption("v,value", $aOptions, $iOption) Then
__DebugPrint("[value] " & $aOptions[$iOption][1], "_ValidateOptions")
$aReturn[$GRE_OPT_VALUE] = $aOptions[$iOption][1]
Else
_OptParse_Display("Value required. Use --value to specify the registry value to modify.", "Error")
Exit($GRE_ERROR_NOVALUE)
EndIf
If _OptParse_MatchOption("r,remove", $aOptions, $iOption) Then
__DebugPrint("[action] remove", "_ValidateOptions")
$aReturn[$GRE_OPT_ACTION] = $GRE_ACTION_REMOVE
Return $aReturn
ElseIf _OptParse_MatchOption("a,add", $aOptions, $iOption) Then
Local $sType, $sData, $bTypeRequired = True, $bDataRequired = True
__DebugPrint("[action] add", "_ValidateOptions")
$aReturn[$GRE_OPT_ACTION] = $GRE_ACTION_ADD
; Handle special values and determine whether data is required
If StringLeft($aReturn[$GRE_OPT_VALUE], "2") == "**" Then
Select
Case StringMid($aReturn[$GRE_OPT_VALUE], 3, 4) = "Del." Or _
StringMid($aReturn[$GRE_OPT_VALUE], 3, 7) = "DelVals" Or _
StringMid($aReturn[$GRE_OPT_VALUE], 3, 9) = "SecureKey"
__DebugPrint("Special value detected; data not required.", "_ValidateOptions")
$bTypeRequired = False
$bDataRequired = False
Case StringMid($aReturn[$GRE_OPT_VALUE], 3, 12) = "DeleteValues" Or _
StringMid($aReturn[$GRE_OPT_VALUE], 3, 10) = "DeleteKeys"
__DebugPrint("Special value detected; data required.", "_ValidateOptions")
$bTypeRequired = False
Case Else
_OptParse_Display("Invalid special value: " & $aReturn[$GRE_OPT_VALUE], "Error")
Exit($GRE_ERROR_INVALIDSPECVAL)
EndSelect
EndIf
; Check for type definition
If _OptParse_MatchOption("t,type", $aOptions, $iOption) Then
__DebugPrint("[type] " & $aOptions[$iOption][1], "_ValidateOptions")
$aReturn[$GRE_OPT_TYPE] = StringUpper($aOptions[$iOption][1])
$aReturn[$GRE_OPT_TYPE] = _ArraySearch($g_REGTYPES, $aReturn[$GRE_OPT_TYPE])
If @error Then
_OptParse_Display("Invalid type argument: " & $aOptions[$iOption][1], "Error")
Exit($GRE_ERROR_INVALIDTYPE)
EndIf
ElseIf $bTypeRequired Then
_OptParse_Display("Type required. Use --type to specify the registry type to add.", "Error")
Exit($GRE_ERROR_NOTYPE)
EndIf
; Check for data definition
If _OptParse_MatchOption("d,data", $aOptions, $iOption) Then
__DebugPrint("[data] " & $aOptions[$iOption][1], "_ValidateOptions")
$aReturn[$GRE_OPT_DATA] = $aOptions[$iOption][1]
ElseIf $bDataRequired Then
_OptParse_Display("Data required. Use --data to specify the registry data to add.", "Error")
Exit($GRE_ERROR_NODATA)
EndIf
Return $aReturn
EndIf
EndFunc ;==>_ValidateOptions
Func _WritePolFile($sFilename)
Local $hOutfile, $iMax
; Open file for writing
__DebugPrint("Writing output file...", "_WritePolFile")
$hOutfile = FileOpen($sFilename, 26)
If $hOutfile = -1 Then
If Not $g_bSilent Then MsgBox(0x1010, $GRE_TITLE, "ERROR: File could not be created [" & $sFilename & "].")
Return SetError($GRE_ERROR_FILEWRITE, 0, -1)
EndIf
; Write header information
FileWrite($hOutfile, Binary($REGISTRY_FILE_SIGNATURE))
FileWrite($hOutfile, Binary($REGISTRY_FILE_VERSION))
; Write entries
$iMax = UBound($g_aEntries) - 1
For $i = 0 To $iMax
FileWrite($hOutfile, StringToBinary("[" & $g_aEntries[$i][$POLENTRY_KEY], $REGISTRY_FILE_ENCODING))
FileWrite($hOutfile, StringToBinary(";", $REGISTRY_FILE_ENCODING))
FileWrite($hOutfile, StringToBinary($g_aEntries[$i][$POLENTRY_VALUE], $REGISTRY_FILE_ENCODING))
FileWrite($hOutfile, StringToBinary(";", $REGISTRY_FILE_ENCODING))
FileWrite($hOutfile, $g_aEntries[$i][$POLENTRY_TYPE])
FileWrite($hOutfile, StringToBinary(";", $REGISTRY_FILE_ENCODING))
FileWrite($hOutfile, $g_aEntries[$i][$POLENTRY_SIZE])
FileWrite($hOutfile, StringToBinary(";", $REGISTRY_FILE_ENCODING))
FileWrite($hOutfile, $g_aEntries[$i][$POLENTRY_DATA])
FileWrite($hOutfile, StringToBinary("]", $REGISTRY_FILE_ENCODING))
Next
; Close file
FileClose($hOutfile)
EndFunc ;==>_WritePolFile
Func _Ev_btDelete()
Local $iIndex = _GUICtrlListView_GetSelectedIndices($g_MainCtrl[$MAIN_LVENTR])
If $iIndex <> "" Then
_DeleteEntry(_GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $iIndex), _GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $iIndex, 1))
If Not @error Then
_GUICtrlListView_DeleteItem($g_MainCtrl[$MAIN_LVENTR], $iIndex)
_ModifyFile($g_bOpen, True)
EndIf
EndIf
EndFunc ;==>_Ev_btDelete
Func _Ev_btEdit()
Local $iEntry, $iIndex = _GUICtrlListView_GetSelectedIndices($g_MainCtrl[$MAIN_LVENTR])
If $iIndex <> "" Then
$iEntry = _FindEntry(_GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $iIndex), _GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $iIndex, 1))
If Not @error Then
$g_iEditLVIndex = $iIndex
_EditEntry($iEntry)
EndIf
EndIf
EndFunc ;==>_Ev_btEdit
Func _Ev_btEntryCancel()
GUISetState(@SW_ENABLE, $g_MainCtrl[$MAIN_GUI])
GUIDelete($g_EntryCtrl[$ENT_GUI])
EndFunc ;==>_Ev_btEntryCancel
Func _Ev_btEntryOk()
Local $iIndex, $iEntry, $sKey, $sValue, $iType, $vData
$sKey = GUICtrlRead($g_EntryCtrl[$ENT_INKEY])
$sValue = GUICtrlRead($g_EntryCtrl[$ENT_INVALU])
$iType = $g_ENTRYREGTYPE_CONV[_GUICtrlComboBox_GetCurSel($g_EntryCtrl[$ENT_CBTYPE])]
$vData = GUICtrlRead($g_EntryCtrl[$ENT_INDATA])
Switch _GUICtrlComboBox_GetCurSel($g_EntryCtrl[$ENT_CBENTR])
Case $ENTRY_TYPE_DEL
$sValue = "**Del." & $sValue
$iType = $REG_SZ
Case $ENTRY_TYPE_DELMULVALS
$vData = $sValue
$sValue = "**DeleteValues"
$iType = $REG_SZ
Case $ENTRY_TYPE_DELALLVALS
$sValue = "**DelVals."
$iType = $REG_SZ
Case $ENTRY_TYPE_DELKEYS
$vData = $sValue
$sValue = "**DeleteKeys" & ChrW(0)
$iType = $REG_SZ
Case $ENTRY_TYPE_SECKEY
$sValue = "**SecureKey=" & _GUICtrlComboBox_GetCurSel($g_EntryCtrl[$ENT_CBTYPE])
$iType = $REG_SZ
EndSwitch
$iEntry = _AddEntry($sKey, $sValue, $iType, $vData)
If $g_iEditLVIndex == -1 Then
$iIndex = _GUICtrlListView_AddItem($g_MainCtrl[$MAIN_LVENTR], $g_aEntries[$iEntry][$POLENTRY_KEY])
If $iIndex <> -1 Then
_GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $iIndex, $g_aEntries[$iEntry][$POLENTRY_VALUE], 1)
_GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $iIndex, $g_REGTYPES[$g_aEntries[$iEntry][$POLENTRY_TYPE]], 2)
_GUICtrlListView_AddSubItem($g_MainCtrl[$MAIN_LVENTR], $iIndex, _GetFormattedData($iEntry), 3)
EndIf
Else
Local $sLVKey, $sLVValue
$sLVKey = _GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex)
$sLVValue = _GUICtrlListView_GetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, 1)
; Update list view entry
_GUICtrlListView_SetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, $g_aEntries[$iEntry][$POLENTRY_KEY])
_GUICtrlListView_SetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, $g_aEntries[$iEntry][$POLENTRY_VALUE], 1)
_GUICtrlListView_SetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, $g_REGTYPES[$g_aEntries[$iEntry][$POLENTRY_TYPE]], 2)
_GUICtrlListView_SetItemText($g_MainCtrl[$MAIN_LVENTR], $g_iEditLVIndex, _GetFormattedData($iEntry), 3)
; Delete old entry if necessary
If $sLVKey <> $sKey Or $sLVValue <> $sValue Then _DeleteEntry($sLVKey, $sLVValue)
EndIf
_ModifyFile($g_bOpen, True)
GUISetState(@SW_ENABLE, $g_MainCtrl[$MAIN_GUI])
GUIDelete($g_EntryCtrl[$ENT_GUI])
EndFunc ;==>_Ev_btEntryOk
Func _Ev_btNew()
_EditEntry()
EndFunc ;==>_Ev_btNew
Func _Ev_cbEntryType()
Local $iSelected = _GUICtrlComboBox_GetCurSel($g_EntryCtrl[$ENT_CBENTR])
If $iSelected = $g_EntryCtrl[$ENT_ILASTENTR] Then Return
Switch $iSelected
Case $ENTRY_TYPE_NORM
GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_HIDE)
GUICtrlSetData($g_EntryCtrl[$ENT_LBVALU], "Value:")
GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_SHOW)
GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_SHOW)
GUICtrlSetPos($g_EntryCtrl[$ENT_LBTYPE], 20, 108)
GUICtrlSetData($g_EntryCtrl[$ENT_LBTYPE], "Type:")
GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_SHOW)
GUICtrlSetPos($g_EntryCtrl[$ENT_CBTYPE], 70, 105, 240)
_GUICtrlComboBox_ResetContent($g_EntryCtrl[$ENT_CBTYPE])
GUICtrlSetData($g_EntryCtrl[$ENT_CBTYPE], _ArrayToString($g_ENTRYREGTYPES), $g_ENTRYREGTYPES[0])
GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_SHOW)
GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_SHOW)
GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_SHOW)
Case $ENTRY_TYPE_DEL
GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
GUICtrlSetData($g_EntryCtrl[$ENT_LBVALU], "Value:")
GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_SHOW)
GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_SHOW)
GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 100)
GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], "Deletes the value from the associated key.")
GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
Case $ENTRY_TYPE_DELMULVALS
GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
GUICtrlSetData($g_EntryCtrl[$ENT_LBVALU], "Values:")
GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_SHOW)
GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_SHOW)
GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 100)
GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], _
StringFormat("Deletes multiple values from the associated key. Specify multiple values using a " & _
"semicolon-delimited list.rnExample: type;size;NoRun;NoFind"))
GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
Case $ENTRY_TYPE_DELALLVALS
GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 68)
GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], "Deletes all values from the associated key.")
GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
Case $ENTRY_TYPE_DELKEYS
GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
GUICtrlSetData($g_EntryCtrl[$ENT_LBVALU], "Subkeys:")
GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_SHOW)
GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_SHOW)
GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 100)
GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], _
StringFormat("Deletes multiple subkeys from the associated key. Specify multiple subkeys using a " & _
"semicolon-delimited list.rnExample: type;size;NoRun;NoFind"))
GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
Case $ENTRY_TYPE_SECKEY
GUICtrlSetState($g_EntryCtrl[$ENT_LBVALU], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_INVALU], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_LBDATA], $GUI_HIDE)
GUICtrlSetState($g_EntryCtrl[$ENT_INDATA], $GUI_HIDE)
GUICtrlSetPos($g_EntryCtrl[$ENT_LBTYPE], 20, 76)
GUICtrlSetData($g_EntryCtrl[$ENT_LBTYPE], "Secure:")
GUICtrlSetState($g_EntryCtrl[$ENT_LBTYPE], $GUI_SHOW)
GUICtrlSetPos($g_EntryCtrl[$ENT_CBTYPE], 70, 73, 50)
_GUICtrlComboBox_ResetContent($g_EntryCtrl[$ENT_CBTYPE])
GUICtrlSetData($g_EntryCtrl[$ENT_CBTYPE], "False|True", "True")
GUICtrlSetState($g_EntryCtrl[$ENT_CBTYPE], $GUI_SHOW)
GUICtrlSetPos($g_EntryCtrl[$ENT_LBDESC], 70, 100)
GUICtrlSetData($g_EntryCtrl[$ENT_LBDESC], _
"Secures the associated key, giving administrators and the system full control, and giving " & _
"users read-only access. If set to False, access to the key resets to whatever is set on the root.")
GUICtrlSetState($g_EntryCtrl[$ENT_LBDESC], $GUI_SHOW)
EndSwitch
$g_EntryCtrl[$ENT_ILASTENTR] = $iSelected
EndFunc ;==>_Ev_cbEntryType
Func _Ev_miFileClose()
If Not _CloseFile() Then Return
Exit($GRE_ERROR_NONE)
EndFunc ;==>_Ev_miFileClose
Func _Ev_miFileNew()
If Not _CloseFile() Then Return
_OpenFile()
EndFunc ;==>_Ev_miFileNew
Func _Ev_miFileOpenFile()
If Not _CloseFile() Then Return
Local $sFilename = FileOpenDialog("Select GPO Registry File", "", "GPO Registry Files (*.pol)|All Files (*.*)", 3, "", $g_MainCtrl[$MAIN_GUI])
If @error Then Return
_OpenFile($sFilename)
EndFunc ;==>_Ev_miFileOpenFile
Func _Ev_miFileOpenSystem()
If Not _CloseFile() Then Return
Switch @GUI_CtrlId
Case $g_MainCtrl[$MAIN_MIMPOL]
_OpenFile($MACHINE_REGISTRY_FILE)
Case $g_MainCtrl[$MAIN_MIUPOL]
_OpenFile($USER_REGISTRY_FILE)
EndSwitch
EndFunc ;==>_Ev_miFileOpenSystem
Func _Ev_miFileSave()
Switch @GUI_CtrlId
Case $g_MainCtrl[$MAIN_MISAVE]
_SaveFile()
Case $g_MainCtrl[$MAIN_MISAVA]
_SaveFile(True)
EndSwitch
EndFunc ;==>_Ev_miFileSave
Func _WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
Local $tNMHDR, $hWndFrom, $iCode
$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$hWndFrom = DllStructGetData($tNMHDR, "hWndFrom")
$iCode = DllStructGetData($tNMHDR, "Code")
If $hWndFrom = $g_MainCtrl[$MAIN_LVENTR] And $iCode == $NM_DBLCLK Then _Ev_btEdit()
Return $GUI_RUNDEFMSG
EndFunc ;==>_WM_NOTIFY
Func __DebugPrint($sMessage, $sSource = "Info", $bOverride = False)
If Not $g_bDebug And Not $bOverride Then Return
Local $sLine = StringFormat("%02d%02d%04d %02d:%02d:%02d %-20s %srn", _
@MON, @MDAY, @YEAR, @HOUR, @MIN, @SEC, $sSource, $sMessage)
If @Compiled Then
FileWrite($GRE_LOG_FILE, $sLine)
Else
ConsoleWrite($sLine)
EndIf
EndFunc ;==>__DebugPrint
Func __PrintEnvironment()
Local $sEnv = @CRLF
$sEnv &= StringFormat(" OSVersion: %srn", @OSVersion)
$sEnv &= StringFormat(" OSArch: %srn", @OSArch)
$sEnv &= StringFormat(" AutoItX64: %srn", @AutoItX64)
$sEnv &= StringFormat(" WindowsDir: %srn", @WindowsDir)
$sEnv &= StringFormat(" SystemDir: %srn", @SystemDir)
$sEnv &= StringFormat(" TempDir: %srn", @TempDir)
$sEnv &= StringFormat(" ComSpec: %srn", @ComSpec)
$sEnv &= StringFormat(" ProgramFilesDir: %s", @ProgramFilesDir)
__DebugPrint($sEnv, "__PrintEnvironment", True)
EndFunc ;==>__PrintEnvironmentEnjoy and please let me know if there are any issues.
GRE_source.zip
**Note: On Windows Vista and above, administrator rights are required to save to the system group policy folder. Compile with the requestedExecutionLevel=requireAdministrator directive to ensure administrator access.