├── .gitignore ├── LICENSE ├── README.md ├── actions ├── action.go ├── comhandler.go ├── email.go ├── execution.go ├── messagebox.go └── properties.go ├── build.sh ├── cmd ├── actions_windows.go ├── dummy.go ├── dynamicinfo_windows.go ├── main.go ├── parseall_windows.go ├── triggers_windows.go ├── utils.go └── utils_windows.go ├── dynamicinfo └── dynamicinfo.go ├── generate.sh ├── generated ├── actions.go ├── actions_test.go ├── aligned_bstr.go ├── aligned_bstr_expand_size.go ├── aligned_buffer.go ├── aligned_u1.go ├── aligned_u4.go ├── bstr.go ├── dynamic_info.go ├── dynamic_info_test.go ├── filetime.go ├── helpers_test.go ├── job_schedule.go ├── optional_settings.go ├── triggers.go ├── triggers_test.go ├── tstime.go ├── tstimeperiod.go └── user_info.go ├── go.mod ├── go.sum ├── kaitai ├── actions.ksy ├── aligned │ ├── bstr.ksy │ ├── bstr_expand_size.ksy │ ├── buffer.ksy │ ├── u1.ksy │ └── u4.ksy ├── dynamic_info.ksy ├── job_schedule.ksy ├── optional_settings.ksy ├── triggers.ksy ├── user_info.ksy └── util │ ├── bstr.ksy │ ├── filetime.ksy │ ├── tstime.ksy │ └── tstimeperiod.ksy ├── triggers ├── boot_trigger.go ├── event_trigger.go ├── generic_trigger_data.go ├── header.go ├── idle_trigger.go ├── job_bucket.go ├── job_schedule.go ├── logon_trigger.go ├── optional_settings.go ├── registration_trigger.go ├── session_change_trigger.go ├── time_trigger.go ├── triggers.go ├── user_info.go └── wnf_state_change_trigger.go └── utils ├── bitmap.go ├── hexdump.go ├── sid.go ├── time.go └── uuid.go /.gitignore: -------------------------------------------------------------------------------- 1 | out/** 2 | .vscode/** -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 G DATA Advanced Analytics GmbH 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | winreg-tasks 2 | ============ 3 | 4 | This repository contains structure definitions and some tooling for the BLOBs found in the TaskCache registry key on Windows (`HKLM\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache`). [I wrote a blog post](https://cyber.wtf/?p=1923) which gives some background knowledge on what this is all about. 5 | 6 | To successfully run the tool, it must be launched from a command window with elevated privileges. Otherwise, the tool cannot read the registry keys which are needed to display the requested information. 7 | 8 | Examples: 9 | ```powershell 10 | # display the available commands: 11 | .\winreg-tasks.exe [-h|--help] 12 | 13 | # iterates all tasks and prints a list of Actions, Triggers, 14 | # and the DynamicInfo of all tasks registered to the system 15 | .\winreg-tasks.exe parseall 16 | # same as before but only prints errors; most useful when you 17 | # changed something and want to see if anything broke 18 | .\winreg-tasks.exe parseall -q 19 | 20 | # get a more detailed dump of the actions of a task: 21 | .\winreg-tasks.exe actions '{00000000-1111-2222-3333-444444444444}' 22 | # you can pass the path alternatively (leading backslash required!): 23 | .\winreg-tasks.exe actions '\My Task' 24 | 25 | # get the triggers of a given task: 26 | .\winreg-tasks.exe triggers '{00000000-1111-2222-3333-444444444444}' 27 | # you can pass the path alternatively (leading backslash required!): 28 | .\winreg-tasks.exe triggers '\My Task' 29 | 30 | # get the DynamicInfo of a given task: 31 | .\winreg-tasks.exe dynamicinfo '{00000000-1111-2222-3333-444444444444}' 32 | # you can pass the path alternatively (leading backslash required!): 33 | .\winreg-tasks.exe dynamicinfo '\My Task' 34 | ``` 35 | 36 | All commands (except `parseall`) support the `-d` or `--dump` flag which prints the data read from the registry key as a 16 bytes wide hex dump. I found it much more easy to work with these dumps than exporting a value of a key with regedit and then converting the `hex:00,11,22,...` notation to something more readable. 37 | 38 | Generate 39 | ======== 40 | 41 | If you want to re-generate the source files, just use the `generate.sh` script. If you need another language, please adapt the script to your needs. 42 | 43 | **Note**: the current release (v0.9) version of kaitai does not support UTF16 strings in Golang. You need to compile the upstream version from Github. Since I don't know anything about scala, the steps below might not be how it's supposed to be done. It works, however, so you might want stick with the following commands if you're not familiar with scala either: 44 | ```bash 45 | # install sbt and scala 2.X (important: it MUST be scala 2.X; the lastest release 3.X is incompatible); I use sdkman and would everyone else encourage to do so as well 46 | sdk install sbt 47 | sdk install scala 2.13.8 48 | 49 | # clone kaitai-struct-compiler 50 | git clone https://github.com/kaitai-io/kaitai_struct_compiler ~/projects/kaitai 51 | cd ~/projects/kaitai 52 | 53 | # generate the staging package (this is where I'm pretty sure there is a much more efficient way to do this): 54 | sbt stage 55 | 56 | # cd into package sources 57 | git clone https://github.com/GDATAAdvancedAnalytics/winreg-tasks ~/projects/winreg-tasks 58 | cd ~/projects/winreg-tasks 59 | 60 | # run generate script 61 | KAITAI_COMPILER=~/projects/kaitai/jvm/target/universal/stage/bin/kaitai-struct-compiler ./generate.sh 62 | ``` 63 | 64 | 65 | Build 66 | ===== 67 | If you did not change anything and just want to use the tool, simply download and run the pre-built exe file from the releases. 68 | 69 | If you want to build the exe file yourself or introduced changes to the source code, you can use the provided build script; the `winreg-tasks.exe` is written to the `out` folder. Just make sure, you have a working installation of Golang 1.18 (or later) and then run: 70 | ```bash 71 | ./build.sh 72 | ``` 73 | Or, if you are on a Windows platform, you might just want to install the package from source: 74 | ```powershell 75 | go install github.com/GDATAAdvancedAnalytics/winreg-tasks/cmd@latest 76 | ``` 77 | 78 | Using the Generated Code 79 | ======================== 80 | At least for golang, using the generated code is as simple as importing this repository as a package. The Golang files located in `./golang/cmd/` may serve as examples on how to use this package. 81 | 82 | Minimum example: 83 | ```golang 84 | package main 85 | 86 | import ( 87 | "bytes" 88 | "fmt" 89 | "log" 90 | 91 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 92 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 93 | "golang.org/x/sys/windows/registry" 94 | ) 95 | 96 | func main() { 97 | key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{B75AF762-3C5C-4C74-ADB1-B99F98FDE0E5}`, registry.QUERY_VALUE) 98 | if err != nil { 99 | fmt.Printf("cannot open task key: %v", err) 100 | return 101 | } 102 | defer key.Close() 103 | 104 | dynamicInfoRaw, _, err := key.GetBinaryValue("DynamicInfo") 105 | if err != nil { 106 | fmt.Printf("cannot get dynamic info for task: %v", err) 107 | return 108 | } 109 | 110 | dynamicInfo := generated.NewDynamicInfo() 111 | if err = dynamicInfo.Read(kaitai.NewStream(bytes.NewReader(dynamicInfoRaw)), dynamicInfo, dynamicInfo); err != nil { 112 | fmt.Printf("cannot parse dynamic info: %v", err) 113 | return 114 | } 115 | 116 | lastErrorCode := dynamicInfo.LastErrorCode 117 | log.Printf("Last Error Code: 0x%08x", lastErrorCode) 118 | } 119 | ``` 120 | 121 | 122 | Licensing 123 | ========= 124 | Copyright 2022 G DATA Advanced Analytics GmbH 125 | 126 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 127 | 128 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 129 | 130 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 131 | -------------------------------------------------------------------------------- /actions/action.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package actions 4 | 5 | import ( 6 | "bytes" 7 | "errors" 8 | "fmt" 9 | 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 11 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 12 | ) 13 | 14 | var ( 15 | ErrUnknownPropertiesMagic = errors.New("unknown action properties magic") 16 | ) 17 | 18 | type Actions struct { 19 | Context string 20 | Properties []Properties 21 | Version uint16 22 | } 23 | 24 | // FromBytes takes the content of an Actions Values and parses it. 25 | func FromBytes(raw []byte) (*Actions, error) { 26 | stream := kaitai.NewStream(bytes.NewReader(raw)) 27 | generatedActions := generated.NewActions() 28 | 29 | if err := generatedActions.Read(stream, nil, generatedActions); err != nil { 30 | return nil, err 31 | } 32 | 33 | if eof, err := stream.EOF(); !eof { 34 | return nil, fmt.Errorf("did not parse all data") 35 | } else if err != nil { 36 | return nil, fmt.Errorf("error trying to eof-check (%v)", err) 37 | } 38 | 39 | properties := make([]Properties, len(generatedActions.Actions)) 40 | for i, action := range generatedActions.Actions { 41 | var props Properties 42 | var err error 43 | 44 | switch action.Magic { 45 | case uint16(ExecutionPropertiesMagic): 46 | props, err = NewExecutionProperties(action.Id.Str, action.Properties.(*generated.Actions_ExeTaskProperties)) 47 | 48 | case uint16(ComHandlerPropertiesMagic): 49 | props, err = NewComHandlerProperties(action.Id.Str, action.Properties.(*generated.Actions_ComHandlerProperties)) 50 | 51 | case uint16(EmailPropertiesMagic): 52 | props, err = NewEmailProperties(action.Id.Str, action.Properties.(*generated.Actions_EmailTaskProperties)) 53 | 54 | case uint16(MessageboxPropertiesMagic): 55 | props, err = NewMessageboxProperties(action.Id.Str, action.Properties.(*generated.Actions_MessageboxTaskProperties)) 56 | 57 | default: 58 | return nil, ErrUnknownPropertiesMagic 59 | } 60 | 61 | if err != nil { 62 | return nil, fmt.Errorf(`failed to parse action %d (%v)`, i, err) 63 | } 64 | 65 | properties[i] = props 66 | } 67 | 68 | context := "" 69 | if generatedActions.Context != nil { 70 | context = generatedActions.Context.Str 71 | } 72 | 73 | actions := &Actions{ 74 | Context: context, 75 | Properties: properties, 76 | Version: generatedActions.Version, 77 | } 78 | 79 | return actions, nil 80 | } 81 | -------------------------------------------------------------------------------- /actions/comhandler.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package actions 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 10 | "github.com/google/uuid" 11 | ) 12 | 13 | const ComHandlerPropertiesMagic PropertiesMagic = 0x7777 14 | 15 | type ComHandlerProperties struct { 16 | Id string 17 | 18 | Clsid uuid.UUID 19 | Data string 20 | } 21 | 22 | func NewComHandlerProperties(id string, gen *generated.Actions_ComHandlerProperties) (*ComHandlerProperties, error) { 23 | clsid, err := utils.UuidFromMemory(gen.Clsid) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | return &ComHandlerProperties{ 29 | Id: id, 30 | Clsid: clsid, 31 | Data: gen.Data.Str, 32 | }, nil 33 | } 34 | 35 | func IsComHandlerProperties(properties Properties) bool { 36 | return properties.Magic() == ComHandlerPropertiesMagic 37 | } 38 | 39 | func (c ComHandlerProperties) Magic() PropertiesMagic { 40 | return ComHandlerPropertiesMagic 41 | } 42 | 43 | func (e ComHandlerProperties) Name() string { 44 | return "ComHandler" 45 | } 46 | 47 | func (c ComHandlerProperties) String() string { 48 | return fmt.Sprintf( 49 | ``, 50 | c.Id, c.Clsid.String(), c.Data, 51 | ) 52 | } 53 | -------------------------------------------------------------------------------- /actions/email.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package actions 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | ) 10 | 11 | const EmailPropertiesMagic PropertiesMagic = 0x8888 12 | 13 | type EmailHeader struct { 14 | Name string 15 | Value string 16 | } 17 | 18 | type EmailProperties struct { 19 | Id string 20 | 21 | From string 22 | To string 23 | Cc string 24 | Bcc string 25 | ReplyTo string 26 | Server string 27 | Subject string 28 | Body string 29 | AttachmentFilenames []string 30 | Headers []EmailHeader 31 | } 32 | 33 | func NewEmailProperties(id string, gen *generated.Actions_EmailTaskProperties) (*EmailProperties, error) { 34 | attachmentFilenames := make([]string, gen.NumAttachmentFilenames) 35 | for i, file := range gen.AttachmentFilenames { 36 | attachmentFilenames[i] = file.Str 37 | } 38 | 39 | headers := make([]EmailHeader, gen.NumHeaders) 40 | for i, header := range gen.Headers { 41 | headers[i] = EmailHeader{Name: header.Key.Str, Value: header.Value.Str} 42 | } 43 | 44 | return &EmailProperties{ 45 | Id: id, 46 | From: gen.From.Str, 47 | To: gen.To.Str, 48 | Cc: gen.Cc.Str, 49 | Bcc: gen.Bcc.Str, 50 | ReplyTo: gen.ReplyTo.Str, 51 | Server: gen.Server.Str, 52 | Subject: gen.Subject.Str, 53 | Body: gen.Body.Str, 54 | AttachmentFilenames: attachmentFilenames, 55 | Headers: headers, 56 | }, nil 57 | } 58 | 59 | func IsEmailProperties(properties Properties) bool { 60 | return properties.Magic() == EmailPropertiesMagic 61 | } 62 | 63 | func (e EmailProperties) Magic() PropertiesMagic { 64 | return EmailPropertiesMagic 65 | } 66 | 67 | func (e EmailProperties) Name() string { 68 | return "Email" 69 | } 70 | 71 | func (e EmailProperties) String() string { 72 | return fmt.Sprintf( 73 | ``, 74 | e.Id, e.From, e.To, e.Subject, 75 | ) 76 | } 77 | -------------------------------------------------------------------------------- /actions/execution.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package actions 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | ) 10 | 11 | const ExecutionPropertiesMagic PropertiesMagic = 0x6666 12 | 13 | type ExecutionProperties struct { 14 | Id string 15 | 16 | Arguments string 17 | Command string 18 | WorkingDirectory string 19 | 20 | Flags uint16 21 | } 22 | 23 | func NewExecutionProperties(id string, gen *generated.Actions_ExeTaskProperties) (*ExecutionProperties, error) { 24 | return &ExecutionProperties{ 25 | Id: id, 26 | Arguments: gen.Arguments.Str, 27 | Command: gen.Command.Str, 28 | WorkingDirectory: gen.WorkingDirectory.Str, 29 | Flags: gen.Flags, 30 | }, nil 31 | } 32 | 33 | func IsExecutionProperties(properties Properties) bool { 34 | return properties.Magic() == ExecutionPropertiesMagic 35 | } 36 | 37 | func (e ExecutionProperties) Magic() PropertiesMagic { 38 | return ExecutionPropertiesMagic 39 | } 40 | 41 | func (e ExecutionProperties) Name() string { 42 | return "Execution" 43 | } 44 | 45 | func (e ExecutionProperties) String() string { 46 | return fmt.Sprintf( 47 | ``, 43 | m.Id, m.Caption, m.Content, 44 | ) 45 | } 46 | -------------------------------------------------------------------------------- /actions/properties.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package actions 4 | 5 | type PropertiesMagic uint16 6 | 7 | type Properties interface { 8 | Magic() PropertiesMagic 9 | Name() string 10 | String() string 11 | } 12 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mkdir -p out 4 | 5 | GOOS=windows GOARCH=386 go build -o ./out/winreg-tasks-386.exe -trimpath ./cmd 6 | GOOS=windows GOARCH=amd64 go build -o ./out/winreg-tasks-amd64.exe -trimpath ./cmd 7 | -------------------------------------------------------------------------------- /cmd/actions_windows.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/actions" 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 11 | ) 12 | 13 | func actionsHandler(args ...string) { 14 | key := openTaskKey(args[0]) 15 | if key == 0 { 16 | log.Fatalln("cannot open task key") 17 | } 18 | defer key.Close() 19 | 20 | dump := false 21 | if len(args) > 1 && (args[1] == "-d" || args[1] == "--dump") { 22 | dump = true 23 | } 24 | 25 | actionsRaw, _, err := key.GetBinaryValue("Actions") 26 | if err != nil { 27 | log.Fatalf("cannot get actions for task: %v", err) 28 | } 29 | 30 | if dump { 31 | hex := utils.Hexdump(actionsRaw, 16) 32 | fmt.Println(hex) 33 | } 34 | 35 | actions, err := actions.FromBytes(actionsRaw) 36 | if err != nil { 37 | log.Fatalf("cannot parse actions: %v", err) 38 | } 39 | 40 | log.Println("Context: " + actions.Context) 41 | log.Println(`Actions:`) 42 | 43 | if len(actions.Properties) == 0 { 44 | log.Println("\t") 45 | return 46 | } 47 | 48 | for _, props := range actions.Properties { 49 | log.Println("\t" + props.String()) 50 | } 51 | } 52 | 53 | func init() { 54 | registerCommand(Command{ 55 | Name: "actions", 56 | Args: []string{"", "[-d|--dump]"}, 57 | RequiredArgCount: 1, 58 | Func: actionsHandler, 59 | }) 60 | } 61 | -------------------------------------------------------------------------------- /cmd/dummy.go: -------------------------------------------------------------------------------- 1 | //go:build debug 2 | // +build debug 3 | 4 | // SPDX-License-Identifier: MIT 5 | 6 | package main 7 | 8 | import "fmt" 9 | 10 | func dummy(args ...string) { 11 | switch len(args) { 12 | case 0: 13 | fmt.Println("no args") 14 | 15 | case 1: 16 | fmt.Printf("one arg: %s\n", args[0]) 17 | 18 | default: 19 | fmt.Printf("more than one arg: %v\n", args) 20 | } 21 | } 22 | 23 | func init() { 24 | registerCommand(Command{ 25 | Name: "dummy", 26 | Args: []string{"[foo]", "[bar]"}, 27 | // RequiredArgCount: 1, 28 | Func: dummy, 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /cmd/dynamicinfo_windows.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/dynamicinfo" 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 11 | ) 12 | 13 | func dynamicInfo(args ...string) { 14 | key := openTaskKey(args[0]) 15 | if key == 0 { 16 | log.Fatalln("cannot open task key") 17 | } 18 | defer key.Close() 19 | 20 | dump := false 21 | if len(args) > 1 && (args[1] == "-d" || args[1] == "--dump") { 22 | dump = true 23 | } 24 | 25 | dynamicInfoRaw, _, err := key.GetBinaryValue("DynamicInfo") 26 | if err != nil { 27 | log.Fatalf("cannot get dynamic info for task: %v", err) 28 | } 29 | 30 | if dump { 31 | hex := utils.Hexdump(dynamicInfoRaw, 16) 32 | fmt.Println(hex) 33 | } 34 | 35 | dynamicInfo, err := dynamicinfo.FromBytes(dynamicInfoRaw) 36 | if err != nil { 37 | log.Fatalf("cannot parse DynamicInfo: %v", err) 38 | } 39 | 40 | log.Printf("Creation Time: %s", dynamicInfo.CreationTime.String()) 41 | log.Printf("Last Run Time: %s", dynamicInfo.LastRunTime.String()) 42 | log.Printf("Task State: 0x%08x", dynamicInfo.TaskState) 43 | log.Printf("Last Error Code: 0x%08x", dynamicInfo.LastErrorCode) 44 | log.Printf("Last Successful Run Time: %s", dynamicInfo.LastSuccessfulRunTime.String()) 45 | } 46 | 47 | func init() { 48 | registerCommand(Command{ 49 | Name: "dynamicinfo", 50 | Args: []string{"", "[-d|--dump]"}, 51 | RequiredArgCount: 1, 52 | Func: dynamicInfo, 53 | }) 54 | } 55 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "os" 9 | "strings" 10 | ) 11 | 12 | type Command struct { 13 | Name string 14 | Args []string 15 | RequiredArgCount int 16 | Func func(args ...string) 17 | } 18 | 19 | func help() { 20 | fmt.Printf("Usage: %s [args...]\n", os.Args[0]) 21 | 22 | fmt.Println("Available Commands:") 23 | for _, command := range commands { 24 | fmt.Printf("\t%s %s\n", command.Name, strings.Join(command.Args, " ")) 25 | } 26 | } 27 | 28 | // noreturn if argument count mismatch 29 | func ensureArgs(n int) { 30 | if len(os.Args) < 2+n { 31 | fmt.Println("argument count mismatch!") 32 | help() 33 | os.Exit(1) 34 | } 35 | } 36 | 37 | var ( 38 | commands map[string]Command 39 | ) 40 | 41 | func registerCommand(command Command) { 42 | if commands == nil { 43 | commands = make(map[string]Command) 44 | } 45 | commands[command.Name] = command 46 | } 47 | 48 | func main() { 49 | switch len(os.Args) { 50 | case 1: 51 | help() 52 | return 53 | case 2: 54 | if os.Args[1] == "-h" || os.Args[1] == "--help" { 55 | help() 56 | return 57 | } 58 | } 59 | 60 | if command, ok := commands[os.Args[1]]; ok { 61 | ensureArgs(command.RequiredArgCount) 62 | 63 | args := []string{} 64 | if len(os.Args) > 2 { 65 | args = os.Args[2:] 66 | } 67 | 68 | command.Func(args...) 69 | } else { 70 | log.Println("Invalid command!") 71 | help() 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /cmd/parseall_windows.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "strings" 9 | "time" 10 | 11 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/actions" 12 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/dynamicinfo" 13 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/triggers" 14 | "golang.org/x/sys/windows/registry" 15 | ) 16 | 17 | func readAndParse(taskId string, key registry.Key, value string, parserCallback func(data []byte) (string, error), quiet bool) error { 18 | rawData, _, err := key.GetBinaryValue(value) 19 | if err != nil { 20 | return err 21 | } 22 | 23 | result, err := parserCallback(rawData) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | if !quiet { 29 | log.Printf("Task %s - %s: %s", taskId, value, result) 30 | } 31 | 32 | return nil 33 | } 34 | 35 | func parseTriggers(data []byte) (string, error) { 36 | triggs, err := triggers.FromBytes(data, time.Local) 37 | if err != nil { 38 | return "", err 39 | } 40 | 41 | if len(triggs.Triggers) == 0 { 42 | return "", nil 43 | } 44 | 45 | var triggers []string 46 | 47 | for _, trigger := range triggs.Triggers { 48 | triggers = append(triggers, trigger.Name()) 49 | } 50 | 51 | return strings.Join(triggers, ", "), nil 52 | } 53 | 54 | func parseActions(data []byte) (string, error) { 55 | actions, err := actions.FromBytes(data) 56 | if err != nil { 57 | return "", err 58 | } 59 | 60 | if len(actions.Properties) == 0 { 61 | return "", nil 62 | } 63 | 64 | var propCollection []string 65 | 66 | for _, props := range actions.Properties { 67 | propCollection = append(propCollection, props.Name()) 68 | } 69 | 70 | return strings.Join(propCollection, ", "), nil 71 | } 72 | 73 | func parseDynamicInfo(data []byte) (string, error) { 74 | dynamicInfo, err := dynamicinfo.FromBytes(data) 75 | if err != nil { 76 | return "", err 77 | } 78 | 79 | ret := fmt.Sprintf( 80 | "Creation Time: %s, Last Run Time: %s, Last Error Code: 0x%08x", 81 | dynamicInfo.CreationTime.String(), dynamicInfo.LastRunTime.String(), 82 | dynamicInfo.LastErrorCode, 83 | ) 84 | 85 | return ret, nil 86 | } 87 | 88 | func parseAll(args ...string) { 89 | quiet := false 90 | if len(args) > 0 && (args[0] == "-q" || args[0] == "--quiet") { 91 | quiet = true 92 | } 93 | 94 | taskDir, err := openKey(`Tasks`) 95 | if err != nil { 96 | log.Println(err) 97 | return 98 | } 99 | defer taskDir.Close() 100 | 101 | tasks, err := taskDir.ReadSubKeyNames(-1) 102 | if err != nil { 103 | log.Printf("cannot get task list from registry: %v\n", err) 104 | return 105 | } 106 | 107 | for _, taskId := range tasks { 108 | key := openTaskKey(taskId) 109 | 110 | if err := readAndParse(taskId, key, "Actions", parseActions, quiet); err != nil { 111 | log.Printf("error reading Actions of task %s: %v", taskId, err) 112 | } 113 | 114 | if err := readAndParse(taskId, key, "Triggers", parseTriggers, quiet); err != nil { 115 | log.Printf("error reading Triggers of task %s: %v", taskId, err) 116 | } 117 | 118 | if err := readAndParse(taskId, key, "DynamicInfo", parseDynamicInfo, quiet); err != nil { 119 | log.Printf("error reading DynamicInfo of task %s: %v", taskId, err) 120 | } 121 | } 122 | 123 | } 124 | 125 | func init() { 126 | registerCommand(Command{ 127 | Name: "parseall", 128 | Args: []string{"[-q|--quiet]"}, 129 | Func: parseAll, 130 | }) 131 | } 132 | -------------------------------------------------------------------------------- /cmd/triggers_windows.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "time" 9 | 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/triggers" 11 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 12 | ) 13 | 14 | func handleTriggers(args ...string) { 15 | key := openTaskKey(args[0]) 16 | if key == 0 { 17 | log.Fatalln("cannot open task key") 18 | } 19 | defer key.Close() 20 | 21 | dump := false 22 | 23 | if len(args) > 1 && (args[1] == "-d" || args[1] == "--dump") { 24 | dump = true 25 | } 26 | 27 | triggersRaw, _, err := key.GetBinaryValue("Triggers") 28 | if err != nil { 29 | log.Fatalf("cannot get triggers for task: %v", err) 30 | } 31 | 32 | if dump { 33 | hex := utils.Hexdump(triggersRaw, 16) 34 | fmt.Println(hex) 35 | } 36 | 37 | triggers, err := triggers.FromBytes(triggersRaw, time.Local) 38 | if err != nil { 39 | log.Fatalf("cannot parse triggers: %v", err) 40 | } 41 | 42 | log.Println("Header:") 43 | log.Printf("\tVersion: %d", triggers.Header.Version) 44 | log.Printf("\tStartBoundary: %s", triggers.Header.StartBoundary.String()) 45 | log.Printf("\tEndBoundary: %s", triggers.Header.EndBoundary.String()) 46 | 47 | log.Println("JobBucket:") 48 | log.Printf("\tFlags: %08x", triggers.JobBucket.Flags) 49 | log.Printf("\tCRC32: %08x", triggers.JobBucket.Crc32) 50 | log.Printf("\tPrincipal ID: %s", triggers.JobBucket.PrincipalId) 51 | log.Printf("\tDisplay Name: %s", triggers.JobBucket.DisplayName) 52 | log.Printf("\tUser: %s", triggers.JobBucket.UserInfo.UserToString()) 53 | 54 | log.Println("Triggers:") 55 | if len(triggers.Triggers) == 0 { 56 | log.Println("\t") 57 | return 58 | } 59 | 60 | for _, trigger := range triggers.Triggers { 61 | log.Println("\t" + trigger.String()) 62 | } 63 | } 64 | 65 | func init() { 66 | registerCommand(Command{ 67 | Name: "triggers", 68 | RequiredArgCount: 1, 69 | Args: []string{"", "[-d|--dump]"}, 70 | Func: handleTriggers, 71 | }) 72 | } 73 | -------------------------------------------------------------------------------- /cmd/utils.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | func toGolangHexBytes(data []byte) string { 11 | str := "" 12 | 13 | for _, c := range data { 14 | str += fmt.Sprintf(`0x%02x, `, c) 15 | } 16 | 17 | return strings.TrimSuffix(str, ` `) 18 | } 19 | -------------------------------------------------------------------------------- /cmd/utils_windows.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "log" 8 | "strings" 9 | "syscall" 10 | "unsafe" 11 | 12 | "golang.org/x/sys/windows/registry" 13 | ) 14 | 15 | const ( 16 | taskKeyBase = `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\` 17 | ) 18 | 19 | func getUUIDFromTaskPath(path string) (string, error) { 20 | key, err := openKey(`Tree\` + path) 21 | if err != nil { 22 | return "", err 23 | } 24 | 25 | val, _, err := key.GetStringValue("Id") 26 | if err != nil { 27 | return "", err 28 | } 29 | 30 | return val, nil 31 | } 32 | 33 | func openKey(subKey string) (registry.Key, error) { 34 | return registry.OpenKey(registry.LOCAL_MACHINE, taskKeyBase+subKey, registry.QUERY_VALUE|registry.ENUMERATE_SUB_KEYS) 35 | } 36 | 37 | func openTaskKey(keyId string) registry.Key { 38 | var err error 39 | 40 | switch { 41 | case strings.HasPrefix(keyId, `\`): 42 | keyId, err = getUUIDFromTaskPath(keyId) 43 | if err != nil { 44 | log.Printf("cannot convert task path to uuid: %v\n", err) 45 | return 0 46 | } 47 | fallthrough 48 | 49 | case strings.HasPrefix(keyId, `{`): 50 | key, err := openKey(`Tasks\` + keyId) 51 | if err != nil { 52 | log.Printf("cannot open key %s: %v\n", keyId, err) 53 | return 0 54 | } 55 | return key 56 | 57 | default: 58 | log.Printf("task id unknown. must start with \\ or {") 59 | return 0 60 | } 61 | } 62 | 63 | func binarySidToString(raw []byte) string { 64 | sid := (*syscall.SID)(unsafe.Pointer(&raw[0])) 65 | 66 | strSid, err := sid.String() 67 | if err != nil { 68 | return fmt.Sprintf("", err) 69 | } 70 | return strSid 71 | } 72 | -------------------------------------------------------------------------------- /dynamicinfo/dynamicinfo.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package dynamicinfo 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "time" 9 | 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 11 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 12 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 13 | ) 14 | 15 | type DynamicInfo struct { 16 | Magic uint32 17 | CreationTime time.Time 18 | LastRunTime time.Time 19 | TaskState uint32 20 | LastErrorCode uint32 21 | LastSuccessfulRunTime time.Time 22 | } 23 | 24 | func FromBytes(raw []byte) (*DynamicInfo, error) { 25 | stream := kaitai.NewStream(bytes.NewReader(raw)) 26 | generatedDynamicInfo := generated.NewDynamicInfo() 27 | 28 | if err := generatedDynamicInfo.Read(stream, nil, generatedDynamicInfo); err != nil { 29 | return nil, err 30 | } 31 | 32 | if eof, err := stream.EOF(); !eof { 33 | return nil, fmt.Errorf("did not parse all data") 34 | } else if err != nil { 35 | return nil, fmt.Errorf("error trying to eof-check (%v)", err) 36 | } 37 | 38 | magic := uint32(generatedDynamicInfo.Magic[3])<<24 | 39 | uint32(generatedDynamicInfo.Magic[2])<<16 | 40 | uint32(generatedDynamicInfo.Magic[1])<<8 | 41 | uint32(generatedDynamicInfo.Magic[0]) 42 | 43 | return &DynamicInfo{ 44 | Magic: magic, 45 | CreationTime: utils.TimeFromFILETIME(generatedDynamicInfo.CreationTime), 46 | LastRunTime: utils.TimeFromFILETIME(generatedDynamicInfo.LastRunTime), 47 | TaskState: generatedDynamicInfo.TaskState, 48 | LastErrorCode: generatedDynamicInfo.LastErrorCode, 49 | LastSuccessfulRunTime: utils.TimeFromFILETIME(generatedDynamicInfo.LastSuccessfulRunTime), 50 | }, nil 51 | } 52 | 53 | func (d DynamicInfo) String() string { 54 | return fmt.Sprintf( 55 | ``, 56 | d.CreationTime.String(), d.LastRunTime.String(), d.LastErrorCode, 57 | ) 58 | } 59 | -------------------------------------------------------------------------------- /generate.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SOURCE_DIR="kaitai" 4 | SOURCES="${SOURCE_DIR}/*.ksy" 5 | 6 | KAITAI_COMPILER="${KAITAI_COMPILER:-kaitai-struct-compiler}" 7 | 8 | KAITAI_GOLANG_PACKAGE="generated" 9 | KAITAI_GOLANG_OPTIONS="--target go --outdir ./ --go-package ${KAITAI_GOLANG_PACKAGE}" 10 | 11 | for f in "$SOURCES"; do 12 | $KAITAI_COMPILER $KAITAI_GOLANG_OPTIONS $f 13 | done 14 | 15 | go mod tidy; 16 | -------------------------------------------------------------------------------- /generated/actions.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | type Actions struct { 8 | Version uint16 9 | Context *Bstr 10 | Actions []*Actions_Action 11 | _io *kaitai.Stream 12 | _root *Actions 13 | _parent interface{} 14 | } 15 | func NewActions() *Actions { 16 | return &Actions{ 17 | } 18 | } 19 | 20 | func (this *Actions) Read(io *kaitai.Stream, parent interface{}, root *Actions) (err error) { 21 | this._io = io 22 | this._parent = parent 23 | this._root = root 24 | 25 | tmp1, err := this._io.ReadU2le() 26 | if err != nil { 27 | return err 28 | } 29 | this.Version = uint16(tmp1) 30 | if (this.Version == 3) { 31 | tmp2 := NewBstr() 32 | err = tmp2.Read(this._io, this, nil) 33 | if err != nil { 34 | return err 35 | } 36 | this.Context = tmp2 37 | } 38 | for i := 1;; i++ { 39 | tmp3, err := this._io.EOF() 40 | if err != nil { 41 | return err 42 | } 43 | if tmp3 { 44 | break 45 | } 46 | tmp4 := NewActions_Action() 47 | err = tmp4.Read(this._io, this, this._root) 48 | if err != nil { 49 | return err 50 | } 51 | this.Actions = append(this.Actions, tmp4) 52 | } 53 | return err 54 | } 55 | type Actions_ComHandlerProperties struct { 56 | Clsid []byte 57 | Data *Bstr 58 | _io *kaitai.Stream 59 | _root *Actions 60 | _parent *Actions_Action 61 | } 62 | func NewActions_ComHandlerProperties() *Actions_ComHandlerProperties { 63 | return &Actions_ComHandlerProperties{ 64 | } 65 | } 66 | 67 | func (this *Actions_ComHandlerProperties) Read(io *kaitai.Stream, parent *Actions_Action, root *Actions) (err error) { 68 | this._io = io 69 | this._parent = parent 70 | this._root = root 71 | 72 | tmp5, err := this._io.ReadBytes(int(16)) 73 | if err != nil { 74 | return err 75 | } 76 | tmp5 = tmp5 77 | this.Clsid = tmp5 78 | tmp6 := NewBstr() 79 | err = tmp6.Read(this._io, this, nil) 80 | if err != nil { 81 | return err 82 | } 83 | this.Data = tmp6 84 | return err 85 | } 86 | type Actions_EmailTaskProperties struct { 87 | From *Bstr 88 | To *Bstr 89 | Cc *Bstr 90 | Bcc *Bstr 91 | ReplyTo *Bstr 92 | Server *Bstr 93 | Subject *Bstr 94 | Body *Bstr 95 | NumAttachmentFilenames uint32 96 | AttachmentFilenames []*Bstr 97 | NumHeaders uint32 98 | Headers []*Actions_KeyValueString 99 | _io *kaitai.Stream 100 | _root *Actions 101 | _parent *Actions_Action 102 | } 103 | func NewActions_EmailTaskProperties() *Actions_EmailTaskProperties { 104 | return &Actions_EmailTaskProperties{ 105 | } 106 | } 107 | 108 | func (this *Actions_EmailTaskProperties) Read(io *kaitai.Stream, parent *Actions_Action, root *Actions) (err error) { 109 | this._io = io 110 | this._parent = parent 111 | this._root = root 112 | 113 | tmp7 := NewBstr() 114 | err = tmp7.Read(this._io, this, nil) 115 | if err != nil { 116 | return err 117 | } 118 | this.From = tmp7 119 | tmp8 := NewBstr() 120 | err = tmp8.Read(this._io, this, nil) 121 | if err != nil { 122 | return err 123 | } 124 | this.To = tmp8 125 | tmp9 := NewBstr() 126 | err = tmp9.Read(this._io, this, nil) 127 | if err != nil { 128 | return err 129 | } 130 | this.Cc = tmp9 131 | tmp10 := NewBstr() 132 | err = tmp10.Read(this._io, this, nil) 133 | if err != nil { 134 | return err 135 | } 136 | this.Bcc = tmp10 137 | tmp11 := NewBstr() 138 | err = tmp11.Read(this._io, this, nil) 139 | if err != nil { 140 | return err 141 | } 142 | this.ReplyTo = tmp11 143 | tmp12 := NewBstr() 144 | err = tmp12.Read(this._io, this, nil) 145 | if err != nil { 146 | return err 147 | } 148 | this.Server = tmp12 149 | tmp13 := NewBstr() 150 | err = tmp13.Read(this._io, this, nil) 151 | if err != nil { 152 | return err 153 | } 154 | this.Subject = tmp13 155 | tmp14 := NewBstr() 156 | err = tmp14.Read(this._io, this, nil) 157 | if err != nil { 158 | return err 159 | } 160 | this.Body = tmp14 161 | tmp15, err := this._io.ReadU4le() 162 | if err != nil { 163 | return err 164 | } 165 | this.NumAttachmentFilenames = uint32(tmp15) 166 | for i := 0; i < int(this.NumAttachmentFilenames); i++ { 167 | _ = i 168 | tmp16 := NewBstr() 169 | err = tmp16.Read(this._io, this, nil) 170 | if err != nil { 171 | return err 172 | } 173 | this.AttachmentFilenames = append(this.AttachmentFilenames, tmp16) 174 | } 175 | tmp17, err := this._io.ReadU4le() 176 | if err != nil { 177 | return err 178 | } 179 | this.NumHeaders = uint32(tmp17) 180 | for i := 0; i < int(this.NumHeaders); i++ { 181 | _ = i 182 | tmp18 := NewActions_KeyValueString() 183 | err = tmp18.Read(this._io, this, this._root) 184 | if err != nil { 185 | return err 186 | } 187 | this.Headers = append(this.Headers, tmp18) 188 | } 189 | return err 190 | } 191 | type Actions_KeyValueString struct { 192 | Key *Bstr 193 | Value *Bstr 194 | _io *kaitai.Stream 195 | _root *Actions 196 | _parent *Actions_EmailTaskProperties 197 | } 198 | func NewActions_KeyValueString() *Actions_KeyValueString { 199 | return &Actions_KeyValueString{ 200 | } 201 | } 202 | 203 | func (this *Actions_KeyValueString) Read(io *kaitai.Stream, parent *Actions_EmailTaskProperties, root *Actions) (err error) { 204 | this._io = io 205 | this._parent = parent 206 | this._root = root 207 | 208 | tmp19 := NewBstr() 209 | err = tmp19.Read(this._io, this, nil) 210 | if err != nil { 211 | return err 212 | } 213 | this.Key = tmp19 214 | tmp20 := NewBstr() 215 | err = tmp20.Read(this._io, this, nil) 216 | if err != nil { 217 | return err 218 | } 219 | this.Value = tmp20 220 | return err 221 | } 222 | type Actions_ExeTaskProperties struct { 223 | Command *Bstr 224 | Arguments *Bstr 225 | WorkingDirectory *Bstr 226 | Flags uint16 227 | _io *kaitai.Stream 228 | _root *Actions 229 | _parent *Actions_Action 230 | } 231 | func NewActions_ExeTaskProperties() *Actions_ExeTaskProperties { 232 | return &Actions_ExeTaskProperties{ 233 | } 234 | } 235 | 236 | func (this *Actions_ExeTaskProperties) Read(io *kaitai.Stream, parent *Actions_Action, root *Actions) (err error) { 237 | this._io = io 238 | this._parent = parent 239 | this._root = root 240 | 241 | tmp21 := NewBstr() 242 | err = tmp21.Read(this._io, this, nil) 243 | if err != nil { 244 | return err 245 | } 246 | this.Command = tmp21 247 | tmp22 := NewBstr() 248 | err = tmp22.Read(this._io, this, nil) 249 | if err != nil { 250 | return err 251 | } 252 | this.Arguments = tmp22 253 | tmp23 := NewBstr() 254 | err = tmp23.Read(this._io, this, nil) 255 | if err != nil { 256 | return err 257 | } 258 | this.WorkingDirectory = tmp23 259 | if (this._root.Version == 3) { 260 | tmp24, err := this._io.ReadU2le() 261 | if err != nil { 262 | return err 263 | } 264 | this.Flags = uint16(tmp24) 265 | } 266 | return err 267 | } 268 | type Actions_MessageboxTaskProperties struct { 269 | Caption *Bstr 270 | Content *Bstr 271 | _io *kaitai.Stream 272 | _root *Actions 273 | _parent *Actions_Action 274 | } 275 | func NewActions_MessageboxTaskProperties() *Actions_MessageboxTaskProperties { 276 | return &Actions_MessageboxTaskProperties{ 277 | } 278 | } 279 | 280 | func (this *Actions_MessageboxTaskProperties) Read(io *kaitai.Stream, parent *Actions_Action, root *Actions) (err error) { 281 | this._io = io 282 | this._parent = parent 283 | this._root = root 284 | 285 | tmp25 := NewBstr() 286 | err = tmp25.Read(this._io, this, nil) 287 | if err != nil { 288 | return err 289 | } 290 | this.Caption = tmp25 291 | tmp26 := NewBstr() 292 | err = tmp26.Read(this._io, this, nil) 293 | if err != nil { 294 | return err 295 | } 296 | this.Content = tmp26 297 | return err 298 | } 299 | type Actions_Action struct { 300 | Magic uint16 301 | Id *Bstr 302 | Properties interface{} 303 | _io *kaitai.Stream 304 | _root *Actions 305 | _parent *Actions 306 | } 307 | func NewActions_Action() *Actions_Action { 308 | return &Actions_Action{ 309 | } 310 | } 311 | 312 | func (this *Actions_Action) Read(io *kaitai.Stream, parent *Actions, root *Actions) (err error) { 313 | this._io = io 314 | this._parent = parent 315 | this._root = root 316 | 317 | tmp27, err := this._io.ReadU2le() 318 | if err != nil { 319 | return err 320 | } 321 | this.Magic = uint16(tmp27) 322 | tmp28 := NewBstr() 323 | err = tmp28.Read(this._io, this, nil) 324 | if err != nil { 325 | return err 326 | } 327 | this.Id = tmp28 328 | switch (this.Magic) { 329 | case 26214: 330 | tmp29 := NewActions_ExeTaskProperties() 331 | err = tmp29.Read(this._io, this, this._root) 332 | if err != nil { 333 | return err 334 | } 335 | this.Properties = tmp29 336 | case 30583: 337 | tmp30 := NewActions_ComHandlerProperties() 338 | err = tmp30.Read(this._io, this, this._root) 339 | if err != nil { 340 | return err 341 | } 342 | this.Properties = tmp30 343 | case 34952: 344 | tmp31 := NewActions_EmailTaskProperties() 345 | err = tmp31.Read(this._io, this, this._root) 346 | if err != nil { 347 | return err 348 | } 349 | this.Properties = tmp31 350 | case 39321: 351 | tmp32 := NewActions_MessageboxTaskProperties() 352 | err = tmp32.Read(this._io, this, this._root) 353 | if err != nil { 354 | return err 355 | } 356 | this.Properties = tmp32 357 | } 358 | return err 359 | } 360 | -------------------------------------------------------------------------------- /generated/actions_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package generated_test 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "testing" 9 | 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 11 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 12 | ) 13 | 14 | func TestTaskParser_ExeTasks(t *testing.T) { 15 | blob := []byte{ 16 | 0x03, 0x00, 17 | 0x0c, 0x00, 0x00, 0x00, 18 | 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 19 | 20 | 0x66, 0x66, 21 | 0x08, 0x00, 0x00, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x63, 0x00, 22 | 0x1a, 0x00, 0x00, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 23 | 0x00, 0x00, 0x00, 0x00, 24 | 0x00, 0x00, 0x00, 0x00, 25 | 0x01, 0x00, 26 | 27 | 0x66, 0x66, 28 | 0x08, 0x00, 0x00, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x63, 0x00, 29 | 0x10, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 30 | 0x00, 0x00, 0x00, 0x00, 31 | 0x00, 0x00, 0x00, 0x00, 32 | 0x00, 0x00, 33 | 34 | 0x66, 0x66, 35 | 0x08, 0x00, 0x00, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x63, 0x00, 36 | 0x42, 0x00, 0x00, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x44, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6b, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x5c, 0x00, 0x77, 0x00, 0x69, 0x00, 0x74, 0x00, 0x68, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x2e, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00, 37 | 0x10, 0x00, 0x00, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x32, 0x00, 38 | 0x00, 0x00, 0x00, 0x00, 39 | 0x00, 0x00, 40 | 41 | 0x66, 0x66, 42 | 0x08, 0x00, 0x00, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x63, 0x00, 43 | 0x2c, 0x00, 0x00, 0x00, 0x44, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x79, 0x00, 0x5f, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x70, 0x00, 0x73, 0x00, 0x31, 0x00, 44 | 0x00, 0x00, 0x00, 0x00, 45 | 0x14, 0x00, 0x00, 0x00, 0x43, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 46 | 0x00, 0x00, 47 | 48 | 0x66, 0x66, 49 | 0x08, 0x00, 0x00, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x63, 0x00, 50 | 0x1e, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x5c, 0x00, 0x69, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 51 | 0x12, 0x00, 0x00, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x31, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x32, 0x00, 52 | 0x1a, 0x00, 0x00, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x69, 0x00, 53 | 0x6e, 0x00, 0x67, 0x00, 0x64, 0x00, 0x69, 0x00, 0x72, 54 | 0x00, 0x00, 55 | } 56 | 57 | expected := []*generated.Actions_ExeTaskProperties{ 58 | {Command: &generated.Bstr{Str: "execution.exe"}, Arguments: &generated.Bstr{Str: ""}, WorkingDirectory: &generated.Bstr{Str: ""}, Flags: uint16(1)}, 59 | {Command: &generated.Bstr{Str: "moar.exe"}, Arguments: &generated.Bstr{Str: ""}, WorkingDirectory: &generated.Bstr{Str: ""}, Flags: uint16(0)}, 60 | {Command: &generated.Bstr{Str: `C:\users\case\Desktop\witharg.xml`}, Arguments: &generated.Bstr{Str: "arg arg2"}, WorkingDirectory: &generated.Bstr{Str: ""}, Flags: uint16(0)}, 61 | {Command: &generated.Bstr{Str: `D:\only_workingdir.ps1`}, Arguments: &generated.Bstr{Str: ""}, WorkingDirectory: &generated.Bstr{Str: `C:\windows`}, Flags: uint16(0)}, 62 | {Command: &generated.Bstr{Str: `z:\allof\it.exe`}, Arguments: &generated.Bstr{Str: "arg1 arg2"}, WorkingDirectory: &generated.Bstr{Str: `c:\workingdir`}, Flags: uint16(0)}, 63 | } 64 | 65 | tt := generated.NewActions() 66 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 67 | t.Error(fmt.Sprintf("Read (%v)", err)) 68 | } 69 | 70 | if tt.Context.Str != "Author" { 71 | t.Error("Context") 72 | } 73 | 74 | if len(tt.Actions) != 5 { 75 | t.Error("Amount of Tasks") 76 | } 77 | 78 | for i, task := range tt.Actions { 79 | e := &generated.Actions_Action{ 80 | Id: &generated.Bstr{Str: "exec"}, 81 | Magic: uint16(0x6666), 82 | Properties: expected[i], 83 | } 84 | if err := compareExeTask(task, e); err != nil { 85 | t.Errorf("Task %d (%v)", i, err) 86 | } 87 | } 88 | } 89 | 90 | func TestTaskParser_ComHandler(t *testing.T) { 91 | blob := []byte{ 92 | 0x03, 0x00, 93 | 0x0a, 0x00, 0x00, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 94 | 95 | 0x77, 0x77, 96 | 0x14, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x72, 0x00, 97 | 0xb9, 0xd1, 0xbc, 0x61, 0x0c, 0x34, 0xec, 0x40, 0x9d, 0x41, 0xd7, 0xf1, 0xc0, 0x63, 0x2f, 0x05, 98 | 0x24, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x43, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x73, 0x00, 99 | } 100 | 101 | expected_task := &generated.Actions_Action{ 102 | Id: &generated.Bstr{Str: "comhandler"}, 103 | Magic: uint16(0x7777), 104 | Properties: &generated.Actions_ComHandlerProperties{ 105 | Clsid: []byte{0xb9, 0xd1, 0xbc, 0x61, 0x0c, 0x34, 0xec, 0x40, 0x9d, 0x41, 0xd7, 0xf1, 0xc0, 0x63, 0x2f, 0x05}, 106 | Data: &generated.Bstr{Str: "MissingCredentials"}, 107 | }, 108 | } 109 | 110 | tt := generated.NewActions() 111 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 112 | t.Error(fmt.Sprintf("Read (%v)", err)) 113 | t.FailNow() 114 | } 115 | 116 | if tt.Context.Str != "Users" { 117 | t.Error("Context") 118 | } 119 | 120 | if len(tt.Actions) != 1 { 121 | t.Error("Amount of Tasks") 122 | } 123 | 124 | if err := compareComHandlerTask(tt.Actions[0], expected_task); err != nil { 125 | t.Error(err) 126 | } 127 | } 128 | 129 | func TestTaskParser_MessageBox(t *testing.T) { 130 | blob := []byte{ 131 | 0x03, 0x00, 132 | 0x0c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 133 | 134 | 0x99, 0x99, 135 | 0x14, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x78, 0x00, 136 | 0x1e, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x5c, 0x00, 0x69, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 137 | 0x12, 0x00, 0x00, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x31, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x32, 0x00, 138 | } 139 | 140 | expected_task := &generated.Actions_Action{ 141 | Id: &generated.Bstr{Str: "messagebox"}, 142 | Magic: uint16(0x9999), 143 | Properties: &generated.Actions_MessageboxTaskProperties{ 144 | Caption: &generated.Bstr{Str: `z:\allof\it.exe`}, 145 | Content: &generated.Bstr{Str: "arg1 arg2"}, 146 | }, 147 | } 148 | 149 | tt := generated.NewActions() 150 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 151 | t.Error(fmt.Sprintf("Read (%v)", err)) 152 | t.FailNow() 153 | } 154 | 155 | if tt.Context.Str != "Author" { 156 | t.Error("Context") 157 | } 158 | 159 | if len(tt.Actions) != 1 { 160 | t.Error("Amount of Tasks") 161 | } 162 | 163 | if err := compareMessageBoxTask(tt.Actions[0], expected_task); err != nil { 164 | t.Error(err) 165 | } 166 | } 167 | 168 | func TestTaskParser_EmailTask(t *testing.T) { 169 | blob := []byte{ 170 | 0x03, 0x00, 171 | 0x0c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 172 | 173 | 0x88, 0x88, 174 | 0x0a, 0x00, 0x00, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6c, 0x00, 175 | 0x02, 0x00, 0x00, 0x00, 0x62, 0x00, 176 | 0x02, 0x00, 0x00, 0x00, 0x63, 0x00, 177 | 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 178 | 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 179 | 0x02, 0x00, 0x00, 0x00, 0x66, 0x00, 180 | 0x02, 0x00, 0x00, 0x00, 0x67, 0x00, 181 | 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, 182 | 0x02, 0x00, 0x00, 0x00, 0x69, 0x00, 183 | 0x03, 0x00, 0x00, 0x00, 184 | 0x02, 0x00, 0x00, 0x00, 0x6a, 0x00, 185 | 0x02, 0x00, 0x00, 0x00, 0x6b, 0x00, 186 | 0x02, 0x00, 0x00, 0x00, 0x6c, 0x00, 187 | 0x02, 0x00, 0x00, 0x00, 188 | 0x02, 0x00, 0x00, 0x00, 0x6d, 0x00, 189 | 0x02, 0x00, 0x00, 0x00, 0x6e, 0x00, 190 | 0x02, 0x00, 0x00, 0x00, 0x6f, 0x00, 191 | 0x02, 0x00, 0x00, 0x00, 0x70, 0x00, 192 | } 193 | 194 | expected_task := &generated.Actions_Action{ 195 | Id: &generated.Bstr{Str: "email"}, 196 | Magic: uint16(0x8888), 197 | Properties: &generated.Actions_EmailTaskProperties{ 198 | Server: &generated.Bstr{Str: "g"}, 199 | Subject: &generated.Bstr{Str: "h"}, 200 | To: &generated.Bstr{Str: "c"}, 201 | Cc: &generated.Bstr{Str: "d"}, 202 | Bcc: &generated.Bstr{Str: "e"}, 203 | ReplyTo: &generated.Bstr{Str: "f"}, 204 | From: &generated.Bstr{Str: "b"}, 205 | Body: &generated.Bstr{Str: "i"}, 206 | Headers: []*generated.Actions_KeyValueString{ 207 | {Key: &generated.Bstr{Str: "m"}, Value: &generated.Bstr{Str: "n"}}, 208 | {Key: &generated.Bstr{Str: "o"}, Value: &generated.Bstr{Str: "p"}}, 209 | }, 210 | AttachmentFilenames: []*generated.Bstr{ 211 | {Str: "j"}, 212 | {Str: "k"}, 213 | {Str: "l"}, 214 | }, 215 | }, 216 | } 217 | 218 | tt := generated.NewActions() 219 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 220 | t.Error(fmt.Sprintf("Read (%v)", err)) 221 | t.FailNow() 222 | } 223 | 224 | if tt.Context.Str != "Author" { 225 | t.Error("Context") 226 | } 227 | 228 | if len(tt.Actions) != 1 { 229 | t.Error("Amount of Tasks") 230 | } 231 | 232 | if err := compareEmailTask(tt.Actions[0], expected_task); err != nil { 233 | t.Error(err) 234 | } 235 | } 236 | 237 | func TestTaskParser_MixedAll(t *testing.T) { 238 | blob := []byte{ 239 | 0x03, 0x00, 240 | 0x0c, 0x00, 0x00, 0x00, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 241 | 242 | 0x66, 0x66, 243 | 0x08, 0x00, 0x00, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x63, 0x00, 244 | 0x1a, 0x00, 0x00, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 245 | 0x00, 0x00, 0x00, 0x00, 246 | 0x00, 0x00, 0x00, 0x00, 247 | 0x01, 0x00, 248 | 249 | 0x77, 0x77, 250 | 0x14, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x68, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x72, 0x00, 251 | 0xb9, 0xd1, 0xbc, 0x61, 0x0c, 0x34, 0xec, 0x40, 0x9d, 0x41, 0xd7, 0xf1, 0xc0, 0x63, 0x2f, 0x05, 252 | 0x24, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x43, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x73, 0x00, 253 | 254 | 0x88, 0x88, 255 | 0x0a, 0x00, 0x00, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x69, 0x00, 0x6c, 0x00, 256 | 0x02, 0x00, 0x00, 0x00, 0x62, 0x00, 257 | 0x02, 0x00, 0x00, 0x00, 0x63, 0x00, 258 | 0x02, 0x00, 0x00, 0x00, 0x64, 0x00, 259 | 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 260 | 0x02, 0x00, 0x00, 0x00, 0x66, 0x00, 261 | 0x02, 0x00, 0x00, 0x00, 0x67, 0x00, 262 | 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, 263 | 0x02, 0x00, 0x00, 0x00, 0x69, 0x00, 264 | 0x03, 0x00, 0x00, 0x00, 265 | 0x02, 0x00, 0x00, 0x00, 0x6a, 0x00, 266 | 0x02, 0x00, 0x00, 0x00, 0x6b, 0x00, 267 | 0x02, 0x00, 0x00, 0x00, 0x6c, 0x00, 268 | 0x02, 0x00, 0x00, 0x00, 269 | 0x02, 0x00, 0x00, 0x00, 0x6d, 0x00, 270 | 0x02, 0x00, 0x00, 0x00, 0x6e, 0x00, 271 | 0x02, 0x00, 0x00, 0x00, 0x6f, 0x00, 272 | 0x02, 0x00, 0x00, 0x00, 0x70, 0x00, 273 | 274 | 0x99, 0x99, 275 | 0x14, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x78, 0x00, 276 | 0x1e, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x3a, 0x00, 0x5c, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x5c, 0x00, 0x69, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x65, 0x00, 0x78, 0x00, 0x65, 0x00, 277 | 0x12, 0x00, 0x00, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x31, 0x00, 0x20, 0x00, 0x61, 0x00, 0x72, 0x00, 0x67, 0x00, 0x32, 0x00, 278 | } 279 | 280 | expected_exe := &generated.Actions_Action{ 281 | Id: &generated.Bstr{Str: "exec"}, 282 | Magic: uint16(0x6666), 283 | Properties: &generated.Actions_ExeTaskProperties{ 284 | Command: &generated.Bstr{Str: "execution.exe"}, 285 | Arguments: &generated.Bstr{Str: ""}, 286 | WorkingDirectory: &generated.Bstr{Str: ""}, 287 | Flags: uint16(1), 288 | }, 289 | } 290 | 291 | expected_comhandler := &generated.Actions_Action{ 292 | Id: &generated.Bstr{Str: "comhandler"}, 293 | Magic: uint16(0x7777), 294 | Properties: &generated.Actions_ComHandlerProperties{ 295 | Clsid: []byte{0xb9, 0xd1, 0xbc, 0x61, 0x0c, 0x34, 0xec, 0x40, 0x9d, 0x41, 0xd7, 0xf1, 0xc0, 0x63, 0x2f, 0x05}, 296 | Data: &generated.Bstr{Str: "MissingCredentials"}, 297 | }, 298 | } 299 | 300 | expected_email := &generated.Actions_Action{ 301 | Id: &generated.Bstr{Str: "email"}, 302 | Magic: uint16(0x8888), 303 | Properties: &generated.Actions_EmailTaskProperties{ 304 | Server: &generated.Bstr{Str: "g"}, 305 | Subject: &generated.Bstr{Str: "h"}, 306 | To: &generated.Bstr{Str: "c"}, 307 | Cc: &generated.Bstr{Str: "d"}, 308 | Bcc: &generated.Bstr{Str: "e"}, 309 | ReplyTo: &generated.Bstr{Str: "f"}, 310 | From: &generated.Bstr{Str: "b"}, 311 | Body: &generated.Bstr{Str: "i"}, 312 | Headers: []*generated.Actions_KeyValueString{ 313 | {Key: &generated.Bstr{Str: "m"}, Value: &generated.Bstr{Str: "n"}}, 314 | {Key: &generated.Bstr{Str: "o"}, Value: &generated.Bstr{Str: "p"}}, 315 | }, 316 | AttachmentFilenames: []*generated.Bstr{ 317 | {Str: "j"}, 318 | {Str: "k"}, 319 | {Str: "l"}, 320 | }, 321 | }, 322 | } 323 | 324 | expected_messagebox := &generated.Actions_Action{ 325 | Id: &generated.Bstr{Str: "messagebox"}, 326 | Magic: uint16(0x9999), 327 | Properties: &generated.Actions_MessageboxTaskProperties{ 328 | Caption: &generated.Bstr{Str: `z:\allof\it.exe`}, 329 | Content: &generated.Bstr{Str: "arg1 arg2"}, 330 | }, 331 | } 332 | 333 | tt := generated.NewActions() 334 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 335 | t.Error(fmt.Sprintf("Read (%v)", err)) 336 | t.FailNow() 337 | } 338 | 339 | if tt.Context.Str != "Author" { 340 | t.Error("Context") 341 | } 342 | 343 | if len(tt.Actions) != 4 { 344 | t.Error("Amount of Tasks") 345 | } 346 | 347 | if err := compareExeTask(tt.Actions[0], expected_exe); err != nil { 348 | t.Errorf("ExecTask failed: %v", err) 349 | } 350 | 351 | if err := compareComHandlerTask(tt.Actions[1], expected_comhandler); err != nil { 352 | t.Errorf("ComHandler failed: %v", err) 353 | } 354 | 355 | if err := compareEmailTask(tt.Actions[2], expected_email); err != nil { 356 | t.Errorf("EmailTask failed: %v", err) 357 | } 358 | 359 | if err := compareMessageBoxTask(tt.Actions[3], expected_messagebox); err != nil { 360 | t.Errorf("MesageBoxTask failed: %v", err) 361 | } 362 | } 363 | -------------------------------------------------------------------------------- /generated/aligned_bstr.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import ( 6 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 7 | "golang.org/x/text/encoding/unicode" 8 | ) 9 | 10 | type AlignedBstr struct { 11 | ByteCount *AlignedU4 12 | String string 13 | BlockPadding []byte 14 | _io *kaitai.Stream 15 | _root *AlignedBstr 16 | _parent interface{} 17 | } 18 | func NewAlignedBstr() *AlignedBstr { 19 | return &AlignedBstr{ 20 | } 21 | } 22 | 23 | func (this *AlignedBstr) Read(io *kaitai.Stream, parent interface{}, root *AlignedBstr) (err error) { 24 | this._io = io 25 | this._parent = parent 26 | this._root = root 27 | 28 | tmp1 := NewAlignedU4() 29 | err = tmp1.Read(this._io, this, nil) 30 | if err != nil { 31 | return err 32 | } 33 | this.ByteCount = tmp1 34 | tmp2, err := this._io.ReadBytes(int(this.ByteCount.Value)) 35 | if err != nil { 36 | return err 37 | } 38 | tmp2 = tmp2 39 | tmp3, err := kaitai.BytesToStr(tmp2, unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder()) 40 | if err != nil { 41 | return err 42 | } 43 | this.String = tmp3 44 | tmp5 := this.ByteCount.Value % 8 45 | if tmp5 < 0 { 46 | tmp5 += 8 47 | } 48 | tmp4 := (8 - tmp5) % 8 49 | if tmp4 < 0 { 50 | tmp4 += 8 51 | } 52 | tmp6, err := this._io.ReadBytes(int(tmp4)) 53 | if err != nil { 54 | return err 55 | } 56 | tmp6 = tmp6 57 | this.BlockPadding = tmp6 58 | return err 59 | } 60 | -------------------------------------------------------------------------------- /generated/aligned_bstr_expand_size.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import ( 6 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 7 | "golang.org/x/text/encoding/unicode" 8 | ) 9 | 10 | type AlignedBstrExpandSize struct { 11 | StringLength *AlignedU4 12 | Content string 13 | Padding []byte 14 | _io *kaitai.Stream 15 | _root *AlignedBstrExpandSize 16 | _parent interface{} 17 | _f_byteCount bool 18 | byteCount int 19 | } 20 | func NewAlignedBstrExpandSize() *AlignedBstrExpandSize { 21 | return &AlignedBstrExpandSize{ 22 | } 23 | } 24 | 25 | func (this *AlignedBstrExpandSize) Read(io *kaitai.Stream, parent interface{}, root *AlignedBstrExpandSize) (err error) { 26 | this._io = io 27 | this._parent = parent 28 | this._root = root 29 | 30 | tmp1 := NewAlignedU4() 31 | err = tmp1.Read(this._io, this, nil) 32 | if err != nil { 33 | return err 34 | } 35 | this.StringLength = tmp1 36 | if (this.StringLength.Value > 0) { 37 | tmp2, err := this.ByteCount() 38 | if err != nil { 39 | return err 40 | } 41 | tmp3, err := this._io.ReadBytes(int(tmp2)) 42 | if err != nil { 43 | return err 44 | } 45 | tmp3 = tmp3 46 | tmp4, err := kaitai.BytesToStr(tmp3, unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder()) 47 | if err != nil { 48 | return err 49 | } 50 | this.Content = tmp4 51 | } 52 | if (this.StringLength.Value > 0) { 53 | tmp7, err := this.ByteCount() 54 | if err != nil { 55 | return err 56 | } 57 | tmp6 := tmp7 % 8 58 | if tmp6 < 0 { 59 | tmp6 += 8 60 | } 61 | tmp5 := (8 - tmp6) % 8 62 | if tmp5 < 0 { 63 | tmp5 += 8 64 | } 65 | tmp8, err := this._io.ReadBytes(int(tmp5)) 66 | if err != nil { 67 | return err 68 | } 69 | tmp8 = tmp8 70 | this.Padding = tmp8 71 | } 72 | return err 73 | } 74 | func (this *AlignedBstrExpandSize) ByteCount() (v int, err error) { 75 | if (this._f_byteCount) { 76 | return this.byteCount, nil 77 | } 78 | this.byteCount = int(((this.StringLength.Value * 2) + 2)) 79 | this._f_byteCount = true 80 | return this.byteCount, nil 81 | } 82 | -------------------------------------------------------------------------------- /generated/aligned_buffer.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | type AlignedBuffer struct { 8 | Size *AlignedU4 9 | Data []byte 10 | Padding []byte 11 | _io *kaitai.Stream 12 | _root *AlignedBuffer 13 | _parent interface{} 14 | } 15 | func NewAlignedBuffer() *AlignedBuffer { 16 | return &AlignedBuffer{ 17 | } 18 | } 19 | 20 | func (this *AlignedBuffer) Read(io *kaitai.Stream, parent interface{}, root *AlignedBuffer) (err error) { 21 | this._io = io 22 | this._parent = parent 23 | this._root = root 24 | 25 | tmp1 := NewAlignedU4() 26 | err = tmp1.Read(this._io, this, nil) 27 | if err != nil { 28 | return err 29 | } 30 | this.Size = tmp1 31 | tmp2, err := this._io.ReadBytes(int(this.Size.Value)) 32 | if err != nil { 33 | return err 34 | } 35 | tmp2 = tmp2 36 | this.Data = tmp2 37 | tmp4 := this.Size.Value % 8 38 | if tmp4 < 0 { 39 | tmp4 += 8 40 | } 41 | tmp3 := (8 - tmp4) % 8 42 | if tmp3 < 0 { 43 | tmp3 += 8 44 | } 45 | tmp5, err := this._io.ReadBytes(int(tmp3)) 46 | if err != nil { 47 | return err 48 | } 49 | tmp5 = tmp5 50 | this.Padding = tmp5 51 | return err 52 | } 53 | -------------------------------------------------------------------------------- /generated/aligned_u1.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | type AlignedU1 struct { 8 | Value uint8 9 | Padding []byte 10 | _io *kaitai.Stream 11 | _root *AlignedU1 12 | _parent interface{} 13 | } 14 | func NewAlignedU1() *AlignedU1 { 15 | return &AlignedU1{ 16 | } 17 | } 18 | 19 | func (this *AlignedU1) Read(io *kaitai.Stream, parent interface{}, root *AlignedU1) (err error) { 20 | this._io = io 21 | this._parent = parent 22 | this._root = root 23 | 24 | tmp1, err := this._io.ReadU1() 25 | if err != nil { 26 | return err 27 | } 28 | this.Value = tmp1 29 | tmp2, err := this._io.ReadBytes(int(7)) 30 | if err != nil { 31 | return err 32 | } 33 | tmp2 = tmp2 34 | this.Padding = tmp2 35 | return err 36 | } 37 | -------------------------------------------------------------------------------- /generated/aligned_u4.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | type AlignedU4 struct { 8 | Value uint32 9 | Padding []byte 10 | _io *kaitai.Stream 11 | _root *AlignedU4 12 | _parent interface{} 13 | } 14 | func NewAlignedU4() *AlignedU4 { 15 | return &AlignedU4{ 16 | } 17 | } 18 | 19 | func (this *AlignedU4) Read(io *kaitai.Stream, parent interface{}, root *AlignedU4) (err error) { 20 | this._io = io 21 | this._parent = parent 22 | this._root = root 23 | 24 | tmp1, err := this._io.ReadU4le() 25 | if err != nil { 26 | return err 27 | } 28 | this.Value = uint32(tmp1) 29 | tmp2, err := this._io.ReadBytes(int(4)) 30 | if err != nil { 31 | return err 32 | } 33 | tmp2 = tmp2 34 | this.Padding = tmp2 35 | return err 36 | } 37 | -------------------------------------------------------------------------------- /generated/bstr.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import ( 6 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 7 | "golang.org/x/text/encoding/unicode" 8 | ) 9 | 10 | type Bstr struct { 11 | Len uint32 12 | Str string 13 | _io *kaitai.Stream 14 | _root *Bstr 15 | _parent interface{} 16 | } 17 | func NewBstr() *Bstr { 18 | return &Bstr{ 19 | } 20 | } 21 | 22 | func (this *Bstr) Read(io *kaitai.Stream, parent interface{}, root *Bstr) (err error) { 23 | this._io = io 24 | this._parent = parent 25 | this._root = root 26 | 27 | tmp1, err := this._io.ReadU4le() 28 | if err != nil { 29 | return err 30 | } 31 | this.Len = uint32(tmp1) 32 | tmp2, err := this._io.ReadBytes(int(this.Len)) 33 | if err != nil { 34 | return err 35 | } 36 | tmp2 = tmp2 37 | tmp3, err := kaitai.BytesToStr(tmp2, unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder()) 38 | if err != nil { 39 | return err 40 | } 41 | this.Str = tmp3 42 | return err 43 | } 44 | -------------------------------------------------------------------------------- /generated/dynamic_info.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | type DynamicInfo struct { 8 | Magic []byte 9 | CreationTime uint64 10 | LastRunTime uint64 11 | TaskState uint32 12 | LastErrorCode uint32 13 | LastSuccessfulRunTime uint64 14 | _io *kaitai.Stream 15 | _root *DynamicInfo 16 | _parent interface{} 17 | } 18 | func NewDynamicInfo() *DynamicInfo { 19 | return &DynamicInfo{ 20 | } 21 | } 22 | 23 | func (this *DynamicInfo) Read(io *kaitai.Stream, parent interface{}, root *DynamicInfo) (err error) { 24 | this._io = io 25 | this._parent = parent 26 | this._root = root 27 | 28 | tmp1, err := this._io.ReadBytes(int(4)) 29 | if err != nil { 30 | return err 31 | } 32 | tmp1 = tmp1 33 | this.Magic = tmp1 34 | tmp2, err := this._io.ReadU8le() 35 | if err != nil { 36 | return err 37 | } 38 | this.CreationTime = uint64(tmp2) 39 | tmp3, err := this._io.ReadU8le() 40 | if err != nil { 41 | return err 42 | } 43 | this.LastRunTime = uint64(tmp3) 44 | tmp4, err := this._io.ReadU4le() 45 | if err != nil { 46 | return err 47 | } 48 | this.TaskState = uint32(tmp4) 49 | tmp5, err := this._io.ReadU4le() 50 | if err != nil { 51 | return err 52 | } 53 | this.LastErrorCode = uint32(tmp5) 54 | tmp6, err := this._io.ReadU8le() 55 | if err != nil { 56 | return err 57 | } 58 | this.LastSuccessfulRunTime = uint64(tmp6) 59 | return err 60 | } 61 | -------------------------------------------------------------------------------- /generated/dynamic_info_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package generated_test 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "testing" 9 | 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 11 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 12 | ) 13 | 14 | func TestDynamicInfo_Read_WithErrorCode(t *testing.T) { 15 | blob := []byte{ 16 | 0x03, 0x00, 0x00, 0x00, 0xe9, 0x79, 0x2d, 0xf1, 17 | 0x31, 0x1c, 0xd8, 0x01, 0xb4, 0x4a, 0x8b, 0x8d, 18 | 0x3e, 0x1c, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 19 | 0x02, 0x00, 0x07, 0x80, 0xe4, 0x70, 0xd5, 0x67, 20 | 0x34, 0x1c, 0xd8, 0x01, 21 | } 22 | 23 | tt := generated.NewDynamicInfo() 24 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 25 | t.Error(fmt.Sprintf("Read (%v)", err)) 26 | } 27 | 28 | if tt.CreationTime != 0x01d81c31f12d79e9 { 29 | t.Error("CreationTime") 30 | } 31 | 32 | if tt.LastRunTime != 0x01d81c3e8d8b4ab4 { 33 | t.Error("LastRunTime") 34 | } 35 | 36 | if tt.TaskState != 0x00000000 { 37 | t.Error("TaskState") 38 | } 39 | 40 | if tt.LastErrorCode != 0x80070002 { 41 | t.Error("LastErrorCode") 42 | } 43 | 44 | if tt.LastSuccessfulRunTime != 0x01d81c3467d570e4 { 45 | t.Error("LastSuccessfulRunTime") 46 | } 47 | } 48 | 49 | func TestDynamicInfo_Read_WithSuccess(t *testing.T) { 50 | blob := []byte{ 51 | 0x03, 0x00, 0x00, 0x00, 0xe9, 0x79, 0x2d, 0xf1, 52 | 0x31, 0x1c, 0xd8, 0x01, 0x96, 0xc1, 0x54, 0xa5, 53 | 0x3e, 0x1c, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0xf6, 0x79, 0xa3, 0xa5, 55 | 0x3e, 0x1c, 0xd8, 0x01, 56 | } 57 | 58 | tt := generated.NewDynamicInfo() 59 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 60 | t.Error(fmt.Sprintf("Read (%v)", err)) 61 | } 62 | 63 | if tt.CreationTime != 0x01d81c31f12d79e9 { 64 | t.Error("CreationTime") 65 | } 66 | 67 | if tt.LastRunTime != 0x01d81c3ea554c196 { 68 | t.Error("LastRunTime") 69 | } 70 | 71 | if tt.TaskState != 0x00000000 { 72 | t.Error("TaskState") 73 | } 74 | 75 | if tt.LastErrorCode != 0x00000000 { 76 | t.Error("LastErrorCode") 77 | } 78 | 79 | if tt.LastSuccessfulRunTime != 0x01d81c3ea5a379f6 { 80 | t.Error("LastSuccessfulRunTime") 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /generated/filetime.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | type Filetime struct { 8 | LowDateTime uint32 9 | HighDateTime uint32 10 | _io *kaitai.Stream 11 | _root *Filetime 12 | _parent interface{} 13 | } 14 | func NewFiletime() *Filetime { 15 | return &Filetime{ 16 | } 17 | } 18 | 19 | func (this *Filetime) Read(io *kaitai.Stream, parent interface{}, root *Filetime) (err error) { 20 | this._io = io 21 | this._parent = parent 22 | this._root = root 23 | 24 | tmp1, err := this._io.ReadU4le() 25 | if err != nil { 26 | return err 27 | } 28 | this.LowDateTime = uint32(tmp1) 29 | tmp2, err := this._io.ReadU4le() 30 | if err != nil { 31 | return err 32 | } 33 | this.HighDateTime = uint32(tmp2) 34 | return err 35 | } 36 | -------------------------------------------------------------------------------- /generated/helpers_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package generated_test 4 | 5 | import ( 6 | "bytes" 7 | "errors" 8 | "fmt" 9 | 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 11 | ) 12 | 13 | func compareExeTask(task, expected *generated.Actions_Action) error { 14 | if task.Id.Str != expected.Id.Str { 15 | return errors.New("Task Id") 16 | } 17 | if task.Magic != expected.Magic { 18 | return errors.New("Task Magic") 19 | } 20 | t_props, ok := task.Properties.(*generated.Actions_ExeTaskProperties) 21 | if !ok { 22 | return errors.New("Task Type Cast") 23 | } 24 | 25 | e_props := expected.Properties.(*generated.Actions_ExeTaskProperties) 26 | 27 | if t_props.Arguments.Str != e_props.Arguments.Str { 28 | return errors.New("Task Props Arguments") 29 | } 30 | if t_props.Command.Str != e_props.Command.Str { 31 | return errors.New("Task Props Command") 32 | } 33 | if t_props.WorkingDirectory.Str != e_props.WorkingDirectory.Str { 34 | return errors.New("Task Props WorkingDirectory") 35 | } 36 | if t_props.Flags != e_props.Flags { 37 | return errors.New("Task Props HideAppWindow") 38 | } 39 | return nil 40 | } 41 | 42 | func compareComHandlerTask(task, expected *generated.Actions_Action) error { 43 | if task.Id.Str != expected.Id.Str { 44 | return errors.New("Task Id") 45 | } 46 | if task.Magic != expected.Magic { 47 | return errors.New("Task Magic") 48 | } 49 | t_props, ok := task.Properties.(*generated.Actions_ComHandlerProperties) 50 | if !ok { 51 | return errors.New("Task Type Cast") 52 | } 53 | 54 | e_props := expected.Properties.(*generated.Actions_ComHandlerProperties) 55 | 56 | if !bytes.Equal(t_props.Clsid, e_props.Clsid) { 57 | return errors.New("Task Props Arguments") 58 | } 59 | if t_props.Data.Str != e_props.Data.Str { 60 | return errors.New("Task Props Command") 61 | } 62 | return nil 63 | } 64 | 65 | func compareMessageBoxTask(task, expected *generated.Actions_Action) error { 66 | if task.Id.Str != expected.Id.Str { 67 | return errors.New("Task Id") 68 | } 69 | if task.Magic != expected.Magic { 70 | return errors.New("Task Magic") 71 | } 72 | t_props, ok := task.Properties.(*generated.Actions_MessageboxTaskProperties) 73 | if !ok { 74 | return errors.New("Task Type Cast") 75 | } 76 | 77 | e_props := expected.Properties.(*generated.Actions_MessageboxTaskProperties) 78 | 79 | if t_props.Caption.Str != e_props.Caption.Str { 80 | return errors.New("Task Props Caption") 81 | } 82 | if t_props.Content.Str != e_props.Content.Str { 83 | return errors.New("Task Props Content") 84 | } 85 | return nil 86 | } 87 | 88 | func compareEmailTask(task, expected *generated.Actions_Action) error { 89 | if task.Id.Str != expected.Id.Str { 90 | return errors.New("Task Id") 91 | } 92 | if task.Magic != expected.Magic { 93 | return errors.New("Task Magic") 94 | } 95 | 96 | props, ok := task.Properties.(*generated.Actions_EmailTaskProperties) 97 | if !ok { 98 | return errors.New("Task Type conversion error") 99 | } 100 | 101 | e_props := expected.Properties.(*generated.Actions_EmailTaskProperties) 102 | 103 | if props.Server.Str != e_props.Server.Str { 104 | return errors.New("Server") 105 | } 106 | if props.Subject.Str != e_props.Subject.Str { 107 | return errors.New("Subject") 108 | } 109 | if props.To.Str != e_props.To.Str { 110 | return errors.New("To") 111 | } 112 | if props.Cc.Str != e_props.Cc.Str { 113 | return errors.New("Cc") 114 | } 115 | if props.Bcc.Str != e_props.Bcc.Str { 116 | return errors.New("Bcc") 117 | } 118 | if props.ReplyTo.Str != e_props.ReplyTo.Str { 119 | return errors.New("ReplyTo") 120 | } 121 | if props.From.Str != e_props.From.Str { 122 | return errors.New("From") 123 | } 124 | if props.Body.Str != e_props.Body.Str { 125 | return errors.New("Body") 126 | } 127 | if len(props.Headers) != len(e_props.Headers) { 128 | return errors.New("Headers Length") 129 | } 130 | for i := range props.Headers { 131 | if props.Headers[i].Key.Str != e_props.Headers[i].Key.Str { 132 | return fmt.Errorf("Header %d Name mismatch", i) 133 | } 134 | if props.Headers[i].Value.Str != e_props.Headers[i].Value.Str { 135 | return fmt.Errorf("Header %d Value mismatch", i) 136 | } 137 | } 138 | if len(props.AttachmentFilenames) != len(e_props.AttachmentFilenames) { 139 | return errors.New("Attachments Length") 140 | } 141 | for i := range props.AttachmentFilenames { 142 | if props.AttachmentFilenames[i].Str != e_props.AttachmentFilenames[i].Str { 143 | return fmt.Errorf("Attachment %d mismatch", i) 144 | } 145 | } 146 | return nil 147 | } 148 | -------------------------------------------------------------------------------- /generated/job_schedule.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | 8 | type JobSchedule_TimeMode int 9 | const ( 10 | JobSchedule_TimeMode__OneTime JobSchedule_TimeMode = 0 11 | JobSchedule_TimeMode__Daily JobSchedule_TimeMode = 1 12 | JobSchedule_TimeMode__Weekly JobSchedule_TimeMode = 2 13 | JobSchedule_TimeMode__DaysInMonths JobSchedule_TimeMode = 3 14 | JobSchedule_TimeMode__DaysInWeeksInMonths JobSchedule_TimeMode = 4 15 | ) 16 | 17 | type JobSchedule_DayOfWeek int 18 | const ( 19 | JobSchedule_DayOfWeek__Sunday JobSchedule_DayOfWeek = 1 20 | JobSchedule_DayOfWeek__Monday JobSchedule_DayOfWeek = 2 21 | JobSchedule_DayOfWeek__Tuesday JobSchedule_DayOfWeek = 4 22 | JobSchedule_DayOfWeek__Wednesday JobSchedule_DayOfWeek = 8 23 | JobSchedule_DayOfWeek__Thursday JobSchedule_DayOfWeek = 16 24 | JobSchedule_DayOfWeek__Friday JobSchedule_DayOfWeek = 32 25 | JobSchedule_DayOfWeek__Saturday JobSchedule_DayOfWeek = 64 26 | ) 27 | 28 | type JobSchedule_Months int 29 | const ( 30 | JobSchedule_Months__January JobSchedule_Months = 1 31 | JobSchedule_Months__February JobSchedule_Months = 2 32 | JobSchedule_Months__March JobSchedule_Months = 4 33 | JobSchedule_Months__April JobSchedule_Months = 8 34 | JobSchedule_Months__May JobSchedule_Months = 16 35 | JobSchedule_Months__June JobSchedule_Months = 32 36 | JobSchedule_Months__July JobSchedule_Months = 64 37 | JobSchedule_Months__August JobSchedule_Months = 128 38 | JobSchedule_Months__September JobSchedule_Months = 256 39 | JobSchedule_Months__October JobSchedule_Months = 512 40 | JobSchedule_Months__November JobSchedule_Months = 1024 41 | JobSchedule_Months__December JobSchedule_Months = 2048 42 | ) 43 | type JobSchedule struct { 44 | StartBoundary *Tstime 45 | EndBoundary *Tstime 46 | Unknown0 *Tstime 47 | RepetitionIntervalSeconds uint32 48 | RepetitionDurationSeconds uint32 49 | ExecutionTimeLimitSeconds uint32 50 | Mode JobSchedule_TimeMode 51 | Data1 uint16 52 | Data2 uint16 53 | Data3 uint16 54 | Pad0 uint16 55 | StopTasksAtDurationEnd uint8 56 | IsEnabled uint8 57 | Pad1 uint16 58 | Unknown1 uint32 59 | MaxDelaySeconds uint32 60 | Pad2 uint32 61 | _io *kaitai.Stream 62 | _root *JobSchedule 63 | _parent interface{} 64 | } 65 | func NewJobSchedule() *JobSchedule { 66 | return &JobSchedule{ 67 | } 68 | } 69 | 70 | func (this *JobSchedule) Read(io *kaitai.Stream, parent interface{}, root *JobSchedule) (err error) { 71 | this._io = io 72 | this._parent = parent 73 | this._root = root 74 | 75 | tmp1 := NewTstime() 76 | err = tmp1.Read(this._io, this, nil) 77 | if err != nil { 78 | return err 79 | } 80 | this.StartBoundary = tmp1 81 | tmp2 := NewTstime() 82 | err = tmp2.Read(this._io, this, nil) 83 | if err != nil { 84 | return err 85 | } 86 | this.EndBoundary = tmp2 87 | tmp3 := NewTstime() 88 | err = tmp3.Read(this._io, this, nil) 89 | if err != nil { 90 | return err 91 | } 92 | this.Unknown0 = tmp3 93 | tmp4, err := this._io.ReadU4le() 94 | if err != nil { 95 | return err 96 | } 97 | this.RepetitionIntervalSeconds = uint32(tmp4) 98 | tmp5, err := this._io.ReadU4le() 99 | if err != nil { 100 | return err 101 | } 102 | this.RepetitionDurationSeconds = uint32(tmp5) 103 | tmp6, err := this._io.ReadU4le() 104 | if err != nil { 105 | return err 106 | } 107 | this.ExecutionTimeLimitSeconds = uint32(tmp6) 108 | tmp7, err := this._io.ReadU4le() 109 | if err != nil { 110 | return err 111 | } 112 | this.Mode = JobSchedule_TimeMode(tmp7) 113 | tmp8, err := this._io.ReadU2le() 114 | if err != nil { 115 | return err 116 | } 117 | this.Data1 = uint16(tmp8) 118 | tmp9, err := this._io.ReadU2le() 119 | if err != nil { 120 | return err 121 | } 122 | this.Data2 = uint16(tmp9) 123 | tmp10, err := this._io.ReadU2le() 124 | if err != nil { 125 | return err 126 | } 127 | this.Data3 = uint16(tmp10) 128 | tmp11, err := this._io.ReadU2le() 129 | if err != nil { 130 | return err 131 | } 132 | this.Pad0 = uint16(tmp11) 133 | tmp12, err := this._io.ReadU1() 134 | if err != nil { 135 | return err 136 | } 137 | this.StopTasksAtDurationEnd = tmp12 138 | tmp13, err := this._io.ReadU1() 139 | if err != nil { 140 | return err 141 | } 142 | this.IsEnabled = tmp13 143 | tmp14, err := this._io.ReadU2le() 144 | if err != nil { 145 | return err 146 | } 147 | this.Pad1 = uint16(tmp14) 148 | tmp15, err := this._io.ReadU4le() 149 | if err != nil { 150 | return err 151 | } 152 | this.Unknown1 = uint32(tmp15) 153 | tmp16, err := this._io.ReadU4le() 154 | if err != nil { 155 | return err 156 | } 157 | this.MaxDelaySeconds = uint32(tmp16) 158 | tmp17, err := this._io.ReadU4le() 159 | if err != nil { 160 | return err 161 | } 162 | this.Pad2 = uint32(tmp17) 163 | return err 164 | } 165 | -------------------------------------------------------------------------------- /generated/optional_settings.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | 8 | type OptionalSettings_Privilege int64 9 | const ( 10 | OptionalSettings_Privilege__SeCreateTokenPrivilege OptionalSettings_Privilege = 4 11 | OptionalSettings_Privilege__SeAssignPrimaryTokenPrivilege OptionalSettings_Privilege = 8 12 | OptionalSettings_Privilege__SeLockMemoryPrivilege OptionalSettings_Privilege = 16 13 | OptionalSettings_Privilege__SeIncreaseQuotaPrivilege OptionalSettings_Privilege = 32 14 | OptionalSettings_Privilege__SeMachineAccountPrivilege OptionalSettings_Privilege = 64 15 | OptionalSettings_Privilege__SeTcbPrivilege OptionalSettings_Privilege = 128 16 | OptionalSettings_Privilege__SeSecurityPrivilege OptionalSettings_Privilege = 256 17 | OptionalSettings_Privilege__SeTakeOwnershipPrivilege OptionalSettings_Privilege = 512 18 | OptionalSettings_Privilege__SeLoadDriverPrivilege OptionalSettings_Privilege = 1024 19 | OptionalSettings_Privilege__SeSystemProfilePrivilege OptionalSettings_Privilege = 2048 20 | OptionalSettings_Privilege__SeSystemtimePrivilege OptionalSettings_Privilege = 4096 21 | OptionalSettings_Privilege__SeProfileSingleProcessPrivilege OptionalSettings_Privilege = 8192 22 | OptionalSettings_Privilege__SeIncreaseBasePriorityPrivilege OptionalSettings_Privilege = 16384 23 | OptionalSettings_Privilege__SeCreatePagefilePrivilege OptionalSettings_Privilege = 32768 24 | OptionalSettings_Privilege__SeCreatePermanentPrivilege OptionalSettings_Privilege = 65536 25 | OptionalSettings_Privilege__SeBackupPrivilege OptionalSettings_Privilege = 131072 26 | OptionalSettings_Privilege__SeRestorePrivilege OptionalSettings_Privilege = 262144 27 | OptionalSettings_Privilege__SeShutdownPrivilege OptionalSettings_Privilege = 524288 28 | OptionalSettings_Privilege__SeDebugPrivilege OptionalSettings_Privilege = 1048576 29 | OptionalSettings_Privilege__SeAuditPrivilege OptionalSettings_Privilege = 2097152 30 | OptionalSettings_Privilege__SeSystemEnvironmentPrivilege OptionalSettings_Privilege = 4194304 31 | OptionalSettings_Privilege__SeChangeNotifyPrivilege OptionalSettings_Privilege = 8388608 32 | OptionalSettings_Privilege__SeRemoteShutdownPrivilege OptionalSettings_Privilege = 16777216 33 | OptionalSettings_Privilege__SeUndockPrivilege OptionalSettings_Privilege = 33554432 34 | OptionalSettings_Privilege__SeSyncAgentPrivilege OptionalSettings_Privilege = 67108864 35 | OptionalSettings_Privilege__SeEnableDelegationPrivilege OptionalSettings_Privilege = 134217728 36 | OptionalSettings_Privilege__SeManageVolumePrivilege OptionalSettings_Privilege = 268435456 37 | OptionalSettings_Privilege__SeImpersonatePrivilege OptionalSettings_Privilege = 536870912 38 | OptionalSettings_Privilege__SeCreateGlobalPrivilege OptionalSettings_Privilege = 1073741824 39 | OptionalSettings_Privilege__SeTrustedCredManAccessPrivilege OptionalSettings_Privilege = 2147483648 40 | OptionalSettings_Privilege__SeRelabelPrivilege OptionalSettings_Privilege = 4294967296 41 | OptionalSettings_Privilege__SeIncreaseWorkingSetPrivilege OptionalSettings_Privilege = 8589934592 42 | OptionalSettings_Privilege__SeTimeZonePrivilege OptionalSettings_Privilege = 17179869184 43 | OptionalSettings_Privilege__SeCreateSymbolicLinkPrivilege OptionalSettings_Privilege = 34359738368 44 | OptionalSettings_Privilege__SeDelegateSessionUserImpersonatePrivilege OptionalSettings_Privilege = 68719476736 45 | ) 46 | type OptionalSettings struct { 47 | Len *AlignedU4 48 | IdleDurationSeconds uint32 49 | IdleWaitTimeoutSeconds uint32 50 | ExecutionTimeLimitSeconds uint32 51 | DeleteExpiredTaskAfter uint32 52 | Priority uint32 53 | RestartOnFailureDelay uint32 54 | RestartOnFailureRetries uint32 55 | NetworkId []byte 56 | Padding0 []byte 57 | Privileges OptionalSettings_Privilege 58 | Periodicity *Tstimeperiod 59 | Deadline *Tstimeperiod 60 | Exclusive uint8 61 | Padding1 []byte 62 | _io *kaitai.Stream 63 | _root *OptionalSettings 64 | _parent interface{} 65 | } 66 | func NewOptionalSettings() *OptionalSettings { 67 | return &OptionalSettings{ 68 | } 69 | } 70 | 71 | func (this *OptionalSettings) Read(io *kaitai.Stream, parent interface{}, root *OptionalSettings) (err error) { 72 | this._io = io 73 | this._parent = parent 74 | this._root = root 75 | 76 | tmp1 := NewAlignedU4() 77 | err = tmp1.Read(this._io, this, nil) 78 | if err != nil { 79 | return err 80 | } 81 | this.Len = tmp1 82 | if (this.Len.Value > 0) { 83 | tmp2, err := this._io.ReadU4le() 84 | if err != nil { 85 | return err 86 | } 87 | this.IdleDurationSeconds = uint32(tmp2) 88 | } 89 | if (this.Len.Value > 0) { 90 | tmp3, err := this._io.ReadU4le() 91 | if err != nil { 92 | return err 93 | } 94 | this.IdleWaitTimeoutSeconds = uint32(tmp3) 95 | } 96 | if (this.Len.Value > 0) { 97 | tmp4, err := this._io.ReadU4le() 98 | if err != nil { 99 | return err 100 | } 101 | this.ExecutionTimeLimitSeconds = uint32(tmp4) 102 | } 103 | if (this.Len.Value > 0) { 104 | tmp5, err := this._io.ReadU4le() 105 | if err != nil { 106 | return err 107 | } 108 | this.DeleteExpiredTaskAfter = uint32(tmp5) 109 | } 110 | if (this.Len.Value > 0) { 111 | tmp6, err := this._io.ReadU4le() 112 | if err != nil { 113 | return err 114 | } 115 | this.Priority = uint32(tmp6) 116 | } 117 | if (this.Len.Value > 0) { 118 | tmp7, err := this._io.ReadU4le() 119 | if err != nil { 120 | return err 121 | } 122 | this.RestartOnFailureDelay = uint32(tmp7) 123 | } 124 | if (this.Len.Value > 0) { 125 | tmp8, err := this._io.ReadU4le() 126 | if err != nil { 127 | return err 128 | } 129 | this.RestartOnFailureRetries = uint32(tmp8) 130 | } 131 | if (this.Len.Value > 0) { 132 | tmp9, err := this._io.ReadBytes(int(16)) 133 | if err != nil { 134 | return err 135 | } 136 | tmp9 = tmp9 137 | this.NetworkId = tmp9 138 | } 139 | if (this.Len.Value > 0) { 140 | tmp10, err := this._io.ReadBytes(int(4)) 141 | if err != nil { 142 | return err 143 | } 144 | tmp10 = tmp10 145 | this.Padding0 = tmp10 146 | } 147 | if ( ((this.Len.Value == 56) || (this.Len.Value == 88)) ) { 148 | tmp11, err := this._io.ReadU8le() 149 | if err != nil { 150 | return err 151 | } 152 | this.Privileges = OptionalSettings_Privilege(tmp11) 153 | } 154 | if (this.Len.Value == 88) { 155 | tmp12 := NewTstimeperiod() 156 | err = tmp12.Read(this._io, this, nil) 157 | if err != nil { 158 | return err 159 | } 160 | this.Periodicity = tmp12 161 | } 162 | if (this.Len.Value == 88) { 163 | tmp13 := NewTstimeperiod() 164 | err = tmp13.Read(this._io, this, nil) 165 | if err != nil { 166 | return err 167 | } 168 | this.Deadline = tmp13 169 | } 170 | if (this.Len.Value == 88) { 171 | tmp14, err := this._io.ReadU1() 172 | if err != nil { 173 | return err 174 | } 175 | this.Exclusive = tmp14 176 | } 177 | if (this.Len.Value == 88) { 178 | tmp15, err := this._io.ReadBytes(int(3)) 179 | if err != nil { 180 | return err 181 | } 182 | tmp15 = tmp15 183 | this.Padding1 = tmp15 184 | } 185 | return err 186 | } 187 | -------------------------------------------------------------------------------- /generated/triggers.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | 8 | type Triggers_JobBucketFlags int 9 | const ( 10 | Triggers_JobBucketFlags__RunOnlyIfIdle Triggers_JobBucketFlags = 2 11 | Triggers_JobBucketFlags__RestartOnIdle Triggers_JobBucketFlags = 4 12 | Triggers_JobBucketFlags__StopOnIdleEnd Triggers_JobBucketFlags = 8 13 | Triggers_JobBucketFlags__DisallowStartIfOnBatteries Triggers_JobBucketFlags = 16 14 | Triggers_JobBucketFlags__StopIfGoingOnBatteries Triggers_JobBucketFlags = 32 15 | Triggers_JobBucketFlags__StartWhenAvailable Triggers_JobBucketFlags = 64 16 | Triggers_JobBucketFlags__RunOnlyIfNetworkAvailable Triggers_JobBucketFlags = 128 17 | Triggers_JobBucketFlags__AllowStartOnDemand Triggers_JobBucketFlags = 256 18 | Triggers_JobBucketFlags__WakeToRun Triggers_JobBucketFlags = 512 19 | Triggers_JobBucketFlags__ExecuteParallel Triggers_JobBucketFlags = 1024 20 | Triggers_JobBucketFlags__ExecuteStopExisting Triggers_JobBucketFlags = 2048 21 | Triggers_JobBucketFlags__ExecuteQueue Triggers_JobBucketFlags = 4096 22 | Triggers_JobBucketFlags__ExecuteIgnoreNew Triggers_JobBucketFlags = 8192 23 | Triggers_JobBucketFlags__LogonTypeS4u Triggers_JobBucketFlags = 16384 24 | Triggers_JobBucketFlags__LogonTypeInteractivetoken Triggers_JobBucketFlags = 65536 25 | Triggers_JobBucketFlags__LogonTypePassword Triggers_JobBucketFlags = 262144 26 | Triggers_JobBucketFlags__LogonTypeInteractivetokenorpassword Triggers_JobBucketFlags = 524288 27 | Triggers_JobBucketFlags__Enabled Triggers_JobBucketFlags = 4194304 28 | Triggers_JobBucketFlags__Hidden Triggers_JobBucketFlags = 8388608 29 | Triggers_JobBucketFlags__RunlevelHighestAvailable Triggers_JobBucketFlags = 16777216 30 | Triggers_JobBucketFlags__Task Triggers_JobBucketFlags = 33554432 31 | Triggers_JobBucketFlags__Version Triggers_JobBucketFlags = 67108864 32 | Triggers_JobBucketFlags__TokenSidTypeNone Triggers_JobBucketFlags = 134217728 33 | Triggers_JobBucketFlags__TokenSidTypeUnrestricted Triggers_JobBucketFlags = 268435456 34 | Triggers_JobBucketFlags__Interval Triggers_JobBucketFlags = 536870912 35 | Triggers_JobBucketFlags__AllowHardTerminate Triggers_JobBucketFlags = 1073741824 36 | ) 37 | 38 | type Triggers_SessionState int 39 | const ( 40 | Triggers_SessionState__ConsoleConnect Triggers_SessionState = 1 41 | Triggers_SessionState__ConsoleDisconnect Triggers_SessionState = 2 42 | Triggers_SessionState__RemoteConnect Triggers_SessionState = 3 43 | Triggers_SessionState__RemoteDisconnect Triggers_SessionState = 4 44 | Triggers_SessionState__SessionLock Triggers_SessionState = 5 45 | Triggers_SessionState__SessionUnlock Triggers_SessionState = 6 46 | ) 47 | type Triggers struct { 48 | Header *Triggers_Header 49 | JobBucket *Triggers_JobBucket 50 | Triggers []*Triggers_Trigger 51 | _io *kaitai.Stream 52 | _root *Triggers 53 | _parent interface{} 54 | } 55 | func NewTriggers() *Triggers { 56 | return &Triggers{ 57 | } 58 | } 59 | 60 | func (this *Triggers) Read(io *kaitai.Stream, parent interface{}, root *Triggers) (err error) { 61 | this._io = io 62 | this._parent = parent 63 | this._root = root 64 | 65 | tmp1 := NewTriggers_Header() 66 | err = tmp1.Read(this._io, this, this._root) 67 | if err != nil { 68 | return err 69 | } 70 | this.Header = tmp1 71 | tmp2 := NewTriggers_JobBucket() 72 | err = tmp2.Read(this._io, this, this._root) 73 | if err != nil { 74 | return err 75 | } 76 | this.JobBucket = tmp2 77 | for i := 1;; i++ { 78 | tmp3, err := this._io.EOF() 79 | if err != nil { 80 | return err 81 | } 82 | if tmp3 { 83 | break 84 | } 85 | tmp4 := NewTriggers_Trigger() 86 | err = tmp4.Read(this._io, this, this._root) 87 | if err != nil { 88 | return err 89 | } 90 | this.Triggers = append(this.Triggers, tmp4) 91 | } 92 | return err 93 | } 94 | type Triggers_WnfStateChangeTrigger struct { 95 | GenericData *Triggers_GenericTriggerData 96 | StateName []byte 97 | LenData *AlignedU4 98 | Data []byte 99 | _io *kaitai.Stream 100 | _root *Triggers 101 | _parent *Triggers_Trigger 102 | } 103 | func NewTriggers_WnfStateChangeTrigger() *Triggers_WnfStateChangeTrigger { 104 | return &Triggers_WnfStateChangeTrigger{ 105 | } 106 | } 107 | 108 | func (this *Triggers_WnfStateChangeTrigger) Read(io *kaitai.Stream, parent *Triggers_Trigger, root *Triggers) (err error) { 109 | this._io = io 110 | this._parent = parent 111 | this._root = root 112 | 113 | tmp5 := NewTriggers_GenericTriggerData() 114 | err = tmp5.Read(this._io, this, this._root) 115 | if err != nil { 116 | return err 117 | } 118 | this.GenericData = tmp5 119 | tmp6, err := this._io.ReadBytes(int(8)) 120 | if err != nil { 121 | return err 122 | } 123 | tmp6 = tmp6 124 | this.StateName = tmp6 125 | tmp7 := NewAlignedU4() 126 | err = tmp7.Read(this._io, this, nil) 127 | if err != nil { 128 | return err 129 | } 130 | this.LenData = tmp7 131 | tmp8, err := this._io.ReadBytes(int(this.LenData.Value)) 132 | if err != nil { 133 | return err 134 | } 135 | tmp8 = tmp8 136 | this.Data = tmp8 137 | return err 138 | } 139 | type Triggers_ValueQuery struct { 140 | Name *AlignedBstrExpandSize 141 | Value *AlignedBstrExpandSize 142 | _io *kaitai.Stream 143 | _root *Triggers 144 | _parent *Triggers_EventTrigger 145 | } 146 | func NewTriggers_ValueQuery() *Triggers_ValueQuery { 147 | return &Triggers_ValueQuery{ 148 | } 149 | } 150 | 151 | func (this *Triggers_ValueQuery) Read(io *kaitai.Stream, parent *Triggers_EventTrigger, root *Triggers) (err error) { 152 | this._io = io 153 | this._parent = parent 154 | this._root = root 155 | 156 | tmp9 := NewAlignedBstrExpandSize() 157 | err = tmp9.Read(this._io, this, nil) 158 | if err != nil { 159 | return err 160 | } 161 | this.Name = tmp9 162 | tmp10 := NewAlignedBstrExpandSize() 163 | err = tmp10.Read(this._io, this, nil) 164 | if err != nil { 165 | return err 166 | } 167 | this.Value = tmp10 168 | return err 169 | } 170 | type Triggers_EventTrigger struct { 171 | GenericData *Triggers_GenericTriggerData 172 | Subscription *AlignedBstrExpandSize 173 | Unknown0 uint32 174 | Unknown1 uint32 175 | Unknown2 *AlignedBstrExpandSize 176 | LenValueQueries *AlignedU4 177 | ValueQueries []*Triggers_ValueQuery 178 | _io *kaitai.Stream 179 | _root *Triggers 180 | _parent *Triggers_Trigger 181 | } 182 | func NewTriggers_EventTrigger() *Triggers_EventTrigger { 183 | return &Triggers_EventTrigger{ 184 | } 185 | } 186 | 187 | func (this *Triggers_EventTrigger) Read(io *kaitai.Stream, parent *Triggers_Trigger, root *Triggers) (err error) { 188 | this._io = io 189 | this._parent = parent 190 | this._root = root 191 | 192 | tmp11 := NewTriggers_GenericTriggerData() 193 | err = tmp11.Read(this._io, this, this._root) 194 | if err != nil { 195 | return err 196 | } 197 | this.GenericData = tmp11 198 | tmp12 := NewAlignedBstrExpandSize() 199 | err = tmp12.Read(this._io, this, nil) 200 | if err != nil { 201 | return err 202 | } 203 | this.Subscription = tmp12 204 | tmp13, err := this._io.ReadU4le() 205 | if err != nil { 206 | return err 207 | } 208 | this.Unknown0 = uint32(tmp13) 209 | tmp14, err := this._io.ReadU4le() 210 | if err != nil { 211 | return err 212 | } 213 | this.Unknown1 = uint32(tmp14) 214 | tmp15 := NewAlignedBstrExpandSize() 215 | err = tmp15.Read(this._io, this, nil) 216 | if err != nil { 217 | return err 218 | } 219 | this.Unknown2 = tmp15 220 | tmp16 := NewAlignedU4() 221 | err = tmp16.Read(this._io, this, nil) 222 | if err != nil { 223 | return err 224 | } 225 | this.LenValueQueries = tmp16 226 | for i := 0; i < int(this.LenValueQueries.Value); i++ { 227 | _ = i 228 | tmp17 := NewTriggers_ValueQuery() 229 | err = tmp17.Read(this._io, this, this._root) 230 | if err != nil { 231 | return err 232 | } 233 | this.ValueQueries = append(this.ValueQueries, tmp17) 234 | } 235 | return err 236 | } 237 | type Triggers_IdleTrigger struct { 238 | GenericData *Triggers_GenericTriggerData 239 | _io *kaitai.Stream 240 | _root *Triggers 241 | _parent *Triggers_Trigger 242 | } 243 | func NewTriggers_IdleTrigger() *Triggers_IdleTrigger { 244 | return &Triggers_IdleTrigger{ 245 | } 246 | } 247 | 248 | func (this *Triggers_IdleTrigger) Read(io *kaitai.Stream, parent *Triggers_Trigger, root *Triggers) (err error) { 249 | this._io = io 250 | this._parent = parent 251 | this._root = root 252 | 253 | tmp18 := NewTriggers_GenericTriggerData() 254 | err = tmp18.Read(this._io, this, this._root) 255 | if err != nil { 256 | return err 257 | } 258 | this.GenericData = tmp18 259 | return err 260 | } 261 | type Triggers_JobBucket struct { 262 | Flags *AlignedU4 263 | Crc32 *AlignedU4 264 | PrincipalId *AlignedBstr 265 | DisplayName *AlignedBstr 266 | UserInfo *UserInfo 267 | OptionalSettings *OptionalSettings 268 | _io *kaitai.Stream 269 | _root *Triggers 270 | _parent *Triggers 271 | } 272 | func NewTriggers_JobBucket() *Triggers_JobBucket { 273 | return &Triggers_JobBucket{ 274 | } 275 | } 276 | 277 | func (this *Triggers_JobBucket) Read(io *kaitai.Stream, parent *Triggers, root *Triggers) (err error) { 278 | this._io = io 279 | this._parent = parent 280 | this._root = root 281 | 282 | tmp19 := NewAlignedU4() 283 | err = tmp19.Read(this._io, this, nil) 284 | if err != nil { 285 | return err 286 | } 287 | this.Flags = tmp19 288 | tmp20 := NewAlignedU4() 289 | err = tmp20.Read(this._io, this, nil) 290 | if err != nil { 291 | return err 292 | } 293 | this.Crc32 = tmp20 294 | if (this._root.Header.Version.Value >= 22) { 295 | tmp21 := NewAlignedBstr() 296 | err = tmp21.Read(this._io, this, nil) 297 | if err != nil { 298 | return err 299 | } 300 | this.PrincipalId = tmp21 301 | } 302 | if (this._root.Header.Version.Value >= 23) { 303 | tmp22 := NewAlignedBstr() 304 | err = tmp22.Read(this._io, this, nil) 305 | if err != nil { 306 | return err 307 | } 308 | this.DisplayName = tmp22 309 | } 310 | tmp23 := NewUserInfo() 311 | err = tmp23.Read(this._io, this, nil) 312 | if err != nil { 313 | return err 314 | } 315 | this.UserInfo = tmp23 316 | tmp24 := NewOptionalSettings() 317 | err = tmp24.Read(this._io, this, nil) 318 | if err != nil { 319 | return err 320 | } 321 | this.OptionalSettings = tmp24 322 | return err 323 | } 324 | type Triggers_LogonTrigger struct { 325 | GenericData *Triggers_GenericTriggerData 326 | User *UserInfo 327 | _io *kaitai.Stream 328 | _root *Triggers 329 | _parent *Triggers_Trigger 330 | } 331 | func NewTriggers_LogonTrigger() *Triggers_LogonTrigger { 332 | return &Triggers_LogonTrigger{ 333 | } 334 | } 335 | 336 | func (this *Triggers_LogonTrigger) Read(io *kaitai.Stream, parent *Triggers_Trigger, root *Triggers) (err error) { 337 | this._io = io 338 | this._parent = parent 339 | this._root = root 340 | 341 | tmp25 := NewTriggers_GenericTriggerData() 342 | err = tmp25.Read(this._io, this, this._root) 343 | if err != nil { 344 | return err 345 | } 346 | this.GenericData = tmp25 347 | tmp26 := NewUserInfo() 348 | err = tmp26.Read(this._io, this, nil) 349 | if err != nil { 350 | return err 351 | } 352 | this.User = tmp26 353 | return err 354 | } 355 | type Triggers_SessionChangeTrigger struct { 356 | GenericData *Triggers_GenericTriggerData 357 | StateChange Triggers_SessionState 358 | Padding []byte 359 | User *UserInfo 360 | _io *kaitai.Stream 361 | _root *Triggers 362 | _parent *Triggers_Trigger 363 | } 364 | func NewTriggers_SessionChangeTrigger() *Triggers_SessionChangeTrigger { 365 | return &Triggers_SessionChangeTrigger{ 366 | } 367 | } 368 | 369 | func (this *Triggers_SessionChangeTrigger) Read(io *kaitai.Stream, parent *Triggers_Trigger, root *Triggers) (err error) { 370 | this._io = io 371 | this._parent = parent 372 | this._root = root 373 | 374 | tmp27 := NewTriggers_GenericTriggerData() 375 | err = tmp27.Read(this._io, this, this._root) 376 | if err != nil { 377 | return err 378 | } 379 | this.GenericData = tmp27 380 | tmp28, err := this._io.ReadU4le() 381 | if err != nil { 382 | return err 383 | } 384 | this.StateChange = Triggers_SessionState(tmp28) 385 | tmp29, err := this._io.ReadBytes(int(4)) 386 | if err != nil { 387 | return err 388 | } 389 | tmp29 = tmp29 390 | this.Padding = tmp29 391 | tmp30 := NewUserInfo() 392 | err = tmp30.Read(this._io, this, nil) 393 | if err != nil { 394 | return err 395 | } 396 | this.User = tmp30 397 | return err 398 | } 399 | type Triggers_RegistrationTrigger struct { 400 | GenericData *Triggers_GenericTriggerData 401 | _io *kaitai.Stream 402 | _root *Triggers 403 | _parent *Triggers_Trigger 404 | } 405 | func NewTriggers_RegistrationTrigger() *Triggers_RegistrationTrigger { 406 | return &Triggers_RegistrationTrigger{ 407 | } 408 | } 409 | 410 | func (this *Triggers_RegistrationTrigger) Read(io *kaitai.Stream, parent *Triggers_Trigger, root *Triggers) (err error) { 411 | this._io = io 412 | this._parent = parent 413 | this._root = root 414 | 415 | tmp31 := NewTriggers_GenericTriggerData() 416 | err = tmp31.Read(this._io, this, this._root) 417 | if err != nil { 418 | return err 419 | } 420 | this.GenericData = tmp31 421 | return err 422 | } 423 | type Triggers_GenericTriggerData struct { 424 | StartBoundary *Tstime 425 | EndBoundary *Tstime 426 | DelaySeconds uint32 427 | TimeoutSeconds uint32 428 | RepetitionIntervalSeconds uint32 429 | RepetitionDurationSeconds uint32 430 | RepetitionDurationSeconds2 uint32 431 | StopAtDurationEnd uint8 432 | Padding []byte 433 | Enabled *AlignedU1 434 | Unknown []byte 435 | TriggerId *Bstr 436 | PadToBlock []byte 437 | _io *kaitai.Stream 438 | _root *Triggers 439 | _parent interface{} 440 | } 441 | func NewTriggers_GenericTriggerData() *Triggers_GenericTriggerData { 442 | return &Triggers_GenericTriggerData{ 443 | } 444 | } 445 | 446 | func (this *Triggers_GenericTriggerData) Read(io *kaitai.Stream, parent interface{}, root *Triggers) (err error) { 447 | this._io = io 448 | this._parent = parent 449 | this._root = root 450 | 451 | tmp32 := NewTstime() 452 | err = tmp32.Read(this._io, this, nil) 453 | if err != nil { 454 | return err 455 | } 456 | this.StartBoundary = tmp32 457 | tmp33 := NewTstime() 458 | err = tmp33.Read(this._io, this, nil) 459 | if err != nil { 460 | return err 461 | } 462 | this.EndBoundary = tmp33 463 | tmp34, err := this._io.ReadU4le() 464 | if err != nil { 465 | return err 466 | } 467 | this.DelaySeconds = uint32(tmp34) 468 | tmp35, err := this._io.ReadU4le() 469 | if err != nil { 470 | return err 471 | } 472 | this.TimeoutSeconds = uint32(tmp35) 473 | tmp36, err := this._io.ReadU4le() 474 | if err != nil { 475 | return err 476 | } 477 | this.RepetitionIntervalSeconds = uint32(tmp36) 478 | tmp37, err := this._io.ReadU4le() 479 | if err != nil { 480 | return err 481 | } 482 | this.RepetitionDurationSeconds = uint32(tmp37) 483 | tmp38, err := this._io.ReadU4le() 484 | if err != nil { 485 | return err 486 | } 487 | this.RepetitionDurationSeconds2 = uint32(tmp38) 488 | tmp39, err := this._io.ReadU1() 489 | if err != nil { 490 | return err 491 | } 492 | this.StopAtDurationEnd = tmp39 493 | tmp40, err := this._io.ReadBytes(int(3)) 494 | if err != nil { 495 | return err 496 | } 497 | tmp40 = tmp40 498 | this.Padding = tmp40 499 | tmp41 := NewAlignedU1() 500 | err = tmp41.Read(this._io, this, nil) 501 | if err != nil { 502 | return err 503 | } 504 | this.Enabled = tmp41 505 | tmp42, err := this._io.ReadBytes(int(8)) 506 | if err != nil { 507 | return err 508 | } 509 | tmp42 = tmp42 510 | this.Unknown = tmp42 511 | if (this._root.Header.Version.Value >= 22) { 512 | tmp43 := NewBstr() 513 | err = tmp43.Read(this._io, this, nil) 514 | if err != nil { 515 | return err 516 | } 517 | this.TriggerId = tmp43 518 | } 519 | if (this._root.Header.Version.Value >= 22) { 520 | tmp44 := (8 - (this.TriggerId.Len + 4)) % 8 521 | if tmp44 < 0 { 522 | tmp44 += 8 523 | } 524 | tmp45, err := this._io.ReadBytes(int(tmp44)) 525 | if err != nil { 526 | return err 527 | } 528 | tmp45 = tmp45 529 | this.PadToBlock = tmp45 530 | } 531 | return err 532 | } 533 | type Triggers_TimeTrigger struct { 534 | JobSchedule *JobSchedule 535 | TriggerId *Bstr 536 | Padding []byte 537 | _io *kaitai.Stream 538 | _root *Triggers 539 | _parent *Triggers_Trigger 540 | } 541 | func NewTriggers_TimeTrigger() *Triggers_TimeTrigger { 542 | return &Triggers_TimeTrigger{ 543 | } 544 | } 545 | 546 | func (this *Triggers_TimeTrigger) Read(io *kaitai.Stream, parent *Triggers_Trigger, root *Triggers) (err error) { 547 | this._io = io 548 | this._parent = parent 549 | this._root = root 550 | 551 | tmp46 := NewJobSchedule() 552 | err = tmp46.Read(this._io, this, nil) 553 | if err != nil { 554 | return err 555 | } 556 | this.JobSchedule = tmp46 557 | if (this._root.Header.Version.Value >= 22) { 558 | tmp47 := NewBstr() 559 | err = tmp47.Read(this._io, this, nil) 560 | if err != nil { 561 | return err 562 | } 563 | this.TriggerId = tmp47 564 | } 565 | if (this._root.Header.Version.Value >= 22) { 566 | tmp48 := (8 - (this.TriggerId.Len + 4)) % 8 567 | if tmp48 < 0 { 568 | tmp48 += 8 569 | } 570 | tmp49, err := this._io.ReadBytes(int(tmp48)) 571 | if err != nil { 572 | return err 573 | } 574 | tmp49 = tmp49 575 | this.Padding = tmp49 576 | } 577 | return err 578 | } 579 | type Triggers_Header struct { 580 | Version *AlignedU1 581 | StartBoundary *Tstime 582 | EndBoundary *Tstime 583 | _io *kaitai.Stream 584 | _root *Triggers 585 | _parent *Triggers 586 | } 587 | func NewTriggers_Header() *Triggers_Header { 588 | return &Triggers_Header{ 589 | } 590 | } 591 | 592 | func (this *Triggers_Header) Read(io *kaitai.Stream, parent *Triggers, root *Triggers) (err error) { 593 | this._io = io 594 | this._parent = parent 595 | this._root = root 596 | 597 | tmp50 := NewAlignedU1() 598 | err = tmp50.Read(this._io, this, nil) 599 | if err != nil { 600 | return err 601 | } 602 | this.Version = tmp50 603 | tmp51 := NewTstime() 604 | err = tmp51.Read(this._io, this, nil) 605 | if err != nil { 606 | return err 607 | } 608 | this.StartBoundary = tmp51 609 | tmp52 := NewTstime() 610 | err = tmp52.Read(this._io, this, nil) 611 | if err != nil { 612 | return err 613 | } 614 | this.EndBoundary = tmp52 615 | return err 616 | } 617 | type Triggers_BootTrigger struct { 618 | GenericData *Triggers_GenericTriggerData 619 | _io *kaitai.Stream 620 | _root *Triggers 621 | _parent *Triggers_Trigger 622 | } 623 | func NewTriggers_BootTrigger() *Triggers_BootTrigger { 624 | return &Triggers_BootTrigger{ 625 | } 626 | } 627 | 628 | func (this *Triggers_BootTrigger) Read(io *kaitai.Stream, parent *Triggers_Trigger, root *Triggers) (err error) { 629 | this._io = io 630 | this._parent = parent 631 | this._root = root 632 | 633 | tmp53 := NewTriggers_GenericTriggerData() 634 | err = tmp53.Read(this._io, this, this._root) 635 | if err != nil { 636 | return err 637 | } 638 | this.GenericData = tmp53 639 | return err 640 | } 641 | type Triggers_Trigger struct { 642 | Magic *AlignedU4 643 | Properties interface{} 644 | _io *kaitai.Stream 645 | _root *Triggers 646 | _parent *Triggers 647 | } 648 | func NewTriggers_Trigger() *Triggers_Trigger { 649 | return &Triggers_Trigger{ 650 | } 651 | } 652 | 653 | func (this *Triggers_Trigger) Read(io *kaitai.Stream, parent *Triggers, root *Triggers) (err error) { 654 | this._io = io 655 | this._parent = parent 656 | this._root = root 657 | 658 | tmp54 := NewAlignedU4() 659 | err = tmp54.Read(this._io, this, nil) 660 | if err != nil { 661 | return err 662 | } 663 | this.Magic = tmp54 664 | switch (this.Magic.Value) { 665 | case 34952: 666 | tmp55 := NewTriggers_RegistrationTrigger() 667 | err = tmp55.Read(this._io, this, this._root) 668 | if err != nil { 669 | return err 670 | } 671 | this.Properties = tmp55 672 | case 43690: 673 | tmp56 := NewTriggers_LogonTrigger() 674 | err = tmp56.Read(this._io, this, this._root) 675 | if err != nil { 676 | return err 677 | } 678 | this.Properties = tmp56 679 | case 65535: 680 | tmp57 := NewTriggers_BootTrigger() 681 | err = tmp57.Read(this._io, this, this._root) 682 | if err != nil { 683 | return err 684 | } 685 | this.Properties = tmp57 686 | case 30583: 687 | tmp58 := NewTriggers_SessionChangeTrigger() 688 | err = tmp58.Read(this._io, this, this._root) 689 | if err != nil { 690 | return err 691 | } 692 | this.Properties = tmp58 693 | case 61166: 694 | tmp59 := NewTriggers_IdleTrigger() 695 | err = tmp59.Read(this._io, this, this._root) 696 | if err != nil { 697 | return err 698 | } 699 | this.Properties = tmp59 700 | case 52428: 701 | tmp60 := NewTriggers_EventTrigger() 702 | err = tmp60.Read(this._io, this, this._root) 703 | if err != nil { 704 | return err 705 | } 706 | this.Properties = tmp60 707 | case 56797: 708 | tmp61 := NewTriggers_TimeTrigger() 709 | err = tmp61.Read(this._io, this, this._root) 710 | if err != nil { 711 | return err 712 | } 713 | this.Properties = tmp61 714 | case 26214: 715 | tmp62 := NewTriggers_WnfStateChangeTrigger() 716 | err = tmp62.Read(this._io, this, this._root) 717 | if err != nil { 718 | return err 719 | } 720 | this.Properties = tmp62 721 | } 722 | return err 723 | } 724 | -------------------------------------------------------------------------------- /generated/triggers_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package generated_test 4 | 5 | import ( 6 | "bytes" 7 | "fmt" 8 | "testing" 9 | 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 11 | "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 12 | ) 13 | 14 | func TestTriggerParser(t *testing.T) { 15 | blob := []byte{ 16 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfc, 0x13, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfc, 0x13, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, 0x21, 0x41, 0x42, 0x48, 0x48, 0x48, 0x48, 0xfb, 0x1d, 0x39, 0xe9, 0x48, 0x48, 0x48, 0x48, 0x0e, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf4, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfc, 0x13, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfc, 0x13, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x77, 0x00, 0x75, 0x00, 0x61, 0x00, 0x75, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfc, 0x13, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfc, 0x13, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfc, 0x13, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xda, 0xfc, 0x13, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x03, 0x00, 0x00, 0x80, 0xf4, 0x03, 0x00, 0x10, 0x0e, 0x00, 0x00, 0x80, 0x51, 0x01, 0x00, 0x80, 0x51, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 17 | } 18 | 19 | tt := generated.NewTriggers() 20 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 21 | t.Errorf("Read (%v)", err) 22 | } 23 | 24 | fmt.Printf("%v\n", tt) 25 | } 26 | 27 | func TestTimeTrigger(t *testing.T) { 28 | blob := []byte{ 29 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x5f, 0x69, 0x07, 0x76, 0x4b, 0xd8, 0x01, 0x00, 0x07, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, 0x21, 0x41, 0x43, 0x48, 0x48, 0x48, 0x48, 0x7f, 0x74, 0x6e, 0xc6, 0x48, 0x48, 0x48, 0x48, 0x0e, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf4, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 30 | 31 | 0xdd, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x5f, 0x69, 0x07, 0x76, 0x4b, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 32 | 33 | 0xdd, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x23, 0x33, 0x09, 0x76, 0x4b, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0x00, 0xc0, 0xa8, 0x00, 0x00, 0x80, 0xf4, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x04, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 34 | 35 | 0xdd, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x6d, 0x90, 0x0e, 0x76, 0x4b, 0xd8, 0x01, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x2d, 0x57, 0x87, 0x47, 0x6a, 0xd9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x03, 0x00, 0x00, 0x80, 0x51, 0x01, 0x00, 0x80, 0xf4, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 36 | 37 | 0xdd, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0xa8, 0xe8, 0x16, 0x76, 0x4b, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc1, 0x21, 0x06, 0x08, 0x94, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 38 | 39 | 0xdd, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x80, 0x6a, 0xd4, 0x22, 0x76, 0x4b, 0xd8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x38, 0x00, 0x0c, 0x00, 0x22, 0x05, 0x00, 0x00, 0x00, 0x01, 0x04, 0x15, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 40 | } 41 | 42 | tt := generated.NewTriggers() 43 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 44 | t.Errorf("Read (%v)", err) 45 | } 46 | 47 | fmt.Printf("%v\n", tt) 48 | } 49 | 50 | func TestLogonTrigger(t *testing.T) { 51 | blob := []byte{ 52 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x80, 0xf7, 0xb8, 0x17, 0x1b, 0x4a, 0xd8, 0x01, 0x00, 0x07, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0xb9, 0x3a, 0x66, 0xa2, 0x66, 0xd9, 0x01, 0x38, 0x21, 0x41, 0x42, 0x48, 0x48, 0x48, 0x48, 0x28, 0x7e, 0xd8, 0x72, 0x48, 0x48, 0x48, 0x48, 0x0e, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf4, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 53 | 54 | 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x04, 0x00, 0x00, 0x00, 0x07, 0x00, 0x80, 0xf7, 0xb8, 0x17, 0x1b, 0x4a, 0xd8, 0x01, 0x00, 0x07, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0xb9, 0x3a, 0x66, 0xa2, 0x66, 0xd9, 0x01, 0x1e, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x84, 0x03, 0x00, 0x00, 0x84, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 55 | } 56 | 57 | blob = []byte{ 58 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x10, 0x22, 0x80, 0x67, 0x10, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x10, 0x22, 0x80, 0x67, 0x10, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x08, 0xc2, 0x03, 0x48, 0x48, 0x48, 0x48, 0xa3, 0x4c, 0x0a, 0x9b, 0x48, 0x48, 0x48, 0x48, 0x18, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x05, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf4, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 59 | 60 | 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x10, 0x22, 0x80, 0x67, 0x10, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x10, 0x22, 0x80, 0x67, 0x10, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x87, 0x00, 0x01, 0xa9, 0x9a, 0x07, 0x2c, 0xaa, 0x9a, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 61 | } 62 | 63 | tt := generated.NewTriggers() 64 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 65 | t.Errorf("Read (%v)", err) 66 | } 67 | 68 | fmt.Printf("%v\n", tt) 69 | } 70 | 71 | func TestBootTrigger(t *testing.T) { 72 | blob := []byte{ 73 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, 0x21, 0x41, 0x42, 0x48, 0x48, 0x48, 0x48, 0xc2, 0x8e, 0x2e, 0x75, 0x48, 0x48, 0x48, 0x48, 0x0e, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf4, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 74 | 75 | 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 76 | } 77 | 78 | tt := generated.NewTriggers() 79 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 80 | t.Errorf("Read (%v)", err) 81 | } 82 | 83 | fmt.Printf("%v\n", tt) 84 | } 85 | 86 | func TestStateChangeTrigger(t *testing.T) { 87 | blob := []byte{ 88 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xf3, 0x4a, 0xfa, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xf3, 0x4a, 0xfa, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, 0x11, 0x42, 0x42, 0x48, 0x48, 0x48, 0x48, 0x96, 0xa1, 0x16, 0x7b, 0x48, 0x48, 0x48, 0x48, 0x18, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x4c, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x05, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 89 | 90 | 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xf3, 0x4a, 0xfa, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0xf3, 0x4a, 0xfa, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01, 0x90, 0x83, 0x25, 0x87, 0x02, 0x00, 0x00, 0x18, 0x91, 0x83, 0x25, 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x75, 0x18, 0xbc, 0xa3, 0x2b, 0x18, 0x83, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 91 | 92 | 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf3, 0x4a, 0xfa, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0xf3, 0x4a, 0xfa, 0x7f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x01, 0x9d, 0x83, 0x25, 0x87, 0x02, 0x00, 0x00, 0x18, 0x9e, 0x83, 0x25, 0x87, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x75, 0x28, 0xbc, 0xa3, 0x2b, 0x18, 0x83, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 93 | } 94 | 95 | tt := generated.NewTriggers() 96 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 97 | t.Errorf("Read (%v)", err) 98 | } 99 | 100 | fmt.Printf("%v\n", tt) 101 | } 102 | 103 | func TestSessionBasedTrigger(t *testing.T) { 104 | blob := []byte{ 105 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xc7, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xc7, 0x69, 0x63, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, 0x21, 0x41, 0x42, 0x48, 0x48, 0x48, 0x48, 0x92, 0x74, 0x3f, 0x34, 0x48, 0x48, 0x48, 0x48, 0x0e, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf4, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x77, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xc7, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xc7, 0x69, 0x63, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xa3, 0xab, 0x75, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 106 | } 107 | 108 | tt := generated.NewTriggers() 109 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 110 | t.Errorf("Read (%v)", err) 111 | } 112 | 113 | fmt.Printf("%v\n", tt) 114 | } 115 | 116 | func TestRegistrationTrigger(t *testing.T) { 117 | 118 | } 119 | 120 | func TestEventTrigger(t *testing.T) { 121 | blob := []byte{ 122 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x38, 0x21, 0x41, 0x42, 0x48, 0x48, 0x48, 0x48, 0x2f, 0xb9, 0x6e, 0x38, 0x48, 0x48, 0x48, 0x48, 0x0e, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x41, 0x00, 0x75, 0x00, 0x74, 0x00, 0x68, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x00, 0x00, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x01, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x15, 0x00, 0x00, 0x00, 0xc9, 0x6b, 0x75, 0xc2, 0xed, 0xfb, 0x83, 0x8d, 0xe8, 0xbe, 0x10, 0xfe, 0xe8, 0x03, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x1a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x43, 0x00, 0x41, 0x00, 0x53, 0x00, 0x45, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x43, 0x00, 0x5c, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0xf4, 0x03, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3c, 0x00, 0x00, 0x00, 0x80, 0x51, 0x01, 0x00, 0x78, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x51, 0x00, 0x75, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x51, 0x00, 0x75, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x20, 0x00, 0x49, 0x00, 0x64, 0x00, 0x3d, 0x00, 0x22, 0x00, 0x30, 0x00, 0x22, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61, 0x00, 0x74, 0x00, 0x68, 0x00, 0x3d, 0x00, 0x22, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2d, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x45, 0x00, 0x78, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x56, 0x00, 0x69, 0x00, 0x72, 0x00, 0x74, 0x00, 0x75, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x7a, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x41, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x44, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x22, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x53, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61, 0x00, 0x74, 0x00, 0x68, 0x00, 0x3d, 0x00, 0x22, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2d, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x45, 0x00, 0x78, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x56, 0x00, 0x69, 0x00, 0x72, 0x00, 0x74, 0x00, 0x75, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x7a, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x41, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x44, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x22, 0x00, 0x3e, 0x00, 0x2a, 0x00, 0x5b, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x5b, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x5b, 0x00, 0x40, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x3d, 0x00, 0x27, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2d, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x45, 0x00, 0x78, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x56, 0x00, 0x69, 0x00, 0x72, 0x00, 0x74, 0x00, 0x75, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x7a, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x2d, 0x00, 0x41, 0x00, 0x67, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x44, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x27, 0x00, 0x5d, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x45, 0x00, 0x76, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x49, 0x00, 0x44, 0x00, 0x3d, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x5d, 0x00, 0x5d, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x53, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x51, 0x00, 0x75, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x51, 0x00, 0x75, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0x8f, 0x14, 0x29, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0xcc, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x51, 0x00, 0x75, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x51, 0x00, 0x75, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x20, 0x00, 0x49, 0x00, 0x64, 0x00, 0x3d, 0x00, 0x22, 0x00, 0x30, 0x00, 0x22, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61, 0x00, 0x74, 0x00, 0x68, 0x00, 0x3d, 0x00, 0x22, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x44, 0x00, 0x41, 0x00, 0x47, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x45, 0x00, 0x76, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x61, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x50, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x22, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x53, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00, 0x50, 0x00, 0x61, 0x00, 0x74, 0x00, 0x68, 0x00, 0x3d, 0x00, 0x22, 0x00, 0x4d, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x74, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x2d, 0x00, 0x57, 0x00, 0x44, 0x00, 0x41, 0x00, 0x47, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x63, 0x00, 0x79, 0x00, 0x45, 0x00, 0x76, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x75, 0x00, 0x61, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x2d, 0x00, 0x47, 0x00, 0x50, 0x00, 0x2f, 0x00, 0x4f, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x22, 0x00, 0x3e, 0x00, 0x2a, 0x00, 0x5b, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x5b, 0x00, 0x28, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x75, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x3d, 0x00, 0x27, 0x00, 0x63, 0x00, 0x61, 0x00, 0x73, 0x00, 0x65, 0x00, 0x2d, 0x00, 0x70, 0x00, 0x63, 0x00, 0x27, 0x00, 0x29, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x28, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x76, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x3d, 0x00, 0x31, 0x00, 0x20, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x76, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x3d, 0x00, 0x33, 0x00, 0x29, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x28, 0x00, 0x62, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x28, 0x00, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x64, 0x00, 0x73, 0x00, 0x2c, 0x00, 0x31, 0x00, 0x38, 0x00, 0x30, 0x00, 0x31, 0x00, 0x34, 0x00, 0x33, 0x00, 0x39, 0x00, 0x38, 0x00, 0x35, 0x00, 0x30, 0x00, 0x39, 0x00, 0x34, 0x00, 0x38, 0x00, 0x31, 0x00, 0x39, 0x00, 0x38, 0x00, 0x34, 0x00, 0x29, 0x00, 0x29, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x28, 0x00, 0x45, 0x00, 0x76, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x49, 0x00, 0x44, 0x00, 0x3d, 0x00, 0x31, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x45, 0x00, 0x76, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x49, 0x00, 0x44, 0x00, 0x3d, 0x00, 0x32, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x45, 0x00, 0x76, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x49, 0x00, 0x44, 0x00, 0x3d, 0x00, 0x33, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x45, 0x00, 0x76, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x49, 0x00, 0x44, 0x00, 0x3d, 0x00, 0x34, 0x00, 0x29, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00, 0x63, 0x00, 0x75, 0x00, 0x72, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, 0x5b, 0x00, 0x40, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x49, 0x00, 0x44, 0x00, 0x3d, 0x00, 0x27, 0x00, 0x53, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x35, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x31, 0x00, 0x2d, 0x00, 0x33, 0x00, 0x32, 0x00, 0x36, 0x00, 0x32, 0x00, 0x34, 0x00, 0x37, 0x00, 0x35, 0x00, 0x32, 0x00, 0x30, 0x00, 0x39, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x33, 0x00, 0x37, 0x00, 0x34, 0x00, 0x32, 0x00, 0x33, 0x00, 0x37, 0x00, 0x31, 0x00, 0x36, 0x00, 0x35, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x32, 0x00, 0x36, 0x00, 0x32, 0x00, 0x35, 0x00, 0x31, 0x00, 0x30, 0x00, 0x33, 0x00, 0x31, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x27, 0x00, 0x5d, 0x00, 0x20, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x20, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x43, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x5b, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x64, 0x00, 0x69, 0x00, 0x66, 0x00, 0x66, 0x00, 0x28, 0x00, 0x40, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x54, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x29, 0x00, 0x20, 0x00, 0x26, 0x00, 0x6c, 0x00, 0x74, 0x00, 0x3b, 0x00, 0x3d, 0x00, 0x20, 0x00, 0x34, 0x00, 0x33, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x5d, 0x00, 0x5d, 0x00, 0x5d, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x53, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x51, 0x00, 0x75, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0x51, 0x00, 0x75, 0x00, 0x65, 0x00, 0x72, 0x00, 0x79, 0x00, 0x4c, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 123 | } 124 | 125 | tt := generated.NewTriggers() 126 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 127 | t.Errorf("Read (%v)", err) 128 | } 129 | 130 | fmt.Printf("%v\n", tt) 131 | } 132 | 133 | func TestIdleTrigger(t *testing.T) { 134 | 135 | } 136 | 137 | func TestUnknownTrigger(t *testing.T) { 138 | blob := []byte{ 139 | 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x10, 0x22, 0xa0, 0x83, 0x10, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x10, 0x22, 0xa0, 0x83, 0x10, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc8, 0x85, 0xc0, 0x02, 0x48, 0x48, 0x48, 0x48, 0x97, 0xe9, 0xe3, 0x31, 0x48, 0x48, 0x48, 0x48, 0x0a, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x00, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x05, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x0c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x2c, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 140 | 141 | 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x10, 0x22, 0xa0, 0x83, 0x10, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x10, 0x22, 0xa0, 0x83, 0x10, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x87, 0x00, 0x01, 0x00, 0x72, 0x00, 0x79, 0x00, 0x43, 0x00, 0x6c, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x01, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 142 | 143 | 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x10, 0x22, 0xa0, 0x83, 0x10, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x10, 0x22, 0xa0, 0x83, 0x10, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x87, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xa3, 0xab, 0x75, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x75, 0x40, 0xbc, 0xa3, 0x3e, 0x0b, 0x84, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 144 | 145 | 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x10, 0x22, 0xa0, 0x83, 0x10, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x10, 0x22, 0xa0, 0x83, 0x10, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe3, 0x87, 0x00, 0x01, 0x7e, 0xe8, 0xfa, 0xcd, 0x31, 0x1c, 0xbe, 0x6f, 0x8a, 0x99, 0x8f, 0x0c, 0x0b, 0x3e, 0x42, 0x00, 0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0x48, 0x75, 0xf8, 0xbc, 0xa3, 0x3e, 0x06, 0x83, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 146 | } 147 | 148 | tt := generated.NewTriggers() 149 | if err := tt.Read(kaitai.NewStream(bytes.NewReader(blob)), tt, tt); err != nil { 150 | t.Errorf("Read (%v)", err) 151 | } 152 | 153 | fmt.Printf("%v\n", tt) 154 | } 155 | -------------------------------------------------------------------------------- /generated/tstime.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | type Tstime struct { 8 | IsLocalized uint8 9 | Pad []byte 10 | Filetime *Filetime 11 | _io *kaitai.Stream 12 | _root *Tstime 13 | _parent interface{} 14 | } 15 | func NewTstime() *Tstime { 16 | return &Tstime{ 17 | } 18 | } 19 | 20 | func (this *Tstime) Read(io *kaitai.Stream, parent interface{}, root *Tstime) (err error) { 21 | this._io = io 22 | this._parent = parent 23 | this._root = root 24 | 25 | tmp1, err := this._io.ReadU1() 26 | if err != nil { 27 | return err 28 | } 29 | this.IsLocalized = tmp1 30 | tmp2, err := this._io.ReadBytes(int(7)) 31 | if err != nil { 32 | return err 33 | } 34 | tmp2 = tmp2 35 | this.Pad = tmp2 36 | tmp3 := NewFiletime() 37 | err = tmp3.Read(this._io, this, nil) 38 | if err != nil { 39 | return err 40 | } 41 | this.Filetime = tmp3 42 | return err 43 | } 44 | -------------------------------------------------------------------------------- /generated/tstimeperiod.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | type Tstimeperiod struct { 8 | Year uint16 9 | Month uint16 10 | Week uint16 11 | Day uint16 12 | Hour uint16 13 | Minute uint16 14 | Second uint16 15 | _io *kaitai.Stream 16 | _root *Tstimeperiod 17 | _parent interface{} 18 | } 19 | func NewTstimeperiod() *Tstimeperiod { 20 | return &Tstimeperiod{ 21 | } 22 | } 23 | 24 | func (this *Tstimeperiod) Read(io *kaitai.Stream, parent interface{}, root *Tstimeperiod) (err error) { 25 | this._io = io 26 | this._parent = parent 27 | this._root = root 28 | 29 | tmp1, err := this._io.ReadU2le() 30 | if err != nil { 31 | return err 32 | } 33 | this.Year = uint16(tmp1) 34 | tmp2, err := this._io.ReadU2le() 35 | if err != nil { 36 | return err 37 | } 38 | this.Month = uint16(tmp2) 39 | tmp3, err := this._io.ReadU2le() 40 | if err != nil { 41 | return err 42 | } 43 | this.Week = uint16(tmp3) 44 | tmp4, err := this._io.ReadU2le() 45 | if err != nil { 46 | return err 47 | } 48 | this.Day = uint16(tmp4) 49 | tmp5, err := this._io.ReadU2le() 50 | if err != nil { 51 | return err 52 | } 53 | this.Hour = uint16(tmp5) 54 | tmp6, err := this._io.ReadU2le() 55 | if err != nil { 56 | return err 57 | } 58 | this.Minute = uint16(tmp6) 59 | tmp7, err := this._io.ReadU2le() 60 | if err != nil { 61 | return err 62 | } 63 | this.Second = uint16(tmp7) 64 | return err 65 | } 66 | -------------------------------------------------------------------------------- /generated/user_info.go: -------------------------------------------------------------------------------- 1 | // Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT. 2 | 3 | package generated 4 | 5 | import "github.com/kaitai-io/kaitai_struct_go_runtime/kaitai" 6 | 7 | 8 | type UserInfo_SidType int 9 | const ( 10 | UserInfo_SidType__User UserInfo_SidType = 1 11 | UserInfo_SidType__Group UserInfo_SidType = 2 12 | UserInfo_SidType__Domain UserInfo_SidType = 3 13 | UserInfo_SidType__Alias UserInfo_SidType = 4 14 | UserInfo_SidType__WellKnownGroup UserInfo_SidType = 5 15 | UserInfo_SidType__DeletedAccount UserInfo_SidType = 6 16 | UserInfo_SidType__Invalid UserInfo_SidType = 7 17 | UserInfo_SidType__Unknown UserInfo_SidType = 8 18 | UserInfo_SidType__Computer UserInfo_SidType = 9 19 | UserInfo_SidType__Label UserInfo_SidType = 10 20 | UserInfo_SidType__LogonSession UserInfo_SidType = 11 21 | ) 22 | type UserInfo struct { 23 | SkipUser *AlignedU1 24 | SkipSid *AlignedU1 25 | SidType *AlignedU4 26 | Sid *AlignedBuffer 27 | Username *AlignedBstr 28 | _io *kaitai.Stream 29 | _root *UserInfo 30 | _parent interface{} 31 | } 32 | func NewUserInfo() *UserInfo { 33 | return &UserInfo{ 34 | } 35 | } 36 | 37 | func (this *UserInfo) Read(io *kaitai.Stream, parent interface{}, root *UserInfo) (err error) { 38 | this._io = io 39 | this._parent = parent 40 | this._root = root 41 | 42 | tmp1 := NewAlignedU1() 43 | err = tmp1.Read(this._io, this, nil) 44 | if err != nil { 45 | return err 46 | } 47 | this.SkipUser = tmp1 48 | if (this.SkipUser.Value == 0) { 49 | tmp2 := NewAlignedU1() 50 | err = tmp2.Read(this._io, this, nil) 51 | if err != nil { 52 | return err 53 | } 54 | this.SkipSid = tmp2 55 | } 56 | if ( ((this.SkipUser.Value == 0) && (this.SkipSid.Value == 0)) ) { 57 | tmp3 := NewAlignedU4() 58 | err = tmp3.Read(this._io, this, nil) 59 | if err != nil { 60 | return err 61 | } 62 | this.SidType = tmp3 63 | } 64 | if ( ((this.SkipUser.Value == 0) && (this.SkipSid.Value == 0)) ) { 65 | tmp4 := NewAlignedBuffer() 66 | err = tmp4.Read(this._io, this, nil) 67 | if err != nil { 68 | return err 69 | } 70 | this.Sid = tmp4 71 | } 72 | if (this.SkipUser.Value == 0) { 73 | tmp5 := NewAlignedBstr() 74 | err = tmp5.Read(this._io, this, nil) 75 | if err != nil { 76 | return err 77 | } 78 | this.Username = tmp5 79 | } 80 | return err 81 | } 82 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/GDATAAdvancedAnalytics/winreg-tasks 2 | 3 | go 1.18 4 | 5 | require github.com/kaitai-io/kaitai_struct_go_runtime v0.0.0-20220323120020-bcb4c4493cea 6 | 7 | require ( 8 | github.com/google/uuid v1.3.0 9 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a 10 | golang.org/x/text v0.3.7 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 2 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 3 | github.com/kaitai-io/kaitai_struct_go_runtime v0.0.0-20220323120020-bcb4c4493cea h1:E0sACr2FN0L/ml1gLIKRJ2tNJyDO/R0vyLZKK/Cdy5g= 4 | github.com/kaitai-io/kaitai_struct_go_runtime v0.0.0-20220323120020-bcb4c4493cea/go.mod h1:fBebEoDoc0xNbZsIcRQWqDp4jViaTKv6uxAUjmCFGgM= 5 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= 6 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 7 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 8 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 9 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 10 | -------------------------------------------------------------------------------- /kaitai/actions.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: actions 5 | endian: le 6 | imports: 7 | - ./util/bstr 8 | 9 | seq: 10 | - id: version 11 | type: u2 12 | 13 | - id: context # must match the principal_id of the JobBucket 14 | type: bstr 15 | if: version == 3 16 | 17 | - id: actions 18 | type: action 19 | repeat: eos 20 | 21 | types: 22 | action: 23 | seq: 24 | - id: magic 25 | type: u2 26 | - id: id 27 | type: bstr 28 | - id: properties 29 | type: 30 | switch-on: magic 31 | cases: 32 | 0x6666: exe_task_properties 33 | 0x7777: com_handler_properties 34 | 0x8888: email_task_properties 35 | 0x9999: messagebox_task_properties 36 | 37 | com_handler_properties: 38 | seq: 39 | - id: clsid 40 | size: 16 41 | - id: data 42 | type: bstr 43 | 44 | exe_task_properties: 45 | seq: 46 | - id: command 47 | type: bstr 48 | - id: arguments 49 | type: bstr 50 | - id: working_directory 51 | type: bstr 52 | - id: flags 53 | type: u2 54 | if: _root.version == 3 55 | 56 | email_task_properties: 57 | seq: 58 | - id: from 59 | type: bstr 60 | - id: to 61 | type: bstr 62 | - id: cc 63 | type: bstr 64 | - id: bcc 65 | type: bstr 66 | - id: reply_to 67 | type: bstr 68 | - id: server 69 | type: bstr 70 | - id: subject 71 | type: bstr 72 | - id: body 73 | type: bstr 74 | - id: num_attachment_filenames 75 | type: u4 76 | - id: attachment_filenames 77 | type: bstr 78 | repeat: expr 79 | repeat-expr: num_attachment_filenames 80 | - id: num_headers 81 | type: u4 82 | - id: headers 83 | type: key_value_string 84 | repeat: expr 85 | repeat-expr: num_headers 86 | 87 | messagebox_task_properties: 88 | seq: 89 | - id: caption 90 | type: bstr 91 | - id: content 92 | type: bstr 93 | 94 | key_value_string: 95 | seq: 96 | - id: key 97 | type: bstr 98 | - id: value 99 | type: bstr 100 | -------------------------------------------------------------------------------- /kaitai/aligned/bstr.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: aligned_bstr 5 | endian: le 6 | imports: 7 | - ./u4 8 | 9 | seq: 10 | - id: byte_count 11 | type: aligned_u4 12 | - id: string 13 | size: byte_count.value 14 | encoding: utf-16le 15 | type: str 16 | - id: block_padding 17 | size: (8 - (byte_count.value % 8)) % 8 18 | -------------------------------------------------------------------------------- /kaitai/aligned/bstr_expand_size.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: aligned_bstr_expand_size 5 | endian: le 6 | imports: 7 | - ./u4 8 | 9 | seq: 10 | - id: string_length 11 | type: aligned_u4 12 | - id: content 13 | size: byte_count 14 | if: string_length.value > 0 15 | encoding: utf-16le 16 | type: str 17 | - id: padding 18 | size: (8 - (byte_count % 8)) % 8 19 | if: string_length.value > 0 20 | 21 | instances: 22 | byte_count: 23 | value: string_length.value * 2 + 2 24 | -------------------------------------------------------------------------------- /kaitai/aligned/buffer.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: aligned_buffer 5 | endian: le 6 | imports: 7 | - ./u4 8 | 9 | seq: 10 | - id: size 11 | type: aligned_u4 12 | - id: data 13 | size: size.value 14 | - id: padding 15 | size: (8 - (size.value % 8)) % 8 16 | -------------------------------------------------------------------------------- /kaitai/aligned/u1.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: aligned_u1 5 | endian: le 6 | 7 | seq: 8 | - id: value 9 | type: u1 10 | - id: padding 11 | size: 7 12 | -------------------------------------------------------------------------------- /kaitai/aligned/u4.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: aligned_u4 5 | endian: le 6 | 7 | seq: 8 | - id: value 9 | type: u4 10 | - id: padding 11 | size: 4 12 | -------------------------------------------------------------------------------- /kaitai/dynamic_info.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: dynamic_info 5 | endian: le 6 | seq: 7 | - id: magic 8 | size: 4 9 | - id: creation_time 10 | type: u8 11 | - id: last_run_time 12 | type: u8 13 | - id: task_state # not used in recent Windows version; always zero 14 | type: u4 15 | - id: last_error_code 16 | type: u4 17 | - id: last_successful_run_time 18 | type: u8 19 | -------------------------------------------------------------------------------- /kaitai/job_schedule.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: job_schedule 5 | endian: le 6 | imports: 7 | - ./util/bstr 8 | - ./util/filetime 9 | - ./util/tstime 10 | 11 | seq: 12 | - id: start_boundary 13 | type: tstime 14 | - id: end_boundary 15 | type: tstime 16 | - id: unknown0 17 | type: tstime 18 | - id: repetition_interval_seconds 19 | type: u4 20 | - id: repetition_duration_seconds 21 | type: u4 22 | - id: execution_time_limit_seconds 23 | type: u4 24 | - id: mode 25 | type: u4 26 | enum: time_mode 27 | - id: data1 28 | type: u2 29 | - id: data2 30 | type: u2 31 | - id: data3 32 | type: u2 33 | - id: pad0 34 | type: u2 35 | - id: stop_tasks_at_duration_end 36 | type: u1 37 | - id: is_enabled 38 | type: u1 39 | - id: pad1 40 | type: u2 41 | - id: unknown1 42 | type: u4 43 | - id: max_delay_seconds 44 | type: u4 45 | - id: pad2 46 | type: u4 47 | 48 | enums: 49 | time_mode: 50 | # run at 51 | 0: one_time 52 | 53 | # run at and repeat every days 54 | 1: daily 55 | 56 | # run on days of week <(data2 as day_of_week bitmap)> every weeks starting at 57 | 2: weekly 58 | 59 | # run in months <(data3 as months bitmap> on days <(data2:data1 as day in month bitmap)> 60 | # starting at 61 | 3: days_in_months 62 | 63 | # run in months <(data3 as months bitmap> in weeks <(data2 as week bitmap)> 64 | # on days <(data1 as day_of_week bitmap)> starting at 65 | 4: days_in_weeks_in_months 66 | 67 | day_of_week: 68 | 0x1: sunday 69 | 0x2: monday 70 | 0x4: tuesday 71 | 0x8: wednesday 72 | 0x10: thursday 73 | 0x20: friday 74 | 0x40: saturday 75 | 76 | months: 77 | 0x1: january 78 | 0x2: february 79 | 0x4: march 80 | 0x8: april 81 | 0x10: may 82 | 0x20: june 83 | 0x40: july 84 | 0x80: august 85 | 0x100: september 86 | 0x200: october 87 | 0x400: november 88 | 0x800: december 89 | -------------------------------------------------------------------------------- /kaitai/optional_settings.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: optional_settings 5 | endian: le 6 | imports: 7 | - ./aligned/u4 8 | - ./util/tstimeperiod 9 | 10 | seq: 11 | - id: len 12 | type: aligned_u4 13 | - id: idle_duration_seconds 14 | type: u4 15 | if: len.value > 0 16 | - id: idle_wait_timeout_seconds 17 | type: u4 18 | if: len.value > 0 19 | - id: execution_time_limit_seconds 20 | type: u4 21 | if: len.value > 0 22 | - id: delete_expired_task_after 23 | type: u4 24 | if: len.value > 0 25 | - id: priority 26 | type: u4 27 | if: len.value > 0 28 | - id: restart_on_failure_delay 29 | type: u4 30 | if: len.value > 0 31 | - id: restart_on_failure_retries 32 | type: u4 33 | if: len.value > 0 34 | - id: network_id 35 | size: 16 36 | if: len.value > 0 37 | - id: padding0 38 | size: 4 39 | if: len.value > 0 40 | - id: privileges 41 | type: u8 42 | enum: privilege 43 | if: len.value == 0x38 or len.value == 0x58 44 | - id: periodicity 45 | type: tstimeperiod 46 | if: len.value == 0x58 47 | - id: deadline 48 | type: tstimeperiod 49 | if: len.value == 0x58 50 | - id: exclusive 51 | type: u1 52 | if: len.value == 0x58 53 | - id: padding1 54 | size: 3 55 | if: len.value == 0x58 56 | 57 | enums: 58 | privilege: 59 | 0x4: se_create_token_privilege 60 | 0x8: se_assign_primary_token_privilege 61 | 0x10: se_lock_memory_privilege 62 | 0x20: se_increase_quota_privilege 63 | 0x40: se_machine_account_privilege 64 | 0x80: se_tcb_privilege 65 | 0x100: se_security_privilege 66 | 0x200: se_take_ownership_privilege 67 | 0x400: se_load_driver_privilege 68 | 0x800: se_system_profile_privilege 69 | 0x1000: se_systemtime_privilege 70 | 0x2000: se_profile_single_process_privilege 71 | 0x4000: se_increase_base_priority_privilege 72 | 0x8000: se_create_pagefile_privilege 73 | 0x10000: se_create_permanent_privilege 74 | 0x20000: se_backup_privilege 75 | 0x40000: se_restore_privilege 76 | 0x80000: se_shutdown_privilege 77 | 0x100000: se_debug_privilege 78 | 0x200000: se_audit_privilege 79 | 0x400000: se_system_environment_privilege 80 | 0x800000: se_change_notify_privilege 81 | 0x1000000: se_remote_shutdown_privilege 82 | 0x2000000: se_undock_privilege 83 | 0x4000000: se_sync_agent_privilege 84 | 0x8000000: se_enable_delegation_privilege 85 | 0x10000000: se_manage_volume_privilege 86 | 0x20000000: se_impersonate_privilege 87 | 0x40000000: se_create_global_privilege 88 | 0x80000000: se_trusted_cred_man_access_privilege 89 | 0x100000000: se_relabel_privilege 90 | 0x200000000: se_increase_working_set_privilege 91 | 0x400000000: se_time_zone_privilege 92 | 0x800000000: se_create_symbolic_link_privilege 93 | 0x1000000000: se_delegate_session_user_impersonate_privilege 94 | -------------------------------------------------------------------------------- /kaitai/triggers.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: triggers 5 | endian: le 6 | imports: 7 | - ./aligned/bstr 8 | - ./aligned/bstr_expand_size 9 | - ./aligned/buffer 10 | - ./aligned/u1 11 | - ./aligned/u4 12 | - ./util/bstr 13 | - ./util/filetime 14 | - ./util/tstime 15 | - ./util/tstimeperiod 16 | - ./job_schedule 17 | - ./optional_settings 18 | - ./user_info 19 | 20 | seq: 21 | - id: header 22 | type: header 23 | 24 | - id: job_bucket 25 | type: job_bucket 26 | 27 | - id: triggers 28 | repeat: eos 29 | type: trigger 30 | 31 | enums: 32 | job_bucket_flags: 33 | # 0x1: flags_0x1 34 | 0x2: run_only_if_idle 35 | 0x4: restart_on_idle 36 | 0x8: stop_on_idle_end 37 | 0x10: disallow_start_if_on_batteries 38 | 0x20: stop_if_going_on_batteries 39 | 0x40: start_when_available 40 | 0x80: run_only_if_network_available 41 | 0x100: allow_start_on_demand 42 | 0x200: wake_to_run 43 | 0x400: execute_parallel 44 | 0x800: execute_stop_existing 45 | 0x1000: execute_queue 46 | 0x2000: execute_ignore_new 47 | 0x4000: logon_type_s4u 48 | # 0x8000: flags_0x8000 49 | 0x10000: logon_type_interactivetoken 50 | # 0x20000: flags_0x20000 51 | 0x40000: logon_type_password 52 | 0x80000: logon_type_interactivetokenorpassword 53 | # 0x100000: flags_0x100000 54 | # 0x200000: flags_0x200000 55 | 0x400000: enabled 56 | 0x800000: hidden 57 | 0x1000000: runlevel_highest_available 58 | 0x2000000: task 59 | 0x4000000: version 60 | 0x8000000: token_sid_type_none 61 | 0x10000000: token_sid_type_unrestricted 62 | 0x20000000: interval 63 | 0x40000000: allow_hard_terminate 64 | 65 | session_state: 66 | 1: console_connect 67 | 2: console_disconnect 68 | 3: remote_connect 69 | 4: remote_disconnect 70 | 5: session_lock 71 | 6: session_unlock 72 | 73 | types: 74 | header: 75 | seq: 76 | - id: version 77 | type: aligned_u1 78 | 79 | - id: start_boundary # the earliest startBoundary of all triggers 80 | type: tstime 81 | 82 | - id: end_boundary # the latest endBoundary of all triggers 83 | type: tstime 84 | 85 | job_bucket: 86 | seq: 87 | - id: flags 88 | type: aligned_u4 89 | - id: crc32 # the crc32 hash of the task XML 90 | type: aligned_u4 91 | - id: principal_id 92 | type: aligned_bstr 93 | if: _root.header.version.value >= 0x16 94 | - id: display_name 95 | type: aligned_bstr 96 | if: _root.header.version.value >= 0x17 97 | - id: user_info 98 | type: user_info 99 | - id: optional_settings 100 | type: optional_settings 101 | 102 | trigger: 103 | seq: 104 | - id: magic 105 | type: aligned_u4 106 | 107 | - id: properties 108 | type: 109 | switch-on: magic.value 110 | cases: 111 | 0x6666: wnf_state_change_trigger 112 | 0x7777: session_change_trigger 113 | 0x8888: registration_trigger 114 | 0xaaaa: logon_trigger 115 | 0xcccc: event_trigger 116 | 0xdddd: time_trigger 117 | 0xeeee: idle_trigger 118 | 0xffff: boot_trigger 119 | 120 | generic_trigger_data: 121 | seq: 122 | - id: start_boundary 123 | type: tstime 124 | - id: end_boundary 125 | type: tstime 126 | - id: delay_seconds 127 | type: u4 128 | - id: timeout_seconds 129 | type: u4 130 | - id: repetition_interval_seconds 131 | type: u4 132 | - id: repetition_duration_seconds 133 | type: u4 134 | - id: repetition_duration_seconds_2 135 | type: u4 136 | - id: stop_at_duration_end 137 | type: u1 138 | - id: padding 139 | size: 3 140 | - id: enabled 141 | type: aligned_u1 142 | - id: unknown 143 | size: 8 144 | - id: trigger_id 145 | type: bstr 146 | if: _root.header.version.value >= 0x16 147 | - id: pad_to_block 148 | size: (8 - (trigger_id.len + 4)) % 8 149 | if: _root.header.version.value >= 0x16 150 | 151 | wnf_state_change_trigger: 152 | seq: 153 | - id: generic_data 154 | type: generic_trigger_data 155 | - id: state_name 156 | size: 8 157 | - id: len_data 158 | type: aligned_u4 159 | - id: data 160 | size: len_data.value 161 | 162 | session_change_trigger: 163 | seq: 164 | - id: generic_data 165 | type: generic_trigger_data 166 | - id: state_change 167 | type: u4 168 | enum: session_state 169 | - id: padding 170 | size: 4 171 | - id: user 172 | type: user_info 173 | 174 | registration_trigger: 175 | seq: 176 | - id: generic_data 177 | type: generic_trigger_data 178 | 179 | logon_trigger: 180 | seq: 181 | - id: generic_data 182 | type: generic_trigger_data 183 | - id: user 184 | type: user_info 185 | 186 | event_trigger: 187 | seq: 188 | - id: generic_data 189 | type: generic_trigger_data 190 | - id: subscription 191 | type: aligned_bstr_expand_size 192 | - id: unknown0 193 | type: u4 194 | - id: unknown1 195 | type: u4 196 | - id: unknown2 197 | type: aligned_bstr_expand_size 198 | - id: len_value_queries 199 | type: aligned_u4 200 | - id: value_queries 201 | type: value_query 202 | repeat: expr 203 | repeat-expr: len_value_queries.value 204 | 205 | time_trigger: 206 | seq: 207 | - id: job_schedule 208 | type: job_schedule 209 | - id: trigger_id 210 | type: bstr 211 | if: _root.header.version.value >= 0x16 212 | - id: padding 213 | size: (8 - (trigger_id.len + 4)) % 8 214 | if: _root.header.version.value >= 0x16 215 | 216 | idle_trigger: 217 | seq: 218 | - id: generic_data 219 | type: generic_trigger_data 220 | 221 | boot_trigger: 222 | seq: 223 | - id: generic_data 224 | type: generic_trigger_data 225 | 226 | value_query: 227 | seq: 228 | - id: name 229 | type: aligned_bstr_expand_size 230 | - id: value 231 | type: aligned_bstr_expand_size 232 | -------------------------------------------------------------------------------- /kaitai/user_info.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: user_info 5 | endian: le 6 | imports: 7 | - ./aligned/u1 8 | - ./aligned/u4 9 | - ./aligned/buffer 10 | - ./aligned/bstr 11 | 12 | seq: 13 | - id: skip_user 14 | type: aligned_u1 15 | - id: skip_sid 16 | type: aligned_u1 17 | if: skip_user.value == 0 18 | - id: sid_type 19 | type: aligned_u4 20 | if: skip_user.value == 0 and skip_sid.value == 0 21 | - id: sid 22 | type: aligned_buffer 23 | if: skip_user.value == 0 and skip_sid.value == 0 24 | - id: username 25 | type: aligned_bstr 26 | if: skip_user.value == 0 27 | 28 | enums: 29 | sid_type: # SID_NAME_USE enum in WinAPI 30 | 1: user 31 | 2: group 32 | 3: domain 33 | 4: alias 34 | 5: well_known_group 35 | 6: deleted_account 36 | 7: invalid 37 | 8: unknown 38 | 9: computer 39 | 10: label 40 | 11: logon_session 41 | -------------------------------------------------------------------------------- /kaitai/util/bstr.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: bstr 5 | endian: le 6 | 7 | seq: 8 | - id: len 9 | type: u4 10 | - id: str 11 | type: str 12 | encoding: utf-16le 13 | size: len 14 | -------------------------------------------------------------------------------- /kaitai/util/filetime.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: filetime 5 | endian: le 6 | 7 | seq: 8 | - id: low_date_time 9 | type: u4 10 | - id: high_date_time 11 | type: u4 12 | -------------------------------------------------------------------------------- /kaitai/util/tstime.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: tstime 5 | endian: le 6 | imports: 7 | - filetime 8 | 9 | seq: 10 | - id: is_localized 11 | type: u1 12 | - id: pad 13 | size: 7 14 | - id: filetime 15 | type: filetime 16 | -------------------------------------------------------------------------------- /kaitai/util/tstimeperiod.ksy: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: MIT 2 | 3 | meta: 4 | id: tstimeperiod 5 | endian: le 6 | 7 | seq: 8 | - id: year 9 | type: u2 10 | - id: month 11 | type: u2 12 | - id: week 13 | type: u2 14 | - id: day # if used in conjunction with week this is "day of week" 15 | type: u2 16 | - id: hour 17 | type: u2 18 | - id: minute 19 | type: u2 20 | - id: second 21 | type: u2 22 | -------------------------------------------------------------------------------- /triggers/boot_trigger.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "time" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | ) 10 | 11 | const BootTriggerMagic TriggerMagic = 0xFFFF 12 | 13 | type BootTrigger struct { 14 | GenericData *GenericTriggerData 15 | } 16 | 17 | func NewBootTrigger(gen *generated.Triggers_BootTrigger, tz *time.Location) (*BootTrigger, error) { 18 | generic, err := NewGenericTriggerData(gen.GenericData, tz) 19 | if err != nil { 20 | return nil, err 21 | } 22 | 23 | return &BootTrigger{ 24 | GenericData: generic, 25 | }, nil 26 | } 27 | 28 | func IsBootTrigger(trigger Trigger) bool { 29 | return trigger.Magic() == BootTriggerMagic 30 | } 31 | 32 | func (t BootTrigger) Id() string { 33 | return t.GenericData.TriggerId 34 | } 35 | 36 | func (t BootTrigger) Magic() TriggerMagic { 37 | return BootTriggerMagic 38 | } 39 | 40 | func (t BootTrigger) Name() string { 41 | return "Boot" 42 | } 43 | 44 | func (t BootTrigger) String() string { 45 | return `` 46 | } 47 | -------------------------------------------------------------------------------- /triggers/event_trigger.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 10 | ) 11 | 12 | const EventTriggerMagic TriggerMagic = 0xCCCC 13 | 14 | type ValueQuery struct { 15 | Name string 16 | Query string 17 | } 18 | 19 | type EventTrigger struct { 20 | GenericTriggerData *GenericTriggerData 21 | Subscription string 22 | Unknown0 uint32 23 | Unknown1 uint32 24 | Unknown2 string 25 | ValueQueries []ValueQuery 26 | } 27 | 28 | func NewEventTrigger(gen *generated.Triggers_EventTrigger, tz *time.Location) (*EventTrigger, error) { 29 | generic, err := NewGenericTriggerData(gen.GenericData, tz) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | valueQueries := make([]ValueQuery, gen.LenValueQueries.Value) 35 | for i, query := range gen.ValueQueries { 36 | valueQueries[i] = ValueQuery{ 37 | Name: query.Name.Content, 38 | Query: query.Value.Content, 39 | } 40 | } 41 | 42 | return &EventTrigger{ 43 | GenericTriggerData: generic, 44 | Subscription: gen.Subscription.Content, 45 | Unknown0: gen.Unknown0, 46 | Unknown1: gen.Unknown1, 47 | Unknown2: gen.Unknown2.Content, 48 | ValueQueries: valueQueries, 49 | }, nil 50 | } 51 | 52 | func IsEventTrigger(trigger Trigger) bool { 53 | return trigger.Magic() == EventTriggerMagic 54 | } 55 | 56 | func (t EventTrigger) Id() string { 57 | return t.GenericTriggerData.TriggerId 58 | } 59 | 60 | func (t EventTrigger) Magic() TriggerMagic { 61 | return EventTriggerMagic 62 | } 63 | 64 | func (t EventTrigger) Name() string { 65 | return "Event" 66 | } 67 | 68 | func (t EventTrigger) String() string { 69 | return fmt.Sprintf(``, t.Subscription) 70 | } 71 | -------------------------------------------------------------------------------- /triggers/generic_trigger_data.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "time" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 10 | ) 11 | 12 | type GenericTriggerData struct { 13 | StartBoundary time.Time 14 | EndBoundary time.Time 15 | Delay time.Duration 16 | Timeout time.Duration 17 | RepetitionInterval time.Duration 18 | RepetitionDuration time.Duration 19 | RepetitionDuration2 time.Duration 20 | StopAtDurationEnd bool 21 | Enabled bool 22 | Unknown []byte 23 | TriggerId string 24 | } 25 | 26 | func NewGenericTriggerData(gen *generated.Triggers_GenericTriggerData, tz *time.Location) (*GenericTriggerData, error) { 27 | triggerId := "" 28 | if gen.TriggerId != nil { 29 | triggerId = gen.TriggerId.Str 30 | } 31 | 32 | return &GenericTriggerData{ 33 | StartBoundary: utils.TimeFromTSTime(gen.StartBoundary, tz), 34 | EndBoundary: utils.TimeFromTSTime(gen.EndBoundary, tz), 35 | Delay: time.Duration(gen.DelaySeconds) * time.Second, 36 | Timeout: time.Duration(gen.TimeoutSeconds) * time.Second, 37 | RepetitionInterval: time.Duration(gen.RepetitionIntervalSeconds) * time.Second, 38 | RepetitionDuration: time.Duration(gen.RepetitionDurationSeconds) * time.Second, 39 | RepetitionDuration2: time.Duration(gen.RepetitionDurationSeconds2) * time.Second, 40 | StopAtDurationEnd: gen.StopAtDurationEnd != 0, 41 | Enabled: gen.Enabled.Value != 0, 42 | Unknown: gen.Unknown[:], 43 | TriggerId: triggerId, 44 | }, nil 45 | } 46 | -------------------------------------------------------------------------------- /triggers/header.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "time" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 10 | ) 11 | 12 | type Header struct { 13 | // The version of the structure 14 | Version uint8 15 | // The earliest StartBoundary of all triggers 16 | StartBoundary time.Time 17 | // The latest EndBoundary of all triggers 18 | EndBoundary time.Time 19 | } 20 | 21 | // NewHeader converts a generated Triggers_Headers into a more accessible Header object 22 | // 23 | // The tz must be set to the timezone where the the Trigger data were originally created in. 24 | // Otherwise there might be differences in the times represented by this code and what Windows 25 | // shows in the Task Scheduler MMC snap-in. 26 | func NewHeader(gen *generated.Triggers_Header, tz *time.Location) (*Header, error) { 27 | return &Header{ 28 | Version: gen.Version.Value, 29 | StartBoundary: utils.TimeFromTSTime(gen.StartBoundary, tz), 30 | EndBoundary: utils.TimeFromTSTime(gen.EndBoundary, tz), 31 | }, nil 32 | } 33 | -------------------------------------------------------------------------------- /triggers/idle_trigger.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "time" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | ) 10 | 11 | const IdleTriggerMagic TriggerMagic = 0xEEEE 12 | 13 | type IdleTrigger struct { 14 | GenericData *GenericTriggerData 15 | } 16 | 17 | func NewIdleTrigger(gen *generated.Triggers_IdleTrigger, tz *time.Location) (*IdleTrigger, error) { 18 | generic, err := NewGenericTriggerData(gen.GenericData, tz) 19 | if err != nil { 20 | return nil, err 21 | } 22 | 23 | return &IdleTrigger{ 24 | GenericData: generic, 25 | }, nil 26 | } 27 | 28 | func IsIdleTrigger(trigger Trigger) bool { 29 | return trigger.Magic() == IdleTriggerMagic 30 | } 31 | 32 | func (t IdleTrigger) Id() string { 33 | return t.GenericData.TriggerId 34 | } 35 | 36 | func (t IdleTrigger) Magic() TriggerMagic { 37 | return IdleTriggerMagic 38 | } 39 | 40 | func (t IdleTrigger) Name() string { 41 | return "Idle" 42 | } 43 | 44 | func (t IdleTrigger) String() string { 45 | return `` 46 | } 47 | -------------------------------------------------------------------------------- /triggers/job_bucket.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 6 | 7 | type JobBucket struct { 8 | Flags uint32 9 | Crc32 uint32 10 | PrincipalId string 11 | DisplayName string 12 | UserInfo *UserInfo 13 | OptionalSettings *OptionalSettings 14 | } 15 | 16 | func NewJobBucket(gen *generated.Triggers_JobBucket) (*JobBucket, error) { 17 | userInfo, err := NewUserInfo(gen.UserInfo) 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | optionalSettings, err := NewOptionalSettings(gen.OptionalSettings) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | principalId := "" 28 | if gen.PrincipalId != nil { 29 | principalId = gen.PrincipalId.String 30 | } 31 | 32 | displayName := "" 33 | if gen.DisplayName != nil { 34 | displayName = gen.DisplayName.String 35 | } 36 | 37 | return &JobBucket{ 38 | Flags: gen.Flags.Value, 39 | Crc32: gen.Crc32.Value, 40 | PrincipalId: principalId, 41 | DisplayName: displayName, 42 | UserInfo: userInfo, 43 | OptionalSettings: optionalSettings, 44 | }, nil 45 | } 46 | -------------------------------------------------------------------------------- /triggers/job_schedule.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 11 | ) 12 | 13 | type TimeMode int 14 | 15 | const ( 16 | // runs at JobSchedule.Start 17 | OneTime TimeMode = 0 18 | // runs at JobSchedule.Start and repeats every JobSchedule.RepeatEvery days 19 | Daily TimeMode = 1 20 | // run on JobSchedule.DaysOfWeek every JobSchedule.RepeatEvery weeks starting at JobSchedule.Start 21 | Weekly TimeMode = 2 22 | // run in JobSchedule.Months on JobSchedule.DaysInMonth starting at JobSchedule.Start 23 | DaysInMonths TimeMode = 3 24 | // run in JobSchedule.Months in JobSchedule.WeeksInMonth on JobSchedule.DaysOfWeek starting at JobSchedule.Start 25 | DaysInWeeksInMonths TimeMode = 4 26 | ) 27 | 28 | type DayOfWeek int 29 | 30 | const ( 31 | Sunday DayOfWeek = 0x01 32 | Monday DayOfWeek = 0x02 33 | Tuesday DayOfWeek = 0x04 34 | Wednesday DayOfWeek = 0x08 35 | Thursday DayOfWeek = 0x10 36 | Friday DayOfWeek = 0x20 37 | Saturday DayOfWeek = 0x40 38 | ) 39 | 40 | type Months int 41 | 42 | const ( 43 | January Months = 0x001 44 | February Months = 0x002 45 | March Months = 0x004 46 | April Months = 0x008 47 | May Months = 0x010 48 | June Months = 0x020 49 | July Months = 0x040 50 | August Months = 0x080 51 | September Months = 0x100 52 | October Months = 0x200 53 | November Months = 0x400 54 | December Months = 0x800 55 | ) 56 | 57 | type JobSchedule struct { 58 | StartBoundary time.Time 59 | EndBoundary time.Time 60 | Unknown0 time.Time 61 | RepetitionInterval time.Duration 62 | RepetitionDuration time.Duration 63 | ExecutionTimeLimit time.Duration 64 | Mode TimeMode 65 | // value depends on Mode setting 66 | DaysOfWeek DayOfWeek 67 | // value depends on Mode setting 68 | Months Months 69 | // bitmap of days in month; first day is 0x1, second is 0x2, third is 0x4, and so on 70 | DaysInMonth uint32 71 | // bitmap of weeks in month; first week is 0x1, second is 0x2, third is 0x4, and so on 72 | WeeksInMonth uint16 73 | // meaning of value depends on mode; check TimeMode constants 74 | RepeatEvery uint 75 | StopTasksAtDurationEnd bool 76 | Enabled bool 77 | Unknown1 uint32 78 | MaxDelay time.Duration 79 | } 80 | 81 | func NewJobSchedule(gen *generated.JobSchedule, tz *time.Location) (*JobSchedule, error) { 82 | schedule := &JobSchedule{ 83 | StartBoundary: utils.TimeFromTSTime(gen.StartBoundary, tz), 84 | EndBoundary: utils.TimeFromTSTime(gen.EndBoundary, tz), 85 | Unknown0: utils.TimeFromTSTime(gen.Unknown0, tz), 86 | RepetitionInterval: time.Second * time.Duration(gen.RepetitionIntervalSeconds), 87 | RepetitionDuration: time.Second * time.Duration(gen.RepetitionDurationSeconds), 88 | ExecutionTimeLimit: time.Second * time.Duration(gen.ExecutionTimeLimitSeconds), 89 | Mode: TimeMode(gen.Mode), 90 | StopTasksAtDurationEnd: gen.StopTasksAtDurationEnd != 0, 91 | Enabled: gen.IsEnabled != 0, 92 | Unknown1: gen.Unknown1, 93 | MaxDelay: time.Second * time.Duration(gen.MaxDelaySeconds), 94 | } 95 | 96 | switch schedule.Mode { 97 | case OneTime: 98 | break 99 | case Daily: 100 | schedule.RepeatEvery = uint(gen.Data1) 101 | case Weekly: 102 | schedule.RepeatEvery = uint(gen.Data1) 103 | schedule.DaysOfWeek = DayOfWeek(gen.Data2) 104 | case DaysInMonths: 105 | schedule.Months = Months(gen.Data3) 106 | schedule.DaysInMonth = uint32(gen.Data2)<<16 | uint32(gen.Data1) 107 | case DaysInWeeksInMonths: 108 | schedule.DaysOfWeek = DayOfWeek(gen.Data1) 109 | schedule.WeeksInMonth = gen.Data2 110 | schedule.Months = Months(gen.Data3) 111 | } 112 | 113 | return schedule, nil 114 | } 115 | 116 | func TimeModeToString(mode TimeMode) string { 117 | switch mode { 118 | case OneTime: 119 | return "OneTime" 120 | case Daily: 121 | return "Daily" 122 | case Weekly: 123 | return "Weekly" 124 | case DaysInMonths: 125 | return "DaysInMonths" 126 | case DaysInWeeksInMonths: 127 | return "DaysInWeeksInMonths" 128 | default: 129 | return fmt.Sprintf("%d", mode) 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /triggers/logon_trigger.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 10 | ) 11 | 12 | const LogonTriggerMagic TriggerMagic = 0xAAAA 13 | 14 | type LogonTrigger struct { 15 | GenericData *GenericTriggerData 16 | User *UserInfo 17 | } 18 | 19 | func NewLogonTrigger(gen *generated.Triggers_LogonTrigger, tz *time.Location) (*LogonTrigger, error) { 20 | generic, err := NewGenericTriggerData(gen.GenericData, tz) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | userInfo, err := NewUserInfo(gen.User) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | return &LogonTrigger{ 31 | GenericData: generic, 32 | User: userInfo, 33 | }, nil 34 | } 35 | 36 | func IsLogonTrigger(trigger Trigger) bool { 37 | return trigger.Magic() == LogonTriggerMagic 38 | } 39 | 40 | func (t LogonTrigger) Id() string { 41 | return t.GenericData.TriggerId 42 | } 43 | 44 | func (t LogonTrigger) Magic() TriggerMagic { 45 | return LogonTriggerMagic 46 | } 47 | 48 | func (t LogonTrigger) Name() string { 49 | return "Logon" 50 | } 51 | 52 | func (t LogonTrigger) String() string { 53 | return fmt.Sprintf( 54 | ``, 55 | t.User.UserToString(), 56 | ) 57 | } 58 | -------------------------------------------------------------------------------- /triggers/optional_settings.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "time" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 10 | "github.com/google/uuid" 11 | ) 12 | 13 | type Privilege int64 14 | 15 | const ( 16 | SeCreateTokenPrivilege Privilege = 0x4 17 | SeAssignPrimaryTokenPrivilege Privilege = 0x8 18 | SeLockMemoryPrivilege Privilege = 0x10 19 | SeIncreaseQuotaPrivilege Privilege = 0x20 20 | SeMachineAccountPrivilege Privilege = 0x40 21 | SeTcbPrivilege Privilege = 0x80 22 | SeSecurityPrivilege Privilege = 0x100 23 | SeTakeOwnershipPrivilege Privilege = 0x200 24 | SeLoadDriverPrivilege Privilege = 0x400 25 | SeSystemProfilePrivilege Privilege = 0x800 26 | SeSystemtimePrivilege Privilege = 0x1000 27 | SeProfileSingleProcessPrivilege Privilege = 0x2000 28 | SeIncreaseBasePriorityPrivilege Privilege = 0x4000 29 | SeCreatePagefilePrivilege Privilege = 0x8000 30 | SeCreatePermanentPrivilege Privilege = 0x10000 31 | SeBackupPrivilege Privilege = 0x20000 32 | SeRestorePrivilege Privilege = 0x40000 33 | SeShutdownPrivilege Privilege = 0x80000 34 | SeDebugPrivilege Privilege = 0x100000 35 | SeAuditPrivilege Privilege = 0x200000 36 | SeSystemEnvironmentPrivilege Privilege = 0x400000 37 | SeChangeNotifyPrivilege Privilege = 0x800000 38 | SeRemoteShutdownPrivilege Privilege = 0x1000000 39 | SeUndockPrivilege Privilege = 0x2000000 40 | SeSyncAgentPrivilege Privilege = 0x4000000 41 | SeEnableDelegationPrivilege Privilege = 0x8000000 42 | SeManageVolumePrivilege Privilege = 0x10000000 43 | SeImpersonatePrivilege Privilege = 0x20000000 44 | SeCreateGlobalPrivilege Privilege = 0x40000000 45 | SeTrustedCredManAccessPrivilege Privilege = 0x80000000 46 | SeRelabelPrivilege Privilege = 0x100000000 47 | SeIncreaseWorkingSetPrivilege Privilege = 0x200000000 48 | SeTimeZonePrivilege Privilege = 0x400000000 49 | SeCreateSymbolicLinkPrivilege Privilege = 0x800000000 50 | SeDelegateSessionUserImpersonatePrivilege Privilege = 0x1000000000 51 | ) 52 | 53 | type OptionalSettings struct { 54 | Length uint32 55 | IdleDuration time.Duration 56 | IdleWaitTimeout time.Duration 57 | ExecutionTimeLimit time.Duration 58 | DeleteExpiredTaskAfter time.Duration 59 | Priority uint32 60 | RestartOnFailureDelay time.Duration 61 | RestartOnFailureRetries uint32 62 | NetworkId uuid.UUID 63 | Privileges Privilege 64 | Periodicity time.Duration 65 | Deadline time.Duration 66 | Exclusive bool 67 | } 68 | 69 | func NewOptionalSettings(gen *generated.OptionalSettings) (*OptionalSettings, error) { 70 | optionalSettings := &OptionalSettings{Length: gen.Len.Value} 71 | 72 | if gen.Len.Value == 0 { 73 | return optionalSettings, nil 74 | } 75 | 76 | optionalSettings.IdleDuration = time.Duration(gen.IdleDurationSeconds) * time.Second 77 | optionalSettings.IdleWaitTimeout = time.Duration(gen.IdleWaitTimeoutSeconds) * time.Second 78 | optionalSettings.ExecutionTimeLimit = time.Duration(gen.ExecutionTimeLimitSeconds) * time.Second 79 | optionalSettings.DeleteExpiredTaskAfter = time.Duration(gen.DeleteExpiredTaskAfter) * time.Second 80 | optionalSettings.Priority = gen.Priority 81 | optionalSettings.RestartOnFailureDelay = time.Duration(gen.RestartOnFailureDelay) * time.Second 82 | optionalSettings.RestartOnFailureRetries = gen.RestartOnFailureRetries 83 | 84 | networkId, err := uuid.FromBytes(gen.NetworkId) 85 | if err != nil { 86 | return nil, err 87 | } 88 | optionalSettings.NetworkId = networkId 89 | 90 | if optionalSettings.Length < 0x38 { 91 | return optionalSettings, nil 92 | } 93 | 94 | optionalSettings.Privileges = Privilege(gen.Privileges) 95 | 96 | if optionalSettings.Length < 0x58 { 97 | return optionalSettings, nil 98 | } 99 | 100 | optionalSettings.Periodicity = utils.DurationFromTSTimePeriod(gen.Periodicity) 101 | optionalSettings.Deadline = utils.DurationFromTSTimePeriod(gen.Deadline) 102 | optionalSettings.Exclusive = gen.Exclusive != 0 103 | 104 | return optionalSettings, nil 105 | } 106 | -------------------------------------------------------------------------------- /triggers/registration_trigger.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "time" 7 | 8 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 9 | ) 10 | 11 | const RegistrationTriggerMagic TriggerMagic = 0x8888 12 | 13 | type RegistrationTrigger struct { 14 | GenericData *GenericTriggerData 15 | } 16 | 17 | func NewRegistrationTrigger(gen *generated.Triggers_RegistrationTrigger, tz *time.Location) (*RegistrationTrigger, error) { 18 | generic, err := NewGenericTriggerData(gen.GenericData, tz) 19 | if err != nil { 20 | return nil, err 21 | } 22 | 23 | return &RegistrationTrigger{ 24 | GenericData: generic, 25 | }, nil 26 | } 27 | 28 | func IsRegistrationTrigger(trigger Trigger) bool { 29 | return trigger.Magic() == RegistrationTriggerMagic 30 | } 31 | 32 | func (t RegistrationTrigger) Id() string { 33 | return t.GenericData.TriggerId 34 | } 35 | 36 | func (t RegistrationTrigger) Magic() TriggerMagic { 37 | return RegistrationTriggerMagic 38 | } 39 | 40 | func (t RegistrationTrigger) Name() string { 41 | return "Registration" 42 | } 43 | 44 | func (t RegistrationTrigger) String() string { 45 | return `` 46 | } 47 | -------------------------------------------------------------------------------- /triggers/session_change_trigger.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 10 | ) 11 | 12 | const SessionChangeTriggerMagic TriggerMagic = 0x7777 13 | 14 | type SessionState int 15 | 16 | const ( 17 | ConsoleConnect SessionState = 1 18 | ConsoleDisconnect SessionState = 2 19 | RemoteConnect SessionState = 3 20 | RemoteDisconnect SessionState = 4 21 | SessionLock SessionState = 5 22 | SessionUnlock SessionState = 6 23 | ) 24 | 25 | type SessionChangeTrigger struct { 26 | GenericTriggerData *GenericTriggerData 27 | StateChange SessionState 28 | User *UserInfo 29 | } 30 | 31 | func NewSessionChangeTrigger(gen *generated.Triggers_SessionChangeTrigger, tz *time.Location) (*SessionChangeTrigger, error) { 32 | genericTriggerData, err := NewGenericTriggerData(gen.GenericData, tz) 33 | if err != nil { 34 | return nil, err 35 | } 36 | 37 | userInfo, err := NewUserInfo(gen.User) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | return &SessionChangeTrigger{ 43 | GenericTriggerData: genericTriggerData, 44 | User: userInfo, 45 | StateChange: SessionState(gen.StateChange), 46 | }, nil 47 | } 48 | 49 | func IsSessionChangeTrigger(trigger Trigger) bool { 50 | return trigger.Magic() == SessionChangeTriggerMagic 51 | } 52 | 53 | func (t SessionChangeTrigger) Id() string { 54 | return t.GenericTriggerData.TriggerId 55 | } 56 | 57 | func (t SessionChangeTrigger) Magic() TriggerMagic { 58 | return SessionChangeTriggerMagic 59 | } 60 | 61 | func (t SessionChangeTrigger) Name() string { 62 | return "SessionChange" 63 | } 64 | 65 | func (t SessionChangeTrigger) String() string { 66 | return fmt.Sprintf( 67 | ``, 68 | t.User.UserToString(), t.StateChange, 69 | ) 70 | } 71 | -------------------------------------------------------------------------------- /triggers/time_trigger.go: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | package triggers 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | 9 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/generated" 10 | "github.com/GDATAAdvancedAnalytics/winreg-tasks/utils" 11 | ) 12 | 13 | const TimeTriggerMagic TriggerMagic = 0xDDDD 14 | 15 | type TimeTrigger struct { 16 | JobSchedule *JobSchedule 17 | 18 | id string 19 | } 20 | 21 | func NewTimeTrigger(gen *generated.Triggers_TimeTrigger, tz *time.Location) (*TimeTrigger, error) { 22 | schedule, err := NewJobSchedule(gen.JobSchedule, tz) 23 | if err != nil { 24 | return nil, err 25 | } 26 | 27 | triggerId := "" 28 | if gen.TriggerId != nil { 29 | triggerId = gen.TriggerId.Str 30 | } 31 | 32 | return &TimeTrigger{ 33 | JobSchedule: schedule, 34 | id: triggerId, 35 | }, nil 36 | } 37 | 38 | func IsTimeTrigger(trigger Trigger) bool { 39 | return trigger.Magic() == TimeTriggerMagic 40 | } 41 | 42 | func (t TimeTrigger) Id() string { 43 | return t.id 44 | } 45 | 46 | func (t TimeTrigger) Magic() TriggerMagic { 47 | return TimeTriggerMagic 48 | } 49 | 50 | func (t TimeTrigger) Name() string { 51 | return "Time" 52 | } 53 | 54 | func (t TimeTrigger) String() string { 55 | switch t.JobSchedule.Mode { 56 | case OneTime: 57 | return fmt.Sprintf( 58 | `