github.com/iDigitalFlame/xmt@v0.5.4/cmd/dll.go (about) 1 // Copyright (C) 2020 - 2023 iDigitalFlame 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 // 16 17 package cmd 18 19 import ( 20 "context" 21 "time" 22 ) 23 24 // DLL is a struct that can be used to reflectively load a DLL into the memory 25 // of a selected process. Similar to the Assembly struct, this struct can only 26 // be used on Windows devices and will return 'ErrNoWindows' on non-Windows devices. 27 // 28 // The 'SetParent*' function will attempt to set the target that loads the DLL. 29 // If none are specified, the DLL will be loaded into the current process. 30 type DLL struct { 31 Path string 32 t thread 33 Timeout time.Duration 34 } 35 36 // Run will start the DLL thread and wait until it completes. This function 37 // will return the same errors as the 'Start' function if they occur or the 38 // 'Wait' function if any errors occur during thread runtime. 39 // 40 // Always returns nil on non-Windows devices. 41 func (d *DLL) Run() error { 42 if err := d.Start(); err != nil { 43 return err 44 } 45 return d.Wait() 46 } 47 48 // Stop will attempt to terminate the currently running thread. 49 // 50 // Always returns nil on non-Windows devices. 51 func (d *DLL) Stop() error { 52 return d.t.Stop() 53 } 54 55 // Wait will block until the thread completes or is terminated by a call to 56 // Stop. 57 // 58 // This function will return 'ErrNotStarted' if the thread has not been started. 59 func (d *DLL) Wait() error { 60 if !d.t.Running() { 61 if err := d.Start(); err != nil { 62 return err 63 } 64 } 65 return d.t.Wait() 66 } 67 68 // NewDLL creates a new DLL instance that uses the supplied string as the DLL 69 // file path. Similar to '&DLL{Path: p}'. 70 func NewDLL(p string) *DLL { 71 return &DLL{Path: p} 72 } 73 74 // Running returns true if the current thread is running, false otherwise. 75 func (d *DLL) Running() bool { 76 return d.t.Running() 77 } 78 79 // Release will attempt to release the resources for this DLL instance, 80 // including handles. 81 // 82 // After the first call to this function, all other function calls will fail 83 // with errors. Repeated calls to this function return nil and are a NOP. 84 func (d *DLL) Release() error { 85 return d.t.Release() 86 } 87 88 // SetSuspended will delay the execution of this thread and will put the 89 // thread in a suspended state until it is resumed using a Resume call. 90 // 91 // This function has no effect if the device is not running Windows. 92 func (d *DLL) SetSuspended(s bool) { 93 d.t.SetSuspended(s) 94 } 95 96 // Done returns a channel that's closed when this DLL completes 97 // 98 // This can be used to monitor a DLL's status using a select statement. 99 func (d *DLL) Done() <-chan struct{} { 100 return d.t.Done() 101 } 102 103 // ExitCode returns the Exit Code of the thread. If the thread is still running or 104 // has not been started, this function returns an 'ErrNotCompleted' error. 105 func (d *DLL) ExitCode() (int32, error) { 106 return d.t.ExitCode() 107 } 108 109 // Handle returns the handle of the current running thread. The return is an uintptr 110 // that can converted into a Handle. 111 // 112 // This function returns an error if the thread was not started. The handle is 113 // not expected to be valid after the thread exits or is terminated. 114 func (d *DLL) Handle() (uintptr, error) { 115 return d.t.Handle() 116 } 117 118 // NewDLLContext creates a new DLL instance that uses the supplied string as 119 // the DLL file path. 120 // 121 // This function accepts a context that can be used to control the cancellation 122 // of the thread. 123 func NewDLLContext(x context.Context, p string) *DLL { 124 return &DLL{Path: p, t: threadInit(x)} 125 }