Skip to content

Commit

Permalink
add registry section
Browse files Browse the repository at this point in the history
  • Loading branch information
spddl committed Mar 11, 2023
1 parent e4a4e6a commit e56fa55
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 2 deletions.
94 changes: 94 additions & 0 deletions NtQueryKey.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package main

import (
"bytes"
"fmt"
"log"
"syscall"
"unicode/utf16"
"unicode/utf8"
"unsafe"
)

var (
modntdll = syscall.NewLazyDLL("ntdll")
procNtQueryKey = modntdll.NewProc("NtQueryKey")
)

// The KeyInformationClass constants have been derived from the KEY_INFORMATION_CLASS enum definition.
type KeyInformationClass uint32

const (
KeyBasicInformation KeyInformationClass = iota
KeyNodeInformation
KeyFullInformation
KeyNameInformation
KeyCachedInformation
KeyFlagsInformation
KeyVirtualizationInformation
KeyHandleTagsInformation
MaxKeyInfoClass
)

const STATUS_BUFFER_TOO_SMALL = 0xC0000023

// OUT-parameter: KeyInformation, ResultLength.
// *OPT-parameter: KeyInformation.
func NtQueryKey(
keyHandle uintptr,
keyInformationClass KeyInformationClass,
keyInformation *byte,
length uint32,
resultLength *uint32,
) int {
r0, _, _ := procNtQueryKey.Call(keyHandle,
uintptr(keyInformationClass),
uintptr(unsafe.Pointer(keyInformation)),
uintptr(length),
uintptr(unsafe.Pointer(resultLength)))
return int(r0)
}

// GetRegistryLocation(uintptr(device.reg))

func GetRegistryLocation(regHandle uintptr) (string, error) {
var size uint32 = 0
result := NtQueryKey(regHandle, KeyNameInformation, nil, 0, &size)
if result == STATUS_BUFFER_TOO_SMALL {
buf := make([]byte, size)
if result := NtQueryKey(regHandle, KeyNameInformation, &buf[0], size, &size); result == 0 {
regPath, err := DecodeUTF16(buf)
if err != nil {
log.Println(err)
}

tempRegPath := replaceRegistryMachine(regPath)
tempRegPath = generalizeControlSet(tempRegPath)

return `HKEY_LOCAL_MACHINE\` + tempRegPath, nil
}
} else {
return "", fmt.Errorf("error: 0x%X", result)
}
return "", nil
}

func DecodeUTF16(b []byte) (string, error) {
if len(b)%2 != 0 {
return "", fmt.Errorf("must have even length byte slice")
}

u16s := make([]uint16, 1)
ret := &bytes.Buffer{}
b8buf := make([]byte, 4)

lb := len(b)
for i := 0; i < lb; i += 2 {
u16s[0] = uint16(b[i]) + (uint16(b[i+1]) << 8)
r := utf16.Decode(u16s)
n := utf8.EncodeRune(b8buf, r[0])
ret.Write(b8buf[:n])
}

return ret.String(), nil
}
76 changes: 76 additions & 0 deletions SaveBackup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package main

import (
"bytes"
"fmt"
"log"
"strings"
"text/template"

"github.com/lxn/walk"
)

func createRegFile(regpath string, item *Device) string {
packageInfo := template.New("packageInfo")
tmplProperty := template.Must(packageInfo.Parse(string(`Windows Registry Editor Version 5.00
[{{.RegPath}}\Interrupt Management]
[{{.RegPath}}\Interrupt Management\Affinity Policy]
"DevicePolicy"=dword:{{printf "%08d" .Device.DevicePolicy}}
{{if eq .Device.DevicePriority 0}}"DevicePriority"=-{{else}}"DevicePriority"=dword:{{printf "%08d" .Device.DevicePriority}}{{end}}
{{if ne .Device.DevicePolicy 4}}"AssignmentSetOverride"=-{{else}}"AssignmentSetOverride"=hex:{{.AssignmentSetOverride}}{{end}}
[{{.RegPath}}\Interrupt Management\MessageSignaledInterruptProperties]
"MSISupported"=dword:{{printf "%08d" .Device.MsiSupported}}
{{if eq .Device.MsiSupported 1}}{{if ne .Device.MessageNumberLimit 0}}"MessageNumberLimit"=dword:{{printf "%08d" .Device.MessageNumberLimit}}{{end}}{{else}}"MessageNumberLimit"=-{{end}}
`)))

var buf bytes.Buffer
err := tmplProperty.Execute(&buf, struct {
RegPath string
Device Device
AssignmentSetOverride string
}{
regpath,
*item,
addComma(fmt.Sprintf("%x", item.AssignmentSetOverride)),
})

if err != nil {
log.Fatalln(err)
}

return strings.ReplaceAll(buf.String(), "\n", "\r\n")

}

func addComma(data string) string {
var b strings.Builder
for i := 0; i < len(data); i++ {
if i != 0 && i%2 == 0 {
b.WriteString(",")
}
b.WriteString(string(data[i]))
}

return b.String()
}

func saveFileExplorer(owner walk.Form, path, filename, title, filter string) (filePath string, cancel bool, err error) {
dlg := new(walk.FileDialog)

dlg.Title = title
dlg.InitialDirPath = path
dlg.Filter = filter
dlg.FilePath = filename

ok, err := dlg.ShowSave(owner)
if err != nil {
return "", !ok, err
} else if !ok {
return "", !ok, nil
}

return dlg.FilePath, !ok, nil
}
56 changes: 56 additions & 0 deletions dialog.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package main

import (
"log"
"os"
"os/exec"
"sort"
"strings"

"github.com/lxn/walk"
"golang.org/x/sys/windows/registry"

//lint:ignore ST1001 standard behavior lxn/walk
. "github.com/lxn/walk/declarative"
)
Expand Down Expand Up @@ -116,6 +119,7 @@ func RunDialog(owner walk.Form, device *Device) (int, error) {
if device.MsiSupported == 0 {
device.MsiSupported = 1
deviceMessageNumberLimitNE.SetEnabled(true)
device.MessageNumberLimit = uint32(deviceMessageNumberLimitNE.Value())
} else {
device.MsiSupported = 0
deviceMessageNumberLimitNE.SetEnabled(false)
Expand Down Expand Up @@ -222,6 +226,58 @@ func RunDialog(owner walk.Form, device *Device) (int, error) {
},
},
},

GroupBox{
Title: "Registry",
Layout: HBox{},
Children: []Widget{
PushButton{
Text: "Open Device",
OnClicked: func() {
regPath, err := GetRegistryLocation(uintptr(device.reg))
if err != nil {
walk.MsgBox(dlg, "NtQueryKey Error", err.Error(), walk.MsgBoxOK)
}

k, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Applets\Regedit`, registry.SET_VALUE)
if err != nil {
log.Fatal(err)
}
defer k.Close()

if err := k.SetStringValue("LastKey", regPath); err == nil {
exec.Command("regedit", "-m").Start()
}
},
},
PushButton{
Text: "Export current settings",
OnClicked: func() {
regPath, err := GetRegistryLocation(uintptr(device.reg))
if err != nil {
walk.MsgBox(dlg, "NtQueryKey Error", err.Error(), walk.MsgBoxOK)
}

path, err := os.Getwd()
if err != nil {
log.Println(err)
}

filePath, cancel, err := saveFileExplorer(dlg, path, strings.ReplaceAll(device.DeviceDesc, " ", "_")+".reg", "Save current settings", "Registry File (*.reg)|*.reg")
if !cancel || err != nil {
file, err := os.Create(filePath)
if err != nil {
return
}
defer file.Close()

file.WriteString(createRegFile(regPath, device))
}
},
},
HSpacer{},
},
},
},
Functions: map[string]func(args ...interface{}) (interface{}, error){
"checkIrqPolicy": func(args ...interface{}) (interface{}, error) {
Expand Down
26 changes: 26 additions & 0 deletions reg.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"log"
"strings"

"golang.org/x/sys/windows/registry"
)
Expand Down Expand Up @@ -115,3 +116,28 @@ func setAffinityPolicy(item *Device) {
log.Println(err)
}
}

// \REGISTRY\MACHINE\
func replaceRegistryMachine(regPath string) string {
indexMACHINE := strings.Index(regPath, "\\REGISTRY\\MACHINE\\")
if indexMACHINE == -1 {
log.Println("not Found")
return ""
}
return regPath[indexMACHINE+len("\\REGISTRY\\MACHINE\\"):]
}

// replaces ControlSet00X with CurrentControlSet
func generalizeControlSet(regPath string) string {
// https://learn.microsoft.com/en-us/windows-hardware/drivers/install/hklm-system-currentcontrolset-control-registry-tree

regPathArray := strings.Split(regPath, "\\")
for i := 0; i < len(regPathArray); i++ {
if strings.HasPrefix(regPathArray[i], "ControlSet00") {
regPathArray[i] = "CurrentControlSet"
return strings.Join(regPathArray, "\\")
}
}
return strings.Join(regPathArray, "\\")

}
5 changes: 3 additions & 2 deletions run.bat
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ SET filename=GoInterruptPolicy_debug
cls

gocritic check -enableAll -disable="#experimental,#opinionated,#commentedOutCode" ./...
go build -tags debug -o %filename%.exe
go build -tags debug -buildvcs=false -o %filename%.exe

@REM IF %ERRORLEVEL% EQU 0 %filename%.exe -devobj \Device\NTPNP_PCI0015 -policy 4 -cpu 1,2,3 -restart
@REM IF %ERRORLEVEL% E0QU 0 %filename%.exe -devobj \Device\NTPNP_PCI0015 -msisupported 0
@REM IF %ERRORLEVEL% EQU 0 %filename%.exe -devobj \Device\NTPNP_PCI0015 -policy 4 -cpu 1,2,3,4 -restart-on-change
@REM IF %ERRORLEVEL% EQU 0 %filename%.exe -devobj \Device\NTPNP_PCI0015 -msisupported 0
IF %ERRORLEVEL% EQU 0 %filename%.exe

pause
Expand Down

0 comments on commit e56fa55

Please sign in to comment.