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