github.com/iDigitalFlame/xmt@v0.5.4/man/sync_windows.go (about) 1 //go:build windows 2 // +build windows 3 4 // Copyright (C) 2020 - 2023 iDigitalFlame 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program. If not, see <https://www.gnu.org/licenses/>. 18 // 19 20 package man 21 22 import ( 23 "syscall" 24 "unsafe" 25 26 "github.com/iDigitalFlame/xmt/com/pipe" 27 "github.com/iDigitalFlame/xmt/device/winapi" 28 "github.com/iDigitalFlame/xmt/util/xerr" 29 ) 30 31 type objListener uintptr 32 33 func (objListener) Listen() {} 34 func (l objListener) Close() error { 35 return winapi.CloseHandle(uintptr(l)) 36 } 37 func mutexCheck(s string) (bool, error) { 38 if len(s) == 0 || len(s) > 248 { 39 return false, xerr.Sub("invalid path/name", 0x12) 40 } 41 if s[0] != '\\' { 42 s = prefix + s 43 } 44 // 0x120000 - READ_CONTROL | SYNCHRONIZE 45 m, err := winapi.OpenMutex(0x120000, false, s) 46 if err != nil { 47 return false, err 48 } 49 winapi.CloseHandle(m) 50 return true, nil 51 } 52 func eventCheck(s string) (bool, error) { 53 if len(s) == 0 || len(s) > 248 { 54 return false, xerr.Sub("invalid path/name", 0x12) 55 } 56 if s[0] != '\\' { 57 s = prefix + s 58 } 59 // 0x120000 - READ_CONTROL | SYNCHRONIZE 60 e, err := winapi.OpenEvent(0x120000, false, s) 61 if err != nil { 62 return false, err 63 } 64 winapi.CloseHandle(e) 65 return true, nil 66 } 67 func mailslotCheck(s string) (bool, error) { 68 if len(s) == 0 || len(s) > 243 { 69 return false, xerr.Sub("invalid path/name", 0x12) 70 } 71 if len(s) < 4 || (s[0] != '\\' && s[1] != '\\' && s[2] != '.' && s[3] != '\\') { 72 s = slot + s 73 } 74 // 0xC0000000 - FILE_FLAG_OVERLAPPED | FILE_FLAG_WRITE_THROUGH 75 // 0x3 - FILE_SHARE_READ | FILE_SHARE_WRITE 76 // 0x3 - OPEN_EXISTING 77 m, err := winapi.CreateFile(s, 0xC0000000, 0x3, nil, 0x3, 0, 0) 78 if err != nil { 79 return false, err 80 } 81 winapi.CloseHandle(m) 82 return true, nil 83 } 84 func semaphoreCheck(s string) (bool, error) { 85 if len(s) == 0 || len(s) > 248 { 86 return false, xerr.Sub("invalid path/name", 0x12) 87 } 88 if s[0] != '\\' { 89 s = prefix + s 90 } 91 // 0x120000 - READ_CONTROL | SYNCHRONIZE 92 r, err := winapi.OpenSemaphore(0x120000, false, s) 93 if err != nil { 94 return false, err 95 } 96 winapi.CloseHandle(r) 97 return true, nil 98 } 99 func mutexCreate(s string) (listener, error) { 100 if len(s) == 0 || len(s) > 248 { 101 return nil, xerr.Sub("invalid path/name", 0x12) 102 } 103 if s[0] != '\\' { 104 s = prefix + s 105 } 106 var ( 107 v = winapi.SecurityAttributes{InheritHandle: 0} 108 err error 109 ) 110 if v.SecurityDescriptor, err = winapi.SecurityDescriptorFromString(pipe.PermEveryone); err != nil { 111 return nil, err 112 } 113 v.Length = uint32(unsafe.Sizeof(v)) 114 m, err := winapi.CreateMutex(&v, true, s) 115 if m > 0 && err == syscall.ERROR_ALREADY_EXISTS { 116 winapi.CloseHandle(m) 117 return nil, err 118 } 119 if err != nil { 120 return nil, err 121 } 122 return objListener(m), nil 123 } 124 func eventCreate(s string) (listener, error) { 125 if len(s) == 0 || len(s) > 248 { 126 return nil, xerr.Sub("invalid path/name", 0x12) 127 } 128 if s[0] != '\\' { 129 s = prefix + s 130 } 131 var ( 132 v = winapi.SecurityAttributes{InheritHandle: 0} 133 err error 134 ) 135 if v.SecurityDescriptor, err = winapi.SecurityDescriptorFromString(pipe.PermEveryone); err != nil { 136 return nil, err 137 } 138 v.Length = uint32(unsafe.Sizeof(v)) 139 e, err := winapi.CreateEvent(&v, true, true, s) 140 if e > 0 && err == syscall.ERROR_ALREADY_EXISTS { 141 winapi.CloseHandle(e) 142 return nil, err 143 } 144 if err != nil { 145 return nil, err 146 } 147 return objListener(e), nil 148 } 149 func (o objSync) check(s string) (bool, error) { 150 switch o { 151 case Mutex: 152 return mutexCheck(s) 153 case Event: 154 return eventCheck(s) 155 case Mailslot: 156 return mailslotCheck(s) 157 case Semaphore: 158 return semaphoreCheck(s) 159 } 160 return false, xerr.Sub("invalid link type", 0x13) 161 } 162 func mailslotCreate(s string) (listener, error) { 163 if len(s) == 0 || len(s) > 243 { 164 return nil, xerr.Sub("invalid path/name", 0x12) 165 } 166 if len(s) < 4 || (s[0] != '\\' && s[1] != '\\' && s[2] != '.' && s[3] != '\\') { 167 s = slot + s 168 } 169 var ( 170 v = winapi.SecurityAttributes{InheritHandle: 0} 171 err error 172 ) 173 if v.SecurityDescriptor, err = winapi.SecurityDescriptorFromString(pipe.PermEveryone); err != nil { 174 return nil, err 175 } 176 v.Length = uint32(unsafe.Sizeof(v)) 177 r, err := winapi.CreateMailslot(s, 0, -1, &v) 178 if r > 0 && err == syscall.ERROR_ALREADY_EXISTS { 179 winapi.CloseHandle(r) 180 return nil, err 181 } 182 if err != nil { 183 return nil, err 184 } 185 return objListener(r), nil 186 } 187 func semaphoreCreate(s string) (listener, error) { 188 if len(s) == 0 || len(s) > 248 { 189 return nil, xerr.Sub("invalid path/name", 0x12) 190 } 191 if s[0] != '\\' { 192 s = prefix + s 193 } 194 var ( 195 v = winapi.SecurityAttributes{InheritHandle: 0} 196 err error 197 ) 198 if v.SecurityDescriptor, err = winapi.SecurityDescriptorFromString(pipe.PermEveryone); err != nil { 199 return nil, err 200 } 201 v.Length = uint32(unsafe.Sizeof(v)) 202 r, err := winapi.CreateSemaphore(&v, 0, 1, s) 203 if r > 0 && err == syscall.ERROR_ALREADY_EXISTS { 204 winapi.CloseHandle(r) 205 return nil, err 206 } 207 if err != nil { 208 return nil, err 209 } 210 return objListener(r), nil 211 } 212 func (o objSync) create(s string) (listener, error) { 213 switch o { 214 case Mutex: 215 return mutexCreate(s) 216 case Event: 217 return eventCreate(s) 218 case Mailslot: 219 return mailslotCreate(s) 220 case Semaphore: 221 return semaphoreCreate(s) 222 } 223 return nil, xerr.Sub("invalid link type", 0x13) 224 }