1// 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// Fork, exec, wait, etc. 6 7package windows 8 9import ( 10 errorspkg "errors" 11 "unsafe" 12) 13 14// EscapeArg rewrites command line argument s as prescribed 15// in http://msdn.microsoft.com/en-us/library/ms880421. 16// This function returns "" (2 double quotes) if s is empty. 17// Alternatively, these transformations are done: 18// - every back slash (\) is doubled, but only if immediately 19// followed by double quote ("); 20// - every double quote (") is escaped by back slash (\); 21// - finally, s is wrapped with double quotes (arg -> "arg"), 22// but only if there is space or tab inside s. 23func EscapeArg(s string) string { 24 if len(s) == 0 { 25 return "\"\"" 26 } 27 n := len(s) 28 hasSpace := false 29 for i := 0; i < len(s); i++ { 30 switch s[i] { 31 case '"', '\\': 32 n++ 33 case ' ', '\t': 34 hasSpace = true 35 } 36 } 37 if hasSpace { 38 n += 2 39 } 40 if n == len(s) { 41 return s 42 } 43 44 qs := make([]byte, n) 45 j := 0 46 if hasSpace { 47 qs[j] = '"' 48 j++ 49 } 50 slashes := 0 51 for i := 0; i < len(s); i++ { 52 switch s[i] { 53 default: 54 slashes = 0 55 qs[j] = s[i] 56 case '\\': 57 slashes++ 58 qs[j] = s[i] 59 case '"': 60 for ; slashes > 0; slashes-- { 61 qs[j] = '\\' 62 j++ 63 } 64 qs[j] = '\\' 65 j++ 66 qs[j] = s[i] 67 } 68 j++ 69 } 70 if hasSpace { 71 for ; slashes > 0; slashes-- { 72 qs[j] = '\\' 73 j++ 74 } 75 qs[j] = '"' 76 j++ 77 } 78 return string(qs[:j]) 79} 80 81func CloseOnExec(fd Handle) { 82 SetHandleInformation(Handle(fd), HANDLE_FLAG_INHERIT, 0) 83} 84 85// FullPath retrieves the full path of the specified file. 86func FullPath(name string) (path string, err error) { 87 p, err := UTF16PtrFromString(name) 88 if err != nil { 89 return "", err 90 } 91 n := uint32(100) 92 for { 93 buf := make([]uint16, n) 94 n, err = GetFullPathName(p, uint32(len(buf)), &buf[0], nil) 95 if err != nil { 96 return "", err 97 } 98 if n <= uint32(len(buf)) { 99 return UTF16ToString(buf[:n]), nil 100 } 101 } 102} 103 104// NewProcThreadAttributeList allocates a new ProcThreadAttributeList, with the requested maximum number of attributes. 105func NewProcThreadAttributeList(maxAttrCount uint32) (*ProcThreadAttributeList, error) { 106 var size uintptr 107 err := initializeProcThreadAttributeList(nil, maxAttrCount, 0, &size) 108 if err != ERROR_INSUFFICIENT_BUFFER { 109 if err == nil { 110 return nil, errorspkg.New("unable to query buffer size from InitializeProcThreadAttributeList") 111 } 112 return nil, err 113 } 114 const psize = unsafe.Sizeof(uintptr(0)) 115 // size is guaranteed to be ≥1 by InitializeProcThreadAttributeList. 116 al := (*ProcThreadAttributeList)(unsafe.Pointer(&make([]unsafe.Pointer, (size+psize-1)/psize)[0])) 117 err = initializeProcThreadAttributeList(al, maxAttrCount, 0, &size) 118 if err != nil { 119 return nil, err 120 } 121 return al, err 122} 123 124// Update modifies the ProcThreadAttributeList using UpdateProcThreadAttribute. 125func (al *ProcThreadAttributeList) Update(attribute uintptr, flags uint32, value unsafe.Pointer, size uintptr, prevValue unsafe.Pointer, returnedSize *uintptr) error { 126 return updateProcThreadAttribute(al, flags, attribute, value, size, prevValue, returnedSize) 127} 128 129// Delete frees ProcThreadAttributeList's resources. 130func (al *ProcThreadAttributeList) Delete() { 131 deleteProcThreadAttributeList(al) 132} 133