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