2 * COPYRIGHT: See COPYING in the top level directory
4 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
6 * Copyright 2006 Hervé Poussineau
8 * PROJECT: ReactOS system libraries
9 * FILE: lib/advapi32/sec/sid.c
10 * PURPOSE: Security ID functions
15 #include <wine/debug.h>
16 #include <wine/unicode.h>
18 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
20 #define MAX_GUID_STRING_LEN 39
23 AddAuditAccessAceEx(PACL pAcl
,
38 typedef struct _MAX_SID
40 /* same fields as struct _SID */
42 BYTE SubAuthorityCount
;
43 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
44 DWORD SubAuthority
[SID_MAX_SUB_AUTHORITIES
];
47 typedef struct WELLKNOWNSID
50 WELL_KNOWN_SID_TYPE Type
;
54 static const WELLKNOWNSID WellKnownSids
[] =
56 { {0,0}, WinNullSid
, { SID_REVISION
, 1, { SECURITY_NULL_SID_AUTHORITY
}, { SECURITY_NULL_RID
} } },
57 { {'W','D'}, WinWorldSid
, { SID_REVISION
, 1, { SECURITY_WORLD_SID_AUTHORITY
}, { SECURITY_WORLD_RID
} } },
58 { {0,0}, WinLocalSid
, { SID_REVISION
, 1, { SECURITY_LOCAL_SID_AUTHORITY
}, { SECURITY_LOCAL_RID
} } },
59 { {'C','O'}, WinCreatorOwnerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_RID
} } },
60 { {'C','G'}, WinCreatorGroupSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_RID
} } },
61 { {0,0}, WinCreatorOwnerServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_OWNER_SERVER_RID
} } },
62 { {0,0}, WinCreatorGroupServerSid
, { SID_REVISION
, 1, { SECURITY_CREATOR_SID_AUTHORITY
}, { SECURITY_CREATOR_GROUP_SERVER_RID
} } },
63 { {0,0}, WinNtAuthoritySid
, { SID_REVISION
, 0, { SECURITY_NT_AUTHORITY
}, { SECURITY_NULL_RID
} } },
64 { {0,0}, WinDialupSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_DIALUP_RID
} } },
65 { {'N','U'}, WinNetworkSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_RID
} } },
66 { {0,0}, WinBatchSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BATCH_RID
} } },
67 { {'I','U'}, WinInteractiveSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_INTERACTIVE_RID
} } },
68 { {'S','U'}, WinServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_SERVICE_RID
} } },
69 { {'A','N'}, WinAnonymousSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ANONYMOUS_LOGON_RID
} } },
70 { {0,0}, WinProxySid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PROXY_RID
} } },
71 { {'E','D'}, WinEnterpriseControllersSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_ENTERPRISE_CONTROLLERS_RID
} } },
72 { {'P','S'}, WinSelfSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_PRINCIPAL_SELF_RID
} } },
73 { {'A','U'}, WinAuthenticatedUserSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_AUTHENTICATED_USER_RID
} } },
74 { {'R','C'}, WinRestrictedCodeSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_RESTRICTED_CODE_RID
} } },
75 { {0,0}, WinTerminalServerSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_TERMINAL_SERVER_RID
} } },
76 { {0,0}, WinRemoteLogonIdSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_REMOTE_LOGON_RID
} } },
77 { {'S','Y'}, WinLocalSystemSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SYSTEM_RID
} } },
78 { {'L','S'}, WinLocalServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_LOCAL_SERVICE_RID
} } },
79 { {'N','S'}, WinNetworkServiceSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_NETWORK_SERVICE_RID
} } },
80 { {0,0}, WinBuiltinDomainSid
, { SID_REVISION
, 1, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
} } },
81 { {'B','A'}, WinBuiltinAdministratorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ADMINS
} } },
82 { {'B','U'}, WinBuiltinUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_USERS
} } },
83 { {'B','G'}, WinBuiltinGuestsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_GUESTS
} } },
84 { {'P','U'}, WinBuiltinPowerUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_POWER_USERS
} } },
85 { {'A','O'}, WinBuiltinAccountOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_ACCOUNT_OPS
} } },
86 { {'S','O'}, WinBuiltinSystemOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_SYSTEM_OPS
} } },
87 { {'P','O'}, WinBuiltinPrintOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PRINT_OPS
} } },
88 { {'B','O'}, WinBuiltinBackupOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_BACKUP_OPS
} } },
89 { {'R','E'}, WinBuiltinReplicatorSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REPLICATOR
} } },
90 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS
} } },
91 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS
} } },
92 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid
, { SID_REVISION
, 2, { SECURITY_NT_AUTHORITY
}, { SECURITY_BUILTIN_DOMAIN_RID
, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS
} } },
95 static const SID sidWorld
= { SID_REVISION
, 1, { SECURITY_WORLD_SID_AUTHORITY
} , { SECURITY_WORLD_RID
} };
100 static const WCHAR SDDL_ACCESS_ALLOWED
[] = {'A',0};
101 static const WCHAR SDDL_ACCESS_DENIED
[] = {'D',0};
102 static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED
[] = {'O','A',0};
103 static const WCHAR SDDL_OBJECT_ACCESS_DENIED
[] = {'O','D',0};
104 static const WCHAR SDDL_AUDIT
[] = {'A','U',0};
105 static const WCHAR SDDL_ALARM
[] = {'A','L',0};
106 static const WCHAR SDDL_OBJECT_AUDIT
[] = {'O','U',0};
107 static const WCHAR SDDL_OBJECT_ALARM
[] = {'O','L',0};
112 #define ADS_RIGHT_DS_CREATE_CHILD 0x0001
113 #define ADS_RIGHT_DS_DELETE_CHILD 0x0002
114 #define ADS_RIGHT_ACTRL_DS_LIST 0x0004
115 #define ADS_RIGHT_DS_SELF 0x0008
116 #define ADS_RIGHT_DS_READ_PROP 0x0010
117 #define ADS_RIGHT_DS_WRITE_PROP 0x0020
118 #define ADS_RIGHT_DS_DELETE_TREE 0x0040
119 #define ADS_RIGHT_DS_LIST_OBJECT 0x0080
120 #define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100
125 static const WCHAR SDDL_CONTAINER_INHERIT
[] = {'C','I',0};
126 static const WCHAR SDDL_OBJECT_INHERIT
[] = {'O','I',0};
127 static const WCHAR SDDL_NO_PROPAGATE
[] = {'N','P',0};
128 static const WCHAR SDDL_INHERIT_ONLY
[] = {'I','O',0};
129 static const WCHAR SDDL_INHERITED
[] = {'I','D',0};
130 static const WCHAR SDDL_AUDIT_SUCCESS
[] = {'S','A',0};
131 static const WCHAR SDDL_AUDIT_FAILURE
[] = {'F','A',0};
133 static const char * debugstr_sid(PSID sid
)
136 SID
* psid
= (SID
*)sid
;
141 auth
= psid
->IdentifierAuthority
.Value
[5] +
142 (psid
->IdentifierAuthority
.Value
[4] << 8) +
143 (psid
->IdentifierAuthority
.Value
[3] << 16) +
144 (psid
->IdentifierAuthority
.Value
[2] << 24);
146 switch (psid
->SubAuthorityCount
) {
148 return wine_dbg_sprintf("S-%d-%d", psid
->Revision
, auth
);
150 return wine_dbg_sprintf("S-%d-%d-%lu", psid
->Revision
, auth
,
151 psid
->SubAuthority
[0]);
153 return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid
->Revision
, auth
,
154 psid
->SubAuthority
[0], psid
->SubAuthority
[1]);
156 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid
->Revision
, auth
,
157 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2]);
159 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
160 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
161 psid
->SubAuthority
[3]);
163 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
164 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
165 psid
->SubAuthority
[3], psid
->SubAuthority
[4]);
167 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
168 psid
->SubAuthority
[3], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
169 psid
->SubAuthority
[0], psid
->SubAuthority
[4], psid
->SubAuthority
[5]);
171 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
172 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
173 psid
->SubAuthority
[3], psid
->SubAuthority
[4], psid
->SubAuthority
[5],
174 psid
->SubAuthority
[6]);
176 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid
->Revision
, auth
,
177 psid
->SubAuthority
[0], psid
->SubAuthority
[1], psid
->SubAuthority
[2],
178 psid
->SubAuthority
[3], psid
->SubAuthority
[4], psid
->SubAuthority
[5],
179 psid
->SubAuthority
[6], psid
->SubAuthority
[7]);
184 /* set last error code from NT status and get the proper boolean return value */
185 /* used for functions that are a simple wrapper around the corresponding ntdll API */
186 static __inline BOOL
set_ntstatus( NTSTATUS status
)
188 if (status
) SetLastError( RtlNtStatusToDosError( status
));
194 IN
const RECORD
* Table
,
196 OUT SIZE_T
* pKeyLength
,
199 const RECORD
* pRecord
= Table
;
200 while (pRecord
->key
!= NULL
)
202 if (wcsncmp(pRecord
->key
, Key
, wcslen(pRecord
->key
)) == 0)
204 *pKeyLength
= wcslen(pRecord
->key
);
205 *pItem
= pRecord
->value
;
210 SetLastError(ERROR_INVALID_PARAMETER
);
220 WCHAR str
[SDDL_ALIAS_SIZE
+ 1];
226 wcsncpy(str
, Buffer
, SDDL_ALIAS_SIZE
);
227 for (i
= SDDL_ALIAS_SIZE
; i
> 0; i
--)
229 str
[i
] = UNICODE_NULL
;
230 if (ConvertStringSidToSidW(str
, pSid
))
237 end
= wcschr(Buffer
, SDDL_ACE_ENDC
);
240 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
243 strSid
= (LPWSTR
)LocalAlloc(0, (end
- Buffer
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
246 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
249 wcsncpy(strSid
, Buffer
, end
- Buffer
+ 1);
250 strSid
[end
- Buffer
] = UNICODE_NULL
;
251 *pLength
= end
- Buffer
;
252 ret
= ConvertStringSidToSidW(strSid
, pSid
);
257 static const RECORD DaclFlagTable
[] =
259 { SDDL_PROTECTED
, SE_DACL_PROTECTED
},
260 { SDDL_AUTO_INHERIT_REQ
, SE_DACL_AUTO_INHERIT_REQ
},
261 { SDDL_AUTO_INHERITED
, SE_DACL_AUTO_INHERITED
},
265 static const RECORD SaclFlagTable
[] =
267 { SDDL_PROTECTED
, SE_SACL_PROTECTED
},
268 { SDDL_AUTO_INHERIT_REQ
, SE_SACL_AUTO_INHERIT_REQ
},
269 { SDDL_AUTO_INHERITED
, SE_SACL_AUTO_INHERITED
},
273 static const RECORD AceFlagTable
[] =
275 { SDDL_CONTAINER_INHERIT
, CONTAINER_INHERIT_ACE
},
276 { SDDL_OBJECT_INHERIT
, OBJECT_INHERIT_ACE
},
277 { SDDL_NO_PROPAGATE
, NO_PROPAGATE_INHERIT_ACE
},
278 { SDDL_INHERIT_ONLY
, INHERIT_ONLY_ACE
},
279 { SDDL_INHERITED
, INHERITED_ACE
},
280 { SDDL_AUDIT_SUCCESS
, SUCCESSFUL_ACCESS_ACE_FLAG
},
281 { SDDL_AUDIT_FAILURE
, FAILED_ACCESS_ACE_FLAG
},
288 IN
const RECORD
* FlagTable
,
293 LPCWSTR ptr
= Buffer
;
294 SIZE_T PartialLength
;
298 while (*ptr
!= LimitChar
)
300 if (!FindKeyInTable(FlagTable
, ptr
, &PartialLength
, &Flag
))
303 ptr
+= PartialLength
;
305 *pLength
= ptr
- Buffer
;
309 static const RECORD AccessMaskTable
[] =
311 { SDDL_GENERIC_ALL
, GENERIC_ALL
},
312 { SDDL_GENERIC_READ
, GENERIC_READ
},
313 { SDDL_GENERIC_WRITE
, GENERIC_WRITE
},
314 { SDDL_GENERIC_EXECUTE
, GENERIC_EXECUTE
},
315 { SDDL_READ_CONTROL
, READ_CONTROL
},
316 { SDDL_STANDARD_DELETE
, DELETE
},
317 { SDDL_WRITE_DAC
, WRITE_DAC
},
318 { SDDL_WRITE_OWNER
, WRITE_OWNER
},
319 { SDDL_READ_PROPERTY
, ADS_RIGHT_DS_READ_PROP
},
320 { SDDL_WRITE_PROPERTY
, ADS_RIGHT_DS_WRITE_PROP
},
321 { SDDL_CREATE_CHILD
, ADS_RIGHT_DS_CREATE_CHILD
},
322 { SDDL_DELETE_CHILD
, ADS_RIGHT_DS_DELETE_CHILD
},
323 { SDDL_LIST_CHILDREN
, ADS_RIGHT_ACTRL_DS_LIST
},
324 { SDDL_SELF_WRITE
, ADS_RIGHT_DS_SELF
},
325 { SDDL_LIST_OBJECT
, ADS_RIGHT_DS_LIST_OBJECT
},
326 { SDDL_DELETE_TREE
, ADS_RIGHT_DS_DELETE_TREE
},
327 { SDDL_CONTROL_ACCESS
, ADS_RIGHT_DS_CONTROL_ACCESS
},
328 { SDDL_FILE_ALL
, FILE_ALL_ACCESS
},
329 { SDDL_FILE_READ
, FILE_GENERIC_READ
},
330 { SDDL_FILE_WRITE
, FILE_GENERIC_WRITE
},
331 { SDDL_FILE_EXECUTE
, FILE_GENERIC_EXECUTE
},
332 { SDDL_KEY_ALL
, KEY_ALL_ACCESS
},
333 { SDDL_KEY_READ
, KEY_READ
},
334 { SDDL_KEY_WRITE
, KEY_WRITE
},
335 { SDDL_KEY_EXECUTE
, KEY_EXECUTE
},
340 ParseAccessMaskString(
342 OUT DWORD
* pAccessMask
,
345 /* FIXME: Allow hexadecimal string for access rights! */
347 return ParseFlagsString(Buffer
, AccessMaskTable
, SDDL_SEPERATORC
, pAccessMask
, pLength
);
354 OUT BOOL
* pIsGuidValid
,
357 WCHAR GuidStr
[MAX_GUID_STRING_LEN
+ 1];
360 end
= wcschr(Buffer
, SDDL_SEPERATORC
);
363 SetLastError(ERROR_INVALID_PARAMETER
);
367 *pLength
= end
- Buffer
;
368 *pIsGuidValid
= (end
!= Buffer
);
372 if (end
- Buffer
> MAX_GUID_STRING_LEN
- 1)
374 SetLastError(ERROR_INVALID_PARAMETER
);
377 GuidStr
[end
- Buffer
] = UNICODE_NULL
;
378 wcsncpy(GuidStr
, Buffer
, end
- Buffer
);
379 if (RPC_S_OK
!= UuidFromStringW((unsigned short*)&GuidStr
, pGuid
))
381 SetLastError(ERROR_INVALID_PARAMETER
);
387 static const RECORD AceTypeTable
[] =
389 { SDDL_OBJECT_ACCESS_ALLOWED
, ACCESS_ALLOWED_OBJECT_ACE_TYPE
},
390 { SDDL_OBJECT_ACCESS_DENIED
, ACCESS_DENIED_OBJECT_ACE_TYPE
},
391 { SDDL_AUDIT
, SYSTEM_AUDIT_ACE_TYPE
},
392 { SDDL_ALARM
, SYSTEM_ALARM_ACE_TYPE
},
393 { SDDL_OBJECT_AUDIT
, SYSTEM_AUDIT_OBJECT_ACE_TYPE
},
394 { SDDL_OBJECT_ALARM
, SYSTEM_ALARM_OBJECT_ACE_TYPE
},
395 { SDDL_ACCESS_ALLOWED
, ACCESS_ALLOWED_ACE_TYPE
},
396 { SDDL_ACCESS_DENIED
, ACCESS_DENIED_ACE_TYPE
},
406 LPCWSTR ptr
= Buffer
;
407 SIZE_T PartialLength
;
408 DWORD aceType
, aceFlags
, accessMask
;
409 GUID object
, inheritObject
;
410 BOOL objectValid
, inheritObjectValid
;
414 if (*ptr
!= SDDL_ACE_BEGINC
)
416 SetLastError(ERROR_INVALID_PARAMETER
);
419 ptr
++; /* Skip SDDL_ACE_BEGINC */
421 if (!FindKeyInTable(AceTypeTable
, ptr
, &PartialLength
, &aceType
))
423 ptr
+= PartialLength
;
425 if (*ptr
!= SDDL_SEPERATORC
)
427 SetLastError(ERROR_INVALID_PARAMETER
);
430 ptr
++; /* Skip SDDL_SEPERATORC */
432 if (!ParseFlagsString(ptr
, AceFlagTable
, SDDL_SEPERATORC
, &aceFlags
, &PartialLength
))
434 ptr
+= PartialLength
+ 1;
436 if (!ParseAccessMaskString(ptr
, &accessMask
, &PartialLength
))
438 ptr
+= PartialLength
+ 1;
440 if (!ParseGuidString(ptr
, &object
, &objectValid
, &PartialLength
))
442 ptr
+= PartialLength
+ 1;
444 if (!ParseGuidString(ptr
, &inheritObject
, &inheritObjectValid
, &PartialLength
))
446 ptr
+= PartialLength
+ 1;
448 if (!ParseSidString(ptr
, &sid
, &PartialLength
))
450 ptr
+= PartialLength
;
451 if (*ptr
!= SDDL_ACE_ENDC
)
453 SetLastError(ERROR_INVALID_PARAMETER
);
456 ptr
++; /* Skip SDDL_ACE_ENDC */
457 *pLength
= ptr
- Buffer
;
461 case ACCESS_ALLOWED_ACE_TYPE
:
462 ret
= AddAccessAllowedAceEx(
469 case ACCESS_ALLOWED_OBJECT_ACE_TYPE
:
470 ret
= AddAccessAllowedObjectAce(
475 objectValid
? &object
: NULL
,
476 inheritObjectValid
? &inheritObject
: NULL
,
479 case ACCESS_DENIED_ACE_TYPE
:
480 ret
= AddAccessDeniedAceEx(
487 case ACCESS_DENIED_OBJECT_ACE_TYPE
:
488 ret
= AddAccessDeniedObjectAce(
493 objectValid
? &object
: NULL
,
494 inheritObjectValid
? &inheritObject
: NULL
,
497 case SYSTEM_AUDIT_ACE_TYPE
:
498 ret
= AddAuditAccessAceEx(
507 case SYSTEM_AUDIT_OBJECT_ACE_TYPE
:
508 ret
= AddAuditAccessObjectAce(
513 objectValid
? &object
: NULL
,
514 inheritObjectValid
? &inheritObject
: NULL
,
519 case SYSTEM_ALARM_ACE_TYPE
:
520 case SYSTEM_ALARM_OBJECT_ACE_TYPE
:
523 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
531 /* Exported functions */
537 AllocateLocallyUniqueId(PLUID Luid
)
541 Status
= NtAllocateLocallyUniqueId (Luid
);
542 if (!NT_SUCCESS (Status
))
544 SetLastError(RtlNtStatusToDosError(Status
));
556 AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority
,
557 BYTE nSubAuthorityCount
,
558 DWORD dwSubAuthority0
,
559 DWORD dwSubAuthority1
,
560 DWORD dwSubAuthority2
,
561 DWORD dwSubAuthority3
,
562 DWORD dwSubAuthority4
,
563 DWORD dwSubAuthority5
,
564 DWORD dwSubAuthority6
,
565 DWORD dwSubAuthority7
,
570 Status
= RtlAllocateAndInitializeSid(pIdentifierAuthority
,
581 if (!NT_SUCCESS(Status
))
583 SetLastError(RtlNtStatusToDosError(Status
));
595 CopySid(DWORD nDestinationSidLength
,
596 PSID pDestinationSid
,
601 Status
= RtlCopySid(nDestinationSidLength
,
604 if (!NT_SUCCESS (Status
))
606 SetLastError(RtlNtStatusToDosError(Status
));
614 /******************************************************************************
615 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
619 ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor
,
621 SECURITY_INFORMATION SecurityInformation
,
622 LPWSTR
*OutputString
,
625 if (SDRevision
!= SDDL_REVISION_1
)
627 ERR("Pogram requested unknown SDDL revision %d\n", SDRevision
);
628 SetLastError(ERROR_UNKNOWN_REVISION
);
632 FIXME("%s() not implemented!\n", __FUNCTION__
);
633 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
638 /******************************************************************************
639 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
643 ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor
,
645 SECURITY_INFORMATION Information
,
651 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor
, SDRevision
, Information
, &wstr
, &len
))
655 lenA
= WideCharToMultiByte(CP_ACP
, 0, wstr
, len
, NULL
, 0, NULL
, NULL
);
656 *OutputString
= HeapAlloc(GetProcessHeap(), 0, lenA
);
657 WideCharToMultiByte(CP_ACP
, 0, wstr
, len
, *OutputString
, lenA
, NULL
, NULL
);
660 if (OutputLen
!= NULL
)
666 *OutputString
= NULL
;
673 /******************************************************************************
674 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
678 ConvertStringSecurityDescriptorToSecurityDescriptorW(
679 IN LPCWSTR StringSecurityDescriptor
,
680 IN DWORD StringSDRevision
,
681 OUT PSECURITY_DESCRIPTOR
* SecurityDescriptor
,
682 OUT PULONG SecurityDescriptorSize
)
684 PSECURITY_DESCRIPTOR sd
= NULL
;
687 if (!StringSecurityDescriptor
)
688 SetLastError(ERROR_INVALID_PARAMETER
);
689 else if (StringSDRevision
!= SDDL_REVISION_1
)
690 SetLastError(ERROR_INVALID_PARAMETER
);
693 LPCWSTR ptr
= StringSecurityDescriptor
;
694 DWORD numberOfAces
= 0;
695 DWORD relativeSdSize
;
697 PSECURITY_DESCRIPTOR relativeSd
= NULL
;
701 /* An easy way to know how much space we need for an ACL is to count
702 * the number of ACEs and say that we have 1 SID by ACE
704 ptr
= wcschr(StringSecurityDescriptor
, SDDL_ACE_BEGINC
);
708 ptr
= wcschr(ptr
+ 1, SDDL_ACE_BEGINC
);
710 MaxAclSize
= sizeof(ACL
) + numberOfAces
*
711 (sizeof(ACCESS_ALLOWED_OBJECT_ACE
) + SECURITY_MAX_SID_SIZE
);
713 sd
= (SECURITY_DESCRIPTOR
*)LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR
));
716 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
719 ret
= InitializeSecurityDescriptor(sd
, SECURITY_DESCRIPTOR_REVISION
);
723 /* Now, really parse the string */
724 ptr
= StringSecurityDescriptor
;
727 if (ptr
[1] != SDDL_DELIMINATORC
)
729 SetLastError(ERROR_INVALID_PARAMETER
);
742 ret
= ParseSidString(ptr
, &pSid
, &Length
);
746 ret
= SetSecurityDescriptorOwner(sd
, pSid
, FALSE
);
748 ret
= SetSecurityDescriptorGroup(sd
, pSid
, FALSE
);
762 BOOL isDacl
= (ptr
[-2] == 'D');
765 ret
= ParseFlagsString(ptr
, DaclFlagTable
, SDDL_ACE_BEGINC
, &aclFlags
, &Length
);
767 ret
= ParseFlagsString(ptr
, SaclFlagTable
, SDDL_ACE_BEGINC
, &aclFlags
, &Length
);
770 pAcl
= (PACL
)LocalAlloc(0, MaxAclSize
);
773 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
777 if (!InitializeAcl(pAcl
, (DWORD
)MaxAclSize
, ACL_REVISION_DS
))
784 ret
= SetSecurityDescriptorControl(
786 (SECURITY_DESCRIPTOR_CONTROL
)aclFlags
,
787 (SECURITY_DESCRIPTOR_CONTROL
)aclFlags
);
795 while (*ptr
== SDDL_ACE_BEGINC
)
797 ret
= ParseAceString(ptr
, pAcl
, &Length
);
806 ret
= SetSecurityDescriptorDacl(sd
, TRUE
, pAcl
, FALSE
);
808 ret
= SetSecurityDescriptorSacl(sd
, TRUE
, pAcl
, FALSE
);
818 SetLastError(ERROR_INVALID_PARAMETER
);
829 LocalFree(relativeSd
);
830 relativeSd
= LocalAlloc(0, relativeSdSize
);
833 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
836 ret
= MakeSelfRelativeSD(sd
, relativeSd
, &relativeSdSize
);
837 if (ret
|| GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
840 if (SecurityDescriptorSize
)
841 *SecurityDescriptorSize
= relativeSdSize
;
842 *SecurityDescriptor
= relativeSd
;
845 if (GetSecurityDescriptorOwner(sd
, &pSid
, &dummy
))
847 if (GetSecurityDescriptorGroup(sd
, &pSid
, &dummy
))
849 if (GetSecurityDescriptorDacl(sd
, &present
, &pAcl
, &dummy
) && present
)
851 if (GetSecurityDescriptorSacl(sd
, &present
, &pAcl
, &dummy
) && present
)
859 /* Winehq cvs 20050916 */
860 /******************************************************************************
861 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
864 BOOL WINAPI
ConvertStringSecurityDescriptorToSecurityDescriptorA(
865 LPCSTR StringSecurityDescriptor
,
866 DWORD StringSDRevision
,
867 PSECURITY_DESCRIPTOR
* SecurityDescriptor
,
868 PULONG SecurityDescriptorSize
)
872 LPWSTR StringSecurityDescriptorW
;
874 len
= MultiByteToWideChar(CP_ACP
, 0, StringSecurityDescriptor
, -1, NULL
, 0);
875 StringSecurityDescriptorW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
877 if (StringSecurityDescriptorW
)
879 MultiByteToWideChar(CP_ACP
, 0, StringSecurityDescriptor
, -1, StringSecurityDescriptorW
, len
);
881 ret
= ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW
,
882 StringSDRevision
, SecurityDescriptor
,
883 SecurityDescriptorSize
);
884 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW
);
894 EqualPrefixSid(PSID pSid1
,
897 return RtlEqualPrefixSid (pSid1
, pSid2
);
908 return RtlEqualSid (pSid1
, pSid2
);
916 * Docs says this function does NOT return a value
917 * even thou it's defined to return a PVOID...
922 return RtlFreeSid(pSid
);
930 GetLengthSid(PSID pSid
)
932 return (DWORD
)RtlLengthSid(pSid
);
939 PSID_IDENTIFIER_AUTHORITY STDCALL
940 GetSidIdentifierAuthority(PSID pSid
)
942 return RtlIdentifierAuthoritySid(pSid
);
950 GetSidLengthRequired(UCHAR nSubAuthorityCount
)
952 return (DWORD
)RtlLengthRequiredSid(nSubAuthorityCount
);
960 GetSidSubAuthority(PSID pSid
,
963 return (PDWORD
)RtlSubAuthoritySid(pSid
, nSubAuthority
);
971 GetSidSubAuthorityCount(PSID pSid
)
973 return RtlSubAuthorityCountSid(pSid
);
981 InitializeSid(PSID Sid
,
982 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority
,
983 BYTE nSubAuthorityCount
)
987 Status
= RtlInitializeSid(Sid
,
988 pIdentifierAuthority
,
990 if (!NT_SUCCESS(Status
))
992 SetLastError(RtlNtStatusToDosError(Status
));
1004 IsValidSid(PSID pSid
)
1006 return (BOOL
)RtlValidSid(pSid
);
1014 ConvertSidToStringSidW(PSID Sid
,
1018 UNICODE_STRING UnicodeString
;
1019 WCHAR FixedBuffer
[64];
1021 if (!RtlValidSid(Sid
))
1023 SetLastError(ERROR_INVALID_SID
);
1027 UnicodeString
.Length
= 0;
1028 UnicodeString
.MaximumLength
= sizeof(FixedBuffer
);
1029 UnicodeString
.Buffer
= FixedBuffer
;
1030 Status
= RtlConvertSidToUnicodeString(&UnicodeString
, Sid
, FALSE
);
1031 if (STATUS_BUFFER_TOO_SMALL
== Status
)
1033 Status
= RtlConvertSidToUnicodeString(&UnicodeString
, Sid
, TRUE
);
1036 if (!NT_SUCCESS(Status
))
1038 SetLastError(RtlNtStatusToDosError(Status
));
1042 *StringSid
= LocalAlloc(LMEM_FIXED
, UnicodeString
.Length
+ sizeof(WCHAR
));
1043 if (NULL
== *StringSid
)
1045 if (UnicodeString
.Buffer
!= FixedBuffer
)
1047 RtlFreeUnicodeString(&UnicodeString
);
1049 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1053 MoveMemory(*StringSid
, UnicodeString
.Buffer
, UnicodeString
.Length
);
1054 ZeroMemory((PCHAR
) *StringSid
+ UnicodeString
.Length
, sizeof(WCHAR
));
1055 if (UnicodeString
.Buffer
!= FixedBuffer
)
1057 RtlFreeUnicodeString(&UnicodeString
);
1068 ConvertSidToStringSidA(PSID Sid
,
1074 if (!ConvertSidToStringSidW(Sid
, &StringSidW
))
1079 Len
= WideCharToMultiByte(CP_ACP
, 0, StringSidW
, -1, NULL
, 0, NULL
, NULL
);
1082 LocalFree(StringSidW
);
1083 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1087 *StringSid
= LocalAlloc(LMEM_FIXED
, Len
);
1088 if (NULL
== *StringSid
)
1090 LocalFree(StringSidW
);
1091 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1095 if (!WideCharToMultiByte(CP_ACP
, 0, StringSidW
, -1, *StringSid
, Len
, NULL
, NULL
))
1097 LocalFree(StringSid
);
1098 LocalFree(StringSidW
);
1102 LocalFree(StringSidW
);
1112 EqualDomainSid(IN PSID pSid1
,
1125 GetWindowsAccountDomainSid(IN PSID pSid
,
1126 OUT PSID ppDomainSid
,
1127 IN OUT DWORD
* cbSid
)
1138 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType
,
1139 IN PSID DomainSid OPTIONAL
,
1141 IN OUT DWORD
* cbSid
)
1144 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType
, debugstr_sid(DomainSid
), pSid
, cbSid
);
1146 if (DomainSid
!= NULL
)
1148 FIXME("Only local computer supported!\n");
1149 SetLastError(ERROR_INVALID_PARAMETER
); /* FIXME */
1153 if (cbSid
== NULL
|| pSid
== NULL
)
1155 SetLastError(ERROR_INVALID_PARAMETER
);
1159 for (i
= 0; i
< sizeof(WellKnownSids
)/sizeof(WellKnownSids
[0]); i
++)
1161 if (WellKnownSids
[i
].Type
== WellKnownSidType
)
1163 DWORD length
= GetSidLengthRequired(WellKnownSids
[i
].Sid
.SubAuthorityCount
);
1165 if (*cbSid
< length
)
1167 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1171 CopyMemory(pSid
, &WellKnownSids
[i
].Sid
.Revision
, length
);
1177 SetLastError(ERROR_INVALID_PARAMETER
);
1186 IsWellKnownSid(IN PSID pSid
,
1187 IN WELL_KNOWN_SID_TYPE WellKnownSidType
)
1190 TRACE("(%s, %d)\n", debugstr_sid(pSid
), WellKnownSidType
);
1192 for (i
= 0; i
< sizeof(WellKnownSids
) / sizeof(WellKnownSids
[0]); i
++)
1194 if (WellKnownSids
[i
].Type
== WellKnownSidType
)
1196 if (EqualSid(pSid
, (PSID
)((ULONG_PTR
)&WellKnownSids
[i
].Sid
.Revision
)))
1209 ConvertStringSidToSidA(IN LPCSTR StringSid
,
1212 BOOL bRetVal
= FALSE
;
1214 if (!StringSid
|| !sid
)
1215 SetLastError(ERROR_INVALID_PARAMETER
);
1218 UINT len
= MultiByteToWideChar(CP_ACP
, 0, StringSid
, -1, NULL
, 0);
1219 LPWSTR wStringSid
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1220 MultiByteToWideChar(CP_ACP
, 0, StringSid
, - 1, wStringSid
, len
);
1221 bRetVal
= ConvertStringSidToSidW(wStringSid
, sid
);
1222 HeapFree(GetProcessHeap(), 0, wStringSid
);
1228 /******************************************************************************
1229 * ComputeStringSidSize
1232 ComputeStringSidSize(LPCWSTR StringSid
)
1234 DWORD size
= sizeof(SID
);
1236 if (StringSid
[0] == 'S' && StringSid
[1] == '-') /* S-R-I-S-S */
1241 if (*StringSid
== '-')
1247 size
+= (ctok
- 3) * sizeof(DWORD
);
1249 else /* String constant format - Only available in winxp and above */
1253 for (i
= 0; i
< sizeof(WellKnownSids
)/sizeof(WellKnownSids
[0]); i
++)
1254 if (!strncmpW(WellKnownSids
[i
].wstr
, StringSid
, 2))
1255 size
+= (WellKnownSids
[i
].Sid
.SubAuthorityCount
- 1) * sizeof(DWORD
);
1261 static const RECORD SidTable
[] =
1263 { SDDL_ACCOUNT_OPERATORS
, WinBuiltinAccountOperatorsSid
},
1264 { SDDL_ALIAS_PREW2KCOMPACC
, WinBuiltinPreWindows2000CompatibleAccessSid
},
1265 { SDDL_ANONYMOUS
, WinAnonymousSid
},
1266 { SDDL_AUTHENTICATED_USERS
, WinAuthenticatedUserSid
},
1267 { SDDL_BUILTIN_ADMINISTRATORS
, WinBuiltinAdministratorsSid
},
1268 { SDDL_BUILTIN_GUESTS
, WinBuiltinGuestsSid
},
1269 { SDDL_BACKUP_OPERATORS
, WinBuiltinBackupOperatorsSid
},
1270 { SDDL_BUILTIN_USERS
, WinBuiltinUsersSid
},
1271 { SDDL_CERT_SERV_ADMINISTRATORS
, WinAccountCertAdminsSid
/* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
1272 { SDDL_CREATOR_GROUP
, WinCreatorGroupSid
},
1273 { SDDL_CREATOR_OWNER
, WinCreatorOwnerSid
},
1274 { SDDL_DOMAIN_ADMINISTRATORS
, WinAccountDomainAdminsSid
/* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
1275 { SDDL_DOMAIN_COMPUTERS
, WinAccountComputersSid
/* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
1276 { SDDL_DOMAIN_DOMAIN_CONTROLLERS
, WinAccountControllersSid
/* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
1277 { SDDL_DOMAIN_GUESTS
, WinAccountDomainGuestsSid
/* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
1278 { SDDL_DOMAIN_USERS
, WinAccountDomainUsersSid
/* FIXME: DOMAIN_GROUP_RID_USERS */ },
1279 { SDDL_ENTERPRISE_ADMINS
, WinAccountEnterpriseAdminsSid
/* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
1280 { SDDL_ENTERPRISE_DOMAIN_CONTROLLERS
, WinLogonIdsSid
/* FIXME: SECURITY_SERVER_LOGON_RID */ },
1281 { SDDL_EVERYONE
, WinWorldSid
},
1282 { SDDL_GROUP_POLICY_ADMINS
, WinAccountPolicyAdminsSid
/* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
1283 { SDDL_INTERACTIVE
, WinInteractiveSid
},
1284 { SDDL_LOCAL_ADMIN
, WinAccountAdministratorSid
/* FIXME: DOMAIN_USER_RID_ADMIN */ },
1285 { SDDL_LOCAL_GUEST
, WinAccountGuestSid
/* FIXME: DOMAIN_USER_RID_GUEST */ },
1286 { SDDL_LOCAL_SERVICE
, WinLocalServiceSid
},
1287 { SDDL_LOCAL_SYSTEM
, WinLocalSystemSid
},
1288 { SDDL_NETWORK
, WinNetworkSid
},
1289 { SDDL_NETWORK_CONFIGURATION_OPS
, WinBuiltinNetworkConfigurationOperatorsSid
},
1290 { SDDL_NETWORK_SERVICE
, WinNetworkServiceSid
},
1291 { SDDL_PRINTER_OPERATORS
, WinBuiltinPrintOperatorsSid
},
1292 { SDDL_PERSONAL_SELF
, WinSelfSid
},
1293 { SDDL_POWER_USERS
, WinBuiltinPowerUsersSid
},
1294 { SDDL_RAS_SERVERS
, WinAccountRasAndIasServersSid
/* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
1295 { SDDL_REMOTE_DESKTOP
, WinBuiltinRemoteDesktopUsersSid
},
1296 { SDDL_REPLICATOR
, WinBuiltinReplicatorSid
},
1297 { SDDL_RESTRICTED_CODE
, WinRestrictedCodeSid
},
1298 { SDDL_SCHEMA_ADMINISTRATORS
, WinAccountSchemaAdminsSid
/* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
1299 { SDDL_SERVER_OPERATORS
, WinBuiltinSystemOperatorsSid
},
1300 { SDDL_SERVICE
, WinServiceSid
},
1308 ConvertStringSidToSidW(IN LPCWSTR StringSid
,
1312 DWORD i
, cBytes
, identAuth
, csubauth
;
1316 TRACE("%s %p\n", debugstr_w(StringSid
), sid
);
1320 SetLastError(ERROR_INVALID_SID
);
1323 for (i
= 0; i
< sizeof(SidTable
) / sizeof(SidTable
[0]) - 1; i
++)
1325 if (wcscmp(StringSid
, SidTable
[i
].key
) == 0)
1327 WELL_KNOWN_SID_TYPE knownSid
= (WELL_KNOWN_SID_TYPE
)SidTable
[i
].value
;
1328 size
= SECURITY_MAX_SID_SIZE
;
1329 *sid
= LocalAlloc(0, size
);
1332 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1335 ret
= CreateWellKnownSid(
1342 SetLastError(ERROR_INVALID_SID
);
1349 /* That's probably a string S-R-I-S-S... */
1350 if (StringSid
[0] != 'S' || StringSid
[1] != '-')
1352 SetLastError(ERROR_INVALID_SID
);
1356 cBytes
= ComputeStringSidSize(StringSid
);
1357 pisid
= (SID
*)LocalAlloc( 0, cBytes
);
1360 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1365 csubauth
= ((cBytes
- sizeof(SID
)) / sizeof(DWORD
)) + 1;
1367 StringSid
+= 2; /* Advance to Revision */
1368 pisid
->Revision
= atoiW(StringSid
);
1370 if (pisid
->Revision
!= SDDL_REVISION
)
1372 TRACE("Revision %d is unknown\n", pisid
->Revision
);
1373 goto lend
; /* ERROR_INVALID_SID */
1377 TRACE("SubAuthorityCount is 0\n");
1378 goto lend
; /* ERROR_INVALID_SID */
1381 pisid
->SubAuthorityCount
= csubauth
;
1383 /* Advance to identifier authority */
1384 while (*StringSid
&& *StringSid
!= '-')
1386 if (*StringSid
== '-')
1389 /* MS' implementation can't handle values greater than 2^32 - 1, so
1390 * we don't either; assume most significant bytes are always 0
1392 pisid
->IdentifierAuthority
.Value
[0] = 0;
1393 pisid
->IdentifierAuthority
.Value
[1] = 0;
1394 identAuth
= atoiW(StringSid
);
1395 pisid
->IdentifierAuthority
.Value
[5] = identAuth
& 0xff;
1396 pisid
->IdentifierAuthority
.Value
[4] = (identAuth
& 0xff00) >> 8;
1397 pisid
->IdentifierAuthority
.Value
[3] = (identAuth
& 0xff0000) >> 16;
1398 pisid
->IdentifierAuthority
.Value
[2] = (identAuth
& 0xff000000) >> 24;
1400 /* Advance to first sub authority */
1401 while (*StringSid
&& *StringSid
!= '-')
1403 if (*StringSid
== '-')
1408 while (*StringSid
&& *StringSid
!= '-')
1410 if (*StringSid
== '-')
1413 pisid
->SubAuthority
[i
++] = atoiW(StringSid
);
1416 if (i
!= pisid
->SubAuthorityCount
)
1417 goto lend
; /* ERROR_INVALID_SID */
1424 SetLastError(ERROR_INVALID_SID
);
1426 TRACE("returning %s\n", ret
? "TRUE" : "FALSE");