Source file
src/syscall/syscall_windows.go
Documentation: syscall
1
2
3
4
5
6
7 package syscall
8
9 import (
10 errorspkg "errors"
11 "internal/bytealg"
12 "internal/itoa"
13 "internal/oserror"
14 "internal/race"
15 "runtime"
16 "sync"
17 "unsafe"
18 )
19
20 type Handle uintptr
21
22 const InvalidHandle = ^Handle(0)
23
24
25
26
27
28
29 func StringToUTF16(s string) []uint16 {
30 a, err := UTF16FromString(s)
31 if err != nil {
32 panic("syscall: string with NUL passed to StringToUTF16")
33 }
34 return a
35 }
36
37
38
39
40
41 func UTF16FromString(s string) ([]uint16, error) {
42 if bytealg.IndexByteString(s, 0) != -1 {
43 return nil, EINVAL
44 }
45
46
47
48
49
50
51 buf := make([]uint16, 0, len(s)+1)
52 buf = encodeWTF16(s, buf)
53 return append(buf, 0), nil
54 }
55
56
57
58
59 func UTF16ToString(s []uint16) string {
60 maxLen := 0
61 for i, v := range s {
62 if v == 0 {
63 s = s[0:i]
64 break
65 }
66 switch {
67 case v <= rune1Max:
68 maxLen += 1
69 case v <= rune2Max:
70 maxLen += 2
71 default:
72
73
74
75
76
77
78 maxLen += 3
79 }
80 }
81 buf := decodeWTF16(s, make([]byte, 0, maxLen))
82 return unsafe.String(unsafe.SliceData(buf), len(buf))
83 }
84
85
86
87 func utf16PtrToString(p *uint16) string {
88 if p == nil {
89 return ""
90 }
91 end := unsafe.Pointer(p)
92 n := 0
93 for *(*uint16)(end) != 0 {
94 end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
95 n++
96 }
97 return UTF16ToString(unsafe.Slice(p, n))
98 }
99
100
101
102
103
104
105
106 func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] }
107
108
109
110
111
112 func UTF16PtrFromString(s string) (*uint16, error) {
113 a, err := UTF16FromString(s)
114 if err != nil {
115 return nil, err
116 }
117 return &a[0], nil
118 }
119
120
121
122
123
124
125
126
127 type Errno uintptr
128
129 func langid(pri, sub uint16) uint32 { return uint32(sub)<<10 | uint32(pri) }
130
131
132
133
134
135 func FormatMessage(flags uint32, msgsrc uint32, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) {
136 return formatMessage(flags, uintptr(msgsrc), msgid, langid, buf, args)
137 }
138
139 func (e Errno) Error() string {
140
141 idx := int(e - APPLICATION_ERROR)
142 if 0 <= idx && idx < len(errors) {
143 return errors[idx]
144 }
145
146 var flags uint32 = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_IGNORE_INSERTS
147 b := make([]uint16, 300)
148 n, err := formatMessage(flags, 0, uint32(e), langid(LANG_ENGLISH, SUBLANG_ENGLISH_US), b, nil)
149 if err != nil {
150 n, err = formatMessage(flags, 0, uint32(e), 0, b, nil)
151 if err != nil {
152 return "winapi error #" + itoa.Itoa(int(e))
153 }
154 }
155
156 for ; n > 0 && (b[n-1] == '\n' || b[n-1] == '\r'); n-- {
157 }
158 return UTF16ToString(b[:n])
159 }
160
161 const (
162 _ERROR_NOT_ENOUGH_MEMORY = Errno(8)
163 _ERROR_NOT_SUPPORTED = Errno(50)
164 _ERROR_BAD_NETPATH = Errno(53)
165 _ERROR_CALL_NOT_IMPLEMENTED = Errno(120)
166 )
167
168 func (e Errno) Is(target error) bool {
169 switch target {
170 case oserror.ErrPermission:
171 return e == ERROR_ACCESS_DENIED ||
172 e == EACCES ||
173 e == EPERM
174 case oserror.ErrExist:
175 return e == ERROR_ALREADY_EXISTS ||
176 e == ERROR_DIR_NOT_EMPTY ||
177 e == ERROR_FILE_EXISTS ||
178 e == EEXIST ||
179 e == ENOTEMPTY
180 case oserror.ErrNotExist:
181 return e == ERROR_FILE_NOT_FOUND ||
182 e == _ERROR_BAD_NETPATH ||
183 e == ERROR_PATH_NOT_FOUND ||
184 e == ENOENT
185 case errorspkg.ErrUnsupported:
186 return e == _ERROR_NOT_SUPPORTED ||
187 e == _ERROR_CALL_NOT_IMPLEMENTED ||
188 e == ENOSYS ||
189 e == ENOTSUP ||
190 e == EOPNOTSUPP ||
191 e == EWINDOWS
192 }
193 return false
194 }
195
196 func (e Errno) Temporary() bool {
197 return e == EINTR || e == EMFILE || e.Timeout()
198 }
199
200 func (e Errno) Timeout() bool {
201 return e == EAGAIN || e == EWOULDBLOCK || e == ETIMEDOUT
202 }
203
204
205 func compileCallback(fn any, cleanstack bool) uintptr
206
207
208
209
210
211
212
213 func NewCallback(fn any) uintptr {
214 return compileCallback(fn, true)
215 }
216
217
218
219
220
221
222
223 func NewCallbackCDecl(fn any) uintptr {
224 return compileCallback(fn, false)
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335 func makeInheritSa() *SecurityAttributes {
336 var sa SecurityAttributes
337 sa.Length = uint32(unsafe.Sizeof(sa))
338 sa.InheritHandle = 1
339 return &sa
340 }
341
342 func Open(path string, mode int, perm uint32) (fd Handle, err error) {
343 if len(path) == 0 {
344 return InvalidHandle, ERROR_FILE_NOT_FOUND
345 }
346 pathp, err := UTF16PtrFromString(path)
347 if err != nil {
348 return InvalidHandle, err
349 }
350 var access uint32
351 switch mode & (O_RDONLY | O_WRONLY | O_RDWR) {
352 case O_RDONLY:
353 access = GENERIC_READ
354 case O_WRONLY:
355 access = GENERIC_WRITE
356 case O_RDWR:
357 access = GENERIC_READ | GENERIC_WRITE
358 }
359 if mode&O_CREAT != 0 {
360 access |= GENERIC_WRITE
361 }
362 if mode&O_APPEND != 0 {
363 access &^= GENERIC_WRITE
364 access |= FILE_APPEND_DATA
365 }
366 sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
367 var sa *SecurityAttributes
368 if mode&O_CLOEXEC == 0 {
369 sa = makeInheritSa()
370 }
371 var createmode uint32
372 switch {
373 case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
374 createmode = CREATE_NEW
375 case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
376 createmode = CREATE_ALWAYS
377 case mode&O_CREAT == O_CREAT:
378 createmode = OPEN_ALWAYS
379 case mode&O_TRUNC == O_TRUNC:
380 createmode = TRUNCATE_EXISTING
381 default:
382 createmode = OPEN_EXISTING
383 }
384 var attrs uint32 = FILE_ATTRIBUTE_NORMAL
385 if perm&S_IWRITE == 0 {
386 attrs = FILE_ATTRIBUTE_READONLY
387 if createmode == CREATE_ALWAYS {
388
389
390
391
392
393
394
395
396 h, e := CreateFile(pathp, access, sharemode, sa, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
397 switch e {
398 case ERROR_FILE_NOT_FOUND, _ERROR_BAD_NETPATH, ERROR_PATH_NOT_FOUND:
399
400
401
402 default:
403
404 return h, e
405 }
406 }
407 }
408 if createmode == OPEN_EXISTING && access == GENERIC_READ {
409
410 attrs |= FILE_FLAG_BACKUP_SEMANTICS
411 }
412 if mode&O_SYNC != 0 {
413 const _FILE_FLAG_WRITE_THROUGH = 0x80000000
414 attrs |= _FILE_FLAG_WRITE_THROUGH
415 }
416 return CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0)
417 }
418
419 func Read(fd Handle, p []byte) (n int, err error) {
420 var done uint32
421 e := ReadFile(fd, p, &done, nil)
422 if e != nil {
423 if e == ERROR_BROKEN_PIPE {
424
425 return 0, nil
426 }
427 return 0, e
428 }
429 return int(done), nil
430 }
431
432 func Write(fd Handle, p []byte) (n int, err error) {
433 var done uint32
434 e := WriteFile(fd, p, &done, nil)
435 if e != nil {
436 return 0, e
437 }
438 return int(done), nil
439 }
440
441 func ReadFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error {
442 err := readFile(fd, p, done, overlapped)
443 if race.Enabled {
444 if *done > 0 {
445 race.WriteRange(unsafe.Pointer(&p[0]), int(*done))
446 }
447 race.Acquire(unsafe.Pointer(&ioSync))
448 }
449 if msanenabled && *done > 0 {
450 msanWrite(unsafe.Pointer(&p[0]), int(*done))
451 }
452 if asanenabled && *done > 0 {
453 asanWrite(unsafe.Pointer(&p[0]), int(*done))
454 }
455 return err
456 }
457
458 func WriteFile(fd Handle, p []byte, done *uint32, overlapped *Overlapped) error {
459 if race.Enabled {
460 race.ReleaseMerge(unsafe.Pointer(&ioSync))
461 }
462 err := writeFile(fd, p, done, overlapped)
463 if race.Enabled && *done > 0 {
464 race.ReadRange(unsafe.Pointer(&p[0]), int(*done))
465 }
466 if msanenabled && *done > 0 {
467 msanRead(unsafe.Pointer(&p[0]), int(*done))
468 }
469 if asanenabled && *done > 0 {
470 asanRead(unsafe.Pointer(&p[0]), int(*done))
471 }
472 return err
473 }
474
475 var ioSync int64
476
477 var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx")
478
479 const ptrSize = unsafe.Sizeof(uintptr(0))
480
481
482
483 func setFilePointerEx(handle Handle, distToMove int64, newFilePointer *int64, whence uint32) error {
484 var e1 Errno
485 if unsafe.Sizeof(uintptr(0)) == 8 {
486 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 4, uintptr(handle), uintptr(distToMove), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0, 0)
487 } else {
488
489 switch runtime.GOARCH {
490 default:
491 panic("unsupported 32-bit architecture")
492 case "386":
493
494 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 5, uintptr(handle), uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0)
495 case "arm":
496
497
498 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 6, uintptr(handle), 0, uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence))
499 }
500 }
501 if e1 != 0 {
502 return errnoErr(e1)
503 }
504 return nil
505 }
506
507 func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
508 var w uint32
509 switch whence {
510 case 0:
511 w = FILE_BEGIN
512 case 1:
513 w = FILE_CURRENT
514 case 2:
515 w = FILE_END
516 }
517 err = setFilePointerEx(fd, offset, &newoffset, w)
518 return
519 }
520
521 func Close(fd Handle) (err error) {
522 return CloseHandle(fd)
523 }
524
525 var (
526 Stdin = getStdHandle(STD_INPUT_HANDLE)
527 Stdout = getStdHandle(STD_OUTPUT_HANDLE)
528 Stderr = getStdHandle(STD_ERROR_HANDLE)
529 )
530
531 func getStdHandle(h int) (fd Handle) {
532 r, _ := GetStdHandle(h)
533 return r
534 }
535
536 const ImplementsGetwd = true
537
538 func Getwd() (wd string, err error) {
539 b := make([]uint16, 300)
540
541
542
543
544
545 for {
546 n, e := GetCurrentDirectory(uint32(len(b)), &b[0])
547 if e != nil {
548 return "", e
549 }
550 if int(n) <= len(b) {
551 return UTF16ToString(b[:n]), nil
552 }
553 b = make([]uint16, n)
554 }
555 }
556
557 func Chdir(path string) (err error) {
558 pathp, err := UTF16PtrFromString(path)
559 if err != nil {
560 return err
561 }
562 return SetCurrentDirectory(pathp)
563 }
564
565 func Mkdir(path string, mode uint32) (err error) {
566 pathp, err := UTF16PtrFromString(path)
567 if err != nil {
568 return err
569 }
570 return CreateDirectory(pathp, nil)
571 }
572
573 func Rmdir(path string) (err error) {
574 pathp, err := UTF16PtrFromString(path)
575 if err != nil {
576 return err
577 }
578 return RemoveDirectory(pathp)
579 }
580
581 func Unlink(path string) (err error) {
582 pathp, err := UTF16PtrFromString(path)
583 if err != nil {
584 return err
585 }
586 return DeleteFile(pathp)
587 }
588
589 func Rename(oldpath, newpath string) (err error) {
590 from, err := UTF16PtrFromString(oldpath)
591 if err != nil {
592 return err
593 }
594 to, err := UTF16PtrFromString(newpath)
595 if err != nil {
596 return err
597 }
598 return MoveFile(from, to)
599 }
600
601 func ComputerName() (name string, err error) {
602 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
603 b := make([]uint16, n)
604 e := GetComputerName(&b[0], &n)
605 if e != nil {
606 return "", e
607 }
608 return UTF16ToString(b[:n]), nil
609 }
610
611 func Ftruncate(fd Handle, length int64) (err error) {
612 curoffset, e := Seek(fd, 0, 1)
613 if e != nil {
614 return e
615 }
616 defer Seek(fd, curoffset, 0)
617 _, e = Seek(fd, length, 0)
618 if e != nil {
619 return e
620 }
621 e = SetEndOfFile(fd)
622 if e != nil {
623 return e
624 }
625 return nil
626 }
627
628 func Gettimeofday(tv *Timeval) (err error) {
629 var ft Filetime
630 GetSystemTimeAsFileTime(&ft)
631 *tv = NsecToTimeval(ft.Nanoseconds())
632 return nil
633 }
634
635 func Pipe(p []Handle) (err error) {
636 if len(p) != 2 {
637 return EINVAL
638 }
639 var r, w Handle
640 e := CreatePipe(&r, &w, makeInheritSa(), 0)
641 if e != nil {
642 return e
643 }
644 p[0] = r
645 p[1] = w
646 return nil
647 }
648
649 func Utimes(path string, tv []Timeval) (err error) {
650 if len(tv) != 2 {
651 return EINVAL
652 }
653 pathp, e := UTF16PtrFromString(path)
654 if e != nil {
655 return e
656 }
657 h, e := CreateFile(pathp,
658 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
659 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
660 if e != nil {
661 return e
662 }
663 defer Close(h)
664 a := Filetime{}
665 w := Filetime{}
666 if tv[0].Nanoseconds() != 0 {
667 a = NsecToFiletime(tv[0].Nanoseconds())
668 }
669 if tv[0].Nanoseconds() != 0 {
670 w = NsecToFiletime(tv[1].Nanoseconds())
671 }
672 return SetFileTime(h, nil, &a, &w)
673 }
674
675
676 const _UTIME_OMIT = -1
677
678 func UtimesNano(path string, ts []Timespec) (err error) {
679 if len(ts) != 2 {
680 return EINVAL
681 }
682 pathp, e := UTF16PtrFromString(path)
683 if e != nil {
684 return e
685 }
686 h, e := CreateFile(pathp,
687 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
688 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
689 if e != nil {
690 return e
691 }
692 defer Close(h)
693 a := Filetime{}
694 w := Filetime{}
695 if ts[0].Nsec != _UTIME_OMIT {
696 a = NsecToFiletime(TimespecToNsec(ts[0]))
697 }
698 if ts[1].Nsec != _UTIME_OMIT {
699 w = NsecToFiletime(TimespecToNsec(ts[1]))
700 }
701 return SetFileTime(h, nil, &a, &w)
702 }
703
704 func Fsync(fd Handle) (err error) {
705 return FlushFileBuffers(fd)
706 }
707
708 func Chmod(path string, mode uint32) (err error) {
709 p, e := UTF16PtrFromString(path)
710 if e != nil {
711 return e
712 }
713 attrs, e := GetFileAttributes(p)
714 if e != nil {
715 return e
716 }
717 if mode&S_IWRITE != 0 {
718 attrs &^= FILE_ATTRIBUTE_READONLY
719 } else {
720 attrs |= FILE_ATTRIBUTE_READONLY
721 }
722 return SetFileAttributes(p, attrs)
723 }
724
725 func LoadCancelIoEx() error {
726 return procCancelIoEx.Find()
727 }
728
729 func LoadSetFileCompletionNotificationModes() error {
730 return procSetFileCompletionNotificationModes.Find()
731 }
732
733
734
735 const socket_error = uintptr(^uint32(0))
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772 var SocketDisableIPv6 bool
773
774 type RawSockaddrInet4 struct {
775 Family uint16
776 Port uint16
777 Addr [4]byte
778 Zero [8]uint8
779 }
780
781 type RawSockaddrInet6 struct {
782 Family uint16
783 Port uint16
784 Flowinfo uint32
785 Addr [16]byte
786 Scope_id uint32
787 }
788
789 type RawSockaddr struct {
790 Family uint16
791 Data [14]int8
792 }
793
794 type RawSockaddrAny struct {
795 Addr RawSockaddr
796 Pad [100]int8
797 }
798
799 type Sockaddr interface {
800 sockaddr() (ptr unsafe.Pointer, len int32, err error)
801 }
802
803 type SockaddrInet4 struct {
804 Port int
805 Addr [4]byte
806 raw RawSockaddrInet4
807 }
808
809 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) {
810 if sa.Port < 0 || sa.Port > 0xFFFF {
811 return nil, 0, EINVAL
812 }
813 sa.raw.Family = AF_INET
814 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
815 p[0] = byte(sa.Port >> 8)
816 p[1] = byte(sa.Port)
817 sa.raw.Addr = sa.Addr
818 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
819 }
820
821 type SockaddrInet6 struct {
822 Port int
823 ZoneId uint32
824 Addr [16]byte
825 raw RawSockaddrInet6
826 }
827
828 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
829 if sa.Port < 0 || sa.Port > 0xFFFF {
830 return nil, 0, EINVAL
831 }
832 sa.raw.Family = AF_INET6
833 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
834 p[0] = byte(sa.Port >> 8)
835 p[1] = byte(sa.Port)
836 sa.raw.Scope_id = sa.ZoneId
837 sa.raw.Addr = sa.Addr
838 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
839 }
840
841 type RawSockaddrUnix struct {
842 Family uint16
843 Path [UNIX_PATH_MAX]int8
844 }
845
846 type SockaddrUnix struct {
847 Name string
848 raw RawSockaddrUnix
849 }
850
851 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
852 name := sa.Name
853 n := len(name)
854 if n > len(sa.raw.Path) {
855 return nil, 0, EINVAL
856 }
857 if n == len(sa.raw.Path) && name[0] != '@' {
858 return nil, 0, EINVAL
859 }
860 sa.raw.Family = AF_UNIX
861 for i := 0; i < n; i++ {
862 sa.raw.Path[i] = int8(name[i])
863 }
864
865 sl := int32(2)
866 if n > 0 {
867 sl += int32(n) + 1
868 }
869 if sa.raw.Path[0] == '@' || (sa.raw.Path[0] == 0 && sl > 3) {
870
871 sa.raw.Path[0] = 0
872
873 sl--
874 }
875
876 return unsafe.Pointer(&sa.raw), sl, nil
877 }
878
879 func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
880 switch rsa.Addr.Family {
881 case AF_UNIX:
882 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
883 sa := new(SockaddrUnix)
884 if pp.Path[0] == 0 {
885
886
887
888
889
890 pp.Path[0] = '@'
891 }
892
893
894
895
896
897
898 n := 0
899 for n < len(pp.Path) && pp.Path[n] != 0 {
900 n++
901 }
902 sa.Name = string(unsafe.Slice((*byte)(unsafe.Pointer(&pp.Path[0])), n))
903 return sa, nil
904
905 case AF_INET:
906 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
907 sa := new(SockaddrInet4)
908 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
909 sa.Port = int(p[0])<<8 + int(p[1])
910 sa.Addr = pp.Addr
911 return sa, nil
912
913 case AF_INET6:
914 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
915 sa := new(SockaddrInet6)
916 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
917 sa.Port = int(p[0])<<8 + int(p[1])
918 sa.ZoneId = pp.Scope_id
919 sa.Addr = pp.Addr
920 return sa, nil
921 }
922 return nil, EAFNOSUPPORT
923 }
924
925 func Socket(domain, typ, proto int) (fd Handle, err error) {
926 if domain == AF_INET6 && SocketDisableIPv6 {
927 return InvalidHandle, EAFNOSUPPORT
928 }
929 return socket(int32(domain), int32(typ), int32(proto))
930 }
931
932 func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
933 v := int32(value)
934 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
935 }
936
937 func Bind(fd Handle, sa Sockaddr) (err error) {
938 ptr, n, err := sa.sockaddr()
939 if err != nil {
940 return err
941 }
942 return bind(fd, ptr, n)
943 }
944
945 func Connect(fd Handle, sa Sockaddr) (err error) {
946 ptr, n, err := sa.sockaddr()
947 if err != nil {
948 return err
949 }
950 return connect(fd, ptr, n)
951 }
952
953 func Getsockname(fd Handle) (sa Sockaddr, err error) {
954 var rsa RawSockaddrAny
955 l := int32(unsafe.Sizeof(rsa))
956 if err = getsockname(fd, &rsa, &l); err != nil {
957 return
958 }
959 return rsa.Sockaddr()
960 }
961
962 func Getpeername(fd Handle) (sa Sockaddr, err error) {
963 var rsa RawSockaddrAny
964 l := int32(unsafe.Sizeof(rsa))
965 if err = getpeername(fd, &rsa, &l); err != nil {
966 return
967 }
968 return rsa.Sockaddr()
969 }
970
971 func Listen(s Handle, n int) (err error) {
972 return listen(s, int32(n))
973 }
974
975 func Shutdown(fd Handle, how int) (err error) {
976 return shutdown(fd, int32(how))
977 }
978
979 func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
980 var rsa unsafe.Pointer
981 var len int32
982 if to != nil {
983 rsa, len, err = to.sockaddr()
984 if err != nil {
985 return err
986 }
987 }
988 r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
989 if r1 == socket_error {
990 if e1 != 0 {
991 err = errnoErr(e1)
992 } else {
993 err = EINVAL
994 }
995 }
996 return err
997 }
998
999 func wsaSendtoInet4(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet4, overlapped *Overlapped, croutine *byte) (err error) {
1000 rsa, len, err := to.sockaddr()
1001 if err != nil {
1002 return err
1003 }
1004 r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
1005 if r1 == socket_error {
1006 if e1 != 0 {
1007 err = errnoErr(e1)
1008 } else {
1009 err = EINVAL
1010 }
1011 }
1012 return err
1013 }
1014
1015 func wsaSendtoInet6(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *SockaddrInet6, overlapped *Overlapped, croutine *byte) (err error) {
1016 rsa, len, err := to.sockaddr()
1017 if err != nil {
1018 return err
1019 }
1020 r1, _, e1 := Syscall9(procWSASendTo.Addr(), 9, uintptr(s), uintptr(unsafe.Pointer(bufs)), uintptr(bufcnt), uintptr(unsafe.Pointer(sent)), uintptr(flags), uintptr(unsafe.Pointer(rsa)), uintptr(len), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(croutine)))
1021 if r1 == socket_error {
1022 if e1 != 0 {
1023 err = errnoErr(e1)
1024 } else {
1025 err = EINVAL
1026 }
1027 }
1028 return err
1029 }
1030
1031 func LoadGetAddrInfo() error {
1032 return procGetAddrInfoW.Find()
1033 }
1034
1035 var connectExFunc struct {
1036 once sync.Once
1037 addr uintptr
1038 err error
1039 }
1040
1041 func LoadConnectEx() error {
1042 connectExFunc.once.Do(func() {
1043 var s Handle
1044 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
1045 if connectExFunc.err != nil {
1046 return
1047 }
1048 defer CloseHandle(s)
1049 var n uint32
1050 connectExFunc.err = WSAIoctl(s,
1051 SIO_GET_EXTENSION_FUNCTION_POINTER,
1052 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
1053 uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
1054 (*byte)(unsafe.Pointer(&connectExFunc.addr)),
1055 uint32(unsafe.Sizeof(connectExFunc.addr)),
1056 &n, nil, 0)
1057 })
1058 return connectExFunc.err
1059 }
1060
1061 func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
1062 r1, _, e1 := Syscall9(connectExFunc.addr, 7, uintptr(s), uintptr(name), uintptr(namelen), uintptr(unsafe.Pointer(sendBuf)), uintptr(sendDataLen), uintptr(unsafe.Pointer(bytesSent)), uintptr(unsafe.Pointer(overlapped)), 0, 0)
1063 if r1 == 0 {
1064 if e1 != 0 {
1065 err = error(e1)
1066 } else {
1067 err = EINVAL
1068 }
1069 }
1070 return
1071 }
1072
1073 func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
1074 err := LoadConnectEx()
1075 if err != nil {
1076 return errorspkg.New("failed to find ConnectEx: " + err.Error())
1077 }
1078 ptr, n, err := sa.sockaddr()
1079 if err != nil {
1080 return err
1081 }
1082 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
1083 }
1084
1085
1086 type Rusage struct {
1087 CreationTime Filetime
1088 ExitTime Filetime
1089 KernelTime Filetime
1090 UserTime Filetime
1091 }
1092
1093 type WaitStatus struct {
1094 ExitCode uint32
1095 }
1096
1097 func (w WaitStatus) Exited() bool { return true }
1098
1099 func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
1100
1101 func (w WaitStatus) Signal() Signal { return -1 }
1102
1103 func (w WaitStatus) CoreDump() bool { return false }
1104
1105 func (w WaitStatus) Stopped() bool { return false }
1106
1107 func (w WaitStatus) Continued() bool { return false }
1108
1109 func (w WaitStatus) StopSignal() Signal { return -1 }
1110
1111 func (w WaitStatus) Signaled() bool { return false }
1112
1113 func (w WaitStatus) TrapCause() int { return -1 }
1114
1115
1116
1117 type Timespec struct {
1118 Sec int64
1119 Nsec int64
1120 }
1121
1122 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
1123
1124 func NsecToTimespec(nsec int64) (ts Timespec) {
1125 ts.Sec = nsec / 1e9
1126 ts.Nsec = nsec % 1e9
1127 return
1128 }
1129
1130
1131
1132 func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }
1133 func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
1134 return 0, nil, EWINDOWS
1135 }
1136 func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return EWINDOWS }
1137 func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS }
1138
1139
1140
1141
1142
1143
1144
1145
1146 type Linger struct {
1147 Onoff int32
1148 Linger int32
1149 }
1150
1151 type sysLinger struct {
1152 Onoff uint16
1153 Linger uint16
1154 }
1155
1156 type IPMreq struct {
1157 Multiaddr [4]byte
1158 Interface [4]byte
1159 }
1160
1161 type IPv6Mreq struct {
1162 Multiaddr [16]byte
1163 Interface uint32
1164 }
1165
1166 func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, EWINDOWS }
1167
1168 func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
1169 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
1170 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
1171 }
1172
1173 func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
1174 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
1175 }
1176 func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
1177 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
1178 }
1179 func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS }
1180
1181 func Getpid() (pid int) { return int(getCurrentProcessId()) }
1182
1183 func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
1184
1185
1186
1187
1188
1189
1190
1191
1192 var data1 win32finddata1
1193 handle, err = findFirstFile1(name, &data1)
1194 if err == nil {
1195 copyFindData(data, &data1)
1196 }
1197 return
1198 }
1199
1200 func FindNextFile(handle Handle, data *Win32finddata) (err error) {
1201 var data1 win32finddata1
1202 err = findNextFile1(handle, &data1)
1203 if err == nil {
1204 copyFindData(data, &data1)
1205 }
1206 return
1207 }
1208
1209 func getProcessEntry(pid int) (*ProcessEntry32, error) {
1210 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
1211 if err != nil {
1212 return nil, err
1213 }
1214 defer CloseHandle(snapshot)
1215 var procEntry ProcessEntry32
1216 procEntry.Size = uint32(unsafe.Sizeof(procEntry))
1217 if err = Process32First(snapshot, &procEntry); err != nil {
1218 return nil, err
1219 }
1220 for {
1221 if procEntry.ProcessID == uint32(pid) {
1222 return &procEntry, nil
1223 }
1224 err = Process32Next(snapshot, &procEntry)
1225 if err != nil {
1226 return nil, err
1227 }
1228 }
1229 }
1230
1231 func Getppid() (ppid int) {
1232 pe, err := getProcessEntry(Getpid())
1233 if err != nil {
1234 return -1
1235 }
1236 return int(pe.ParentProcessID)
1237 }
1238
1239 func fdpath(fd Handle, buf []uint16) ([]uint16, error) {
1240 const (
1241 FILE_NAME_NORMALIZED = 0
1242 VOLUME_NAME_DOS = 0
1243 )
1244 for {
1245 n, err := getFinalPathNameByHandle(fd, &buf[0], uint32(len(buf)), FILE_NAME_NORMALIZED|VOLUME_NAME_DOS)
1246 if err == nil {
1247 buf = buf[:n]
1248 break
1249 }
1250 if err != _ERROR_NOT_ENOUGH_MEMORY {
1251 return nil, err
1252 }
1253 buf = append(buf, make([]uint16, n-uint32(len(buf)))...)
1254 }
1255 return buf, nil
1256 }
1257
1258 func Fchdir(fd Handle) (err error) {
1259 var buf [MAX_PATH + 1]uint16
1260 path, err := fdpath(fd, buf[:])
1261 if err != nil {
1262 return err
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 if len(path) >= 4 && path[0] == '\\' && path[1] == '\\' && path[2] == '?' && path[3] == '\\' {
1274 path = path[4:]
1275 }
1276 return SetCurrentDirectory(&path[0])
1277 }
1278
1279
1280 func Link(oldpath, newpath string) (err error) { return EWINDOWS }
1281 func Symlink(path, link string) (err error) { return EWINDOWS }
1282
1283 func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS }
1284 func Chown(path string, uid int, gid int) (err error) { return EWINDOWS }
1285 func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS }
1286 func Fchown(fd Handle, uid int, gid int) (err error) { return EWINDOWS }
1287
1288 func Getuid() (uid int) { return -1 }
1289 func Geteuid() (euid int) { return -1 }
1290 func Getgid() (gid int) { return -1 }
1291 func Getegid() (egid int) { return -1 }
1292 func Getgroups() (gids []int, err error) { return nil, EWINDOWS }
1293
1294 type Signal int
1295
1296 func (s Signal) Signal() {}
1297
1298 func (s Signal) String() string {
1299 if 0 <= s && int(s) < len(signals) {
1300 str := signals[s]
1301 if str != "" {
1302 return str
1303 }
1304 }
1305 return "signal " + itoa.Itoa(int(s))
1306 }
1307
1308 func LoadCreateSymbolicLink() error {
1309 return procCreateSymbolicLinkW.Find()
1310 }
1311
1312
1313 func Readlink(path string, buf []byte) (n int, err error) {
1314 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
1315 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
1316 if err != nil {
1317 return -1, err
1318 }
1319 defer CloseHandle(fd)
1320
1321 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
1322 var bytesReturned uint32
1323 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
1324 if err != nil {
1325 return -1, err
1326 }
1327
1328 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
1329 var s string
1330 switch rdb.ReparseTag {
1331 case IO_REPARSE_TAG_SYMLINK:
1332 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1333 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1334 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1335 if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 {
1336 if len(s) >= 4 && s[:4] == `\??\` {
1337 s = s[4:]
1338 switch {
1339 case len(s) >= 2 && s[1] == ':':
1340
1341 case len(s) >= 4 && s[:4] == `UNC\`:
1342 s = `\\` + s[4:]
1343 default:
1344
1345 }
1346 } else {
1347
1348 }
1349 }
1350 case _IO_REPARSE_TAG_MOUNT_POINT:
1351 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1352 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1353 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1354 if len(s) >= 4 && s[:4] == `\??\` {
1355 s = s[4:]
1356 } else {
1357
1358 }
1359 default:
1360
1361
1362 return -1, ENOENT
1363 }
1364 n = copy(buf, []byte(s))
1365
1366 return n, nil
1367 }
1368
1369
1370 func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) {
1371 return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt)
1372 }
1373
1374
1375 func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error {
1376 var ukey uintptr
1377 var pukey *uintptr
1378 if key != nil {
1379 ukey = uintptr(*key)
1380 pukey = &ukey
1381 }
1382 err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout)
1383 if key != nil {
1384 *key = uint32(ukey)
1385 if uintptr(*key) != ukey && err == nil {
1386 err = errorspkg.New("GetQueuedCompletionStatus returned key overflow")
1387 }
1388 }
1389 return err
1390 }
1391
1392
1393 func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error {
1394 return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped)
1395 }
1396
1397
1398
1399
1400 func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LIST, error) {
1401 var size uintptr
1402 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
1403 if err != ERROR_INSUFFICIENT_BUFFER {
1404 if err == nil {
1405 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
1406 }
1407 return nil, err
1408 }
1409
1410 al := (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(&make([]byte, size)[0]))
1411 err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size)
1412 if err != nil {
1413 return nil, err
1414 }
1415 return al, nil
1416 }
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442 func RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) {
1443 return regEnumKeyEx(key, index, name, nameLen, reserved, class, classLen, lastWriteTime)
1444 }
1445
1446 func GetStartupInfo(startupInfo *StartupInfo) error {
1447 getStartupInfo(startupInfo)
1448 return nil
1449 }
1450
View as plain text