func TestCreateOpenDeleteKey(t *testing.T) { k, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) if err != nil { t.Fatal(err) } defer k.Close() testKName := randKeyName("TestCreateOpenDeleteKey_") testK, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY) if err != nil { t.Fatal(err) } defer testK.Close() if exist { t.Fatalf("key %q already exists", testKName) } testKAgain, exist, err := registry.CreateKey(k, testKName, registry.CREATE_SUB_KEY) if err != nil { t.Fatal(err) } defer testKAgain.Close() if !exist { t.Fatalf("key %q should already exist", testKName) } testKOpened, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS) if err != nil { t.Fatal(err) } defer testKOpened.Close() err = registry.DeleteKey(k, testKName) if err != nil { t.Fatal(err) } testKOpenedAgain, err := registry.OpenKey(k, testKName, registry.ENUMERATE_SUB_KEYS) if err == nil { defer testKOpenedAgain.Close() t.Fatalf("key %q should already been deleted", testKName) } if err != registry.ErrNotExist { t.Fatalf(`unexpected error ("not exist" expected): %v`, err) } }
func TestValues(t *testing.T) { softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) if err != nil { t.Fatal(err) } defer softwareK.Close() testKName := randKeyName("TestValues_") k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE) if err != nil { t.Fatal(err) } defer k.Close() if exist { t.Fatalf("key %q already exists", testKName) } defer registry.DeleteKey(softwareK, testKName) setValues(t, k) enumerateValues(t, k) testValues(t, k) testStat(t, k) deleteValues(t, k) }
func testStat(t *testing.T, k registry.Key) { subk, _, err := registry.CreateKey(k, "subkey", registry.CREATE_SUB_KEY) if err != nil { t.Error(err) return } defer subk.Close() defer registry.DeleteKey(k, "subkey") ki, err := k.Stat() if err != nil { t.Error(err) return } if ki.SubKeyCount != 1 { t.Error("key must have 1 subkey") } if ki.MaxSubKeyLen != 6 { t.Error("key max subkey name length must be 6") } if ki.ValueCount != 24 { t.Errorf("key must have 24 values, but is %d", ki.ValueCount) } if ki.MaxValueNameLen != 12 { t.Errorf("key max value name length must be 10, but is %d", ki.MaxValueNameLen) } if ki.MaxValueLen != 38 { t.Errorf("key max value length must be 38, but is %d", ki.MaxValueLen) } if mt, ct := ki.ModTime(), time.Now(); ct.Sub(mt) > 100*time.Millisecond { t.Errorf("key mod time is not close to current time: mtime=%v current=%v delta=%v", mt, ct, ct.Sub(mt)) } }
// Install modifies PC registry to allow logging with an event source src. // It adds all required keys and values to the event log registry key. // Install uses msgFile as the event message file. If useExpandKey is true, // the event message file is installed as REG_EXPAND_SZ value, // otherwise as REG_SZ. Use bitwise of log.Error, log.Warning and // log.Info to specify events supported by the new event source. func Install(src, msgFile string, useExpandKey bool, eventsSupported uint32) error { appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.CREATE_SUB_KEY) if err != nil { return err } defer appkey.Close() sk, alreadyExist, err := registry.CreateKey(appkey, src, registry.SET_VALUE) if err != nil { return err } defer sk.Close() if alreadyExist { return errors.New(addKeyName + `\` + src + " registry key already exists") } err = sk.SetDWordValue("CustomSource", 1) if err != nil { return err } if useExpandKey { err = sk.SetExpandStringValue("EventMessageFile", msgFile) } else { err = sk.SetStringValue("EventMessageFile", msgFile) } if err != nil { return err } err = sk.SetDWordValue("TypesSupported", eventsSupported) if err != nil { return err } return nil }
// Install modifies PC registry to allow logging with an event source src. // It adds all required keys and values to the event log registry key. // Install uses msgFile as the event message file. If useExpandKey is true, // the event message file is installed as REG_EXPAND_SZ value, // otherwise as REG_SZ. Use bitwise of log.Error, log.Warning and // log.Info to specify events supported by the new event source. func Install(provider, src, msgFile string, useExpandKey bool, eventsSupported uint32) (bool, error) { eventLogKey, err := registry.OpenKey(registry.LOCAL_MACHINE, eventLogKeyName, registry.CREATE_SUB_KEY) if err != nil { return false, err } defer eventLogKey.Close() pk, _, err := registry.CreateKey(eventLogKey, provider, registry.SET_VALUE) if err != nil { return false, err } defer pk.Close() sk, alreadyExist, err := registry.CreateKey(pk, src, registry.SET_VALUE) if err != nil { return false, err } defer sk.Close() if alreadyExist { return true, nil } err = sk.SetDWordValue("CustomSource", 1) if err != nil { return false, err } if useExpandKey { err = sk.SetExpandStringValue("EventMessageFile", msgFile) } else { err = sk.SetStringValue("EventMessageFile", msgFile) } if err != nil { return false, err } err = sk.SetDWordValue("TypesSupported", eventsSupported) if err != nil { return false, err } return false, nil }
// This is a temporary method to fix an issue with the EventMessageFile. // See http://stackoverflow.com/questions/29130586 for details. func fixEventMessageFile(src string) error { const addKeyName = `SYSTEM\CurrentControlSet\Services\EventLog\Application` appkey, err := registry.OpenKey(registry.LOCAL_MACHINE, addKeyName, registry.ALL_ACCESS) if err != nil { return err } defer appkey.Close() sk, alreadyExist, err := registry.CreateKey(appkey, src, registry.ALL_ACCESS) if err != nil { return err } defer sk.Close() if alreadyExist { // Update REG_SZ key with expanded value for %systemroot% variable. err = sk.SetStringValue("EventMessageFile", os.ExpandEnv("${systemroot}\\System32\\EventCreate.exe")) if err != nil { return err } } return nil }
func TestInvalidValues(t *testing.T) { softwareK, err := registry.OpenKey(registry.CURRENT_USER, "Software", registry.QUERY_VALUE) if err != nil { t.Fatal(err) } defer softwareK.Close() testKName := randKeyName("TestInvalidValues_") k, exist, err := registry.CreateKey(softwareK, testKName, registry.CREATE_SUB_KEY|registry.QUERY_VALUE|registry.SET_VALUE) if err != nil { t.Fatal(err) } defer k.Close() if exist { t.Fatalf("key %q already exists", testKName) } defer registry.DeleteKey(softwareK, testKName) var tests = []struct { Type uint32 Name string Data []byte }{ {registry.DWORD, "Dword1", nil}, {registry.DWORD, "Dword2", []byte{1, 2, 3}}, {registry.QWORD, "Qword1", nil}, {registry.QWORD, "Qword2", []byte{1, 2, 3}}, {registry.QWORD, "Qword3", []byte{1, 2, 3, 4, 5, 6, 7}}, {registry.MULTI_SZ, "MultiString1", nil}, {registry.MULTI_SZ, "MultiString2", []byte{0}}, {registry.MULTI_SZ, "MultiString3", []byte{'a', 'b', 0}}, {registry.MULTI_SZ, "MultiString4", []byte{'a', 0, 0, 'b', 0}}, {registry.MULTI_SZ, "MultiString5", []byte{'a', 0, 0}}, } for _, test := range tests { err := k.SetValue(test.Name, test.Type, test.Data) if err != nil { t.Fatalf("SetValue for %q failed: %v", test.Name, err) } } for _, test := range tests { switch test.Type { case registry.DWORD, registry.QWORD: value, valType, err := k.GetIntegerValue(test.Name) if err == nil { t.Errorf("GetIntegerValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value) } case registry.MULTI_SZ: value, valType, err := k.GetStringsValue(test.Name) if err == nil { if len(value) != 0 { t.Errorf("GetStringsValue(%q) succeeded. Returns type=%d value=%v", test.Name, valType, value) } } default: t.Errorf("unsupported type %d for %s value", test.Type, test.Name) } } }
func deployStartup(user *runtime.OSUser, configFile string, exePath string) error { scheduledTaskUTF8 := []byte(strings.Replace(`<?xml version="1.0" encoding="UTF-16"?> <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Date>2016-04-28T17:25:08.4654422</Date> <Author>GenericWorker</Author> <Description>Runs the generic worker.</Description> </RegistrationInfo> <Triggers> <LogonTrigger> <Enabled>true</Enabled> <UserId>GenericWorker</UserId> </LogonTrigger> </Triggers> <Principals> <Principal id="Author"> <UserId>GenericWorker</UserId> <LogonType>InteractiveToken</LogonType> <RunLevel>HighestAvailable</RunLevel> </Principal> </Principals> <Settings> <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <StartWhenAvailable>false</StartWhenAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Enabled>true</Enabled> <Hidden>false</Hidden> <RunOnlyIfIdle>false</RunOnlyIfIdle> <WakeToRun>false</WakeToRun> <ExecutionTimeLimit>PT0S</ExecutionTimeLimit> <Priority>3</Priority> </Settings> <Actions Context="Author"> <Exec> <Command>C:\generic-worker\run-generic-worker.bat</Command> </Exec> </Actions> </Task>`, "\n", "\r\n", -1)) utf16Encoder := unicode.UTF16(unicode.LittleEndian, unicode.UseBOM).NewEncoder() scheduledTaskUTF16, err := utf16Encoder.Bytes(scheduledTaskUTF8) if err != nil { return fmt.Errorf("INTERNAL ERROR: Could not UTF16-encode (static) scheduled task: %s\n\nError received: %s", scheduledTaskUTF8, err) } xmlFilePath := filepath.Join(filepath.Dir(exePath), "Run Generic Worker.xml") err = ioutil.WriteFile(xmlFilePath, scheduledTaskUTF16, 0644) if err != nil { return fmt.Errorf("I was not able to write the file \"Run Generic Worker.xml\" to file location %q with 0644 permissions, due to: %s", xmlFilePath, err) } err = runtime.RunCommands(false, []string{"schtasks", "/create", "/tn", "Run Generic Worker on login", "/xml", xmlFilePath}) if err != nil { return fmt.Errorf("Not able to schedule task \"Run Generic Worker on login\" using schtasks command, due to error: %s\n\nAlso see stderr/stdout logs for output of the command that failed.", err) } k, _, err := registry.CreateKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`, registry.WRITE) if err != nil { return fmt.Errorf(`Was not able to create registry key 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' due to %s`, err) } defer k.Close() err = k.SetDWordValue("AutoAdminLogon", 1) if err != nil { return fmt.Errorf(`Was not able to set registry entry 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon' to 1 due to %s`, err) } err = k.SetStringValue("DefaultUserName", user.Name) if err != nil { return fmt.Errorf(`Was not able to set registry entry 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultUserName' to %q due to %s`, user.Name, err) } err = k.SetStringValue("DefaultPassword", user.Password) if err != nil { return fmt.Errorf(`Was not able to set registry entry 'SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\DefaultPassword' to %q due to %s`, user.Password, err) } batScriptFilePath := filepath.Join(filepath.Dir(exePath), "run-generic-worker.bat") batScriptContents := []byte(strings.Join([]string{ `:: run the generic worker`, ``, `:: cd to folder containing this script`, `pushd %~dp0`, ``, `.\generic-worker.exe run --configure-for-aws > .\generic-worker.log 2>&1`, }, "\r\n")) err = ioutil.WriteFile(batScriptFilePath, batScriptContents, 0755) if err != nil { return fmt.Errorf("Was not able to create file %q with access permissions 0755 due to %s", batScriptFilePath, err) } return nil }