1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file contains unit tests for the RestrictedToken.
7 #define _ATL_NO_EXCEPTIONS
9 #include <atlsecurity.h>
12 #include "base/win/scoped_handle.h"
13 #include "sandbox/win/src/restricted_token.h"
14 #include "sandbox/win/src/sid.h"
15 #include "testing/gtest/include/gtest/gtest.h"
19 // Tests the initializatioin with an invalid token handle.
20 TEST(RestrictedTokenTest
, InvalidHandle
) {
21 RestrictedToken token
;
22 ASSERT_EQ(ERROR_INVALID_HANDLE
, token
.Init(reinterpret_cast<HANDLE
>(0x5555)));
25 // Tests the initialization with NULL as parameter.
26 TEST(RestrictedTokenTest
, DefaultInit
) {
27 // Get the current process token.
28 HANDLE token_handle
= INVALID_HANDLE_VALUE
;
29 ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS
,
32 ASSERT_NE(INVALID_HANDLE_VALUE
, token_handle
);
34 ATL::CAccessToken access_token
;
35 access_token
.Attach(token_handle
);
37 // Create the token using the current token.
38 RestrictedToken token_default
;
39 ASSERT_EQ(ERROR_SUCCESS
, token_default
.Init(NULL
));
41 // Get the handle to the restricted token.
43 base::win::ScopedHandle restricted_token_handle
;
44 ASSERT_EQ(ERROR_SUCCESS
,
45 token_default
.GetRestrictedToken(&restricted_token_handle
));
47 ATL::CAccessToken restricted_token
;
48 restricted_token
.Attach(restricted_token_handle
.Take());
50 ATL::CSid sid_user_restricted
;
51 ATL::CSid sid_user_default
;
52 ATL::CSid sid_owner_restricted
;
53 ATL::CSid sid_owner_default
;
54 ASSERT_TRUE(restricted_token
.GetUser(&sid_user_restricted
));
55 ASSERT_TRUE(access_token
.GetUser(&sid_user_default
));
56 ASSERT_TRUE(restricted_token
.GetOwner(&sid_owner_restricted
));
57 ASSERT_TRUE(access_token
.GetOwner(&sid_owner_default
));
59 // Check if both token have the same owner and user.
60 ASSERT_EQ(sid_user_restricted
, sid_user_default
);
61 ASSERT_EQ(sid_owner_restricted
, sid_owner_default
);
64 // Tests the initialization with a custom token as parameter.
65 TEST(RestrictedTokenTest
, CustomInit
) {
66 // Get the current process token.
67 HANDLE token_handle
= INVALID_HANDLE_VALUE
;
68 ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS
,
71 ASSERT_NE(INVALID_HANDLE_VALUE
, token_handle
);
73 ATL::CAccessToken access_token
;
74 access_token
.Attach(token_handle
);
76 // Change the primary group.
77 access_token
.SetPrimaryGroup(ATL::Sids::World());
79 // Create the token using the current token.
80 RestrictedToken token
;
81 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(access_token
.GetHandle()));
83 // Get the handle to the restricted token.
85 base::win::ScopedHandle restricted_token_handle
;
86 ASSERT_EQ(ERROR_SUCCESS
,
87 token
.GetRestrictedToken(&restricted_token_handle
));
89 ATL::CAccessToken restricted_token
;
90 restricted_token
.Attach(restricted_token_handle
.Take());
92 ATL::CSid sid_restricted
;
93 ATL::CSid sid_default
;
94 ASSERT_TRUE(restricted_token
.GetPrimaryGroup(&sid_restricted
));
95 ASSERT_TRUE(access_token
.GetPrimaryGroup(&sid_default
));
97 // Check if both token have the same owner.
98 ASSERT_EQ(sid_restricted
, sid_default
);
101 // Verifies that the token created by the object are valid.
102 TEST(RestrictedTokenTest
, ResultToken
) {
103 RestrictedToken token
;
104 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
106 ASSERT_EQ(ERROR_SUCCESS
,
107 token
.AddRestrictingSid(ATL::Sids::World().GetPSID()));
109 base::win::ScopedHandle restricted_token
;
110 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&restricted_token
));
112 ASSERT_TRUE(::IsTokenRestricted(restricted_token
.Get()));
116 ASSERT_TRUE(::GetTokenInformation(restricted_token
.Get(),
122 ASSERT_EQ(type
, TokenPrimary
);
124 base::win::ScopedHandle impersonation_token
;
125 ASSERT_EQ(ERROR_SUCCESS
,
126 token
.GetRestrictedTokenForImpersonation(&impersonation_token
));
128 ASSERT_TRUE(::IsTokenRestricted(impersonation_token
.Get()));
130 ASSERT_TRUE(::GetTokenInformation(impersonation_token
.Get(),
136 ASSERT_EQ(type
, TokenImpersonation
);
139 // Verifies that the token created has "Restricted" in its default dacl.
140 TEST(RestrictedTokenTest
, DefaultDacl
) {
141 RestrictedToken token
;
142 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
144 ASSERT_EQ(ERROR_SUCCESS
,
145 token
.AddRestrictingSid(ATL::Sids::World().GetPSID()));
147 base::win::ScopedHandle handle
;
148 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&handle
));
150 ATL::CAccessToken restricted_token
;
151 restricted_token
.Attach(handle
.Take());
154 ASSERT_TRUE(restricted_token
.GetDefaultDacl(&dacl
));
156 bool restricted_found
= false;
158 unsigned int ace_count
= dacl
.GetAceCount();
159 for (unsigned int i
= 0; i
< ace_count
; ++i
) {
161 ACCESS_MASK mask
= 0;
162 dacl
.GetAclEntry(i
, &sid
, &mask
);
163 if (sid
== ATL::Sids::RestrictedCode() && mask
== GENERIC_ALL
) {
164 restricted_found
= true;
169 ASSERT_TRUE(restricted_found
);
172 // Tests the method "AddSidForDenyOnly".
173 TEST(RestrictedTokenTest
, DenySid
) {
174 RestrictedToken token
;
175 base::win::ScopedHandle token_handle
;
177 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
178 ASSERT_EQ(ERROR_SUCCESS
, token
.AddSidForDenyOnly(Sid(WinWorldSid
)));
179 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
181 ATL::CAccessToken restricted_token
;
182 restricted_token
.Attach(token_handle
.Take());
184 ATL::CTokenGroups groups
;
185 ASSERT_TRUE(restricted_token
.GetGroups(&groups
));
187 ATL::CSid::CSidArray sids
;
188 ATL::CAtlArray
<DWORD
> attributes
;
189 groups
.GetSidsAndAttributes(&sids
, &attributes
);
191 for (unsigned int i
= 0; i
< sids
.GetCount(); i
++) {
192 if (ATL::Sids::World() == sids
[i
]) {
193 ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY
,
194 attributes
[i
] & SE_GROUP_USE_FOR_DENY_ONLY
);
199 // Tests the method "AddAllSidsForDenyOnly".
200 TEST(RestrictedTokenTest
, DenySids
) {
201 RestrictedToken token
;
202 base::win::ScopedHandle token_handle
;
204 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
205 ASSERT_EQ(ERROR_SUCCESS
, token
.AddAllSidsForDenyOnly(NULL
));
206 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
208 ATL::CAccessToken restricted_token
;
209 restricted_token
.Attach(token_handle
.Take());
211 ATL::CTokenGroups groups
;
212 ASSERT_TRUE(restricted_token
.GetGroups(&groups
));
214 ATL::CSid::CSidArray sids
;
215 ATL::CAtlArray
<DWORD
> attributes
;
216 groups
.GetSidsAndAttributes(&sids
, &attributes
);
218 // Verify that all sids are really gone.
219 for (unsigned int i
= 0; i
< sids
.GetCount(); i
++) {
220 if ((attributes
[i
] & SE_GROUP_LOGON_ID
) == 0 &&
221 (attributes
[i
] & SE_GROUP_INTEGRITY
) == 0) {
222 ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY
,
223 attributes
[i
] & SE_GROUP_USE_FOR_DENY_ONLY
);
228 // Tests the method "AddAllSidsForDenyOnly" using an exception list.
229 TEST(RestrictedTokenTest
, DenySidsException
) {
230 RestrictedToken token
;
231 base::win::ScopedHandle token_handle
;
233 std::vector
<Sid
> sids_exception
;
234 sids_exception
.push_back(Sid(WinWorldSid
));
236 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
237 ASSERT_EQ(ERROR_SUCCESS
, token
.AddAllSidsForDenyOnly(&sids_exception
));
238 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
240 ATL::CAccessToken restricted_token
;
241 restricted_token
.Attach(token_handle
.Take());
243 ATL::CTokenGroups groups
;
244 ASSERT_TRUE(restricted_token
.GetGroups(&groups
));
246 ATL::CSid::CSidArray sids
;
247 ATL::CAtlArray
<DWORD
> attributes
;
248 groups
.GetSidsAndAttributes(&sids
, &attributes
);
250 // Verify that all sids are really gone.
251 for (unsigned int i
= 0; i
< sids
.GetCount(); i
++) {
252 if ((attributes
[i
] & SE_GROUP_LOGON_ID
) == 0 &&
253 (attributes
[i
] & SE_GROUP_INTEGRITY
) == 0) {
254 if (ATL::Sids::World() == sids
[i
]) {
255 ASSERT_EQ(NULL
, attributes
[i
] & SE_GROUP_USE_FOR_DENY_ONLY
);
257 ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY
,
258 attributes
[i
] & SE_GROUP_USE_FOR_DENY_ONLY
);
264 // Tests test method AddOwnerSidForDenyOnly.
265 TEST(RestrictedTokenTest
, DenyOwnerSid
) {
266 RestrictedToken token
;
267 base::win::ScopedHandle token_handle
;
269 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
270 ASSERT_EQ(ERROR_SUCCESS
, token
.AddUserSidForDenyOnly());
271 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
273 ATL::CAccessToken restricted_token
;
274 restricted_token
.Attach(token_handle
.Take());
276 ATL::CTokenGroups groups
;
277 ASSERT_TRUE(restricted_token
.GetGroups(&groups
));
279 ATL::CSid::CSidArray sids
;
280 ATL::CAtlArray
<DWORD
> attributes
;
281 groups
.GetSidsAndAttributes(&sids
, &attributes
);
284 ASSERT_TRUE(restricted_token
.GetUser(&user_sid
));
286 for (unsigned int i
= 0; i
< sids
.GetCount(); ++i
) {
287 if (user_sid
== sids
[i
]) {
288 ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY
,
289 attributes
[i
] & SE_GROUP_USE_FOR_DENY_ONLY
);
294 // Tests test method AddOwnerSidForDenyOnly with a custom effective token.
295 TEST(RestrictedTokenTest
, DenyOwnerSidCustom
) {
296 // Get the current process token.
297 HANDLE access_handle
= INVALID_HANDLE_VALUE
;
298 ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS
,
301 ASSERT_NE(INVALID_HANDLE_VALUE
, access_handle
);
303 ATL::CAccessToken access_token
;
304 access_token
.Attach(access_handle
);
306 RestrictedToken token
;
307 base::win::ScopedHandle token_handle
;
308 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(access_token
.GetHandle()));
309 ASSERT_EQ(ERROR_SUCCESS
, token
.AddUserSidForDenyOnly());
310 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
312 ATL::CAccessToken restricted_token
;
313 restricted_token
.Attach(token_handle
.Take());
315 ATL::CTokenGroups groups
;
316 ASSERT_TRUE(restricted_token
.GetGroups(&groups
));
318 ATL::CSid::CSidArray sids
;
319 ATL::CAtlArray
<DWORD
> attributes
;
320 groups
.GetSidsAndAttributes(&sids
, &attributes
);
323 ASSERT_TRUE(restricted_token
.GetUser(&user_sid
));
325 for (unsigned int i
= 0; i
< sids
.GetCount(); ++i
) {
326 if (user_sid
== sids
[i
]) {
327 ASSERT_EQ(SE_GROUP_USE_FOR_DENY_ONLY
,
328 attributes
[i
] & SE_GROUP_USE_FOR_DENY_ONLY
);
333 // Tests the method DeleteAllPrivileges.
334 TEST(RestrictedTokenTest
, DeleteAllPrivileges
) {
335 RestrictedToken token
;
336 base::win::ScopedHandle token_handle
;
338 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
339 ASSERT_EQ(ERROR_SUCCESS
, token
.DeleteAllPrivileges(NULL
));
340 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
342 ATL::CAccessToken restricted_token
;
343 restricted_token
.Attach(token_handle
.Take());
345 ATL::CTokenPrivileges privileges
;
346 ASSERT_TRUE(restricted_token
.GetPrivileges(&privileges
));
348 ASSERT_EQ(0, privileges
.GetCount());
351 // Tests the method DeleteAllPrivileges with an exception list.
352 TEST(RestrictedTokenTest
, DeleteAllPrivilegesException
) {
353 RestrictedToken token
;
354 base::win::ScopedHandle token_handle
;
356 std::vector
<base::string16
> exceptions
;
357 exceptions
.push_back(SE_CHANGE_NOTIFY_NAME
);
359 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
360 ASSERT_EQ(ERROR_SUCCESS
, token
.DeleteAllPrivileges(&exceptions
));
361 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
363 ATL::CAccessToken restricted_token
;
364 restricted_token
.Attach(token_handle
.Take());
366 ATL::CTokenPrivileges privileges
;
367 ASSERT_TRUE(restricted_token
.GetPrivileges(&privileges
));
369 ATL::CTokenPrivileges::CNames privilege_names
;
370 ATL::CTokenPrivileges::CAttributes privilege_name_attributes
;
371 privileges
.GetNamesAndAttributes(&privilege_names
,
372 &privilege_name_attributes
);
374 ASSERT_EQ(1, privileges
.GetCount());
376 for (unsigned int i
= 0; i
< privileges
.GetCount(); ++i
) {
377 ASSERT_EQ(privilege_names
[i
], SE_CHANGE_NOTIFY_NAME
);
381 // Tests the method DeletePrivilege.
382 TEST(RestrictedTokenTest
, DeletePrivilege
) {
383 RestrictedToken token
;
384 base::win::ScopedHandle token_handle
;
386 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
387 ASSERT_EQ(ERROR_SUCCESS
, token
.DeletePrivilege(SE_CHANGE_NOTIFY_NAME
));
388 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
390 ATL::CAccessToken restricted_token
;
391 restricted_token
.Attach(token_handle
.Take());
393 ATL::CTokenPrivileges privileges
;
394 ASSERT_TRUE(restricted_token
.GetPrivileges(&privileges
));
396 ATL::CTokenPrivileges::CNames privilege_names
;
397 ATL::CTokenPrivileges::CAttributes privilege_name_attributes
;
398 privileges
.GetNamesAndAttributes(&privilege_names
,
399 &privilege_name_attributes
);
401 for (unsigned int i
= 0; i
< privileges
.GetCount(); ++i
) {
402 ASSERT_NE(privilege_names
[i
], SE_CHANGE_NOTIFY_NAME
);
406 // Checks if a sid is in the restricting list of the restricted token.
407 // Asserts if it's not the case. If count is a positive number, the number of
408 // elements in the restricting sids list has to be equal.
409 void CheckRestrictingSid(const ATL::CAccessToken
&restricted_token
,
410 ATL::CSid sid
, int count
) {
412 BYTE
*memory
= new BYTE
[length
];
413 TOKEN_GROUPS
*groups
= reinterpret_cast<TOKEN_GROUPS
*>(memory
);
414 ASSERT_TRUE(::GetTokenInformation(restricted_token
.GetHandle(),
420 ATL::CTokenGroups
atl_groups(*groups
);
424 ASSERT_EQ(count
, atl_groups
.GetCount());
426 ATL::CSid::CSidArray sids
;
427 ATL::CAtlArray
<DWORD
> attributes
;
428 atl_groups
.GetSidsAndAttributes(&sids
, &attributes
);
430 bool present
= false;
431 for (unsigned int i
= 0; i
< sids
.GetCount(); ++i
) {
432 if (sids
[i
] == sid
) {
438 ASSERT_TRUE(present
);
441 // Tests the method AddRestrictingSid.
442 TEST(RestrictedTokenTest
, AddRestrictingSid
) {
443 RestrictedToken token
;
444 base::win::ScopedHandle token_handle
;
446 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
447 ASSERT_EQ(ERROR_SUCCESS
,
448 token
.AddRestrictingSid(ATL::Sids::World().GetPSID()));
449 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
451 ATL::CAccessToken restricted_token
;
452 restricted_token
.Attach(token_handle
.Take());
454 CheckRestrictingSid(restricted_token
, ATL::Sids::World(), 1);
457 // Tests the method AddRestrictingSidCurrentUser.
458 TEST(RestrictedTokenTest
, AddRestrictingSidCurrentUser
) {
459 RestrictedToken token
;
460 base::win::ScopedHandle token_handle
;
462 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
463 ASSERT_EQ(ERROR_SUCCESS
, token
.AddRestrictingSidCurrentUser());
464 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
466 ATL::CAccessToken restricted_token
;
467 restricted_token
.Attach(token_handle
.Take());
469 restricted_token
.GetUser(&user
);
471 CheckRestrictingSid(restricted_token
, user
, 1);
474 // Tests the method AddRestrictingSidCurrentUser with a custom effective token.
475 TEST(RestrictedTokenTest
, AddRestrictingSidCurrentUserCustom
) {
476 // Get the current process token.
477 HANDLE access_handle
= INVALID_HANDLE_VALUE
;
478 ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS
,
481 ASSERT_NE(INVALID_HANDLE_VALUE
, access_handle
);
483 ATL::CAccessToken access_token
;
484 access_token
.Attach(access_handle
);
486 RestrictedToken token
;
487 base::win::ScopedHandle token_handle
;
488 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(access_token
.GetHandle()));
489 ASSERT_EQ(ERROR_SUCCESS
, token
.AddRestrictingSidCurrentUser());
490 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
492 ATL::CAccessToken restricted_token
;
493 restricted_token
.Attach(token_handle
.Take());
495 restricted_token
.GetUser(&user
);
497 CheckRestrictingSid(restricted_token
, user
, 1);
500 // Tests the method AddRestrictingSidLogonSession.
501 TEST(RestrictedTokenTest
, AddRestrictingSidLogonSession
) {
502 RestrictedToken token
;
503 base::win::ScopedHandle token_handle
;
505 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
506 ASSERT_EQ(ERROR_SUCCESS
, token
.AddRestrictingSidLogonSession());
507 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
509 ATL::CAccessToken restricted_token
;
510 restricted_token
.Attach(token_handle
.Take());
512 restricted_token
.GetLogonSid(&session
);
514 CheckRestrictingSid(restricted_token
, session
, 1);
517 // Tests adding a lot of restricting sids.
518 TEST(RestrictedTokenTest
, AddMultipleRestrictingSids
) {
519 RestrictedToken token
;
520 base::win::ScopedHandle token_handle
;
522 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
523 ASSERT_EQ(ERROR_SUCCESS
, token
.AddRestrictingSidCurrentUser());
524 ASSERT_EQ(ERROR_SUCCESS
, token
.AddRestrictingSidLogonSession());
525 ASSERT_EQ(ERROR_SUCCESS
,
526 token
.AddRestrictingSid(ATL::Sids::World().GetPSID()));
527 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
529 ATL::CAccessToken restricted_token
;
530 restricted_token
.Attach(token_handle
.Take());
532 restricted_token
.GetLogonSid(&session
);
535 BYTE
*memory
= new BYTE
[length
];
536 TOKEN_GROUPS
*groups
= reinterpret_cast<TOKEN_GROUPS
*>(memory
);
537 ASSERT_TRUE(::GetTokenInformation(restricted_token
.GetHandle(),
543 ATL::CTokenGroups
atl_groups(*groups
);
546 ASSERT_EQ(3, atl_groups
.GetCount());
549 // Tests the method "AddRestrictingSidAllSids".
550 TEST(RestrictedTokenTest
, AddAllSidToRestrictingSids
) {
551 RestrictedToken token
;
552 base::win::ScopedHandle token_handle
;
554 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
555 ASSERT_EQ(ERROR_SUCCESS
, token
.AddRestrictingSidAllSids());
556 ASSERT_EQ(ERROR_SUCCESS
, token
.GetRestrictedToken(&token_handle
));
558 ATL::CAccessToken restricted_token
;
559 restricted_token
.Attach(token_handle
.Take());
561 ATL::CTokenGroups groups
;
562 ASSERT_TRUE(restricted_token
.GetGroups(&groups
));
564 ATL::CSid::CSidArray sids
;
565 ATL::CAtlArray
<DWORD
> attributes
;
566 groups
.GetSidsAndAttributes(&sids
, &attributes
);
568 // Verify that all group sids are in the restricting sid list.
569 for (unsigned int i
= 0; i
< sids
.GetCount(); i
++) {
570 if ((attributes
[i
] & SE_GROUP_INTEGRITY
) == 0) {
571 CheckRestrictingSid(restricted_token
, sids
[i
], -1);
575 // Verify that the user is in the restricting sid list.
577 restricted_token
.GetUser(&user
);
578 CheckRestrictingSid(restricted_token
, user
, -1);
581 // Checks the error code when the object is initialized twice.
582 TEST(RestrictedTokenTest
, DoubleInit
) {
583 RestrictedToken token
;
584 ASSERT_EQ(ERROR_SUCCESS
, token
.Init(NULL
));
586 ASSERT_EQ(ERROR_ALREADY_INITIALIZED
, token
.Init(NULL
));
589 } // namespace sandbox