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  }