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