blob: c7ff24b55439667d7a8e96f843204b3ef907e327 [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Windows system calls.
6
7package windows
8
9import (
10 errorspkg "errors"
11 "sync"
12 "syscall"
13 "unicode/utf16"
14 "unsafe"
15)
16
17type Handle uintptr
18
19const InvalidHandle = ^Handle(0)
20
21// StringToUTF16 is deprecated. Use UTF16FromString instead.
22// If s contains a NUL byte this function panics instead of
23// returning an error.
24func StringToUTF16(s string) []uint16 {
25 a, err := UTF16FromString(s)
26 if err != nil {
27 panic("windows: string with NUL passed to StringToUTF16")
28 }
29 return a
30}
31
32// UTF16FromString returns the UTF-16 encoding of the UTF-8 string
33// s, with a terminating NUL added. If s contains a NUL byte at any
34// location, it returns (nil, syscall.EINVAL).
35func UTF16FromString(s string) ([]uint16, error) {
36 for i := 0; i < len(s); i++ {
37 if s[i] == 0 {
38 return nil, syscall.EINVAL
39 }
40 }
41 return utf16.Encode([]rune(s + "\x00")), nil
42}
43
44// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
45// with a terminating NUL removed.
46func UTF16ToString(s []uint16) string {
47 for i, v := range s {
48 if v == 0 {
49 s = s[0:i]
50 break
51 }
52 }
53 return string(utf16.Decode(s))
54}
55
56// StringToUTF16Ptr is deprecated. Use UTF16PtrFromString instead.
57// If s contains a NUL byte this function panics instead of
58// returning an error.
59func StringToUTF16Ptr(s string) *uint16 { return &StringToUTF16(s)[0] }
60
61// UTF16PtrFromString returns pointer to the UTF-16 encoding of
62// the UTF-8 string s, with a terminating NUL added. If s
63// contains a NUL byte at any location, it returns (nil, syscall.EINVAL).
64func UTF16PtrFromString(s string) (*uint16, error) {
65 a, err := UTF16FromString(s)
66 if err != nil {
67 return nil, err
68 }
69 return &a[0], nil
70}
71
72func Getpagesize() int { return 4096 }
73
74// Converts a Go function to a function pointer conforming
75// to the stdcall or cdecl calling convention. This is useful when
76// interoperating with Windows code requiring callbacks.
77// Implemented in runtime/syscall_windows.goc
78func NewCallback(fn interface{}) uintptr
79func NewCallbackCDecl(fn interface{}) uintptr
80
81// windows api calls
82
83//sys GetLastError() (lasterr error)
84//sys LoadLibrary(libname string) (handle Handle, err error) = LoadLibraryW
85//sys LoadLibraryEx(libname string, zero Handle, flags uintptr) (handle Handle, err error) = LoadLibraryExW
86//sys FreeLibrary(handle Handle) (err error)
87//sys GetProcAddress(module Handle, procname string) (proc uintptr, err error)
88//sys GetVersion() (ver uint32, err error)
89//sys FormatMessage(flags uint32, msgsrc uintptr, msgid uint32, langid uint32, buf []uint16, args *byte) (n uint32, err error) = FormatMessageW
90//sys ExitProcess(exitcode uint32)
91//sys CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
92//sys ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
93//sys WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
94//sys SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
95//sys CloseHandle(handle Handle) (err error)
96//sys GetStdHandle(stdhandle uint32) (handle Handle, err error) [failretval==InvalidHandle]
97//sys SetStdHandle(stdhandle uint32, handle Handle) (err error)
98//sys findFirstFile1(name *uint16, data *win32finddata1) (handle Handle, err error) [failretval==InvalidHandle] = FindFirstFileW
99//sys findNextFile1(handle Handle, data *win32finddata1) (err error) = FindNextFileW
100//sys FindClose(handle Handle) (err error)
101//sys GetFileInformationByHandle(handle Handle, data *ByHandleFileInformation) (err error)
102//sys GetCurrentDirectory(buflen uint32, buf *uint16) (n uint32, err error) = GetCurrentDirectoryW
103//sys SetCurrentDirectory(path *uint16) (err error) = SetCurrentDirectoryW
104//sys CreateDirectory(path *uint16, sa *SecurityAttributes) (err error) = CreateDirectoryW
105//sys RemoveDirectory(path *uint16) (err error) = RemoveDirectoryW
106//sys DeleteFile(path *uint16) (err error) = DeleteFileW
107//sys MoveFile(from *uint16, to *uint16) (err error) = MoveFileW
108//sys MoveFileEx(from *uint16, to *uint16, flags uint32) (err error) = MoveFileExW
109//sys GetComputerName(buf *uint16, n *uint32) (err error) = GetComputerNameW
110//sys GetComputerNameEx(nametype uint32, buf *uint16, n *uint32) (err error) = GetComputerNameExW
111//sys SetEndOfFile(handle Handle) (err error)
112//sys GetSystemTimeAsFileTime(time *Filetime)
113//sys GetSystemTimePreciseAsFileTime(time *Filetime)
114//sys GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, err error) [failretval==0xffffffff]
115//sys CreateIoCompletionPort(filehandle Handle, cphandle Handle, key uint32, threadcnt uint32) (handle Handle, err error)
116//sys GetQueuedCompletionStatus(cphandle Handle, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (err error)
117//sys PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uint32, overlapped *Overlapped) (err error)
118//sys CancelIo(s Handle) (err error)
119//sys CancelIoEx(s Handle, o *Overlapped) (err error)
120//sys CreateProcess(appName *uint16, commandLine *uint16, procSecurity *SecurityAttributes, threadSecurity *SecurityAttributes, inheritHandles bool, creationFlags uint32, env *uint16, currentDir *uint16, startupInfo *StartupInfo, outProcInfo *ProcessInformation) (err error) = CreateProcessW
121//sys OpenProcess(da uint32, inheritHandle bool, pid uint32) (handle Handle, err error)
122//sys TerminateProcess(handle Handle, exitcode uint32) (err error)
123//sys GetExitCodeProcess(handle Handle, exitcode *uint32) (err error)
124//sys GetStartupInfo(startupInfo *StartupInfo) (err error) = GetStartupInfoW
125//sys GetCurrentProcess() (pseudoHandle Handle, err error)
126//sys GetProcessTimes(handle Handle, creationTime *Filetime, exitTime *Filetime, kernelTime *Filetime, userTime *Filetime) (err error)
127//sys DuplicateHandle(hSourceProcessHandle Handle, hSourceHandle Handle, hTargetProcessHandle Handle, lpTargetHandle *Handle, dwDesiredAccess uint32, bInheritHandle bool, dwOptions uint32) (err error)
128//sys WaitForSingleObject(handle Handle, waitMilliseconds uint32) (event uint32, err error) [failretval==0xffffffff]
129//sys GetTempPath(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPathW
130//sys CreatePipe(readhandle *Handle, writehandle *Handle, sa *SecurityAttributes, size uint32) (err error)
131//sys GetFileType(filehandle Handle) (n uint32, err error)
132//sys CryptAcquireContext(provhandle *Handle, container *uint16, provider *uint16, provtype uint32, flags uint32) (err error) = advapi32.CryptAcquireContextW
133//sys CryptReleaseContext(provhandle Handle, flags uint32) (err error) = advapi32.CryptReleaseContext
134//sys CryptGenRandom(provhandle Handle, buflen uint32, buf *byte) (err error) = advapi32.CryptGenRandom
135//sys GetEnvironmentStrings() (envs *uint16, err error) [failretval==nil] = kernel32.GetEnvironmentStringsW
136//sys FreeEnvironmentStrings(envs *uint16) (err error) = kernel32.FreeEnvironmentStringsW
137//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, err error) = kernel32.GetEnvironmentVariableW
138//sys SetEnvironmentVariable(name *uint16, value *uint16) (err error) = kernel32.SetEnvironmentVariableW
139//sys SetFileTime(handle Handle, ctime *Filetime, atime *Filetime, wtime *Filetime) (err error)
140//sys GetFileAttributes(name *uint16) (attrs uint32, err error) [failretval==INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
141//sys SetFileAttributes(name *uint16, attrs uint32) (err error) = kernel32.SetFileAttributesW
142//sys GetFileAttributesEx(name *uint16, level uint32, info *byte) (err error) = kernel32.GetFileAttributesExW
143//sys GetCommandLine() (cmd *uint16) = kernel32.GetCommandLineW
144//sys CommandLineToArgv(cmd *uint16, argc *int32) (argv *[8192]*[8192]uint16, err error) [failretval==nil] = shell32.CommandLineToArgvW
145//sys LocalFree(hmem Handle) (handle Handle, err error) [failretval!=0]
146//sys SetHandleInformation(handle Handle, mask uint32, flags uint32) (err error)
147//sys FlushFileBuffers(handle Handle) (err error)
148//sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW
149//sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW
150//sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW
151//sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW
152//sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error)
153//sys UnmapViewOfFile(addr uintptr) (err error)
154//sys FlushViewOfFile(addr uintptr, length uintptr) (err error)
155//sys VirtualLock(addr uintptr, length uintptr) (err error)
156//sys VirtualUnlock(addr uintptr, length uintptr) (err error)
157//sys VirtualAlloc(address uintptr, size uintptr, alloctype uint32, protect uint32) (value uintptr, err error) = kernel32.VirtualAlloc
158//sys VirtualFree(address uintptr, size uintptr, freetype uint32) (err error) = kernel32.VirtualFree
159//sys VirtualProtect(address uintptr, size uintptr, newprotect uint32, oldprotect *uint32) (err error) = kernel32.VirtualProtect
160//sys TransmitFile(s Handle, handle Handle, bytesToWrite uint32, bytsPerSend uint32, overlapped *Overlapped, transmitFileBuf *TransmitFileBuffers, flags uint32) (err error) = mswsock.TransmitFile
161//sys ReadDirectoryChanges(handle Handle, buf *byte, buflen uint32, watchSubTree bool, mask uint32, retlen *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) = kernel32.ReadDirectoryChangesW
162//sys CertOpenSystemStore(hprov Handle, name *uint16) (store Handle, err error) = crypt32.CertOpenSystemStoreW
163//sys CertOpenStore(storeProvider uintptr, msgAndCertEncodingType uint32, cryptProv uintptr, flags uint32, para uintptr) (handle Handle, err error) [failretval==InvalidHandle] = crypt32.CertOpenStore
164//sys CertEnumCertificatesInStore(store Handle, prevContext *CertContext) (context *CertContext, err error) [failretval==nil] = crypt32.CertEnumCertificatesInStore
165//sys CertAddCertificateContextToStore(store Handle, certContext *CertContext, addDisposition uint32, storeContext **CertContext) (err error) = crypt32.CertAddCertificateContextToStore
166//sys CertCloseStore(store Handle, flags uint32) (err error) = crypt32.CertCloseStore
167//sys CertGetCertificateChain(engine Handle, leaf *CertContext, time *Filetime, additionalStore Handle, para *CertChainPara, flags uint32, reserved uintptr, chainCtx **CertChainContext) (err error) = crypt32.CertGetCertificateChain
168//sys CertFreeCertificateChain(ctx *CertChainContext) = crypt32.CertFreeCertificateChain
169//sys CertCreateCertificateContext(certEncodingType uint32, certEncoded *byte, encodedLen uint32) (context *CertContext, err error) [failretval==nil] = crypt32.CertCreateCertificateContext
170//sys CertFreeCertificateContext(ctx *CertContext) (err error) = crypt32.CertFreeCertificateContext
171//sys CertVerifyCertificateChainPolicy(policyOID uintptr, chain *CertChainContext, para *CertChainPolicyPara, status *CertChainPolicyStatus) (err error) = crypt32.CertVerifyCertificateChainPolicy
172//sys RegOpenKeyEx(key Handle, subkey *uint16, options uint32, desiredAccess uint32, result *Handle) (regerrno error) = advapi32.RegOpenKeyExW
173//sys RegCloseKey(key Handle) (regerrno error) = advapi32.RegCloseKey
174//sys RegQueryInfoKey(key Handle, class *uint16, classLen *uint32, reserved *uint32, subkeysLen *uint32, maxSubkeyLen *uint32, maxClassLen *uint32, valuesLen *uint32, maxValueNameLen *uint32, maxValueLen *uint32, saLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegQueryInfoKeyW
175//sys RegEnumKeyEx(key Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, classLen *uint32, lastWriteTime *Filetime) (regerrno error) = advapi32.RegEnumKeyExW
176//sys RegQueryValueEx(key Handle, name *uint16, reserved *uint32, valtype *uint32, buf *byte, buflen *uint32) (regerrno error) = advapi32.RegQueryValueExW
177//sys getCurrentProcessId() (pid uint32) = kernel32.GetCurrentProcessId
178//sys GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
179//sys SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode
180//sys GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo
181//sys WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
182//sys ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
183//sys CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
184//sys Process32First(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32FirstW
185//sys Process32Next(snapshot Handle, procEntry *ProcessEntry32) (err error) = kernel32.Process32NextW
186//sys DeviceIoControl(handle Handle, ioControlCode uint32, inBuffer *byte, inBufferSize uint32, outBuffer *byte, outBufferSize uint32, bytesReturned *uint32, overlapped *Overlapped) (err error)
187// This function returns 1 byte BOOLEAN rather than the 4 byte BOOL.
188//sys CreateSymbolicLink(symlinkfilename *uint16, targetfilename *uint16, flags uint32) (err error) [failretval&0xff==0] = CreateSymbolicLinkW
189//sys CreateHardLink(filename *uint16, existingfilename *uint16, reserved uintptr) (err error) [failretval&0xff==0] = CreateHardLinkW
190//sys GetCurrentThreadId() (id uint32)
191//sys CreateEvent(eventAttrs *SecurityAttributes, manualReset uint32, initialState uint32, name *uint16) (handle Handle, err error) = kernel32.CreateEventW
192//sys CreateEventEx(eventAttrs *SecurityAttributes, name *uint16, flags uint32, desiredAccess uint32) (handle Handle, err error) = kernel32.CreateEventExW
193//sys OpenEvent(desiredAccess uint32, inheritHandle bool, name *uint16) (handle Handle, err error) = kernel32.OpenEventW
194//sys SetEvent(event Handle) (err error) = kernel32.SetEvent
195//sys ResetEvent(event Handle) (err error) = kernel32.ResetEvent
196//sys PulseEvent(event Handle) (err error) = kernel32.PulseEvent
197
198// syscall interface implementation for other packages
199
200func Exit(code int) { ExitProcess(uint32(code)) }
201
202func makeInheritSa() *SecurityAttributes {
203 var sa SecurityAttributes
204 sa.Length = uint32(unsafe.Sizeof(sa))
205 sa.InheritHandle = 1
206 return &sa
207}
208
209func Open(path string, mode int, perm uint32) (fd Handle, err error) {
210 if len(path) == 0 {
211 return InvalidHandle, ERROR_FILE_NOT_FOUND
212 }
213 pathp, err := UTF16PtrFromString(path)
214 if err != nil {
215 return InvalidHandle, err
216 }
217 var access uint32
218 switch mode & (O_RDONLY | O_WRONLY | O_RDWR) {
219 case O_RDONLY:
220 access = GENERIC_READ
221 case O_WRONLY:
222 access = GENERIC_WRITE
223 case O_RDWR:
224 access = GENERIC_READ | GENERIC_WRITE
225 }
226 if mode&O_CREAT != 0 {
227 access |= GENERIC_WRITE
228 }
229 if mode&O_APPEND != 0 {
230 access &^= GENERIC_WRITE
231 access |= FILE_APPEND_DATA
232 }
233 sharemode := uint32(FILE_SHARE_READ | FILE_SHARE_WRITE)
234 var sa *SecurityAttributes
235 if mode&O_CLOEXEC == 0 {
236 sa = makeInheritSa()
237 }
238 var createmode uint32
239 switch {
240 case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
241 createmode = CREATE_NEW
242 case mode&(O_CREAT|O_TRUNC) == (O_CREAT | O_TRUNC):
243 createmode = CREATE_ALWAYS
244 case mode&O_CREAT == O_CREAT:
245 createmode = OPEN_ALWAYS
246 case mode&O_TRUNC == O_TRUNC:
247 createmode = TRUNCATE_EXISTING
248 default:
249 createmode = OPEN_EXISTING
250 }
251 h, e := CreateFile(pathp, access, sharemode, sa, createmode, FILE_ATTRIBUTE_NORMAL, 0)
252 return h, e
253}
254
255func Read(fd Handle, p []byte) (n int, err error) {
256 var done uint32
257 e := ReadFile(fd, p, &done, nil)
258 if e != nil {
259 if e == ERROR_BROKEN_PIPE {
260 // NOTE(brainman): work around ERROR_BROKEN_PIPE is returned on reading EOF from stdin
261 return 0, nil
262 }
263 return 0, e
264 }
265 if raceenabled {
266 if done > 0 {
267 raceWriteRange(unsafe.Pointer(&p[0]), int(done))
268 }
269 raceAcquire(unsafe.Pointer(&ioSync))
270 }
271 return int(done), nil
272}
273
274func Write(fd Handle, p []byte) (n int, err error) {
275 if raceenabled {
276 raceReleaseMerge(unsafe.Pointer(&ioSync))
277 }
278 var done uint32
279 e := WriteFile(fd, p, &done, nil)
280 if e != nil {
281 return 0, e
282 }
283 if raceenabled && done > 0 {
284 raceReadRange(unsafe.Pointer(&p[0]), int(done))
285 }
286 return int(done), nil
287}
288
289var ioSync int64
290
291func Seek(fd Handle, offset int64, whence int) (newoffset int64, err error) {
292 var w uint32
293 switch whence {
294 case 0:
295 w = FILE_BEGIN
296 case 1:
297 w = FILE_CURRENT
298 case 2:
299 w = FILE_END
300 }
301 hi := int32(offset >> 32)
302 lo := int32(offset)
303 // use GetFileType to check pipe, pipe can't do seek
304 ft, _ := GetFileType(fd)
305 if ft == FILE_TYPE_PIPE {
306 return 0, syscall.EPIPE
307 }
308 rlo, e := SetFilePointer(fd, lo, &hi, w)
309 if e != nil {
310 return 0, e
311 }
312 return int64(hi)<<32 + int64(rlo), nil
313}
314
315func Close(fd Handle) (err error) {
316 return CloseHandle(fd)
317}
318
319var (
320 Stdin = getStdHandle(STD_INPUT_HANDLE)
321 Stdout = getStdHandle(STD_OUTPUT_HANDLE)
322 Stderr = getStdHandle(STD_ERROR_HANDLE)
323)
324
325func getStdHandle(stdhandle uint32) (fd Handle) {
326 r, _ := GetStdHandle(stdhandle)
327 CloseOnExec(r)
328 return r
329}
330
331const ImplementsGetwd = true
332
333func Getwd() (wd string, err error) {
334 b := make([]uint16, 300)
335 n, e := GetCurrentDirectory(uint32(len(b)), &b[0])
336 if e != nil {
337 return "", e
338 }
339 return string(utf16.Decode(b[0:n])), nil
340}
341
342func Chdir(path string) (err error) {
343 pathp, err := UTF16PtrFromString(path)
344 if err != nil {
345 return err
346 }
347 return SetCurrentDirectory(pathp)
348}
349
350func Mkdir(path string, mode uint32) (err error) {
351 pathp, err := UTF16PtrFromString(path)
352 if err != nil {
353 return err
354 }
355 return CreateDirectory(pathp, nil)
356}
357
358func Rmdir(path string) (err error) {
359 pathp, err := UTF16PtrFromString(path)
360 if err != nil {
361 return err
362 }
363 return RemoveDirectory(pathp)
364}
365
366func Unlink(path string) (err error) {
367 pathp, err := UTF16PtrFromString(path)
368 if err != nil {
369 return err
370 }
371 return DeleteFile(pathp)
372}
373
374func Rename(oldpath, newpath string) (err error) {
375 from, err := UTF16PtrFromString(oldpath)
376 if err != nil {
377 return err
378 }
379 to, err := UTF16PtrFromString(newpath)
380 if err != nil {
381 return err
382 }
383 return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING)
384}
385
386func ComputerName() (name string, err error) {
387 var n uint32 = MAX_COMPUTERNAME_LENGTH + 1
388 b := make([]uint16, n)
389 e := GetComputerName(&b[0], &n)
390 if e != nil {
391 return "", e
392 }
393 return string(utf16.Decode(b[0:n])), nil
394}
395
396func Ftruncate(fd Handle, length int64) (err error) {
397 curoffset, e := Seek(fd, 0, 1)
398 if e != nil {
399 return e
400 }
401 defer Seek(fd, curoffset, 0)
402 _, e = Seek(fd, length, 0)
403 if e != nil {
404 return e
405 }
406 e = SetEndOfFile(fd)
407 if e != nil {
408 return e
409 }
410 return nil
411}
412
413func Gettimeofday(tv *Timeval) (err error) {
414 var ft Filetime
415 GetSystemTimeAsFileTime(&ft)
416 *tv = NsecToTimeval(ft.Nanoseconds())
417 return nil
418}
419
420func Pipe(p []Handle) (err error) {
421 if len(p) != 2 {
422 return syscall.EINVAL
423 }
424 var r, w Handle
425 e := CreatePipe(&r, &w, makeInheritSa(), 0)
426 if e != nil {
427 return e
428 }
429 p[0] = r
430 p[1] = w
431 return nil
432}
433
434func Utimes(path string, tv []Timeval) (err error) {
435 if len(tv) != 2 {
436 return syscall.EINVAL
437 }
438 pathp, e := UTF16PtrFromString(path)
439 if e != nil {
440 return e
441 }
442 h, e := CreateFile(pathp,
443 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
444 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
445 if e != nil {
446 return e
447 }
448 defer Close(h)
449 a := NsecToFiletime(tv[0].Nanoseconds())
450 w := NsecToFiletime(tv[1].Nanoseconds())
451 return SetFileTime(h, nil, &a, &w)
452}
453
454func UtimesNano(path string, ts []Timespec) (err error) {
455 if len(ts) != 2 {
456 return syscall.EINVAL
457 }
458 pathp, e := UTF16PtrFromString(path)
459 if e != nil {
460 return e
461 }
462 h, e := CreateFile(pathp,
463 FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, nil,
464 OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)
465 if e != nil {
466 return e
467 }
468 defer Close(h)
469 a := NsecToFiletime(TimespecToNsec(ts[0]))
470 w := NsecToFiletime(TimespecToNsec(ts[1]))
471 return SetFileTime(h, nil, &a, &w)
472}
473
474func Fsync(fd Handle) (err error) {
475 return FlushFileBuffers(fd)
476}
477
478func Chmod(path string, mode uint32) (err error) {
479 if mode == 0 {
480 return syscall.EINVAL
481 }
482 p, e := UTF16PtrFromString(path)
483 if e != nil {
484 return e
485 }
486 attrs, e := GetFileAttributes(p)
487 if e != nil {
488 return e
489 }
490 if mode&S_IWRITE != 0 {
491 attrs &^= FILE_ATTRIBUTE_READONLY
492 } else {
493 attrs |= FILE_ATTRIBUTE_READONLY
494 }
495 return SetFileAttributes(p, attrs)
496}
497
498func LoadGetSystemTimePreciseAsFileTime() error {
499 return procGetSystemTimePreciseAsFileTime.Find()
500}
501
502func LoadCancelIoEx() error {
503 return procCancelIoEx.Find()
504}
505
506func LoadSetFileCompletionNotificationModes() error {
507 return procSetFileCompletionNotificationModes.Find()
508}
509
510// net api calls
511
512const socket_error = uintptr(^uint32(0))
513
514//sys WSAStartup(verreq uint32, data *WSAData) (sockerr error) = ws2_32.WSAStartup
515//sys WSACleanup() (err error) [failretval==socket_error] = ws2_32.WSACleanup
516//sys WSAIoctl(s Handle, iocc uint32, inbuf *byte, cbif uint32, outbuf *byte, cbob uint32, cbbr *uint32, overlapped *Overlapped, completionRoutine uintptr) (err error) [failretval==socket_error] = ws2_32.WSAIoctl
517//sys socket(af int32, typ int32, protocol int32) (handle Handle, err error) [failretval==InvalidHandle] = ws2_32.socket
518//sys Setsockopt(s Handle, level int32, optname int32, optval *byte, optlen int32) (err error) [failretval==socket_error] = ws2_32.setsockopt
519//sys Getsockopt(s Handle, level int32, optname int32, optval *byte, optlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockopt
520//sys bind(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.bind
521//sys connect(s Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socket_error] = ws2_32.connect
522//sys getsockname(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getsockname
523//sys getpeername(s Handle, rsa *RawSockaddrAny, addrlen *int32) (err error) [failretval==socket_error] = ws2_32.getpeername
524//sys listen(s Handle, backlog int32) (err error) [failretval==socket_error] = ws2_32.listen
525//sys shutdown(s Handle, how int32) (err error) [failretval==socket_error] = ws2_32.shutdown
526//sys Closesocket(s Handle) (err error) [failretval==socket_error] = ws2_32.closesocket
527//sys AcceptEx(ls Handle, as Handle, buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, recvd *uint32, overlapped *Overlapped) (err error) = mswsock.AcceptEx
528//sys GetAcceptExSockaddrs(buf *byte, rxdatalen uint32, laddrlen uint32, raddrlen uint32, lrsa **RawSockaddrAny, lrsalen *int32, rrsa **RawSockaddrAny, rrsalen *int32) = mswsock.GetAcceptExSockaddrs
529//sys WSARecv(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecv
530//sys WSASend(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASend
531//sys WSARecvFrom(s Handle, bufs *WSABuf, bufcnt uint32, recvd *uint32, flags *uint32, from *RawSockaddrAny, fromlen *int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSARecvFrom
532//sys WSASendTo(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to *RawSockaddrAny, tolen int32, overlapped *Overlapped, croutine *byte) (err error) [failretval==socket_error] = ws2_32.WSASendTo
533//sys GetHostByName(name string) (h *Hostent, err error) [failretval==nil] = ws2_32.gethostbyname
534//sys GetServByName(name string, proto string) (s *Servent, err error) [failretval==nil] = ws2_32.getservbyname
535//sys Ntohs(netshort uint16) (u uint16) = ws2_32.ntohs
536//sys GetProtoByName(name string) (p *Protoent, err error) [failretval==nil] = ws2_32.getprotobyname
537//sys DnsQuery(name string, qtype uint16, options uint32, extra *byte, qrs **DNSRecord, pr *byte) (status error) = dnsapi.DnsQuery_W
538//sys DnsRecordListFree(rl *DNSRecord, freetype uint32) = dnsapi.DnsRecordListFree
539//sys DnsNameCompare(name1 *uint16, name2 *uint16) (same bool) = dnsapi.DnsNameCompare_W
540//sys GetAddrInfoW(nodename *uint16, servicename *uint16, hints *AddrinfoW, result **AddrinfoW) (sockerr error) = ws2_32.GetAddrInfoW
541//sys FreeAddrInfoW(addrinfo *AddrinfoW) = ws2_32.FreeAddrInfoW
542//sys GetIfEntry(pIfRow *MibIfRow) (errcode error) = iphlpapi.GetIfEntry
543//sys GetAdaptersInfo(ai *IpAdapterInfo, ol *uint32) (errcode error) = iphlpapi.GetAdaptersInfo
544//sys SetFileCompletionNotificationModes(handle Handle, flags uint8) (err error) = kernel32.SetFileCompletionNotificationModes
545//sys WSAEnumProtocols(protocols *int32, protocolBuffer *WSAProtocolInfo, bufferLength *uint32) (n int32, err error) [failretval==-1] = ws2_32.WSAEnumProtocolsW
546//sys GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) = iphlpapi.GetAdaptersAddresses
547//sys GetACP() (acp uint32) = kernel32.GetACP
548//sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar
549
550// For testing: clients can set this flag to force
551// creation of IPv6 sockets to return EAFNOSUPPORT.
552var SocketDisableIPv6 bool
553
554type RawSockaddrInet4 struct {
555 Family uint16
556 Port uint16
557 Addr [4]byte /* in_addr */
558 Zero [8]uint8
559}
560
561type RawSockaddrInet6 struct {
562 Family uint16
563 Port uint16
564 Flowinfo uint32
565 Addr [16]byte /* in6_addr */
566 Scope_id uint32
567}
568
569type RawSockaddr struct {
570 Family uint16
571 Data [14]int8
572}
573
574type RawSockaddrAny struct {
575 Addr RawSockaddr
576 Pad [96]int8
577}
578
579type Sockaddr interface {
580 sockaddr() (ptr unsafe.Pointer, len int32, err error) // lowercase; only we can define Sockaddrs
581}
582
583type SockaddrInet4 struct {
584 Port int
585 Addr [4]byte
586 raw RawSockaddrInet4
587}
588
589func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, int32, error) {
590 if sa.Port < 0 || sa.Port > 0xFFFF {
591 return nil, 0, syscall.EINVAL
592 }
593 sa.raw.Family = AF_INET
594 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
595 p[0] = byte(sa.Port >> 8)
596 p[1] = byte(sa.Port)
597 for i := 0; i < len(sa.Addr); i++ {
598 sa.raw.Addr[i] = sa.Addr[i]
599 }
600 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
601}
602
603type SockaddrInet6 struct {
604 Port int
605 ZoneId uint32
606 Addr [16]byte
607 raw RawSockaddrInet6
608}
609
610func (sa *SockaddrInet6) sockaddr() (unsafe.Pointer, int32, error) {
611 if sa.Port < 0 || sa.Port > 0xFFFF {
612 return nil, 0, syscall.EINVAL
613 }
614 sa.raw.Family = AF_INET6
615 p := (*[2]byte)(unsafe.Pointer(&sa.raw.Port))
616 p[0] = byte(sa.Port >> 8)
617 p[1] = byte(sa.Port)
618 sa.raw.Scope_id = sa.ZoneId
619 for i := 0; i < len(sa.Addr); i++ {
620 sa.raw.Addr[i] = sa.Addr[i]
621 }
622 return unsafe.Pointer(&sa.raw), int32(unsafe.Sizeof(sa.raw)), nil
623}
624
625type SockaddrUnix struct {
626 Name string
627}
628
629func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, int32, error) {
630 // TODO(brainman): implement SockaddrUnix.sockaddr()
631 return nil, 0, syscall.EWINDOWS
632}
633
634func (rsa *RawSockaddrAny) Sockaddr() (Sockaddr, error) {
635 switch rsa.Addr.Family {
636 case AF_UNIX:
637 return nil, syscall.EWINDOWS
638
639 case AF_INET:
640 pp := (*RawSockaddrInet4)(unsafe.Pointer(rsa))
641 sa := new(SockaddrInet4)
642 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
643 sa.Port = int(p[0])<<8 + int(p[1])
644 for i := 0; i < len(sa.Addr); i++ {
645 sa.Addr[i] = pp.Addr[i]
646 }
647 return sa, nil
648
649 case AF_INET6:
650 pp := (*RawSockaddrInet6)(unsafe.Pointer(rsa))
651 sa := new(SockaddrInet6)
652 p := (*[2]byte)(unsafe.Pointer(&pp.Port))
653 sa.Port = int(p[0])<<8 + int(p[1])
654 sa.ZoneId = pp.Scope_id
655 for i := 0; i < len(sa.Addr); i++ {
656 sa.Addr[i] = pp.Addr[i]
657 }
658 return sa, nil
659 }
660 return nil, syscall.EAFNOSUPPORT
661}
662
663func Socket(domain, typ, proto int) (fd Handle, err error) {
664 if domain == AF_INET6 && SocketDisableIPv6 {
665 return InvalidHandle, syscall.EAFNOSUPPORT
666 }
667 return socket(int32(domain), int32(typ), int32(proto))
668}
669
670func SetsockoptInt(fd Handle, level, opt int, value int) (err error) {
671 v := int32(value)
672 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&v)), int32(unsafe.Sizeof(v)))
673}
674
675func Bind(fd Handle, sa Sockaddr) (err error) {
676 ptr, n, err := sa.sockaddr()
677 if err != nil {
678 return err
679 }
680 return bind(fd, ptr, n)
681}
682
683func Connect(fd Handle, sa Sockaddr) (err error) {
684 ptr, n, err := sa.sockaddr()
685 if err != nil {
686 return err
687 }
688 return connect(fd, ptr, n)
689}
690
691func Getsockname(fd Handle) (sa Sockaddr, err error) {
692 var rsa RawSockaddrAny
693 l := int32(unsafe.Sizeof(rsa))
694 if err = getsockname(fd, &rsa, &l); err != nil {
695 return
696 }
697 return rsa.Sockaddr()
698}
699
700func Getpeername(fd Handle) (sa Sockaddr, err error) {
701 var rsa RawSockaddrAny
702 l := int32(unsafe.Sizeof(rsa))
703 if err = getpeername(fd, &rsa, &l); err != nil {
704 return
705 }
706 return rsa.Sockaddr()
707}
708
709func Listen(s Handle, n int) (err error) {
710 return listen(s, int32(n))
711}
712
713func Shutdown(fd Handle, how int) (err error) {
714 return shutdown(fd, int32(how))
715}
716
717func WSASendto(s Handle, bufs *WSABuf, bufcnt uint32, sent *uint32, flags uint32, to Sockaddr, overlapped *Overlapped, croutine *byte) (err error) {
718 rsa, l, err := to.sockaddr()
719 if err != nil {
720 return err
721 }
722 return WSASendTo(s, bufs, bufcnt, sent, flags, (*RawSockaddrAny)(unsafe.Pointer(rsa)), l, overlapped, croutine)
723}
724
725func LoadGetAddrInfo() error {
726 return procGetAddrInfoW.Find()
727}
728
729var connectExFunc struct {
730 once sync.Once
731 addr uintptr
732 err error
733}
734
735func LoadConnectEx() error {
736 connectExFunc.once.Do(func() {
737 var s Handle
738 s, connectExFunc.err = Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
739 if connectExFunc.err != nil {
740 return
741 }
742 defer CloseHandle(s)
743 var n uint32
744 connectExFunc.err = WSAIoctl(s,
745 SIO_GET_EXTENSION_FUNCTION_POINTER,
746 (*byte)(unsafe.Pointer(&WSAID_CONNECTEX)),
747 uint32(unsafe.Sizeof(WSAID_CONNECTEX)),
748 (*byte)(unsafe.Pointer(&connectExFunc.addr)),
749 uint32(unsafe.Sizeof(connectExFunc.addr)),
750 &n, nil, 0)
751 })
752 return connectExFunc.err
753}
754
755func connectEx(s Handle, name unsafe.Pointer, namelen int32, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) (err error) {
756 r1, _, e1 := syscall.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)
757 if r1 == 0 {
758 if e1 != 0 {
759 err = error(e1)
760 } else {
761 err = syscall.EINVAL
762 }
763 }
764 return
765}
766
767func ConnectEx(fd Handle, sa Sockaddr, sendBuf *byte, sendDataLen uint32, bytesSent *uint32, overlapped *Overlapped) error {
768 err := LoadConnectEx()
769 if err != nil {
770 return errorspkg.New("failed to find ConnectEx: " + err.Error())
771 }
772 ptr, n, err := sa.sockaddr()
773 if err != nil {
774 return err
775 }
776 return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
777}
778
779// Invented structures to support what package os expects.
780type Rusage struct {
781 CreationTime Filetime
782 ExitTime Filetime
783 KernelTime Filetime
784 UserTime Filetime
785}
786
787type WaitStatus struct {
788 ExitCode uint32
789}
790
791func (w WaitStatus) Exited() bool { return true }
792
793func (w WaitStatus) ExitStatus() int { return int(w.ExitCode) }
794
795func (w WaitStatus) Signal() Signal { return -1 }
796
797func (w WaitStatus) CoreDump() bool { return false }
798
799func (w WaitStatus) Stopped() bool { return false }
800
801func (w WaitStatus) Continued() bool { return false }
802
803func (w WaitStatus) StopSignal() Signal { return -1 }
804
805func (w WaitStatus) Signaled() bool { return false }
806
807func (w WaitStatus) TrapCause() int { return -1 }
808
809// Timespec is an invented structure on Windows, but here for
810// consistency with the corresponding package for other operating systems.
811type Timespec struct {
812 Sec int64
813 Nsec int64
814}
815
816func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
817
818func NsecToTimespec(nsec int64) (ts Timespec) {
819 ts.Sec = nsec / 1e9
820 ts.Nsec = nsec % 1e9
821 return
822}
823
824// TODO(brainman): fix all needed for net
825
826func Accept(fd Handle) (nfd Handle, sa Sockaddr, err error) { return 0, nil, syscall.EWINDOWS }
827func Recvfrom(fd Handle, p []byte, flags int) (n int, from Sockaddr, err error) {
828 return 0, nil, syscall.EWINDOWS
829}
830func Sendto(fd Handle, p []byte, flags int, to Sockaddr) (err error) { return syscall.EWINDOWS }
831func SetsockoptTimeval(fd Handle, level, opt int, tv *Timeval) (err error) { return syscall.EWINDOWS }
832
833// The Linger struct is wrong but we only noticed after Go 1.
834// sysLinger is the real system call structure.
835
836// BUG(brainman): The definition of Linger is not appropriate for direct use
837// with Setsockopt and Getsockopt.
838// Use SetsockoptLinger instead.
839
840type Linger struct {
841 Onoff int32
842 Linger int32
843}
844
845type sysLinger struct {
846 Onoff uint16
847 Linger uint16
848}
849
850type IPMreq struct {
851 Multiaddr [4]byte /* in_addr */
852 Interface [4]byte /* in_addr */
853}
854
855type IPv6Mreq struct {
856 Multiaddr [16]byte /* in6_addr */
857 Interface uint32
858}
859
860func GetsockoptInt(fd Handle, level, opt int) (int, error) { return -1, syscall.EWINDOWS }
861
862func SetsockoptLinger(fd Handle, level, opt int, l *Linger) (err error) {
863 sys := sysLinger{Onoff: uint16(l.Onoff), Linger: uint16(l.Linger)}
864 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&sys)), int32(unsafe.Sizeof(sys)))
865}
866
867func SetsockoptInet4Addr(fd Handle, level, opt int, value [4]byte) (err error) {
868 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(&value[0])), 4)
869}
870func SetsockoptIPMreq(fd Handle, level, opt int, mreq *IPMreq) (err error) {
871 return Setsockopt(fd, int32(level), int32(opt), (*byte)(unsafe.Pointer(mreq)), int32(unsafe.Sizeof(*mreq)))
872}
873func SetsockoptIPv6Mreq(fd Handle, level, opt int, mreq *IPv6Mreq) (err error) {
874 return syscall.EWINDOWS
875}
876
877func Getpid() (pid int) { return int(getCurrentProcessId()) }
878
879func FindFirstFile(name *uint16, data *Win32finddata) (handle Handle, err error) {
880 // NOTE(rsc): The Win32finddata struct is wrong for the system call:
881 // the two paths are each one uint16 short. Use the correct struct,
882 // a win32finddata1, and then copy the results out.
883 // There is no loss of expressivity here, because the final
884 // uint16, if it is used, is supposed to be a NUL, and Go doesn't need that.
885 // For Go 1.1, we might avoid the allocation of win32finddata1 here
886 // by adding a final Bug [2]uint16 field to the struct and then
887 // adjusting the fields in the result directly.
888 var data1 win32finddata1
889 handle, err = findFirstFile1(name, &data1)
890 if err == nil {
891 copyFindData(data, &data1)
892 }
893 return
894}
895
896func FindNextFile(handle Handle, data *Win32finddata) (err error) {
897 var data1 win32finddata1
898 err = findNextFile1(handle, &data1)
899 if err == nil {
900 copyFindData(data, &data1)
901 }
902 return
903}
904
905func getProcessEntry(pid int) (*ProcessEntry32, error) {
906 snapshot, err := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
907 if err != nil {
908 return nil, err
909 }
910 defer CloseHandle(snapshot)
911 var procEntry ProcessEntry32
912 procEntry.Size = uint32(unsafe.Sizeof(procEntry))
913 if err = Process32First(snapshot, &procEntry); err != nil {
914 return nil, err
915 }
916 for {
917 if procEntry.ProcessID == uint32(pid) {
918 return &procEntry, nil
919 }
920 err = Process32Next(snapshot, &procEntry)
921 if err != nil {
922 return nil, err
923 }
924 }
925}
926
927func Getppid() (ppid int) {
928 pe, err := getProcessEntry(Getpid())
929 if err != nil {
930 return -1
931 }
932 return int(pe.ParentProcessID)
933}
934
935// TODO(brainman): fix all needed for os
936func Fchdir(fd Handle) (err error) { return syscall.EWINDOWS }
937func Link(oldpath, newpath string) (err error) { return syscall.EWINDOWS }
938func Symlink(path, link string) (err error) { return syscall.EWINDOWS }
939
940func Fchmod(fd Handle, mode uint32) (err error) { return syscall.EWINDOWS }
941func Chown(path string, uid int, gid int) (err error) { return syscall.EWINDOWS }
942func Lchown(path string, uid int, gid int) (err error) { return syscall.EWINDOWS }
943func Fchown(fd Handle, uid int, gid int) (err error) { return syscall.EWINDOWS }
944
945func Getuid() (uid int) { return -1 }
946func Geteuid() (euid int) { return -1 }
947func Getgid() (gid int) { return -1 }
948func Getegid() (egid int) { return -1 }
949func Getgroups() (gids []int, err error) { return nil, syscall.EWINDOWS }
950
951type Signal int
952
953func (s Signal) Signal() {}
954
955func (s Signal) String() string {
956 if 0 <= s && int(s) < len(signals) {
957 str := signals[s]
958 if str != "" {
959 return str
960 }
961 }
962 return "signal " + itoa(int(s))
963}
964
965func LoadCreateSymbolicLink() error {
966 return procCreateSymbolicLinkW.Find()
967}
968
969// Readlink returns the destination of the named symbolic link.
970func Readlink(path string, buf []byte) (n int, err error) {
971 fd, err := CreateFile(StringToUTF16Ptr(path), GENERIC_READ, 0, nil, OPEN_EXISTING,
972 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 0)
973 if err != nil {
974 return -1, err
975 }
976 defer CloseHandle(fd)
977
978 rdbbuf := make([]byte, MAXIMUM_REPARSE_DATA_BUFFER_SIZE)
979 var bytesReturned uint32
980 err = DeviceIoControl(fd, FSCTL_GET_REPARSE_POINT, nil, 0, &rdbbuf[0], uint32(len(rdbbuf)), &bytesReturned, nil)
981 if err != nil {
982 return -1, err
983 }
984
985 rdb := (*reparseDataBuffer)(unsafe.Pointer(&rdbbuf[0]))
986 var s string
987 switch rdb.ReparseTag {
988 case IO_REPARSE_TAG_SYMLINK:
989 data := (*symbolicLinkReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
990 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
991 s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2])
992 case IO_REPARSE_TAG_MOUNT_POINT:
993 data := (*mountPointReparseBuffer)(unsafe.Pointer(&rdb.reparseBuffer))
994 p := (*[0xffff]uint16)(unsafe.Pointer(&data.PathBuffer[0]))
995 s = UTF16ToString(p[data.PrintNameOffset/2 : (data.PrintNameLength-data.PrintNameOffset)/2])
996 default:
997 // the path is not a symlink or junction but another type of reparse
998 // point
999 return -1, syscall.ENOENT
1000 }
1001 n = copy(buf, []byte(s))
1002
1003 return n, nil
1004}