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/itoa"
12 "internal/oserror"
13 "internal/race"
14 "internal/unsafeheader"
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 for i := 0; i < len(s); i++ {
43 if s[i] == 0 {
44 return nil, EINVAL
45 }
46 }
47 return utf16.Encode([]rune(s + "\x00")), nil
48 }
49
50
51
52 func UTF16ToString(s []uint16) string {
53 for i, v := range s {
54 if v == 0 {
55 s = s[0:i]
56 break
57 }
58 }
59 return string(utf16.Decode(s))
60 }
61
62
63
64 func utf16PtrToString(p *uint16) string {
65 if p == nil {
66 return ""
67 }
68
69 end := unsafe.Pointer(p)
70 n := 0
71 for *(*uint16)(end) != 0 {
72 end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p))
73 n++
74 }
75
76 var s []uint16
77 hdr := (*unsafeheader.Slice)(unsafe.Pointer(&s))
78 hdr.Data = unsafe.Pointer(p)
79 hdr.Cap = n
80 hdr.Len = 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 interface{}, cleanstack bool) uintptr
173
174
175
176
177
178
179
180 func NewCallback(fn interface{}) uintptr {
181 return compileCallback(fn, true)
182 }
183
184
185
186
187
188
189
190 func NewCallbackCDecl(fn interface{}) 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 h, e := CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0)
375 return h, e
376 }
377
378 func Read(fd Handle, p []byte) (n int, err error) {
379 var done uint32
380 e := ReadFile(fd, p, &done, nil)
381 if e != nil {
382 if e == ERROR_BROKEN_PIPE {
383
384 return 0, nil
385 }
386 return 0, e
387 }
388 if race.Enabled {
389 if done > 0 {
390 race.WriteRange(unsafe.Pointer(&p[0]), int(done))
391 }
392 race.Acquire(unsafe.Pointer(&ioSync))
393 }
394 if msanenabled && done > 0 {
395 msanWrite(unsafe.Pointer(&p[0]), int(done))
396 }
397 return int(done), nil
398 }
399
400 func Write(fd Handle, p []byte) (n int, err error) {
401 if race.Enabled {
402 race.ReleaseMerge(unsafe.Pointer(&ioSync))
403 }
404 var done uint32
405 e := WriteFile(fd, p, &done, nil)
406 if e != nil {
407 return 0, e
408 }
409 if race.Enabled && done > 0 {
410 race.ReadRange(unsafe.Pointer(&p[0]), int(done))
411 }
412 if msanenabled && done > 0 {
413 msanRead(unsafe.Pointer(&p[0]), int(done))
414 }
415 return int(done), nil
416 }
417
418 var ioSync int64
419
420 var procSetFilePointerEx = modkernel32.NewProc("SetFilePointerEx")
421
422 const ptrSize = unsafe.Sizeof(uintptr(0))
423
424
425
426 func setFilePointerEx(handle Handle, distToMove int64, newFilePointer *int64, whence uint32) error {
427 var e1 Errno
428 if unsafe.Sizeof(uintptr(0)) == 8 {
429 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 4, uintptr(handle), uintptr(distToMove), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0, 0)
430 } else {
431
432 switch runtime.GOARCH {
433 default:
434 panic("unsupported 32-bit architecture")
435 case "386":
436
437
438 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 5, uintptr(handle), uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence), 0)
439 case "arm":
440
441
442 _, _, e1 = Syscall6(procSetFilePointerEx.Addr(), 6, uintptr(handle), 0, uintptr(distToMove), uintptr(distToMove>>32), uintptr(unsafe.Pointer(newFilePointer)), uintptr(whence))
443 }
444 }
445 if e1 != 0 {
446 return errnoErr(e1)
447 }
448 return nil
449 }
450
451 func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
452 var w uint32
453 switch whence {
454 case 0:
455 w = FILE_BEGIN
456 case 1:
457 w = FILE_CURRENT
458 case 2:
459 w = FILE_END
460 }
461
462 ft, _ := GetFileType(fd)
463 if ft == FILE_TYPE_PIPE {
464 return 0, ESPIPE
465 }
466 err = setFilePointerEx(fd, offset, &newoffset, w)
467 return
468 }
469
470 func Close(fd Handle) (err error) {
471 return CloseHandle(fd)
472 }
473
474 var (
475 Stdin = getStdHandle(STD_INPUT_HANDLE)
476 Stdout = getStdHandle(STD_OUTPUT_HANDLE)
477 Stderr = getStdHandle(STD_ERROR_HANDLE)
478 )
479
480 func getStdHandle(h int) (fd Handle) {
481 r, _ := GetStdHandle(h)
482 return r
483 }
484
485 const ImplementsGetwd = true
486
487 func Getwd() (wd string, err error) {
488 b := make([]uint16, 300)
489 n, e := GetCurrentDirectory(uint32(len(b)), &b[0])
490 if e != nil {
491 return "", e
492 }
493 return string(utf16.Decode(b[0:n])), nil
494 }
495
496 func Chdir(path string) (err error) {
497 pathp, err := UTF16PtrFromString(path)
498 if err != nil {
499 return err
500 }
501 return SetCurrentDirectory(pathp)
502 }
503
504 func Mkdir(path string, mode uint32) (err error) {
505 pathp, err := UTF16PtrFromString(path)
506 if err != nil {
507 return err
508 }
509 return CreateDirectory(pathp, nil)
510 }
511
512 func Rmdir(path string) (err error) {
513 pathp, err := UTF16PtrFromString(path)
514 if err != nil {
515 return err
516 }
517 return RemoveDirectory(pathp)
518 }
519
520 func Unlink(path string) (err error) {
521 pathp, err := UTF16PtrFromString(path)
522 if err != nil {
523 return err
524 }
525 return DeleteFile(pathp)
526 }
527
528 func Rename(oldpath, newpath string) (err error) {
529 from, err := UTF16PtrFromString(oldpath)
530 if err != nil {
531 return err
532 }
533 to, err := UTF16PtrFromString(newpath)
534 if err != nil {
535 return err
536 }
537 return MoveFile(from, to)
538 }
539
540 func ComputerName() (name string, err error) {
541 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
542 b := make([]uint16, n)
543 e := GetComputerName(&b[0], &n)
544 if e != nil {
545 return "", e
546 }
547 return string(utf16.Decode(b[0:n])), nil
548 }
549
550 func Ftruncate(fd Handle, length int64) (err error) {
551 curoffset, e := Seek(fd, 0, 1)
552 if e != nil {
553 return e
554 }
555 defer Seek(fd, curoffset, 0)
556 _, e = Seek(fd, length, 0)
557 if e != nil {
558 return e
559 }
560 e = SetEndOfFile(fd)
561 if e != nil {
562 return e
563 }
564 return nil
565 }
566
567 func Gettimeofday(tv *Timeval) (err error) {
568 var ft Filetime
569 GetSystemTimeAsFileTime(&ft)
570 *tv = NsecToTimeval(ft.Nanoseconds())
571 return nil
572 }
573
574 func Pipe(p []Handle) (err error) {
575 if len(p) != 2 {
576 return EINVAL
577 }
578 var r, w Handle
579 e := CreatePipe(&r, &w, makeInheritSa(), 0)
580 if e != nil {
581 return e
582 }
583 p[0] = r
584 p[1] = w
585 return nil
586 }
587
588 func Utimes(path string, tv []Timeval) (err error) {
589 if len(tv) != 2 {
590 return EINVAL
591 }
592 pathp, e := UTF16PtrFromString(path)
593 if e != nil {
594 return e
595 }
596 h, e := CreateFile(pathp,
597 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
598 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
599 if e != nil {
600 return e
601 }
602 defer Close(h)
603 a := NsecToFiletime(tv[0].Nanoseconds())
604 w := NsecToFiletime(tv[1].Nanoseconds())
605 return SetFileTime(h, nil, &a, &w)
606 }
607
608 func UtimesNano(path string, ts []Timespec) (err error) {
609 if len(ts) != 2 {
610 return EINVAL
611 }
612 pathp, e := UTF16PtrFromString(path)
613 if e != nil {
614 return e
615 }
616 h, e := CreateFile(pathp,
617 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
618 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
619 if e != nil {
620 return e
621 }
622 defer Close(h)
623 a := NsecToFiletime(TimespecToNsec(ts[0]))
624 w := NsecToFiletime(TimespecToNsec(ts[1]))
625 return SetFileTime(h, nil, &a, &w)
626 }
627
628 func Fsync(fd Handle) (err error) {
629 return FlushFileBuffers(fd)
630 }
631
632 func Chmod(path string, mode uint32) (err error) {
633 p, e := UTF16PtrFromString(path)
634 if e != nil {
635 return e
636 }
637 attrs, e := GetFileAttributes(p)
638 if e != nil {
639 return e
640 }
641 if mode&S_IWRITE != 0 {
642 attrs &^= FILE_ATTRIBUTE_READONLY
643 } else {
644 attrs |= FILE_ATTRIBUTE_READONLY
645 }
646 return SetFileAttributes(p, attrs)
647 }
648
649 func LoadCancelIoEx() error {
650 return procCancelIoEx.Find()
651 }
652
653 func LoadSetFileCompletionNotificationModes() error {
654 return procSetFileCompletionNotificationModes.Find()
655 }
656
657
658
659 const socket_error = uintptr(^uint32(0))
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696 var SocketDisableIPv6 bool
697
698 type RawSockaddrInet4 struct {
699 Family uint16
700 Port uint16
701 Addr [4]byte
702 Zero [8]uint8
703 }
704
705 type RawSockaddrInet6 struct {
706 Family uint16
707 Port uint16
708 Flowinfo uint32
709 Addr [16]byte
710 Scope_id uint32
711 }
712
713 type RawSockaddr struct {
714 Family uint16
715 Data [14]int8
716 }
717
718 type RawSockaddrAny struct {
719 Addr RawSockaddr
720 Pad [100]int8
721 }
722
723 type Sockaddr interface {
724 sockaddr() (ptr unsafe.Pointer, len int32, err error)
725 }
726
727 type SockaddrInet4 struct {
728 Port int
729 Addr [4]byte
730 raw RawSockaddrInet4
731 }
732
733 func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) {
734 if sa.Port < 0 || sa.Port > 0xFFFF {
735 return nil, 0, EINVAL
736 }
737 sa.raw.Family = AF_INET
738 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
739 p[0] = byte(sa.Port >> 8)
740 p[1] = byte(sa.Port)
741 for i := 0; i < len(sa.Addr); i++ {
742 sa.raw.Addr[i] = sa.Addr[i]
743 }
744 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
745 }
746
747 type SockaddrInet6 struct {
748 Port int
749 ZoneId uint32
750 Addr [16]byte
751 raw RawSockaddrInet6
752 }
753
754 func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
755 if sa.Port < 0 || sa.Port > 0xFFFF {
756 return nil, 0, EINVAL
757 }
758 sa.raw.Family = AF_INET6
759 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
760 p[0] = byte(sa.Port >> 8)
761 p[1] = byte(sa.Port)
762 sa.raw.Scope_id = sa.ZoneId
763 for i := 0; i < len(sa.Addr); i++ {
764 sa.raw.Addr[i] = sa.Addr[i]
765 }
766 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
767 }
768
769 type RawSockaddrUnix struct {
770 Family uint16
771 Path [UNIX_PATH_MAX]int8
772 }
773
774 type SockaddrUnix struct {
775 Name string
776 raw RawSockaddrUnix
777 }
778
779 func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
780 name := sa.Name
781 n := len(name)
782 if n > len(sa.raw.Path) {
783 return nil, 0, EINVAL
784 }
785 if n == len(sa.raw.Path) && name[0] != '@' {
786 return nil, 0, EINVAL
787 }
788 sa.raw.Family = AF_UNIX
789 for i := 0; i < n; i++ {
790 sa.raw.Path[i] = int8(name[i])
791 }
792
793 sl := int32(2)
794 if n > 0 {
795 sl += int32(n) + 1
796 }
797 if sa.raw.Path[0] == '@' {
798 sa.raw.Path[0] = 0
799
800 sl--
801 }
802
803 return unsafe.Pointer(&sa.raw), sl, nil
804 }
805
806 func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
807 switch rsa.Addr.Family {
808 case AF_UNIX:
809 pp := (*RawSockaddrUnix)(unsafe.Pointer(rsa))
810 sa := new(SockaddrUnix)
811 if pp.Path[0] == 0 {
812
813
814
815
816
817 pp.Path[0] = '@'
818 }
819
820
821
822
823
824
825 n := 0
826 for n < len(pp.Path) && pp.Path[n] != 0 {
827 n++
828 }
829 bytes := (*[len(pp.Path)]byte)(unsafe.Pointer(&pp.Path[0]))[0:n:n]
830 sa.Name = string(bytes)
831 return sa, nil
832
833 case AF_INET:
834 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
835 sa := new(SockaddrInet4)
836 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
837 sa.Port = int(p[0])<<8 + int(p[1])
838 for i := 0; i < len(sa.Addr); i++ {
839 sa.Addr[i] = pp.Addr[i]
840 }
841 return sa, nil
842
843 case AF_INET6:
844 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
845 sa := new(SockaddrInet6)
846 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
847 sa.Port = int(p[0])<<8 + int(p[1])
848 sa.ZoneId = pp.Scope_id
849 for i := 0; i < len(sa.Addr); i++ {
850 sa.Addr[i] = pp.Addr[i]
851 }
852 return sa, nil
853 }
854 return nil, EAFNOSUPPORT
855 }
856
857 func Socket(domain, typ, proto int) (fd Handle, err error) {
858 if domain == AF_INET6 && SocketDisableIPv6 {
859 return InvalidHandle, EAFNOSUPPORT
860 }
861 return socket(int32(domain), int32(typ), int32(proto))
862 }
863
864 func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
865 v := int32(value)
866 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
867 }
868
869 func Bind(fd Handle, sa Sockaddr) (err error) {
870 ptr, n, err := sa.sockaddr()
871 if err != nil {
872 return err
873 }
874 return bind(fd, ptr, n)
875 }
876
877 func Connect(fd Handle, sa Sockaddr) (err error) {
878 ptr, n, err := sa.sockaddr()
879 if err != nil {
880 return err
881 }
882 return connect(fd, ptr, n)
883 }
884
885 func Getsockname(fd Handle) (sa Sockaddr, err error) {
886 var rsa RawSockaddrAny
887 l := int32(unsafe.Sizeof(rsa))
888 if err = getsockname(fd, &rsa, &l); err != nil {
889 return
890 }
891 return rsa.Sockaddr()
892 }
893
894 func Getpeername(fd Handle) (sa Sockaddr, err error) {
895 var rsa RawSockaddrAny
896 l := int32(unsafe.Sizeof(rsa))
897 if err = getpeername(fd, &rsa, &l); err != nil {
898 return
899 }
900 return rsa.Sockaddr()
901 }
902
903 func Listen(s Handle, n int) (err error) {
904 return listen(s, int32(n))
905 }
906
907 func Shutdown(fd Handle, how int) (err error) {
908 return shutdown(fd, int32(how))
909 }
910
911 func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
912 rsa, len, err := to.sockaddr()
913 if err != nil {
914 return err
915 }
916 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)))
917 if r1 == socket_error {
918 if e1 != 0 {
919 err = errnoErr(e1)
920 } else {
921 err = EINVAL
922 }
923 }
924 return err
925 }
926
927 func LoadGetAddrInfo() error {
928 return procGetAddrInfoW.Find()
929 }
930
931 var connectExFunc struct {
932 once sync.Once
933 addr uintptr
934 err error
935 }
936
937 func LoadConnectEx() error {
938 connectExFunc.once.Do(func() {
939 var s Handle
940 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
941 if connectExFunc.err != nil {
942 return
943 }
944 defer CloseHandle(s)
945 var n uint32
946 connectExFunc.err = WSAIoctl(s,
947 SIO_GET_EXTENSION_FUNCTION_POINTER,
948 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
949 uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
950 (*byte)(unsafe.Pointer(&connectExFunc.addr)),
951 uint32(unsafe.Sizeof(connectExFunc.addr)),
952 &n, nil, 0)
953 })
954 return connectExFunc.err
955 }
956
957 func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
958 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)
959 if r1 == 0 {
960 if e1 != 0 {
961 err = error(e1)
962 } else {
963 err = EINVAL
964 }
965 }
966 return
967 }
968
969 func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
970 err := LoadConnectEx()
971 if err != nil {
972 return errorspkg.New("failed to find ConnectEx: " + err.Error())
973 }
974 ptr, n, err := sa.sockaddr()
975 if err != nil {
976 return err
977 }
978 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
979 }
980
981
982 type Rusage struct {
983 CreationTime Filetime
984 ExitTime Filetime
985 KernelTime Filetime
986 UserTime Filetime
987 }
988
989 type WaitStatus struct {
990 ExitCode uint32
991 }
992
993 func (w WaitStatus) Exited() bool { return true }
994
995 func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
996
997 func (w WaitStatus) Signal() Signal { return -1 }
998
999 func (w WaitStatus) CoreDump() bool { return false }
1000
1001 func (w WaitStatus) Stopped() bool { return false }
1002
1003 func (w WaitStatus) Continued() bool { return false }
1004
1005 func (w WaitStatus) StopSignal() Signal { return -1 }
1006
1007 func (w WaitStatus) Signaled() bool { return false }
1008
1009 func (w WaitStatus) TrapCause() int { return -1 }
1010
1011
1012
1013 type Timespec struct {
1014 Sec int64
1015 Nsec int64
1016 }
1017
1018 func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
1019
1020 func NsecToTimespec(nsec int64) (ts Timespec) {
1021 ts.Sec = nsec / 1e9
1022 ts.Nsec = nsec % 1e9
1023 return
1024 }
1025
1026
1027
1028 func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, EWINDOWS }
1029 func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
1030 return 0, nil, EWINDOWS
1031 }
1032 func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return EWINDOWS }
1033 func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return EWINDOWS }
1034
1035
1036
1037
1038
1039
1040
1041
1042 type Linger struct {
1043 Onoff int32
1044 Linger int32
1045 }
1046
1047 type sysLinger struct {
1048 Onoff uint16
1049 Linger uint16
1050 }
1051
1052 type IPMreq struct {
1053 Multiaddr [4]byte
1054 Interface [4]byte
1055 }
1056
1057 type IPv6Mreq struct {
1058 Multiaddr [16]byte
1059 Interface uint32
1060 }
1061
1062 func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, EWINDOWS }
1063
1064 func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
1065 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
1066 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
1067 }
1068
1069 func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
1070 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
1071 }
1072 func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
1073 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
1074 }
1075 func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) { return EWINDOWS }
1076
1077 func Getpid() (pid int) { return int(getCurrentProcessId()) }
1078
1079 func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
1080
1081
1082
1083
1084
1085
1086
1087
1088 var data1 win32finddata1
1089 handle, err = findFirstFile1(name, &data1)
1090 if err == nil {
1091 copyFindData(data, &data1)
1092 }
1093 return
1094 }
1095
1096 func FindNextFile(handle Handle, data *Win32finddata) (err error) {
1097 var data1 win32finddata1
1098 err = findNextFile1(handle, &data1)
1099 if err == nil {
1100 copyFindData(data, &data1)
1101 }
1102 return
1103 }
1104
1105 func getProcessEntry(pid int) (*ProcessEntry32, error) {
1106 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
1107 if err != nil {
1108 return nil, err
1109 }
1110 defer CloseHandle(snapshot)
1111 var procEntry ProcessEntry32
1112 procEntry.Size = uint32(unsafe.Sizeof(procEntry))
1113 if err = Process32First(snapshot, &procEntry); err != nil {
1114 return nil, err
1115 }
1116 for {
1117 if procEntry.ProcessID == uint32(pid) {
1118 return &procEntry, nil
1119 }
1120 err = Process32Next(snapshot, &procEntry)
1121 if err != nil {
1122 return nil, err
1123 }
1124 }
1125 }
1126
1127 func Getppid() (ppid int) {
1128 pe, err := getProcessEntry(Getpid())
1129 if err != nil {
1130 return -1
1131 }
1132 return int(pe.ParentProcessID)
1133 }
1134
1135
1136 func Fchdir(fd Handle) (err error) { return EWINDOWS }
1137 func Link(oldpath, newpath string) (err error) { return EWINDOWS }
1138 func Symlink(path, link string) (err error) { return EWINDOWS }
1139
1140 func Fchmod(fd Handle, mode uint32) (err error) { return EWINDOWS }
1141 func Chown(path string, uid int, gid int) (err error) { return EWINDOWS }
1142 func Lchown(path string, uid int, gid int) (err error) { return EWINDOWS }
1143 func Fchown(fd Handle, uid int, gid int) (err error) { return EWINDOWS }
1144
1145 func Getuid() (uid int) { return -1 }
1146 func Geteuid() (euid int) { return -1 }
1147 func Getgid() (gid int) { return -1 }
1148 func Getegid() (egid int) { return -1 }
1149 func Getgroups() (gids []int, err error) { return nil, EWINDOWS }
1150
1151 type Signal int
1152
1153 func (s Signal) Signal() {}
1154
1155 func (s Signal) String() string {
1156 if 0 <= s && int(s) < len(signals) {
1157 str := signals[s]
1158 if str != "" {
1159 return str
1160 }
1161 }
1162 return "signal " + itoa.Itoa(int(s))
1163 }
1164
1165 func LoadCreateSymbolicLink() error {
1166 return procCreateSymbolicLinkW.Find()
1167 }
1168
1169
1170 func Readlink(path string, buf []byte) (n int, err error) {
1171 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
1172 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
1173 if err != nil {
1174 return -1, err
1175 }
1176 defer CloseHandle(fd)
1177
1178 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
1179 var bytesReturned uint32
1180 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
1181 if err != nil {
1182 return -1, err
1183 }
1184
1185 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
1186 var s string
1187 switch rdb.ReparseTag {
1188 case IO_REPARSE_TAG_SYMLINK:
1189 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1190 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1191 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1192 if data.Flags&_SYMLINK_FLAG_RELATIVE == 0 {
1193 if len(s) >= 4 && s[:4] == `\??\` {
1194 s = s[4:]
1195 switch {
1196 case len(s) >= 2 && s[1] == ':':
1197
1198 case len(s) >= 4 && s[:4] == `UNC\`:
1199 s = `\\` + s[4:]
1200 default:
1201
1202 }
1203 } else {
1204
1205 }
1206 }
1207 case _IO_REPARSE_TAG_MOUNT_POINT:
1208 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
1209 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
1210 s = UTF16ToString(p[data.SubstituteNameOffset/2 : (data.SubstituteNameOffset+data.SubstituteNameLength)/2])
1211 if len(s) >= 4 && s[:4] == `\??\` {
1212 s = s[4:]
1213 } else {
1214
1215 }
1216 default:
1217
1218
1219 return -1, ENOENT
1220 }
1221 n = copy(buf, []byte(s))
1222
1223 return n, nil
1224 }
1225
1226
1227 func CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (Handle, error) {
1228 return createIoCompletionPort(filehandle, cphandle, uintptr(key), threadcnt)
1229 }
1230
1231
1232 func GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) error {
1233 var ukey uintptr
1234 var pukey *uintptr
1235 if key != nil {
1236 ukey = uintptr(*key)
1237 pukey = &ukey
1238 }
1239 err := getQueuedCompletionStatus(cphandle, qty, pukey, overlapped, timeout)
1240 if key != nil {
1241 *key = uint32(ukey)
1242 if uintptr(*key) != ukey && err == nil {
1243 err = errorspkg.New("GetQueuedCompletionStatus returned key overflow")
1244 }
1245 }
1246 return err
1247 }
1248
1249
1250 func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) error {
1251 return postQueuedCompletionStatus(cphandle, qty, uintptr(key), overlapped)
1252 }
1253
1254
1255
1256
1257 func newProcThreadAttributeList(maxAttrCount uint32) (*_PROC_THREAD_ATTRIBUTE_LIST, error) {
1258 var size uintptr
1259 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size)
1260 if err != ERROR_INSUFFICIENT_BUFFER {
1261 if err == nil {
1262 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList")
1263 }
1264 return nil, err
1265 }
1266
1267 al := (*_PROC_THREAD_ATTRIBUTE_LIST)(unsafe.Pointer(&make([]byte, size)[0]))
1268 err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size)
1269 if err != nil {
1270 return nil, err
1271 }
1272 return al, nil
1273 }
1274
View as plain text