1// Copyright 2012 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 5package windows_test 6 7import ( 8 "fmt" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "runtime" 13 "strings" 14 "syscall" 15 "testing" 16 17 "golang.org/x/sys/windows" 18) 19 20func TestWin32finddata(t *testing.T) { 21 dir, err := ioutil.TempDir("", "go-build") 22 if err != nil { 23 t.Fatalf("failed to create temp directory: %v", err) 24 } 25 defer os.RemoveAll(dir) 26 27 path := filepath.Join(dir, "long_name.and_extension") 28 f, err := os.Create(path) 29 if err != nil { 30 t.Fatalf("failed to create %v: %v", path, err) 31 } 32 f.Close() 33 34 type X struct { 35 fd windows.Win32finddata 36 got byte 37 pad [10]byte // to protect ourselves 38 39 } 40 var want byte = 2 // it is unlikely to have this character in the filename 41 x := X{got: want} 42 43 pathp, _ := windows.UTF16PtrFromString(path) 44 h, err := windows.FindFirstFile(pathp, &(x.fd)) 45 if err != nil { 46 t.Fatalf("FindFirstFile failed: %v", err) 47 } 48 err = windows.FindClose(h) 49 if err != nil { 50 t.Fatalf("FindClose failed: %v", err) 51 } 52 53 if x.got != want { 54 t.Fatalf("memory corruption: want=%d got=%d", want, x.got) 55 } 56} 57 58func TestFormatMessage(t *testing.T) { 59 dll := windows.MustLoadDLL("netevent.dll") 60 61 const TITLE_SC_MESSAGE_BOX uint32 = 0xC0001B75 62 const flags uint32 = syscall.FORMAT_MESSAGE_FROM_HMODULE | syscall.FORMAT_MESSAGE_ARGUMENT_ARRAY | syscall.FORMAT_MESSAGE_IGNORE_INSERTS 63 buf := make([]uint16, 300) 64 _, err := windows.FormatMessage(flags, uintptr(dll.Handle), TITLE_SC_MESSAGE_BOX, 0, buf, nil) 65 if err != nil { 66 t.Fatalf("FormatMessage for handle=%x and errno=%x failed: %v", dll.Handle, TITLE_SC_MESSAGE_BOX, err) 67 } 68} 69 70func abort(funcname string, err error) { 71 panic(funcname + " failed: " + err.Error()) 72} 73 74func ExampleLoadLibrary() { 75 h, err := windows.LoadLibrary("kernel32.dll") 76 if err != nil { 77 abort("LoadLibrary", err) 78 } 79 defer windows.FreeLibrary(h) 80 proc, err := windows.GetProcAddress(h, "GetVersion") 81 if err != nil { 82 abort("GetProcAddress", err) 83 } 84 r, _, _ := syscall.Syscall(uintptr(proc), 0, 0, 0, 0) 85 major := byte(r) 86 minor := uint8(r >> 8) 87 build := uint16(r >> 16) 88 print("windows version ", major, ".", minor, " (Build ", build, ")\n") 89} 90 91func TestTOKEN_ALL_ACCESS(t *testing.T) { 92 if windows.TOKEN_ALL_ACCESS != 0xF01FF { 93 t.Errorf("TOKEN_ALL_ACCESS = %x, want 0xF01FF", windows.TOKEN_ALL_ACCESS) 94 } 95} 96 97func TestCreateWellKnownSid(t *testing.T) { 98 sid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid) 99 if err != nil { 100 t.Fatalf("Unable to create well known sid for administrators: %v", err) 101 } 102 if got, want := sid.String(), "S-1-5-32-544"; got != want { 103 t.Fatalf("Builtin Administrators SID = %s, want %s", got, want) 104 } 105} 106 107func TestPseudoTokens(t *testing.T) { 108 version, err := windows.GetVersion() 109 if err != nil { 110 t.Fatal(err) 111 } 112 if ((version&0xffff)>>8)|((version&0xff)<<8) < 0x0602 { 113 return 114 } 115 116 realProcessToken, err := windows.OpenCurrentProcessToken() 117 if err != nil { 118 t.Fatal(err) 119 } 120 defer realProcessToken.Close() 121 realProcessUser, err := realProcessToken.GetTokenUser() 122 if err != nil { 123 t.Fatal(err) 124 } 125 126 pseudoProcessToken := windows.GetCurrentProcessToken() 127 pseudoProcessUser, err := pseudoProcessToken.GetTokenUser() 128 if err != nil { 129 t.Fatal(err) 130 } 131 if !windows.EqualSid(realProcessUser.User.Sid, pseudoProcessUser.User.Sid) { 132 t.Fatal("The real process token does not have the same as the pseudo process token") 133 } 134 135 runtime.LockOSThread() 136 defer runtime.UnlockOSThread() 137 138 err = windows.RevertToSelf() 139 if err != nil { 140 t.Fatal(err) 141 } 142 143 pseudoThreadToken := windows.GetCurrentThreadToken() 144 _, err = pseudoThreadToken.GetTokenUser() 145 if err != windows.ERROR_NO_TOKEN { 146 t.Fatal("Expected an empty thread token") 147 } 148 pseudoThreadEffectiveToken := windows.GetCurrentThreadEffectiveToken() 149 pseudoThreadEffectiveUser, err := pseudoThreadEffectiveToken.GetTokenUser() 150 if err != nil { 151 t.Fatal(nil) 152 } 153 if !windows.EqualSid(realProcessUser.User.Sid, pseudoThreadEffectiveUser.User.Sid) { 154 t.Fatal("The real process token does not have the same as the pseudo thread effective token, even though we aren't impersonating") 155 } 156 157 err = windows.ImpersonateSelf(windows.SecurityImpersonation) 158 if err != nil { 159 t.Fatal(err) 160 } 161 defer windows.RevertToSelf() 162 pseudoThreadUser, err := pseudoThreadToken.GetTokenUser() 163 if err != nil { 164 t.Fatal(err) 165 } 166 if !windows.EqualSid(realProcessUser.User.Sid, pseudoThreadUser.User.Sid) { 167 t.Fatal("The real process token does not have the same as the pseudo thread token after impersonating self") 168 } 169} 170 171func TestGUID(t *testing.T) { 172 guid, err := windows.GenerateGUID() 173 if err != nil { 174 t.Fatal(err) 175 } 176 if guid.Data1 == 0 && guid.Data2 == 0 && guid.Data3 == 0 && guid.Data4 == [8]byte{} { 177 t.Fatal("Got an all zero GUID, which is overwhelmingly unlikely") 178 } 179 want := fmt.Sprintf("{%08X-%04X-%04X-%04X-%012X}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[:2], guid.Data4[2:]) 180 got := guid.String() 181 if got != want { 182 t.Fatalf("String = %q; want %q", got, want) 183 } 184 guid2, err := windows.GUIDFromString(got) 185 if err != nil { 186 t.Fatal(err) 187 } 188 if guid2 != guid { 189 t.Fatalf("Did not parse string back to original GUID = %q; want %q", guid2, guid) 190 } 191 _, err = windows.GUIDFromString("not-a-real-guid") 192 if err != syscall.Errno(windows.CO_E_CLASSSTRING) { 193 t.Fatalf("Bad GUID string error = %v; want CO_E_CLASSSTRING", err) 194 } 195} 196 197func TestKnownFolderPath(t *testing.T) { 198 token, err := windows.OpenCurrentProcessToken() 199 if err != nil { 200 t.Fatal(err) 201 } 202 defer token.Close() 203 profileDir, err := token.GetUserProfileDirectory() 204 if err != nil { 205 t.Fatal(err) 206 } 207 want := filepath.Join(profileDir, "Desktop") 208 got, err := windows.KnownFolderPath(windows.FOLDERID_Desktop, windows.KF_FLAG_DEFAULT) 209 if err != nil { 210 t.Fatal(err) 211 } 212 if want != got { 213 t.Fatalf("Path = %q; want %q", got, want) 214 } 215} 216 217func TestRtlGetVersion(t *testing.T) { 218 version := windows.RtlGetVersion() 219 major, minor, build := windows.RtlGetNtVersionNumbers() 220 // Go is not explictly added to the application compatibility database, so 221 // these two functions should return the same thing. 222 if version.MajorVersion != major || version.MinorVersion != minor || version.BuildNumber != build { 223 t.Fatalf("%d.%d.%d != %d.%d.%d", version.MajorVersion, version.MinorVersion, version.BuildNumber, major, minor, build) 224 } 225} 226 227func TestGetNamedSecurityInfo(t *testing.T) { 228 path, err := windows.GetSystemDirectory() 229 if err != nil { 230 t.Fatal(err) 231 } 232 sd, err := windows.GetNamedSecurityInfo(path, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION) 233 if err != nil { 234 t.Fatal(err) 235 } 236 if !sd.IsValid() { 237 t.Fatal("Invalid security descriptor") 238 } 239 sdOwner, _, err := sd.Owner() 240 if err != nil { 241 t.Fatal(err) 242 } 243 if !sdOwner.IsValid() { 244 t.Fatal("Invalid security descriptor owner") 245 } 246} 247 248func TestGetSecurityInfo(t *testing.T) { 249 sd, err := windows.GetSecurityInfo(windows.CurrentProcess(), windows.SE_KERNEL_OBJECT, windows.DACL_SECURITY_INFORMATION) 250 if err != nil { 251 t.Fatal(err) 252 } 253 if !sd.IsValid() { 254 t.Fatal("Invalid security descriptor") 255 } 256 sdStr := sd.String() 257 if !strings.HasPrefix(sdStr, "D:(A;") { 258 t.Fatalf("DACL = %q; want D:(A;...", sdStr) 259 } 260} 261 262func TestSddlConversion(t *testing.T) { 263 sd, err := windows.SecurityDescriptorFromString("O:BA") 264 if err != nil { 265 t.Fatal(err) 266 } 267 if !sd.IsValid() { 268 t.Fatal("Invalid security descriptor") 269 } 270 sdOwner, _, err := sd.Owner() 271 if err != nil { 272 t.Fatal(err) 273 } 274 if !sdOwner.IsValid() { 275 t.Fatal("Invalid security descriptor owner") 276 } 277 if !sdOwner.IsWellKnown(windows.WinBuiltinAdministratorsSid) { 278 t.Fatalf("Owner = %q; want S-1-5-32-544", sdOwner) 279 } 280} 281 282func TestBuildSecurityDescriptor(t *testing.T) { 283 const want = "O:SYD:(A;;GA;;;BA)" 284 285 adminSid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid) 286 if err != nil { 287 t.Fatal(err) 288 } 289 systemSid, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid) 290 if err != nil { 291 t.Fatal(err) 292 } 293 294 access := []windows.EXPLICIT_ACCESS{{ 295 AccessPermissions: windows.GENERIC_ALL, 296 AccessMode: windows.GRANT_ACCESS, 297 Trustee: windows.TRUSTEE{ 298 TrusteeForm: windows.TRUSTEE_IS_SID, 299 TrusteeType: windows.TRUSTEE_IS_GROUP, 300 TrusteeValue: windows.TrusteeValueFromSID(adminSid), 301 }, 302 }} 303 owner := &windows.TRUSTEE{ 304 TrusteeForm: windows.TRUSTEE_IS_SID, 305 TrusteeType: windows.TRUSTEE_IS_USER, 306 TrusteeValue: windows.TrusteeValueFromSID(systemSid), 307 } 308 309 sd, err := windows.BuildSecurityDescriptor(owner, nil, access, nil, nil) 310 if err != nil { 311 t.Fatal(err) 312 } 313 sd, err = sd.ToAbsolute() 314 if err != nil { 315 t.Fatal(err) 316 } 317 err = sd.SetSACL(nil, false, false) 318 if err != nil { 319 t.Fatal(err) 320 } 321 if got := sd.String(); got != want { 322 t.Fatalf("SD = %q; want %q", got, want) 323 } 324 sd, err = sd.ToSelfRelative() 325 if err != nil { 326 t.Fatal(err) 327 } 328 if got := sd.String(); got != want { 329 t.Fatalf("SD = %q; want %q", got, want) 330 } 331 332 sd, err = windows.NewSecurityDescriptor() 333 if err != nil { 334 t.Fatal(err) 335 } 336 acl, err := windows.ACLFromEntries(access, nil) 337 if err != nil { 338 t.Fatal(err) 339 } 340 err = sd.SetDACL(acl, true, false) 341 if err != nil { 342 t.Fatal(err) 343 } 344 err = sd.SetOwner(systemSid, false) 345 if err != nil { 346 t.Fatal(err) 347 } 348 if got := sd.String(); got != want { 349 t.Fatalf("SD = %q; want %q", got, want) 350 } 351 sd, err = sd.ToSelfRelative() 352 if err != nil { 353 t.Fatal(err) 354 } 355 if got := sd.String(); got != want { 356 t.Fatalf("SD = %q; want %q", got, want) 357 } 358} 359 360func TestGetDiskFreeSpaceEx(t *testing.T) { 361 cwd, err := windows.UTF16PtrFromString(".") 362 if err != nil { 363 t.Fatalf(`failed to call UTF16PtrFromString("."): %v`, err) 364 } 365 var freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes uint64 366 if err := windows.GetDiskFreeSpaceEx(cwd, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes); err != nil { 367 t.Fatalf("failed to call GetDiskFreeSpaceEx: %v", err) 368 } 369 370 if freeBytesAvailableToCaller == 0 { 371 t.Errorf("freeBytesAvailableToCaller: got 0; want > 0") 372 } 373 if totalNumberOfBytes == 0 { 374 t.Errorf("totalNumberOfBytes: got 0; want > 0") 375 } 376 if totalNumberOfFreeBytes == 0 { 377 t.Errorf("totalNumberOfFreeBytes: got 0; want > 0") 378 } 379} 380