1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * WINE COPYRIGHT: 4 * Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net> 5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla) 6 * Copyright 2006 Robert Reif 7 * Copyright 2006 Herv� Poussineau 8 * 9 * PROJECT: ReactOS system libraries 10 * FILE: dll/win32/advapi32/wine/security.c 11 */ 12 13 #include <advapi32.h> 14 15 #include <sddl.h> 16 17 WINE_DEFAULT_DEBUG_CHANNEL(advapi); 18 19 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes); 20 21 typedef struct _ACEFLAG 22 { 23 LPCWSTR wstr; 24 DWORD value; 25 } ACEFLAG, *LPACEFLAG; 26 27 typedef struct _MAX_SID 28 { 29 /* same fields as struct _SID */ 30 BYTE Revision; 31 BYTE SubAuthorityCount; 32 SID_IDENTIFIER_AUTHORITY IdentifierAuthority; 33 DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES]; 34 } MAX_SID; 35 36 typedef struct WELLKNOWNSID 37 { 38 WCHAR wstr[2]; 39 WELL_KNOWN_SID_TYPE Type; 40 MAX_SID Sid; 41 } WELLKNOWNSID; 42 43 static const WELLKNOWNSID WellKnownSids[] = 44 { 45 { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } }, 46 { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } }, 47 { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } }, 48 { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } }, 49 { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } }, 50 { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } }, 51 { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } }, 52 { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } }, 53 { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } }, 54 { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } }, 55 { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } }, 56 { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } }, 57 { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } }, 58 { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } }, 59 { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } }, 60 { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } }, 61 { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } }, 62 { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } }, 63 { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } }, 64 { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } }, 65 { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } }, 66 { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } }, 67 { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } }, 68 { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } }, 69 { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } }, 70 { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } }, 71 { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } }, 72 { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } }, 73 { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } }, 74 { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } }, 75 { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } }, 76 { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } }, 77 { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } }, 78 { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } }, 79 { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } }, 80 { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } }, 81 { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } }, 82 { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } }, 83 { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } }, 84 { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } }, 85 { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } }, 86 { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } }, 87 { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } }, 88 { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } }, 89 { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } }, 90 { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } }, 91 { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } }, 92 { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } }, 93 { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } }, 94 { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } }, 95 { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } }, 96 { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } }, 97 }; 98 99 /* these SIDs must be constructed as relative to some domain - only the RID is well-known */ 100 typedef struct WELLKNOWNRID 101 { 102 WCHAR wstr[2]; 103 WELL_KNOWN_SID_TYPE Type; 104 DWORD Rid; 105 } WELLKNOWNRID; 106 107 static const WELLKNOWNRID WellKnownRids[] = { 108 { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN }, 109 { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST }, 110 { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT }, 111 { {'D','A'}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS }, 112 { {'D','U'}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS }, 113 { {'D','G'}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS }, 114 { {'D','C'}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS }, 115 { {'D','D'}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS }, 116 { {'C','A'}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS }, 117 { {'S','A'}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS }, 118 { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS }, 119 { {'P','A'}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS }, 120 { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS }, 121 }; 122 123 #ifndef __REACTOS__ 124 static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } }; 125 #endif 126 127 static const WCHAR SDDL_NO_READ_UP[] = {'N','R',0}; 128 static const WCHAR SDDL_NO_WRITE_UP[] = {'N','W',0}; 129 static const WCHAR SDDL_NO_EXECUTE_UP[] = {'N','X',0}; 130 131 /* 132 * ACE types 133 */ 134 static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0}; 135 static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0}; 136 #ifndef __REACTOS__ 137 static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED[] = {'O','A',0}; 138 static const WCHAR SDDL_OBJECT_ACCESS_DENIED[] = {'O','D',0}; 139 #endif 140 static const WCHAR SDDL_AUDIT[] = {'A','U',0}; 141 static const WCHAR SDDL_ALARM[] = {'A','L',0}; 142 static const WCHAR SDDL_MANDATORY_LABEL[] = {'M','L',0}; 143 #ifndef __REACTOS__ 144 static const WCHAR SDDL_OBJECT_AUDIT[] = {'O','U',0}; 145 static const WCHAR SDDL_OBJECT_ALARM[] = {'O','L',0}; 146 #endif 147 148 /* 149 * SDDL ADS Rights 150 */ 151 #define ADS_RIGHT_DS_CREATE_CHILD 0x0001 152 #define ADS_RIGHT_DS_DELETE_CHILD 0x0002 153 #define ADS_RIGHT_ACTRL_DS_LIST 0x0004 154 #define ADS_RIGHT_DS_SELF 0x0008 155 #define ADS_RIGHT_DS_READ_PROP 0x0010 156 #define ADS_RIGHT_DS_WRITE_PROP 0x0020 157 #define ADS_RIGHT_DS_DELETE_TREE 0x0040 158 #define ADS_RIGHT_DS_LIST_OBJECT 0x0080 159 #define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100 160 161 /* 162 * ACE flags 163 */ 164 static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0}; 165 static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0}; 166 static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0}; 167 static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0}; 168 static const WCHAR SDDL_INHERITED[] = {'I','D',0}; 169 static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0}; 170 static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0}; 171 172 static const char * debugstr_sid(PSID sid) 173 { 174 int auth = 0; 175 SID * psid = (SID *)sid; 176 177 if (psid == NULL) 178 return "(null)"; 179 180 auth = psid->IdentifierAuthority.Value[5] + 181 (psid->IdentifierAuthority.Value[4] << 8) + 182 (psid->IdentifierAuthority.Value[3] << 16) + 183 (psid->IdentifierAuthority.Value[2] << 24); 184 185 switch (psid->SubAuthorityCount) { 186 case 0: 187 return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth); 188 case 1: 189 return wine_dbg_sprintf("S-%d-%d-%lu", psid->Revision, auth, 190 psid->SubAuthority[0]); 191 case 2: 192 return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid->Revision, auth, 193 psid->SubAuthority[0], psid->SubAuthority[1]); 194 case 3: 195 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid->Revision, auth, 196 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]); 197 case 4: 198 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid->Revision, auth, 199 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2], 200 psid->SubAuthority[3]); 201 case 5: 202 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth, 203 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2], 204 psid->SubAuthority[3], psid->SubAuthority[4]); 205 case 6: 206 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth, 207 psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2], 208 psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]); 209 case 7: 210 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth, 211 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2], 212 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5], 213 psid->SubAuthority[6]); 214 case 8: 215 return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth, 216 psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2], 217 psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5], 218 psid->SubAuthority[6], psid->SubAuthority[7]); 219 } 220 return "(too-big)"; 221 } 222 223 /* set last error code from NT status and get the proper boolean return value */ 224 /* used for functions that are a simple wrapper around the corresponding ntdll API */ 225 static __inline BOOL set_ntstatus( NTSTATUS status ) 226 { 227 if (!NT_SUCCESS(status)) SetLastError( RtlNtStatusToDosError( status )); 228 return NT_SUCCESS(status); 229 } 230 231 static LPWSTR SERV_dup( LPCSTR str ) 232 { 233 UINT len; 234 LPWSTR wstr; 235 236 if( !str ) 237 return NULL; 238 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); 239 wstr = heap_alloc( len*sizeof (WCHAR) ); 240 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len ); 241 return wstr; 242 } 243 244 /************************************************************ 245 * ADVAPI_IsLocalComputer 246 * 247 * Checks whether the server name indicates local machine. 248 */ 249 BOOL ADVAPI_IsLocalComputer(LPCWSTR ServerName) 250 { 251 DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; 252 BOOL Result; 253 LPWSTR buf; 254 255 if (!ServerName || !ServerName[0]) 256 return TRUE; 257 258 buf = heap_alloc(dwSize * sizeof(WCHAR)); 259 Result = GetComputerNameW(buf, &dwSize); 260 if (Result && (ServerName[0] == '\\') && (ServerName[1] == '\\')) 261 ServerName += 2; 262 Result = Result && !lstrcmpW(ServerName, buf); 263 heap_free(buf); 264 265 return Result; 266 } 267 268 /************************************************************ 269 * ADVAPI_GetComputerSid 270 */ 271 BOOL ADVAPI_GetComputerSid(PSID sid) 272 { 273 static const struct /* same fields as struct SID */ 274 { 275 BYTE Revision; 276 BYTE SubAuthorityCount; 277 SID_IDENTIFIER_AUTHORITY IdentifierAuthority; 278 DWORD SubAuthority[4]; 279 } computer_sid = 280 { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } }; 281 282 memcpy( sid, &computer_sid, sizeof(computer_sid) ); 283 return TRUE; 284 } 285 286 /* Exported functions */ 287 288 /* 289 * @implemented 290 */ 291 BOOL WINAPI 292 OpenProcessToken(HANDLE ProcessHandle, 293 DWORD DesiredAccess, 294 PHANDLE TokenHandle) 295 { 296 NTSTATUS Status; 297 298 TRACE("%p, %x, %p.\n", ProcessHandle, DesiredAccess, TokenHandle); 299 300 Status = NtOpenProcessToken(ProcessHandle, 301 DesiredAccess, 302 TokenHandle); 303 if (!NT_SUCCESS(Status)) 304 { 305 ERR("NtOpenProcessToken failed! Status %08x.\n", Status); 306 SetLastError(RtlNtStatusToDosError(Status)); 307 return FALSE; 308 } 309 310 TRACE("Returning token %p.\n", *TokenHandle); 311 312 return TRUE; 313 } 314 315 /****************************************************************************** 316 * OpenThreadToken [ADVAPI32.@] 317 * 318 * Opens the access token associated with a thread handle. 319 * 320 * PARAMS 321 * ThreadHandle [I] Handle to process 322 * DesiredAccess [I] Desired access to the thread 323 * OpenAsSelf [I] ??? 324 * TokenHandle [O] Destination for the token handle 325 * 326 * RETURNS 327 * Success: TRUE. TokenHandle contains the access token. 328 * Failure: FALSE. 329 * 330 * NOTES 331 * See NtOpenThreadToken. 332 */ 333 BOOL WINAPI 334 OpenThreadToken( HANDLE ThreadHandle, DWORD DesiredAccess, 335 BOOL OpenAsSelf, HANDLE *TokenHandle) 336 { 337 return set_ntstatus( NtOpenThreadToken(ThreadHandle, DesiredAccess, OpenAsSelf, TokenHandle)); 338 } 339 340 /* 341 * @implemented 342 */ 343 BOOL WINAPI 344 AdjustTokenGroups(HANDLE TokenHandle, 345 BOOL ResetToDefault, 346 PTOKEN_GROUPS NewState, 347 DWORD BufferLength, 348 PTOKEN_GROUPS PreviousState, 349 PDWORD ReturnLength) 350 { 351 NTSTATUS Status; 352 353 Status = NtAdjustGroupsToken(TokenHandle, 354 ResetToDefault, 355 NewState, 356 BufferLength, 357 PreviousState, 358 (PULONG)ReturnLength); 359 if (!NT_SUCCESS(Status)) 360 { 361 SetLastError(RtlNtStatusToDosError(Status)); 362 return FALSE; 363 } 364 365 return TRUE; 366 } 367 368 /* 369 * @implemented 370 */ 371 BOOL WINAPI 372 AdjustTokenPrivileges(HANDLE TokenHandle, 373 BOOL DisableAllPrivileges, 374 PTOKEN_PRIVILEGES NewState, 375 DWORD BufferLength, 376 PTOKEN_PRIVILEGES PreviousState, 377 PDWORD ReturnLength) 378 { 379 NTSTATUS Status; 380 381 Status = NtAdjustPrivilegesToken(TokenHandle, 382 DisableAllPrivileges, 383 NewState, 384 BufferLength, 385 PreviousState, 386 (PULONG)ReturnLength); 387 if (STATUS_NOT_ALL_ASSIGNED == Status) 388 { 389 SetLastError(ERROR_NOT_ALL_ASSIGNED); 390 return TRUE; 391 } 392 393 if (!NT_SUCCESS(Status)) 394 { 395 SetLastError(RtlNtStatusToDosError(Status)); 396 return FALSE; 397 } 398 399 /* AdjustTokenPrivileges is documented to do this */ 400 SetLastError(ERROR_SUCCESS); 401 402 return TRUE; 403 } 404 405 /* 406 * @implemented 407 */ 408 BOOL WINAPI 409 GetTokenInformation(HANDLE TokenHandle, 410 TOKEN_INFORMATION_CLASS TokenInformationClass, 411 LPVOID TokenInformation, 412 DWORD TokenInformationLength, 413 PDWORD ReturnLength) 414 { 415 NTSTATUS Status; 416 417 Status = NtQueryInformationToken(TokenHandle, 418 TokenInformationClass, 419 TokenInformation, 420 TokenInformationLength, 421 (PULONG)ReturnLength); 422 if (!NT_SUCCESS(Status)) 423 { 424 SetLastError(RtlNtStatusToDosError(Status)); 425 return FALSE; 426 } 427 428 return TRUE; 429 } 430 431 /* 432 * @implemented 433 */ 434 BOOL WINAPI 435 SetTokenInformation(HANDLE TokenHandle, 436 TOKEN_INFORMATION_CLASS TokenInformationClass, 437 LPVOID TokenInformation, 438 DWORD TokenInformationLength) 439 { 440 NTSTATUS Status; 441 442 Status = NtSetInformationToken(TokenHandle, 443 TokenInformationClass, 444 TokenInformation, 445 TokenInformationLength); 446 if (!NT_SUCCESS(Status)) 447 { 448 SetLastError(RtlNtStatusToDosError(Status)); 449 return FALSE; 450 } 451 452 return TRUE; 453 } 454 455 /* 456 * @implemented 457 */ 458 BOOL WINAPI 459 SetThreadToken(IN PHANDLE ThreadHandle OPTIONAL, 460 IN HANDLE TokenHandle) 461 { 462 NTSTATUS Status; 463 HANDLE hThread; 464 465 hThread = (ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread(); 466 467 Status = NtSetInformationThread(hThread, 468 ThreadImpersonationToken, 469 &TokenHandle, 470 sizeof(HANDLE)); 471 if (!NT_SUCCESS(Status)) 472 { 473 SetLastError(RtlNtStatusToDosError(Status)); 474 return FALSE; 475 } 476 477 return TRUE; 478 } 479 480 /************************************************************************* 481 * CreateRestrictedToken [ADVAPI32.@] 482 * 483 * Create a new more restricted token from an existing token. 484 * 485 * PARAMS 486 * baseToken [I] Token to base the new restricted token on 487 * flags [I] Options 488 * nDisableSids [I] Length of disableSids array 489 * disableSids [I] Array of SIDs to disable in the new token 490 * nDeletePrivs [I] Length of deletePrivs array 491 * deletePrivs [I] Array of privileges to delete in the new token 492 * nRestrictSids [I] Length of restrictSids array 493 * restrictSids [I] Array of SIDs to restrict in the new token 494 * newToken [O] Address where the new token is stored 495 * 496 * RETURNS 497 * Success: TRUE 498 * Failure: FALSE 499 */ 500 BOOL WINAPI CreateRestrictedToken( 501 HANDLE baseToken, 502 DWORD flags, 503 DWORD nDisableSids, 504 PSID_AND_ATTRIBUTES disableSids, 505 DWORD nDeletePrivs, 506 PLUID_AND_ATTRIBUTES deletePrivs, 507 DWORD nRestrictSids, 508 PSID_AND_ATTRIBUTES restrictSids, 509 PHANDLE newToken) 510 { 511 TOKEN_TYPE type; 512 SECURITY_IMPERSONATION_LEVEL level = SecurityAnonymous; 513 DWORD size; 514 515 FIXME("(%p, 0x%x, %u, %p, %u, %p, %u, %p, %p): stub\n", 516 baseToken, flags, nDisableSids, disableSids, 517 nDeletePrivs, deletePrivs, 518 nRestrictSids, restrictSids, 519 newToken); 520 521 size = sizeof(type); 522 if (!GetTokenInformation( baseToken, TokenType, &type, size, &size )) return FALSE; 523 if (type == TokenImpersonation) 524 { 525 size = sizeof(level); 526 if (!GetTokenInformation( baseToken, TokenImpersonationLevel, &level, size, &size )) 527 return FALSE; 528 } 529 return DuplicateTokenEx( baseToken, MAXIMUM_ALLOWED, NULL, level, type, newToken ); 530 } 531 532 /****************************************************************************** 533 * AllocateAndInitializeSid [ADVAPI32.@] 534 * 535 * PARAMS 536 * pIdentifierAuthority [] 537 * nSubAuthorityCount [] 538 * nSubAuthority0 [] 539 * nSubAuthority1 [] 540 * nSubAuthority2 [] 541 * nSubAuthority3 [] 542 * nSubAuthority4 [] 543 * nSubAuthority5 [] 544 * nSubAuthority6 [] 545 * nSubAuthority7 [] 546 * pSid [] 547 */ 548 BOOL WINAPI 549 AllocateAndInitializeSid( PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, 550 BYTE nSubAuthorityCount, 551 DWORD nSubAuthority0, DWORD nSubAuthority1, 552 DWORD nSubAuthority2, DWORD nSubAuthority3, 553 DWORD nSubAuthority4, DWORD nSubAuthority5, 554 DWORD nSubAuthority6, DWORD nSubAuthority7, 555 PSID *pSid ) 556 { 557 return set_ntstatus( RtlAllocateAndInitializeSid( 558 pIdentifierAuthority, nSubAuthorityCount, 559 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3, 560 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, 561 pSid )); 562 } 563 564 /* 565 * @implemented 566 * 567 * RETURNS 568 * Docs says this function does NOT return a value 569 * even thou it's defined to return a PVOID... 570 */ 571 PVOID 572 WINAPI 573 FreeSid(PSID pSid) 574 { 575 return RtlFreeSid(pSid); 576 } 577 578 /****************************************************************************** 579 * CopySid [ADVAPI32.@] 580 * 581 * PARAMS 582 * nDestinationSidLength [] 583 * pDestinationSid [] 584 * pSourceSid [] 585 */ 586 BOOL WINAPI 587 CopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid ) 588 { 589 return set_ntstatus(RtlCopySid(nDestinationSidLength, pDestinationSid, pSourceSid)); 590 } 591 592 /* 593 * @unimplemented 594 */ 595 BOOL 596 WINAPI 597 CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType, 598 IN PSID DomainSid OPTIONAL, 599 OUT PSID pSid, 600 IN OUT DWORD* cbSid) 601 { 602 unsigned int i; 603 TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid); 604 605 if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid))) 606 { 607 SetLastError(ERROR_INVALID_PARAMETER); 608 return FALSE; 609 } 610 611 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) { 612 if (WellKnownSids[i].Type == WellKnownSidType) { 613 DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount); 614 615 if (*cbSid < length) 616 { 617 *cbSid = length; 618 SetLastError(ERROR_INSUFFICIENT_BUFFER); 619 return FALSE; 620 } 621 if (!pSid) 622 { 623 SetLastError(ERROR_INVALID_PARAMETER); 624 return FALSE; 625 } 626 CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length); 627 *cbSid = length; 628 return TRUE; 629 } 630 } 631 632 if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES) 633 { 634 SetLastError(ERROR_INVALID_PARAMETER); 635 return FALSE; 636 } 637 638 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++) 639 if (WellKnownRids[i].Type == WellKnownSidType) { 640 UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid); 641 DWORD domain_sid_length = GetSidLengthRequired(domain_subauth); 642 DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1); 643 644 if (*cbSid < output_sid_length) 645 { 646 *cbSid = output_sid_length; 647 SetLastError(ERROR_INSUFFICIENT_BUFFER); 648 return FALSE; 649 } 650 if (!pSid) 651 { 652 SetLastError(ERROR_INVALID_PARAMETER); 653 return FALSE; 654 } 655 CopyMemory(pSid, DomainSid, domain_sid_length); 656 (*GetSidSubAuthorityCount(pSid))++; 657 (*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid; 658 *cbSid = output_sid_length; 659 return TRUE; 660 } 661 662 SetLastError(ERROR_INVALID_PARAMETER); 663 return FALSE; 664 } 665 666 /* 667 * @unimplemented 668 */ 669 BOOL 670 WINAPI 671 IsWellKnownSid(IN PSID pSid, 672 IN WELL_KNOWN_SID_TYPE WellKnownSidType) 673 { 674 unsigned int i; 675 TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType); 676 677 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++) 678 { 679 if (WellKnownSids[i].Type == WellKnownSidType) 680 { 681 if (EqualSid(pSid, (PSID)(&WellKnownSids[i].Sid.Revision))) 682 return TRUE; 683 } 684 } 685 686 return FALSE; 687 } 688 689 /* 690 * @implemented 691 */ 692 BOOL 693 WINAPI 694 IsValidSid(PSID pSid) 695 { 696 return (BOOL)RtlValidSid(pSid); 697 } 698 699 /* 700 * @implemented 701 */ 702 BOOL 703 WINAPI 704 EqualSid(PSID pSid1, 705 PSID pSid2) 706 { 707 SetLastError(ERROR_SUCCESS); 708 return RtlEqualSid (pSid1, pSid2); 709 } 710 711 /* 712 * @implemented 713 */ 714 BOOL 715 WINAPI 716 EqualPrefixSid(PSID pSid1, 717 PSID pSid2) 718 { 719 return RtlEqualPrefixSid (pSid1, pSid2); 720 } 721 722 /* 723 * @implemented 724 */ 725 DWORD 726 WINAPI 727 GetSidLengthRequired(UCHAR nSubAuthorityCount) 728 { 729 return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount); 730 } 731 732 /* 733 * @implemented 734 */ 735 BOOL 736 WINAPI 737 InitializeSid(PSID Sid, 738 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, 739 BYTE nSubAuthorityCount) 740 { 741 NTSTATUS Status; 742 743 Status = RtlInitializeSid(Sid, 744 pIdentifierAuthority, 745 nSubAuthorityCount); 746 if (!NT_SUCCESS(Status)) 747 { 748 SetLastError(RtlNtStatusToDosError(Status)); 749 return FALSE; 750 } 751 752 return TRUE; 753 } 754 755 /* 756 * @implemented 757 */ 758 PSID_IDENTIFIER_AUTHORITY 759 WINAPI 760 GetSidIdentifierAuthority(PSID pSid) 761 { 762 return RtlIdentifierAuthoritySid(pSid); 763 } 764 765 /* 766 * @implemented 767 */ 768 PDWORD 769 WINAPI 770 GetSidSubAuthority(PSID pSid, 771 DWORD nSubAuthority) 772 { 773 SetLastError(ERROR_SUCCESS); 774 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority); 775 } 776 777 /* 778 * @implemented 779 */ 780 PUCHAR 781 WINAPI 782 GetSidSubAuthorityCount(PSID pSid) 783 { 784 SetLastError(ERROR_SUCCESS); 785 return RtlSubAuthorityCountSid(pSid); 786 } 787 788 /* 789 * @implemented 790 */ 791 DWORD 792 WINAPI 793 GetLengthSid(PSID pSid) 794 { 795 return (DWORD)RtlLengthSid(pSid); 796 } 797 798 /* 799 * @implemented 800 */ 801 BOOL 802 WINAPI 803 InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, 804 DWORD dwRevision) 805 { 806 NTSTATUS Status; 807 808 Status = RtlCreateSecurityDescriptor(pSecurityDescriptor, 809 dwRevision); 810 if (!NT_SUCCESS(Status)) 811 { 812 SetLastError(RtlNtStatusToDosError(Status)); 813 return FALSE; 814 } 815 816 return TRUE; 817 } 818 819 /* 820 * @implemented 821 */ 822 BOOL 823 WINAPI 824 MakeAbsoluteSD(PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, 825 PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, 826 LPDWORD lpdwAbsoluteSecurityDescriptorSize, 827 PACL pDacl, 828 LPDWORD lpdwDaclSize, 829 PACL pSacl, 830 LPDWORD lpdwSaclSize, 831 PSID pOwner, 832 LPDWORD lpdwOwnerSize, 833 PSID pPrimaryGroup, 834 LPDWORD lpdwPrimaryGroupSize) 835 { 836 NTSTATUS Status; 837 838 Status = RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor, 839 pAbsoluteSecurityDescriptor, 840 lpdwAbsoluteSecurityDescriptorSize, 841 pDacl, 842 lpdwDaclSize, 843 pSacl, 844 lpdwSaclSize, 845 pOwner, 846 lpdwOwnerSize, 847 pPrimaryGroup, 848 lpdwPrimaryGroupSize); 849 if (!NT_SUCCESS(Status)) 850 { 851 SetLastError(RtlNtStatusToDosError(Status)); 852 return FALSE; 853 } 854 855 return TRUE; 856 } 857 858 /****************************************************************************** 859 * GetKernelObjectSecurity [ADVAPI32.@] 860 */ 861 BOOL WINAPI GetKernelObjectSecurity( 862 HANDLE Handle, 863 SECURITY_INFORMATION RequestedInformation, 864 PSECURITY_DESCRIPTOR pSecurityDescriptor, 865 DWORD nLength, 866 LPDWORD lpnLengthNeeded ) 867 { 868 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation, 869 pSecurityDescriptor, nLength, lpnLengthNeeded); 870 871 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor, 872 nLength, lpnLengthNeeded )); 873 } 874 875 /* 876 * @implemented 877 */ 878 BOOL 879 WINAPI 880 InitializeAcl(PACL pAcl, 881 DWORD nAclLength, 882 DWORD dwAclRevision) 883 { 884 NTSTATUS Status; 885 886 Status = RtlCreateAcl(pAcl, 887 nAclLength, 888 dwAclRevision); 889 if (!NT_SUCCESS(Status)) 890 { 891 SetLastError(RtlNtStatusToDosError(Status)); 892 return FALSE; 893 } 894 895 return TRUE; 896 } 897 898 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe ) 899 { 900 IO_STATUS_BLOCK io_block; 901 902 TRACE("(%p)\n", hNamedPipe); 903 904 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL, 905 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) ); 906 } 907 908 /* 909 * @implemented 910 */ 911 BOOL 912 WINAPI 913 AddAccessAllowedAce(PACL pAcl, 914 DWORD dwAceRevision, 915 DWORD AccessMask, 916 PSID pSid) 917 { 918 NTSTATUS Status; 919 920 Status = RtlAddAccessAllowedAce(pAcl, 921 dwAceRevision, 922 AccessMask, 923 pSid); 924 if (!NT_SUCCESS(Status)) 925 { 926 SetLastError(RtlNtStatusToDosError(Status)); 927 return FALSE; 928 } 929 930 return TRUE; 931 } 932 933 /* 934 * @implemented 935 */ 936 BOOL WINAPI 937 AddAccessAllowedAceEx(PACL pAcl, 938 DWORD dwAceRevision, 939 DWORD AceFlags, 940 DWORD AccessMask, 941 PSID pSid) 942 { 943 NTSTATUS Status; 944 945 Status = RtlAddAccessAllowedAceEx(pAcl, 946 dwAceRevision, 947 AceFlags, 948 AccessMask, 949 pSid); 950 if (!NT_SUCCESS(Status)) 951 { 952 SetLastError(RtlNtStatusToDosError(Status)); 953 return FALSE; 954 } 955 956 return TRUE; 957 } 958 959 /* 960 * @implemented 961 */ 962 BOOL 963 WINAPI 964 AddAccessDeniedAce(PACL pAcl, 965 DWORD dwAceRevision, 966 DWORD AccessMask, 967 PSID pSid) 968 { 969 NTSTATUS Status; 970 971 Status = RtlAddAccessDeniedAce(pAcl, 972 dwAceRevision, 973 AccessMask, 974 pSid); 975 if (!NT_SUCCESS(Status)) 976 { 977 SetLastError(RtlNtStatusToDosError(Status)); 978 return FALSE; 979 } 980 981 return TRUE; 982 } 983 984 /* 985 * @implemented 986 */ 987 BOOL WINAPI 988 AddAccessDeniedAceEx(PACL pAcl, 989 DWORD dwAceRevision, 990 DWORD AceFlags, 991 DWORD AccessMask, 992 PSID pSid) 993 { 994 NTSTATUS Status; 995 996 Status = RtlAddAccessDeniedAceEx(pAcl, 997 dwAceRevision, 998 AceFlags, 999 AccessMask, 1000 pSid); 1001 if (!NT_SUCCESS(Status)) 1002 { 1003 SetLastError(RtlNtStatusToDosError(Status)); 1004 return FALSE; 1005 } 1006 1007 return TRUE; 1008 } 1009 1010 /* 1011 * @implemented 1012 */ 1013 BOOL 1014 WINAPI 1015 AddAce(PACL pAcl, 1016 DWORD dwAceRevision, 1017 DWORD dwStartingAceIndex, 1018 LPVOID pAceList, 1019 DWORD nAceListLength) 1020 { 1021 NTSTATUS Status; 1022 1023 Status = RtlAddAce(pAcl, 1024 dwAceRevision, 1025 dwStartingAceIndex, 1026 pAceList, 1027 nAceListLength); 1028 if (!NT_SUCCESS(Status)) 1029 { 1030 SetLastError(RtlNtStatusToDosError(Status)); 1031 return FALSE; 1032 } 1033 1034 return TRUE; 1035 } 1036 1037 /****************************************************************************** 1038 * DeleteAce [ADVAPI32.@] 1039 */ 1040 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex) 1041 { 1042 return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex)); 1043 } 1044 1045 /* 1046 * @implemented 1047 */ 1048 BOOL 1049 WINAPI 1050 FindFirstFreeAce(PACL pAcl, 1051 LPVOID *pAce) 1052 { 1053 return RtlFirstFreeAce(pAcl, 1054 (PACE*)pAce); 1055 } 1056 1057 /****************************************************************************** 1058 * GetAce [ADVAPI32.@] 1059 */ 1060 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce ) 1061 { 1062 return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce)); 1063 } 1064 1065 /****************************************************************************** 1066 * GetAclInformation [ADVAPI32.@] 1067 */ 1068 BOOL WINAPI GetAclInformation( 1069 PACL pAcl, 1070 LPVOID pAclInformation, 1071 DWORD nAclInformationLength, 1072 ACL_INFORMATION_CLASS dwAclInformationClass) 1073 { 1074 return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation, 1075 nAclInformationLength, dwAclInformationClass)); 1076 } 1077 1078 /* 1079 * @implemented 1080 */ 1081 BOOL 1082 WINAPI 1083 IsValidAcl(PACL pAcl) 1084 { 1085 return RtlValidAcl (pAcl); 1086 } 1087 1088 /* 1089 * @implemented 1090 */ 1091 BOOL WINAPI 1092 AllocateLocallyUniqueId(PLUID Luid) 1093 { 1094 NTSTATUS Status; 1095 1096 Status = NtAllocateLocallyUniqueId (Luid); 1097 if (!NT_SUCCESS (Status)) 1098 { 1099 SetLastError(RtlNtStatusToDosError(Status)); 1100 return FALSE; 1101 } 1102 1103 return TRUE; 1104 } 1105 1106 /********************************************************************** 1107 * LookupPrivilegeDisplayNameA EXPORTED 1108 * 1109 * @unimplemented 1110 */ 1111 BOOL 1112 WINAPI 1113 LookupPrivilegeDisplayNameA(LPCSTR lpSystemName, 1114 LPCSTR lpName, 1115 LPSTR lpDisplayName, 1116 LPDWORD cchDisplayName, 1117 LPDWORD lpLanguageId) 1118 { 1119 UNICODE_STRING lpSystemNameW; 1120 UNICODE_STRING lpNameW; 1121 BOOL ret; 1122 DWORD wLen = 0; 1123 1124 TRACE("%s %s %p %p %p\n", debugstr_a(lpSystemName), debugstr_a(lpName), lpName, cchDisplayName, lpLanguageId); 1125 1126 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName); 1127 RtlCreateUnicodeStringFromAsciiz(&lpNameW, lpName); 1128 ret = LookupPrivilegeDisplayNameW(lpSystemNameW.Buffer, lpNameW.Buffer, NULL, &wLen, lpLanguageId); 1129 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 1130 { 1131 LPWSTR lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR)); 1132 1133 ret = LookupPrivilegeDisplayNameW(lpSystemNameW.Buffer, lpNameW.Buffer, lpDisplayNameW, 1134 &wLen, lpLanguageId); 1135 if (ret) 1136 { 1137 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, lpDisplayName, 1138 *cchDisplayName, NULL, NULL); 1139 1140 if (len == 0) 1141 { 1142 /* WideCharToMultiByte failed */ 1143 ret = FALSE; 1144 } 1145 else if (len > *cchDisplayName) 1146 { 1147 *cchDisplayName = len; 1148 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1149 ret = FALSE; 1150 } 1151 else 1152 { 1153 /* WideCharToMultiByte succeeded, output length needs to be 1154 * length not including NULL terminator 1155 */ 1156 *cchDisplayName = len - 1; 1157 } 1158 } 1159 HeapFree(GetProcessHeap(), 0, lpDisplayNameW); 1160 } 1161 RtlFreeUnicodeString(&lpSystemNameW); 1162 RtlFreeUnicodeString(&lpNameW); 1163 return ret; 1164 } 1165 1166 /********************************************************************** 1167 * LookupPrivilegeNameA EXPORTED 1168 * 1169 * @implemented 1170 */ 1171 BOOL 1172 WINAPI 1173 LookupPrivilegeNameA(LPCSTR lpSystemName, 1174 PLUID lpLuid, 1175 LPSTR lpName, 1176 LPDWORD cchName) 1177 { 1178 UNICODE_STRING lpSystemNameW; 1179 BOOL ret; 1180 DWORD wLen = 0; 1181 1182 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName); 1183 1184 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName); 1185 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen); 1186 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 1187 { 1188 LPWSTR lpNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR)); 1189 1190 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW, 1191 &wLen); 1192 if (ret) 1193 { 1194 /* Windows crashes if cchName is NULL, so will I */ 1195 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName, 1196 *cchName, NULL, NULL); 1197 1198 if (len == 0) 1199 { 1200 /* WideCharToMultiByte failed */ 1201 ret = FALSE; 1202 } 1203 else if (len > *cchName) 1204 { 1205 *cchName = len; 1206 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1207 ret = FALSE; 1208 } 1209 else 1210 { 1211 /* WideCharToMultiByte succeeded, output length needs to be 1212 * length not including NULL terminator 1213 */ 1214 *cchName = len - 1; 1215 } 1216 } 1217 HeapFree(GetProcessHeap(), 0, lpNameW); 1218 } 1219 RtlFreeUnicodeString(&lpSystemNameW); 1220 return ret; 1221 } 1222 1223 /****************************************************************************** 1224 * GetFileSecurityA [ADVAPI32.@] 1225 * 1226 * Obtains Specified information about the security of a file or directory. 1227 * 1228 * PARAMS 1229 * lpFileName [I] Name of the file to get info for 1230 * RequestedInformation [I] SE_ flags from "winnt.h" 1231 * pSecurityDescriptor [O] Destination for security information 1232 * nLength [I] Length of pSecurityDescriptor 1233 * lpnLengthNeeded [O] Destination for length of returned security information 1234 * 1235 * RETURNS 1236 * Success: TRUE. pSecurityDescriptor contains the requested information. 1237 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info. 1238 * 1239 * NOTES 1240 * The information returned is constrained by the callers access rights and 1241 * privileges. 1242 * 1243 * @implemented 1244 */ 1245 BOOL 1246 WINAPI 1247 GetFileSecurityA(LPCSTR lpFileName, 1248 SECURITY_INFORMATION RequestedInformation, 1249 PSECURITY_DESCRIPTOR pSecurityDescriptor, 1250 DWORD nLength, 1251 LPDWORD lpnLengthNeeded) 1252 { 1253 UNICODE_STRING FileName; 1254 BOOL bResult; 1255 1256 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName)) 1257 { 1258 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1259 return FALSE; 1260 } 1261 1262 bResult = GetFileSecurityW(FileName.Buffer, 1263 RequestedInformation, 1264 pSecurityDescriptor, 1265 nLength, 1266 lpnLengthNeeded); 1267 1268 RtlFreeUnicodeString(&FileName); 1269 1270 return bResult; 1271 } 1272 1273 /* 1274 * @implemented 1275 */ 1276 BOOL 1277 WINAPI 1278 GetFileSecurityW(LPCWSTR lpFileName, 1279 SECURITY_INFORMATION RequestedInformation, 1280 PSECURITY_DESCRIPTOR pSecurityDescriptor, 1281 DWORD nLength, 1282 LPDWORD lpnLengthNeeded) 1283 { 1284 OBJECT_ATTRIBUTES ObjectAttributes; 1285 IO_STATUS_BLOCK StatusBlock; 1286 UNICODE_STRING FileName; 1287 ULONG AccessMask = 0; 1288 HANDLE FileHandle; 1289 NTSTATUS Status; 1290 1291 TRACE("GetFileSecurityW() called\n"); 1292 1293 QuerySecurityAccessMask(RequestedInformation, &AccessMask); 1294 1295 if (!RtlDosPathNameToNtPathName_U(lpFileName, 1296 &FileName, 1297 NULL, 1298 NULL)) 1299 { 1300 ERR("Invalid path\n"); 1301 SetLastError(ERROR_INVALID_NAME); 1302 return FALSE; 1303 } 1304 1305 InitializeObjectAttributes(&ObjectAttributes, 1306 &FileName, 1307 OBJ_CASE_INSENSITIVE, 1308 NULL, 1309 NULL); 1310 1311 Status = NtOpenFile(&FileHandle, 1312 AccessMask, 1313 &ObjectAttributes, 1314 &StatusBlock, 1315 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 1316 0); 1317 1318 RtlFreeHeap(RtlGetProcessHeap(), 1319 0, 1320 FileName.Buffer); 1321 1322 if (!NT_SUCCESS(Status)) 1323 { 1324 ERR("NtOpenFile() failed (Status %lx)\n", Status); 1325 SetLastError(RtlNtStatusToDosError(Status)); 1326 return FALSE; 1327 } 1328 1329 Status = NtQuerySecurityObject(FileHandle, 1330 RequestedInformation, 1331 pSecurityDescriptor, 1332 nLength, 1333 lpnLengthNeeded); 1334 NtClose(FileHandle); 1335 if (!NT_SUCCESS(Status)) 1336 { 1337 ERR("NtQuerySecurityObject() failed (Status %lx)\n", Status); 1338 SetLastError(RtlNtStatusToDosError(Status)); 1339 return FALSE; 1340 } 1341 1342 return TRUE; 1343 } 1344 1345 /****************************************************************************** 1346 * SetFileSecurityA [ADVAPI32.@] 1347 * Sets the security of a file or directory 1348 * 1349 * @implemented 1350 */ 1351 BOOL 1352 WINAPI 1353 SetFileSecurityA(LPCSTR lpFileName, 1354 SECURITY_INFORMATION SecurityInformation, 1355 PSECURITY_DESCRIPTOR pSecurityDescriptor) 1356 { 1357 UNICODE_STRING FileName; 1358 BOOL bResult; 1359 1360 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName)) 1361 { 1362 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1363 return FALSE; 1364 } 1365 1366 bResult = SetFileSecurityW(FileName.Buffer, 1367 SecurityInformation, 1368 pSecurityDescriptor); 1369 1370 RtlFreeUnicodeString(&FileName); 1371 1372 return bResult; 1373 } 1374 1375 /****************************************************************************** 1376 * SetFileSecurityW [ADVAPI32.@] 1377 * Sets the security of a file or directory 1378 * 1379 * @implemented 1380 */ 1381 BOOL 1382 WINAPI 1383 SetFileSecurityW(LPCWSTR lpFileName, 1384 SECURITY_INFORMATION SecurityInformation, 1385 PSECURITY_DESCRIPTOR pSecurityDescriptor) 1386 { 1387 OBJECT_ATTRIBUTES ObjectAttributes; 1388 IO_STATUS_BLOCK StatusBlock; 1389 UNICODE_STRING FileName; 1390 ULONG AccessMask = 0; 1391 HANDLE FileHandle; 1392 NTSTATUS Status; 1393 1394 TRACE("SetFileSecurityW() called\n"); 1395 1396 SetSecurityAccessMask(SecurityInformation, &AccessMask); 1397 1398 if (!RtlDosPathNameToNtPathName_U(lpFileName, 1399 &FileName, 1400 NULL, 1401 NULL)) 1402 { 1403 ERR("Invalid path\n"); 1404 SetLastError(ERROR_INVALID_NAME); 1405 return FALSE; 1406 } 1407 1408 InitializeObjectAttributes(&ObjectAttributes, 1409 &FileName, 1410 OBJ_CASE_INSENSITIVE, 1411 NULL, 1412 NULL); 1413 1414 Status = NtOpenFile(&FileHandle, 1415 AccessMask, 1416 &ObjectAttributes, 1417 &StatusBlock, 1418 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 1419 0); 1420 1421 RtlFreeHeap(RtlGetProcessHeap(), 1422 0, 1423 FileName.Buffer); 1424 1425 if (!NT_SUCCESS(Status)) 1426 { 1427 ERR("NtOpenFile() failed (Status %lx)\n", Status); 1428 SetLastError(RtlNtStatusToDosError(Status)); 1429 return FALSE; 1430 } 1431 1432 Status = NtSetSecurityObject(FileHandle, 1433 SecurityInformation, 1434 pSecurityDescriptor); 1435 NtClose(FileHandle); 1436 1437 if (!NT_SUCCESS(Status)) 1438 { 1439 ERR("NtSetSecurityObject() failed (Status %lx)\n", Status); 1440 SetLastError(RtlNtStatusToDosError(Status)); 1441 return FALSE; 1442 } 1443 1444 return TRUE; 1445 } 1446 1447 /****************************************************************************** 1448 * QueryWindows31FilesMigration [ADVAPI32.@] 1449 * 1450 * PARAMS 1451 * x1 [] 1452 */ 1453 BOOL WINAPI 1454 QueryWindows31FilesMigration( DWORD x1 ) 1455 { 1456 FIXME("(%d):stub\n",x1); 1457 return TRUE; 1458 } 1459 1460 /****************************************************************************** 1461 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@] 1462 * 1463 * PARAMS 1464 * x1 [] 1465 * x2 [] 1466 * x3 [] 1467 * x4 [] 1468 */ 1469 BOOL WINAPI 1470 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3, 1471 DWORD x4 ) 1472 { 1473 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4); 1474 return TRUE; 1475 } 1476 1477 /* 1478 * @implemented 1479 */ 1480 BOOL 1481 WINAPI 1482 RevertToSelf(VOID) 1483 { 1484 NTSTATUS Status; 1485 HANDLE Token = NULL; 1486 1487 Status = NtSetInformationThread(NtCurrentThread(), 1488 ThreadImpersonationToken, 1489 &Token, 1490 sizeof(HANDLE)); 1491 if (!NT_SUCCESS(Status)) 1492 { 1493 SetLastError(RtlNtStatusToDosError(Status)); 1494 return FALSE; 1495 } 1496 1497 return TRUE; 1498 } 1499 1500 /* 1501 * @implemented 1502 */ 1503 BOOL 1504 WINAPI 1505 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel) 1506 { 1507 NTSTATUS Status; 1508 1509 Status = RtlImpersonateSelf(ImpersonationLevel); 1510 if (!NT_SUCCESS(Status)) 1511 { 1512 SetLastError(RtlNtStatusToDosError(Status)); 1513 return FALSE; 1514 } 1515 1516 return TRUE; 1517 } 1518 1519 /* 1520 * @implemented 1521 */ 1522 BOOL 1523 WINAPI 1524 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor, 1525 IN HANDLE ClientToken, 1526 IN DWORD DesiredAccess, 1527 IN PGENERIC_MAPPING GenericMapping, 1528 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL, 1529 IN OUT LPDWORD PrivilegeSetLength, 1530 OUT LPDWORD GrantedAccess, 1531 OUT LPBOOL AccessStatus) 1532 { 1533 NTSTATUS Status; 1534 NTSTATUS NtAccessStatus; 1535 1536 /* Do the access check */ 1537 Status = NtAccessCheck(pSecurityDescriptor, 1538 ClientToken, 1539 DesiredAccess, 1540 GenericMapping, 1541 PrivilegeSet, 1542 (PULONG)PrivilegeSetLength, 1543 (PACCESS_MASK)GrantedAccess, 1544 &NtAccessStatus); 1545 1546 /* See if the access check operation succeeded */ 1547 if (!NT_SUCCESS(Status)) 1548 { 1549 /* Check failed */ 1550 SetLastError(RtlNtStatusToDosError(Status)); 1551 return FALSE; 1552 } 1553 1554 /* Now check the access status */ 1555 if (!NT_SUCCESS(NtAccessStatus)) 1556 { 1557 /* Access denied */ 1558 SetLastError(RtlNtStatusToDosError(NtAccessStatus)); 1559 *AccessStatus = FALSE; 1560 } 1561 else 1562 { 1563 /* Access granted */ 1564 *AccessStatus = TRUE; 1565 } 1566 1567 /* Check succeeded */ 1568 return TRUE; 1569 } 1570 1571 /* 1572 * @unimplemented 1573 */ 1574 BOOL WINAPI AccessCheckByType( 1575 PSECURITY_DESCRIPTOR pSecurityDescriptor, 1576 PSID PrincipalSelfSid, 1577 HANDLE ClientToken, 1578 DWORD DesiredAccess, 1579 POBJECT_TYPE_LIST ObjectTypeList, 1580 DWORD ObjectTypeListLength, 1581 PGENERIC_MAPPING GenericMapping, 1582 PPRIVILEGE_SET PrivilegeSet, 1583 LPDWORD PrivilegeSetLength, 1584 LPDWORD GrantedAccess, 1585 LPBOOL AccessStatus) 1586 { 1587 FIXME("stub\n"); 1588 1589 *AccessStatus = TRUE; 1590 1591 return !*AccessStatus; 1592 } 1593 1594 /* 1595 * @implemented 1596 */ 1597 BOOL 1598 WINAPI 1599 SetKernelObjectSecurity(HANDLE Handle, 1600 SECURITY_INFORMATION SecurityInformation, 1601 PSECURITY_DESCRIPTOR SecurityDescriptor) 1602 { 1603 NTSTATUS Status; 1604 1605 Status = NtSetSecurityObject(Handle, 1606 SecurityInformation, 1607 SecurityDescriptor); 1608 if (!NT_SUCCESS(Status)) 1609 { 1610 SetLastError(RtlNtStatusToDosError(Status)); 1611 return FALSE; 1612 } 1613 1614 return TRUE; 1615 } 1616 1617 /* 1618 * @implemented 1619 */ 1620 BOOL 1621 WINAPI 1622 AddAuditAccessAce(PACL pAcl, 1623 DWORD dwAceRevision, 1624 DWORD dwAccessMask, 1625 PSID pSid, 1626 BOOL bAuditSuccess, 1627 BOOL bAuditFailure) 1628 { 1629 NTSTATUS Status; 1630 1631 Status = RtlAddAuditAccessAce(pAcl, 1632 dwAceRevision, 1633 dwAccessMask, 1634 pSid, 1635 bAuditSuccess, 1636 bAuditFailure); 1637 if (!NT_SUCCESS(Status)) 1638 { 1639 SetLastError(RtlNtStatusToDosError(Status)); 1640 return FALSE; 1641 } 1642 1643 return TRUE; 1644 } 1645 1646 /* 1647 * @implemented 1648 */ 1649 BOOL WINAPI 1650 AddAuditAccessAceEx(PACL pAcl, 1651 DWORD dwAceRevision, 1652 DWORD AceFlags, 1653 DWORD dwAccessMask, 1654 PSID pSid, 1655 BOOL bAuditSuccess, 1656 BOOL bAuditFailure) 1657 { 1658 NTSTATUS Status; 1659 1660 Status = RtlAddAuditAccessAceEx(pAcl, 1661 dwAceRevision, 1662 AceFlags, 1663 dwAccessMask, 1664 pSid, 1665 bAuditSuccess, 1666 bAuditFailure); 1667 if (!NT_SUCCESS(Status)) 1668 { 1669 SetLastError(RtlNtStatusToDosError(Status)); 1670 return FALSE; 1671 } 1672 1673 return TRUE; 1674 } 1675 1676 /****************************************************************************** 1677 * LookupAccountNameA [ADVAPI32.@] 1678 * 1679 * @implemented 1680 */ 1681 BOOL 1682 WINAPI 1683 LookupAccountNameA(LPCSTR SystemName, 1684 LPCSTR AccountName, 1685 PSID Sid, 1686 LPDWORD SidLength, 1687 LPSTR ReferencedDomainName, 1688 LPDWORD hReferencedDomainNameLength, 1689 PSID_NAME_USE SidNameUse) 1690 { 1691 BOOL ret; 1692 UNICODE_STRING lpSystemW; 1693 UNICODE_STRING lpAccountW; 1694 LPWSTR lpReferencedDomainNameW = NULL; 1695 1696 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, SystemName); 1697 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, AccountName); 1698 1699 if (ReferencedDomainName) 1700 lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(), 1701 0, 1702 *hReferencedDomainNameLength * sizeof(WCHAR)); 1703 1704 ret = LookupAccountNameW(lpSystemW.Buffer, 1705 lpAccountW.Buffer, 1706 Sid, 1707 SidLength, 1708 lpReferencedDomainNameW, 1709 hReferencedDomainNameLength, 1710 SidNameUse); 1711 1712 if (ret && lpReferencedDomainNameW) 1713 { 1714 WideCharToMultiByte(CP_ACP, 1715 0, 1716 lpReferencedDomainNameW, 1717 *hReferencedDomainNameLength + 1, 1718 ReferencedDomainName, 1719 *hReferencedDomainNameLength + 1, 1720 NULL, 1721 NULL); 1722 } 1723 1724 RtlFreeUnicodeString(&lpSystemW); 1725 RtlFreeUnicodeString(&lpAccountW); 1726 HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW); 1727 1728 return ret; 1729 } 1730 1731 /********************************************************************** 1732 * PrivilegeCheck EXPORTED 1733 * 1734 * @implemented 1735 */ 1736 BOOL WINAPI 1737 PrivilegeCheck(HANDLE ClientToken, 1738 PPRIVILEGE_SET RequiredPrivileges, 1739 LPBOOL pfResult) 1740 { 1741 BOOLEAN Result; 1742 NTSTATUS Status; 1743 1744 Status = NtPrivilegeCheck(ClientToken, 1745 RequiredPrivileges, 1746 &Result); 1747 if (!NT_SUCCESS(Status)) 1748 { 1749 SetLastError(RtlNtStatusToDosError(Status)); 1750 return FALSE; 1751 } 1752 1753 *pfResult = (BOOL)Result; 1754 1755 return TRUE; 1756 } 1757 1758 /****************************************************************************** 1759 * GetSecurityInfoExW EXPORTED 1760 */ 1761 DWORD 1762 WINAPI 1763 GetSecurityInfoExA(HANDLE hObject, 1764 SE_OBJECT_TYPE ObjectType, 1765 SECURITY_INFORMATION SecurityInfo, 1766 LPCSTR lpProvider, 1767 LPCSTR lpProperty, 1768 PACTRL_ACCESSA *ppAccessList, 1769 PACTRL_AUDITA *ppAuditList, 1770 LPSTR *lppOwner, 1771 LPSTR *lppGroup) 1772 { 1773 FIXME("%s() not implemented!\n", __FUNCTION__); 1774 return ERROR_BAD_PROVIDER; 1775 } 1776 1777 1778 /****************************************************************************** 1779 * GetSecurityInfoExW EXPORTED 1780 */ 1781 DWORD 1782 WINAPI 1783 GetSecurityInfoExW(HANDLE hObject, 1784 SE_OBJECT_TYPE ObjectType, 1785 SECURITY_INFORMATION SecurityInfo, 1786 LPCWSTR lpProvider, 1787 LPCWSTR lpProperty, 1788 PACTRL_ACCESSW *ppAccessList, 1789 PACTRL_AUDITW *ppAuditList, 1790 LPWSTR *lppOwner, 1791 LPWSTR *lppGroup) 1792 { 1793 FIXME("%s() not implemented!\n", __FUNCTION__); 1794 return ERROR_BAD_PROVIDER; 1795 } 1796 1797 /****************************************************************************** 1798 * BuildExplicitAccessWithNameA [ADVAPI32.@] 1799 */ 1800 VOID WINAPI 1801 BuildExplicitAccessWithNameA(PEXPLICIT_ACCESSA pExplicitAccess, 1802 LPSTR pTrusteeName, 1803 DWORD AccessPermissions, 1804 ACCESS_MODE AccessMode, 1805 DWORD Inheritance) 1806 { 1807 pExplicitAccess->grfAccessPermissions = AccessPermissions; 1808 pExplicitAccess->grfAccessMode = AccessMode; 1809 pExplicitAccess->grfInheritance = Inheritance; 1810 1811 pExplicitAccess->Trustee.pMultipleTrustee = NULL; 1812 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1813 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME; 1814 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; 1815 pExplicitAccess->Trustee.ptstrName = pTrusteeName; 1816 } 1817 1818 1819 /****************************************************************************** 1820 * BuildExplicitAccessWithNameW [ADVAPI32.@] 1821 */ 1822 VOID WINAPI 1823 BuildExplicitAccessWithNameW(PEXPLICIT_ACCESSW pExplicitAccess, 1824 LPWSTR pTrusteeName, 1825 DWORD AccessPermissions, 1826 ACCESS_MODE AccessMode, 1827 DWORD Inheritance) 1828 { 1829 pExplicitAccess->grfAccessPermissions = AccessPermissions; 1830 pExplicitAccess->grfAccessMode = AccessMode; 1831 pExplicitAccess->grfInheritance = Inheritance; 1832 1833 pExplicitAccess->Trustee.pMultipleTrustee = NULL; 1834 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1835 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME; 1836 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; 1837 pExplicitAccess->Trustee.ptstrName = pTrusteeName; 1838 } 1839 1840 /****************************************************************************** 1841 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@] 1842 */ 1843 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName, 1844 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName, 1845 LPSTR InheritedObjectTypeName, LPSTR Name ) 1846 { 1847 DWORD ObjectsPresent = 0; 1848 1849 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName, 1850 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name)); 1851 1852 /* Fill the OBJECTS_AND_NAME structure */ 1853 pObjName->ObjectType = ObjectType; 1854 if (ObjectTypeName != NULL) 1855 { 1856 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT; 1857 } 1858 1859 pObjName->InheritedObjectTypeName = InheritedObjectTypeName; 1860 if (InheritedObjectTypeName != NULL) 1861 { 1862 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT; 1863 } 1864 1865 pObjName->ObjectsPresent = ObjectsPresent; 1866 pObjName->ptstrName = Name; 1867 1868 /* Fill the TRUSTEE structure */ 1869 pTrustee->pMultipleTrustee = NULL; 1870 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1871 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME; 1872 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 1873 pTrustee->ptstrName = (LPSTR)pObjName; 1874 } 1875 1876 /****************************************************************************** 1877 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@] 1878 */ 1879 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName, 1880 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName, 1881 LPWSTR InheritedObjectTypeName, LPWSTR Name ) 1882 { 1883 DWORD ObjectsPresent = 0; 1884 1885 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName, 1886 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name)); 1887 1888 /* Fill the OBJECTS_AND_NAME structure */ 1889 pObjName->ObjectType = ObjectType; 1890 if (ObjectTypeName != NULL) 1891 { 1892 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT; 1893 } 1894 1895 pObjName->InheritedObjectTypeName = InheritedObjectTypeName; 1896 if (InheritedObjectTypeName != NULL) 1897 { 1898 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT; 1899 } 1900 1901 pObjName->ObjectsPresent = ObjectsPresent; 1902 pObjName->ptstrName = Name; 1903 1904 /* Fill the TRUSTEE structure */ 1905 pTrustee->pMultipleTrustee = NULL; 1906 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1907 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME; 1908 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 1909 pTrustee->ptstrName = (LPWSTR)pObjName; 1910 } 1911 1912 /****************************************************************************** 1913 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@] 1914 */ 1915 VOID WINAPI 1916 BuildTrusteeWithObjectsAndSidA(PTRUSTEEA pTrustee, 1917 POBJECTS_AND_SID pObjSid, 1918 GUID *pObjectGuid, 1919 GUID *pInheritedObjectGuid, 1920 PSID pSid) 1921 { 1922 DWORD ObjectsPresent = 0; 1923 1924 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid); 1925 1926 /* Fill the OBJECTS_AND_SID structure */ 1927 if (pObjectGuid != NULL) 1928 { 1929 pObjSid->ObjectTypeGuid = *pObjectGuid; 1930 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT; 1931 } 1932 else 1933 { 1934 ZeroMemory(&pObjSid->ObjectTypeGuid, 1935 sizeof(GUID)); 1936 } 1937 1938 if (pInheritedObjectGuid != NULL) 1939 { 1940 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid; 1941 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT; 1942 } 1943 else 1944 { 1945 ZeroMemory(&pObjSid->InheritedObjectTypeGuid, 1946 sizeof(GUID)); 1947 } 1948 1949 pObjSid->ObjectsPresent = ObjectsPresent; 1950 pObjSid->pSid = pSid; 1951 1952 /* Fill the TRUSTEE structure */ 1953 pTrustee->pMultipleTrustee = NULL; 1954 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1955 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID; 1956 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 1957 pTrustee->ptstrName = (LPSTR) pObjSid; 1958 } 1959 1960 1961 /****************************************************************************** 1962 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@] 1963 */ 1964 VOID WINAPI 1965 BuildTrusteeWithObjectsAndSidW(PTRUSTEEW pTrustee, 1966 POBJECTS_AND_SID pObjSid, 1967 GUID *pObjectGuid, 1968 GUID *pInheritedObjectGuid, 1969 PSID pSid) 1970 { 1971 DWORD ObjectsPresent = 0; 1972 1973 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid); 1974 1975 /* Fill the OBJECTS_AND_SID structure */ 1976 if (pObjectGuid != NULL) 1977 { 1978 pObjSid->ObjectTypeGuid = *pObjectGuid; 1979 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT; 1980 } 1981 else 1982 { 1983 ZeroMemory(&pObjSid->ObjectTypeGuid, 1984 sizeof(GUID)); 1985 } 1986 1987 if (pInheritedObjectGuid != NULL) 1988 { 1989 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid; 1990 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT; 1991 } 1992 else 1993 { 1994 ZeroMemory(&pObjSid->InheritedObjectTypeGuid, 1995 sizeof(GUID)); 1996 } 1997 1998 pObjSid->ObjectsPresent = ObjectsPresent; 1999 pObjSid->pSid = pSid; 2000 2001 /* Fill the TRUSTEE structure */ 2002 pTrustee->pMultipleTrustee = NULL; 2003 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2004 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID; 2005 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2006 pTrustee->ptstrName = (LPWSTR) pObjSid; 2007 } 2008 2009 /****************************************************************************** 2010 * BuildTrusteeWithSidA [ADVAPI32.@] 2011 */ 2012 VOID WINAPI 2013 BuildTrusteeWithSidA(PTRUSTEE_A pTrustee, 2014 PSID pSid) 2015 { 2016 TRACE("%p %p\n", pTrustee, pSid); 2017 2018 pTrustee->pMultipleTrustee = NULL; 2019 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2020 pTrustee->TrusteeForm = TRUSTEE_IS_SID; 2021 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2022 pTrustee->ptstrName = (LPSTR) pSid; 2023 } 2024 2025 2026 /****************************************************************************** 2027 * BuildTrusteeWithSidW [ADVAPI32.@] 2028 */ 2029 VOID WINAPI 2030 BuildTrusteeWithSidW(PTRUSTEE_W pTrustee, 2031 PSID pSid) 2032 { 2033 TRACE("%p %p\n", pTrustee, pSid); 2034 2035 pTrustee->pMultipleTrustee = NULL; 2036 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2037 pTrustee->TrusteeForm = TRUSTEE_IS_SID; 2038 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2039 pTrustee->ptstrName = (LPWSTR) pSid; 2040 } 2041 2042 /****************************************************************************** 2043 * BuildTrusteeWithNameA [ADVAPI32.@] 2044 */ 2045 VOID WINAPI 2046 BuildTrusteeWithNameA(PTRUSTEE_A pTrustee, 2047 LPSTR name) 2048 { 2049 TRACE("%p %s\n", pTrustee, name); 2050 2051 pTrustee->pMultipleTrustee = NULL; 2052 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2053 pTrustee->TrusteeForm = TRUSTEE_IS_NAME; 2054 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2055 pTrustee->ptstrName = name; 2056 } 2057 2058 /****************************************************************************** 2059 * BuildTrusteeWithNameW [ADVAPI32.@] 2060 */ 2061 VOID WINAPI 2062 BuildTrusteeWithNameW(PTRUSTEE_W pTrustee, 2063 LPWSTR name) 2064 { 2065 TRACE("%p %s\n", pTrustee, name); 2066 2067 pTrustee->pMultipleTrustee = NULL; 2068 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2069 pTrustee->TrusteeForm = TRUSTEE_IS_NAME; 2070 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2071 pTrustee->ptstrName = name; 2072 } 2073 2074 /****************************************************************************** 2075 * GetTrusteeFormA [ADVAPI32.@] 2076 */ 2077 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee) 2078 { 2079 TRACE("(%p)\n", pTrustee); 2080 2081 if (!pTrustee) 2082 return TRUSTEE_BAD_FORM; 2083 2084 return pTrustee->TrusteeForm; 2085 } 2086 2087 /****************************************************************************** 2088 * GetTrusteeFormW [ADVAPI32.@] 2089 */ 2090 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee) 2091 { 2092 TRACE("(%p)\n", pTrustee); 2093 2094 if (!pTrustee) 2095 return TRUSTEE_BAD_FORM; 2096 2097 return pTrustee->TrusteeForm; 2098 } 2099 2100 /****************************************************************************** 2101 * GetTrusteeNameA [ADVAPI32.@] 2102 */ 2103 LPSTR WINAPI 2104 GetTrusteeNameA(PTRUSTEE_A pTrustee) 2105 { 2106 return pTrustee->ptstrName; 2107 } 2108 2109 2110 /****************************************************************************** 2111 * GetTrusteeNameW [ADVAPI32.@] 2112 */ 2113 LPWSTR WINAPI 2114 GetTrusteeNameW(PTRUSTEE_W pTrustee) 2115 { 2116 return pTrustee->ptstrName; 2117 } 2118 2119 /****************************************************************************** 2120 * GetTrusteeTypeA [ADVAPI32.@] 2121 */ 2122 TRUSTEE_TYPE WINAPI 2123 GetTrusteeTypeA(PTRUSTEE_A pTrustee) 2124 { 2125 return pTrustee->TrusteeType; 2126 } 2127 2128 /****************************************************************************** 2129 * GetTrusteeTypeW [ADVAPI32.@] 2130 */ 2131 TRUSTEE_TYPE WINAPI 2132 GetTrusteeTypeW(PTRUSTEE_W pTrustee) 2133 { 2134 return pTrustee->TrusteeType; 2135 } 2136 2137 /* 2138 * @implemented 2139 */ 2140 BOOL 2141 WINAPI 2142 SetAclInformation(PACL pAcl, 2143 LPVOID pAclInformation, 2144 DWORD nAclInformationLength, 2145 ACL_INFORMATION_CLASS dwAclInformationClass) 2146 { 2147 NTSTATUS Status; 2148 2149 Status = RtlSetInformationAcl(pAcl, 2150 pAclInformation, 2151 nAclInformationLength, 2152 dwAclInformationClass); 2153 if (!NT_SUCCESS(Status)) 2154 { 2155 SetLastError(RtlNtStatusToDosError(Status)); 2156 return FALSE; 2157 } 2158 2159 return TRUE; 2160 } 2161 2162 /********************************************************************** 2163 * SetNamedSecurityInfoA EXPORTED 2164 * 2165 * @implemented 2166 */ 2167 DWORD 2168 WINAPI 2169 SetNamedSecurityInfoA(LPSTR pObjectName, 2170 SE_OBJECT_TYPE ObjectType, 2171 SECURITY_INFORMATION SecurityInfo, 2172 PSID psidOwner, 2173 PSID psidGroup, 2174 PACL pDacl, 2175 PACL pSacl) 2176 { 2177 UNICODE_STRING ObjectName; 2178 DWORD Ret; 2179 2180 if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName, pObjectName)) 2181 { 2182 return ERROR_NOT_ENOUGH_MEMORY; 2183 } 2184 2185 Ret = SetNamedSecurityInfoW(ObjectName.Buffer, 2186 ObjectType, 2187 SecurityInfo, 2188 psidOwner, 2189 psidGroup, 2190 pDacl, 2191 pSacl); 2192 2193 RtlFreeUnicodeString(&ObjectName); 2194 2195 return Ret; 2196 } 2197 2198 /* 2199 * @implemented 2200 */ 2201 BOOL 2202 WINAPI 2203 AreAllAccessesGranted(DWORD GrantedAccess, 2204 DWORD DesiredAccess) 2205 { 2206 return (BOOL)RtlAreAllAccessesGranted(GrantedAccess, 2207 DesiredAccess); 2208 } 2209 2210 /* 2211 * @implemented 2212 */ 2213 BOOL 2214 WINAPI 2215 AreAnyAccessesGranted(DWORD GrantedAccess, 2216 DWORD DesiredAccess) 2217 { 2218 return (BOOL)RtlAreAnyAccessesGranted(GrantedAccess, 2219 DesiredAccess); 2220 } 2221 2222 /****************************************************************************** 2223 * ParseAclStringFlags 2224 */ 2225 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl) 2226 { 2227 DWORD flags = 0; 2228 LPCWSTR szAcl = *StringAcl; 2229 2230 while (*szAcl != '(') 2231 { 2232 if (*szAcl == 'P') 2233 { 2234 flags |= SE_DACL_PROTECTED; 2235 } 2236 else if (*szAcl == 'A') 2237 { 2238 szAcl++; 2239 if (*szAcl == 'R') 2240 flags |= SE_DACL_AUTO_INHERIT_REQ; 2241 else if (*szAcl == 'I') 2242 flags |= SE_DACL_AUTO_INHERITED; 2243 } 2244 szAcl++; 2245 } 2246 2247 *StringAcl = szAcl; 2248 return flags; 2249 } 2250 2251 /****************************************************************************** 2252 * ParseAceStringType 2253 */ 2254 static const ACEFLAG AceType[] = 2255 { 2256 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE }, 2257 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE }, 2258 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE }, 2259 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE }, 2260 { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE }, 2261 /* 2262 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE }, 2263 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE }, 2264 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE }, 2265 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE }, 2266 */ 2267 { NULL, 0 }, 2268 }; 2269 2270 static BYTE ParseAceStringType(LPCWSTR* StringAcl) 2271 { 2272 UINT len = 0; 2273 LPCWSTR szAcl = *StringAcl; 2274 const ACEFLAG *lpaf = AceType; 2275 2276 while (*szAcl == ' ') 2277 szAcl++; 2278 2279 while (lpaf->wstr && 2280 (len = strlenW(lpaf->wstr)) && 2281 strncmpW(lpaf->wstr, szAcl, len)) 2282 lpaf++; 2283 2284 if (!lpaf->wstr) 2285 return 0; 2286 2287 *StringAcl = szAcl + len; 2288 return lpaf->value; 2289 } 2290 2291 2292 /****************************************************************************** 2293 * ParseAceStringFlags 2294 */ 2295 static const ACEFLAG AceFlags[] = 2296 { 2297 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE }, 2298 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG }, 2299 { SDDL_INHERITED, INHERITED_ACE }, 2300 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE }, 2301 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE }, 2302 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE }, 2303 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG }, 2304 { NULL, 0 }, 2305 }; 2306 2307 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl) 2308 { 2309 UINT len = 0; 2310 BYTE flags = 0; 2311 LPCWSTR szAcl = *StringAcl; 2312 2313 while (*szAcl == ' ') 2314 szAcl++; 2315 2316 while (*szAcl != ';') 2317 { 2318 const ACEFLAG *lpaf = AceFlags; 2319 2320 while (lpaf->wstr && 2321 (len = strlenW(lpaf->wstr)) && 2322 strncmpW(lpaf->wstr, szAcl, len)) 2323 lpaf++; 2324 2325 if (!lpaf->wstr) 2326 return 0; 2327 2328 flags |= lpaf->value; 2329 szAcl += len; 2330 } 2331 2332 *StringAcl = szAcl; 2333 return flags; 2334 } 2335 2336 2337 /****************************************************************************** 2338 * ParseAceStringRights 2339 */ 2340 static const ACEFLAG AceRights[] = 2341 { 2342 { SDDL_GENERIC_ALL, GENERIC_ALL }, 2343 { SDDL_GENERIC_READ, GENERIC_READ }, 2344 { SDDL_GENERIC_WRITE, GENERIC_WRITE }, 2345 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE }, 2346 2347 { SDDL_READ_CONTROL, READ_CONTROL }, 2348 { SDDL_STANDARD_DELETE, DELETE }, 2349 { SDDL_WRITE_DAC, WRITE_DAC }, 2350 { SDDL_WRITE_OWNER, WRITE_OWNER }, 2351 2352 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP}, 2353 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP}, 2354 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD}, 2355 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD}, 2356 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST}, 2357 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF}, 2358 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT}, 2359 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE}, 2360 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS}, 2361 2362 { SDDL_FILE_ALL, FILE_ALL_ACCESS }, 2363 { SDDL_FILE_READ, FILE_GENERIC_READ }, 2364 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE }, 2365 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE }, 2366 2367 { SDDL_KEY_ALL, KEY_ALL_ACCESS }, 2368 { SDDL_KEY_READ, KEY_READ }, 2369 { SDDL_KEY_WRITE, KEY_WRITE }, 2370 { SDDL_KEY_EXECUTE, KEY_EXECUTE }, 2371 2372 { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP }, 2373 { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP }, 2374 { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP }, 2375 { NULL, 0 }, 2376 }; 2377 2378 static DWORD ParseAceStringRights(LPCWSTR* StringAcl) 2379 { 2380 UINT len = 0; 2381 DWORD rights = 0; 2382 LPCWSTR szAcl = *StringAcl; 2383 2384 while (*szAcl == ' ') 2385 szAcl++; 2386 2387 if ((*szAcl == '0') && (*(szAcl + 1) == 'x')) 2388 { 2389 LPCWSTR p = szAcl; 2390 2391 while (*p && *p != ';') 2392 p++; 2393 2394 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ ) 2395 { 2396 rights = strtoulW(szAcl, NULL, 16); 2397 szAcl = p; 2398 } 2399 else 2400 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl)); 2401 } 2402 else 2403 { 2404 while (*szAcl != ';') 2405 { 2406 const ACEFLAG *lpaf = AceRights; 2407 2408 while (lpaf->wstr && 2409 (len = strlenW(lpaf->wstr)) && 2410 strncmpW(lpaf->wstr, szAcl, len)) 2411 { 2412 lpaf++; 2413 } 2414 2415 if (!lpaf->wstr) 2416 return 0; 2417 2418 rights |= lpaf->value; 2419 szAcl += len; 2420 } 2421 } 2422 2423 *StringAcl = szAcl; 2424 return rights; 2425 } 2426 2427 2428 /****************************************************************************** 2429 * ParseStringAclToAcl 2430 * 2431 * dacl_flags(string_ace1)(string_ace2)... (string_acen) 2432 */ 2433 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 2434 PACL pAcl, LPDWORD cBytes) 2435 { 2436 DWORD val; 2437 DWORD sidlen; 2438 DWORD length = sizeof(ACL); 2439 DWORD acesize = 0; 2440 DWORD acecount = 0; 2441 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */ 2442 DWORD error = ERROR_INVALID_ACL; 2443 2444 TRACE("%s\n", debugstr_w(StringAcl)); 2445 2446 if (!StringAcl) 2447 return FALSE; 2448 2449 if (pAcl) /* pAce is only useful if we're setting values */ 2450 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1); 2451 2452 /* Parse ACL flags */ 2453 *lpdwFlags = ParseAclStringFlags(&StringAcl); 2454 2455 /* Parse ACE */ 2456 while (*StringAcl == '(') 2457 { 2458 StringAcl++; 2459 2460 /* Parse ACE type */ 2461 val = ParseAceStringType(&StringAcl); 2462 if (pAce) 2463 pAce->Header.AceType = (BYTE) val; 2464 if (*StringAcl != ';') 2465 { 2466 error = RPC_S_INVALID_STRING_UUID; 2467 goto lerr; 2468 } 2469 StringAcl++; 2470 2471 /* Parse ACE flags */ 2472 val = ParseAceStringFlags(&StringAcl); 2473 if (pAce) 2474 pAce->Header.AceFlags = (BYTE) val; 2475 if (*StringAcl != ';') 2476 goto lerr; 2477 StringAcl++; 2478 2479 /* Parse ACE rights */ 2480 val = ParseAceStringRights(&StringAcl); 2481 if (pAce) 2482 pAce->Mask = val; 2483 if (*StringAcl != ';') 2484 goto lerr; 2485 StringAcl++; 2486 2487 /* Parse ACE object guid */ 2488 while (*StringAcl == ' ') 2489 StringAcl++; 2490 if (*StringAcl != ';') 2491 { 2492 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); 2493 goto lerr; 2494 } 2495 StringAcl++; 2496 2497 /* Parse ACE inherit object guid */ 2498 while (*StringAcl == ' ') 2499 StringAcl++; 2500 if (*StringAcl != ';') 2501 { 2502 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); 2503 goto lerr; 2504 } 2505 StringAcl++; 2506 2507 /* Parse ACE account sid */ 2508 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen)) 2509 { 2510 while (*StringAcl && *StringAcl != ')') 2511 StringAcl++; 2512 } 2513 2514 if (*StringAcl != ')') 2515 goto lerr; 2516 StringAcl++; 2517 2518 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen; 2519 length += acesize; 2520 if (pAce) 2521 { 2522 pAce->Header.AceSize = acesize; 2523 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize); 2524 } 2525 acecount++; 2526 } 2527 2528 *cBytes = length; 2529 2530 if (length > 0xffff) 2531 { 2532 ERR("ACL too large\n"); 2533 goto lerr; 2534 } 2535 2536 if (pAcl) 2537 { 2538 pAcl->AclRevision = ACL_REVISION; 2539 pAcl->Sbz1 = 0; 2540 pAcl->AclSize = length; 2541 pAcl->AceCount = acecount++; 2542 pAcl->Sbz2 = 0; 2543 } 2544 return TRUE; 2545 2546 lerr: 2547 SetLastError(error); 2548 WARN("Invalid ACE string format\n"); 2549 return FALSE; 2550 } 2551 2552 2553 /****************************************************************************** 2554 * ParseStringSecurityDescriptorToSecurityDescriptor 2555 */ 2556 static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( 2557 LPCWSTR StringSecurityDescriptor, 2558 SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor, 2559 LPDWORD cBytes) 2560 { 2561 BOOL bret = FALSE; 2562 WCHAR toktype; 2563 WCHAR *tok; 2564 LPCWSTR lptoken; 2565 LPBYTE lpNext = NULL; 2566 DWORD len; 2567 2568 *cBytes = sizeof(SECURITY_DESCRIPTOR); 2569 2570 tok = heap_alloc( (lstrlenW(StringSecurityDescriptor) + 1) * sizeof(WCHAR)); 2571 2572 if (SecurityDescriptor) 2573 lpNext = (LPBYTE)(SecurityDescriptor + 1); 2574 2575 while (*StringSecurityDescriptor == ' ') 2576 StringSecurityDescriptor++; 2577 2578 while (*StringSecurityDescriptor) 2579 { 2580 toktype = *StringSecurityDescriptor; 2581 2582 /* Expect char identifier followed by ':' */ 2583 StringSecurityDescriptor++; 2584 if (*StringSecurityDescriptor != ':') 2585 { 2586 SetLastError(ERROR_INVALID_PARAMETER); 2587 goto lend; 2588 } 2589 StringSecurityDescriptor++; 2590 2591 /* Extract token */ 2592 lptoken = StringSecurityDescriptor; 2593 while (*lptoken && *lptoken != ':') 2594 lptoken++; 2595 2596 if (*lptoken) 2597 lptoken--; 2598 2599 len = lptoken - StringSecurityDescriptor; 2600 memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) ); 2601 tok[len] = 0; 2602 2603 switch (toktype) 2604 { 2605 case 'O': 2606 { 2607 DWORD bytes; 2608 2609 if (!ParseStringSidToSid(tok, lpNext, &bytes)) 2610 goto lend; 2611 2612 if (SecurityDescriptor) 2613 { 2614 SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor; 2615 lpNext += bytes; /* Advance to next token */ 2616 } 2617 2618 *cBytes += bytes; 2619 2620 break; 2621 } 2622 2623 case 'G': 2624 { 2625 DWORD bytes; 2626 2627 if (!ParseStringSidToSid(tok, lpNext, &bytes)) 2628 goto lend; 2629 2630 if (SecurityDescriptor) 2631 { 2632 SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor; 2633 lpNext += bytes; /* Advance to next token */ 2634 } 2635 2636 *cBytes += bytes; 2637 2638 break; 2639 } 2640 2641 case 'D': 2642 { 2643 DWORD flags; 2644 DWORD bytes; 2645 2646 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes)) 2647 goto lend; 2648 2649 if (SecurityDescriptor) 2650 { 2651 SecurityDescriptor->Control |= SE_DACL_PRESENT | flags; 2652 SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor; 2653 lpNext += bytes; /* Advance to next token */ 2654 } 2655 2656 *cBytes += bytes; 2657 2658 break; 2659 } 2660 2661 case 'S': 2662 { 2663 DWORD flags; 2664 DWORD bytes; 2665 2666 if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes)) 2667 goto lend; 2668 2669 if (SecurityDescriptor) 2670 { 2671 SecurityDescriptor->Control |= SE_SACL_PRESENT | flags; 2672 SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor; 2673 lpNext += bytes; /* Advance to next token */ 2674 } 2675 2676 *cBytes += bytes; 2677 2678 break; 2679 } 2680 2681 default: 2682 FIXME("Unknown token\n"); 2683 SetLastError(ERROR_INVALID_PARAMETER); 2684 goto lend; 2685 } 2686 2687 StringSecurityDescriptor = lptoken; 2688 } 2689 2690 bret = TRUE; 2691 2692 lend: 2693 heap_free(tok); 2694 return bret; 2695 } 2696 2697 /* Winehq cvs 20050916 */ 2698 /****************************************************************************** 2699 * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@] 2700 * @implemented 2701 */ 2702 BOOL 2703 WINAPI 2704 ConvertStringSecurityDescriptorToSecurityDescriptorA(LPCSTR StringSecurityDescriptor, 2705 DWORD StringSDRevision, 2706 PSECURITY_DESCRIPTOR* SecurityDescriptor, 2707 PULONG SecurityDescriptorSize) 2708 { 2709 UINT len; 2710 BOOL ret = FALSE; 2711 LPWSTR StringSecurityDescriptorW; 2712 2713 len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0); 2714 StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 2715 2716 if (StringSecurityDescriptorW) 2717 { 2718 MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len); 2719 2720 ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW, 2721 StringSDRevision, SecurityDescriptor, 2722 SecurityDescriptorSize); 2723 HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW); 2724 } 2725 2726 return ret; 2727 } 2728 2729 /****************************************************************************** 2730 * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@] 2731 * @implemented 2732 */ 2733 BOOL WINAPI 2734 ConvertStringSecurityDescriptorToSecurityDescriptorW(LPCWSTR StringSecurityDescriptor, 2735 DWORD StringSDRevision, 2736 PSECURITY_DESCRIPTOR* SecurityDescriptor, 2737 PULONG SecurityDescriptorSize) 2738 { 2739 DWORD cBytes; 2740 SECURITY_DESCRIPTOR* psd; 2741 BOOL bret = FALSE; 2742 2743 TRACE("%s\n", debugstr_w(StringSecurityDescriptor)); 2744 2745 if (GetVersion() & 0x80000000) 2746 { 2747 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2748 goto lend; 2749 } 2750 else if (!StringSecurityDescriptor || !SecurityDescriptor) 2751 { 2752 SetLastError(ERROR_INVALID_PARAMETER); 2753 goto lend; 2754 } 2755 else if (StringSDRevision != SID_REVISION) 2756 { 2757 SetLastError(ERROR_UNKNOWN_REVISION); 2758 goto lend; 2759 } 2760 2761 /* Compute security descriptor length */ 2762 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor, 2763 NULL, &cBytes)) 2764 goto lend; 2765 2766 psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes); 2767 if (!psd) goto lend; 2768 2769 psd->Revision = SID_REVISION; 2770 psd->Control |= SE_SELF_RELATIVE; 2771 2772 if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor, 2773 (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes)) 2774 { 2775 LocalFree(psd); 2776 goto lend; 2777 } 2778 2779 if (SecurityDescriptorSize) 2780 *SecurityDescriptorSize = cBytes; 2781 2782 bret = TRUE; 2783 2784 lend: 2785 TRACE(" ret=%d\n", bret); 2786 return bret; 2787 } 2788 2789 static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen) 2790 { 2791 if (cch == -1) 2792 cch = strlenW(string); 2793 2794 if (plen) 2795 *plen += cch; 2796 2797 if (pwptr) 2798 { 2799 memcpy(*pwptr, string, sizeof(WCHAR)*cch); 2800 *pwptr += cch; 2801 } 2802 } 2803 2804 static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen) 2805 { 2806 DWORD i; 2807 WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 }; 2808 WCHAR subauthfmt[] = { '-','%','u',0 }; 2809 WCHAR buf[26]; 2810 SID *pisid = psid; 2811 2812 if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION) 2813 { 2814 SetLastError(ERROR_INVALID_SID); 2815 return FALSE; 2816 } 2817 2818 if (pisid->IdentifierAuthority.Value[0] || 2819 pisid->IdentifierAuthority.Value[1]) 2820 { 2821 FIXME("not matching MS' bugs\n"); 2822 SetLastError(ERROR_INVALID_SID); 2823 return FALSE; 2824 } 2825 2826 sprintfW( buf, fmt, pisid->Revision, 2827 MAKELONG( 2828 MAKEWORD( pisid->IdentifierAuthority.Value[5], 2829 pisid->IdentifierAuthority.Value[4] ), 2830 MAKEWORD( pisid->IdentifierAuthority.Value[3], 2831 pisid->IdentifierAuthority.Value[2] ) 2832 ) ); 2833 DumpString(buf, -1, pwptr, plen); 2834 2835 for( i=0; i<pisid->SubAuthorityCount; i++ ) 2836 { 2837 sprintfW( buf, subauthfmt, pisid->SubAuthority[i] ); 2838 DumpString(buf, -1, pwptr, plen); 2839 } 2840 return TRUE; 2841 } 2842 2843 static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen) 2844 { 2845 size_t i; 2846 for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++) 2847 { 2848 if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision))) 2849 { 2850 DumpString(WellKnownSids[i].wstr, 2, pwptr, plen); 2851 return TRUE; 2852 } 2853 } 2854 2855 return DumpSidNumeric(psid, pwptr, plen); 2856 } 2857 2858 static const LPCWSTR AceRightBitNames[32] = { 2859 SDDL_CREATE_CHILD, /* 0 */ 2860 SDDL_DELETE_CHILD, 2861 SDDL_LIST_CHILDREN, 2862 SDDL_SELF_WRITE, 2863 SDDL_READ_PROPERTY, /* 4 */ 2864 SDDL_WRITE_PROPERTY, 2865 SDDL_DELETE_TREE, 2866 SDDL_LIST_OBJECT, 2867 SDDL_CONTROL_ACCESS, /* 8 */ 2868 NULL, 2869 NULL, 2870 NULL, 2871 NULL, /* 12 */ 2872 NULL, 2873 NULL, 2874 NULL, 2875 SDDL_STANDARD_DELETE, /* 16 */ 2876 SDDL_READ_CONTROL, 2877 SDDL_WRITE_DAC, 2878 SDDL_WRITE_OWNER, 2879 NULL, /* 20 */ 2880 NULL, 2881 NULL, 2882 NULL, 2883 NULL, /* 24 */ 2884 NULL, 2885 NULL, 2886 NULL, 2887 SDDL_GENERIC_ALL, /* 28 */ 2888 SDDL_GENERIC_EXECUTE, 2889 SDDL_GENERIC_WRITE, 2890 SDDL_GENERIC_READ 2891 }; 2892 2893 static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen) 2894 { 2895 static const WCHAR fmtW[] = {'0','x','%','x',0}; 2896 WCHAR buf[15]; 2897 size_t i; 2898 2899 if (mask == 0) 2900 return; 2901 2902 /* first check if the right have name */ 2903 for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++) 2904 { 2905 if (AceRights[i].wstr == NULL) 2906 break; 2907 if (mask == AceRights[i].value) 2908 { 2909 DumpString(AceRights[i].wstr, -1, pwptr, plen); 2910 return; 2911 } 2912 } 2913 2914 /* then check if it can be built from bit names */ 2915 for (i = 0; i < 32; i++) 2916 { 2917 if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL)) 2918 { 2919 /* can't be built from bit names */ 2920 sprintfW(buf, fmtW, mask); 2921 DumpString(buf, -1, pwptr, plen); 2922 return; 2923 } 2924 } 2925 2926 /* build from bit names */ 2927 for (i = 0; i < 32; i++) 2928 if (mask & (1 << i)) 2929 DumpString(AceRightBitNames[i], -1, pwptr, plen); 2930 } 2931 2932 static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen) 2933 { 2934 ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */ 2935 static const WCHAR openbr = '('; 2936 static const WCHAR closebr = ')'; 2937 static const WCHAR semicolon = ';'; 2938 2939 if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE)) 2940 { 2941 SetLastError(ERROR_INVALID_ACL); 2942 return FALSE; 2943 } 2944 2945 piace = pace; 2946 DumpString(&openbr, 1, pwptr, plen); 2947 switch (piace->Header.AceType) 2948 { 2949 case ACCESS_ALLOWED_ACE_TYPE: 2950 DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen); 2951 break; 2952 case ACCESS_DENIED_ACE_TYPE: 2953 DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen); 2954 break; 2955 case SYSTEM_AUDIT_ACE_TYPE: 2956 DumpString(SDDL_AUDIT, -1, pwptr, plen); 2957 break; 2958 case SYSTEM_ALARM_ACE_TYPE: 2959 DumpString(SDDL_ALARM, -1, pwptr, plen); 2960 break; 2961 } 2962 DumpString(&semicolon, 1, pwptr, plen); 2963 2964 if (piace->Header.AceFlags & OBJECT_INHERIT_ACE) 2965 DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen); 2966 if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE) 2967 DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen); 2968 if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) 2969 DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen); 2970 if (piace->Header.AceFlags & INHERIT_ONLY_ACE) 2971 DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen); 2972 if (piace->Header.AceFlags & INHERITED_ACE) 2973 DumpString(SDDL_INHERITED, -1, pwptr, plen); 2974 if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) 2975 DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen); 2976 if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) 2977 DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen); 2978 DumpString(&semicolon, 1, pwptr, plen); 2979 DumpRights(piace->Mask, pwptr, plen); 2980 DumpString(&semicolon, 1, pwptr, plen); 2981 /* objects not supported */ 2982 DumpString(&semicolon, 1, pwptr, plen); 2983 /* objects not supported */ 2984 DumpString(&semicolon, 1, pwptr, plen); 2985 if (!DumpSid((PSID)&piace->SidStart, pwptr, plen)) 2986 return FALSE; 2987 DumpString(&closebr, 1, pwptr, plen); 2988 return TRUE; 2989 } 2990 2991 static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited) 2992 { 2993 WORD count; 2994 int i; 2995 2996 if (protected) 2997 DumpString(SDDL_PROTECTED, -1, pwptr, plen); 2998 if (autoInheritReq) 2999 DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen); 3000 if (autoInherited) 3001 DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen); 3002 3003 if (pacl == NULL) 3004 return TRUE; 3005 3006 if (!IsValidAcl(pacl)) 3007 return FALSE; 3008 3009 count = pacl->AceCount; 3010 for (i = 0; i < count; i++) 3011 { 3012 LPVOID ace; 3013 if (!GetAce(pacl, i, &ace)) 3014 return FALSE; 3015 if (!DumpAce(ace, pwptr, plen)) 3016 return FALSE; 3017 } 3018 3019 return TRUE; 3020 } 3021 3022 static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) 3023 { 3024 static const WCHAR prefix[] = {'O',':',0}; 3025 BOOL bDefaulted; 3026 PSID psid; 3027 3028 if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted)) 3029 return FALSE; 3030 3031 if (psid == NULL) 3032 return TRUE; 3033 3034 DumpString(prefix, -1, pwptr, plen); 3035 if (!DumpSid(psid, pwptr, plen)) 3036 return FALSE; 3037 return TRUE; 3038 } 3039 3040 static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) 3041 { 3042 static const WCHAR prefix[] = {'G',':',0}; 3043 BOOL bDefaulted; 3044 PSID psid; 3045 3046 if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted)) 3047 return FALSE; 3048 3049 if (psid == NULL) 3050 return TRUE; 3051 3052 DumpString(prefix, -1, pwptr, plen); 3053 if (!DumpSid(psid, pwptr, plen)) 3054 return FALSE; 3055 return TRUE; 3056 } 3057 3058 static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) 3059 { 3060 static const WCHAR dacl[] = {'D',':',0}; 3061 SECURITY_DESCRIPTOR_CONTROL control; 3062 BOOL present, defaulted; 3063 DWORD revision; 3064 PACL pacl; 3065 3066 if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted)) 3067 return FALSE; 3068 3069 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision)) 3070 return FALSE; 3071 3072 if (!present) 3073 return TRUE; 3074 3075 DumpString(dacl, 2, pwptr, plen); 3076 if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED)) 3077 return FALSE; 3078 return TRUE; 3079 } 3080 3081 static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen) 3082 { 3083 static const WCHAR sacl[] = {'S',':',0}; 3084 SECURITY_DESCRIPTOR_CONTROL control; 3085 BOOL present, defaulted; 3086 DWORD revision; 3087 PACL pacl; 3088 3089 if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted)) 3090 return FALSE; 3091 3092 if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision)) 3093 return FALSE; 3094 3095 if (!present) 3096 return TRUE; 3097 3098 DumpString(sacl, 2, pwptr, plen); 3099 if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED)) 3100 return FALSE; 3101 return TRUE; 3102 } 3103 3104 /****************************************************************************** 3105 * ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@] 3106 */ 3107 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen) 3108 { 3109 ULONG len; 3110 WCHAR *wptr, *wstr; 3111 3112 if (SDRevision != SDDL_REVISION_1) 3113 { 3114 ERR("Program requested unknown SDDL revision %d\n", SDRevision); 3115 SetLastError(ERROR_UNKNOWN_REVISION); 3116 return FALSE; 3117 } 3118 3119 len = 0; 3120 if (RequestedInformation & OWNER_SECURITY_INFORMATION) 3121 if (!DumpOwner(SecurityDescriptor, NULL, &len)) 3122 return FALSE; 3123 if (RequestedInformation & GROUP_SECURITY_INFORMATION) 3124 if (!DumpGroup(SecurityDescriptor, NULL, &len)) 3125 return FALSE; 3126 if (RequestedInformation & DACL_SECURITY_INFORMATION) 3127 if (!DumpDacl(SecurityDescriptor, NULL, &len)) 3128 return FALSE; 3129 if (RequestedInformation & SACL_SECURITY_INFORMATION) 3130 if (!DumpSacl(SecurityDescriptor, NULL, &len)) 3131 return FALSE; 3132 3133 wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR)); 3134 #ifdef __REACTOS__ 3135 if (wstr == NULL) 3136 return FALSE; 3137 #endif 3138 3139 if (RequestedInformation & OWNER_SECURITY_INFORMATION) 3140 if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) { 3141 LocalFree (wstr); 3142 return FALSE; 3143 } 3144 if (RequestedInformation & GROUP_SECURITY_INFORMATION) 3145 if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) { 3146 LocalFree (wstr); 3147 return FALSE; 3148 } 3149 if (RequestedInformation & DACL_SECURITY_INFORMATION) 3150 if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) { 3151 LocalFree (wstr); 3152 return FALSE; 3153 } 3154 if (RequestedInformation & SACL_SECURITY_INFORMATION) 3155 if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) { 3156 LocalFree (wstr); 3157 return FALSE; 3158 } 3159 *wptr = 0; 3160 3161 TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len); 3162 *OutputString = wstr; 3163 if (OutputLen) 3164 *OutputLen = strlenW(*OutputString)+1; 3165 return TRUE; 3166 } 3167 3168 /****************************************************************************** 3169 * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@] 3170 */ 3171 BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION Information, LPSTR *OutputString, PULONG OutputLen) 3172 { 3173 LPWSTR wstr; 3174 ULONG len; 3175 if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len)) 3176 { 3177 int lenA; 3178 3179 lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL); 3180 *OutputString = heap_alloc(lenA); 3181 #ifdef __REACTOS__ 3182 if (*OutputString == NULL) 3183 { 3184 LocalFree(wstr); 3185 *OutputLen = 0; 3186 return FALSE; 3187 } 3188 #endif 3189 WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL); 3190 LocalFree(wstr); 3191 3192 if (OutputLen != NULL) 3193 *OutputLen = lenA; 3194 return TRUE; 3195 } 3196 else 3197 { 3198 *OutputString = NULL; 3199 if (OutputLen) 3200 *OutputLen = 0; 3201 return FALSE; 3202 } 3203 } 3204 3205 /****************************************************************************** 3206 * ConvertStringSidToSidW [ADVAPI32.@] 3207 */ 3208 BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid) 3209 { 3210 BOOL bret = FALSE; 3211 DWORD cBytes; 3212 3213 TRACE("%s, %p\n", debugstr_w(StringSid), Sid); 3214 if (GetVersion() & 0x80000000) 3215 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 3216 else if (!StringSid || !Sid) 3217 SetLastError(ERROR_INVALID_PARAMETER); 3218 else if (ParseStringSidToSid(StringSid, NULL, &cBytes)) 3219 { 3220 PSID pSid = *Sid = LocalAlloc(0, cBytes); 3221 3222 bret = ParseStringSidToSid(StringSid, pSid, &cBytes); 3223 if (!bret) 3224 LocalFree(*Sid); 3225 } 3226 return bret; 3227 } 3228 3229 /****************************************************************************** 3230 * ConvertStringSidToSidA [ADVAPI32.@] 3231 */ 3232 BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid) 3233 { 3234 BOOL bret = FALSE; 3235 3236 TRACE("%s, %p\n", debugstr_a(StringSid), Sid); 3237 if (GetVersion() & 0x80000000) 3238 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 3239 else if (!StringSid || !Sid) 3240 SetLastError(ERROR_INVALID_PARAMETER); 3241 else 3242 { 3243 WCHAR *wStringSid = SERV_dup(StringSid); 3244 bret = ConvertStringSidToSidW(wStringSid, Sid); 3245 heap_free(wStringSid); 3246 } 3247 return bret; 3248 } 3249 3250 /* 3251 * @implemented 3252 */ 3253 BOOL 3254 WINAPI 3255 ConvertSidToStringSidW(PSID Sid, 3256 LPWSTR *StringSid) 3257 { 3258 NTSTATUS Status; 3259 UNICODE_STRING UnicodeString; 3260 WCHAR FixedBuffer[64]; 3261 3262 if (!RtlValidSid(Sid)) 3263 { 3264 SetLastError(ERROR_INVALID_SID); 3265 return FALSE; 3266 } 3267 3268 UnicodeString.Length = 0; 3269 UnicodeString.MaximumLength = sizeof(FixedBuffer); 3270 UnicodeString.Buffer = FixedBuffer; 3271 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE); 3272 if (STATUS_BUFFER_TOO_SMALL == Status) 3273 { 3274 Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE); 3275 } 3276 3277 if (!NT_SUCCESS(Status)) 3278 { 3279 SetLastError(RtlNtStatusToDosError(Status)); 3280 return FALSE; 3281 } 3282 3283 *StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR)); 3284 if (NULL == *StringSid) 3285 { 3286 if (UnicodeString.Buffer != FixedBuffer) 3287 { 3288 RtlFreeUnicodeString(&UnicodeString); 3289 } 3290 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3291 return FALSE; 3292 } 3293 3294 MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length); 3295 ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR)); 3296 if (UnicodeString.Buffer != FixedBuffer) 3297 { 3298 RtlFreeUnicodeString(&UnicodeString); 3299 } 3300 3301 return TRUE; 3302 } 3303 3304 /* 3305 * @implemented 3306 */ 3307 BOOL 3308 WINAPI 3309 ConvertSidToStringSidA(PSID Sid, 3310 LPSTR *StringSid) 3311 { 3312 LPWSTR StringSidW; 3313 int Len; 3314 3315 if (!ConvertSidToStringSidW(Sid, &StringSidW)) 3316 { 3317 return FALSE; 3318 } 3319 3320 Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL); 3321 if (Len <= 0) 3322 { 3323 LocalFree(StringSidW); 3324 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3325 return FALSE; 3326 } 3327 3328 *StringSid = LocalAlloc(LMEM_FIXED, Len); 3329 if (NULL == *StringSid) 3330 { 3331 LocalFree(StringSidW); 3332 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 3333 return FALSE; 3334 } 3335 3336 if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL)) 3337 { 3338 LocalFree(StringSid); 3339 LocalFree(StringSidW); 3340 return FALSE; 3341 } 3342 3343 LocalFree(StringSidW); 3344 3345 return TRUE; 3346 } 3347 3348 /* 3349 * @unimplemented 3350 */ 3351 BOOL WINAPI 3352 CreateProcessWithLogonW(LPCWSTR lpUsername, 3353 LPCWSTR lpDomain, 3354 LPCWSTR lpPassword, 3355 DWORD dwLogonFlags, 3356 LPCWSTR lpApplicationName, 3357 LPWSTR lpCommandLine, 3358 DWORD dwCreationFlags, 3359 LPVOID lpEnvironment, 3360 LPCWSTR lpCurrentDirectory, 3361 LPSTARTUPINFOW lpStartupInfo, 3362 LPPROCESS_INFORMATION lpProcessInformation) 3363 { 3364 FIXME("%s %s %s 0x%08x %s %s 0x%08x %p %s %p %p stub\n", debugstr_w(lpUsername), debugstr_w(lpDomain), 3365 debugstr_w(lpPassword), dwLogonFlags, debugstr_w(lpApplicationName), 3366 debugstr_w(lpCommandLine), dwCreationFlags, lpEnvironment, debugstr_w(lpCurrentDirectory), 3367 lpStartupInfo, lpProcessInformation); 3368 3369 return FALSE; 3370 } 3371 3372 BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR application_name, LPWSTR command_line, 3373 DWORD creation_flags, void *environment, LPCWSTR current_directory, STARTUPINFOW *startup_info, 3374 PROCESS_INFORMATION *process_information ) 3375 { 3376 FIXME("%p 0x%08x %s %s 0x%08x %p %s %p %p - semi-stub\n", token, 3377 logon_flags, debugstr_w(application_name), debugstr_w(command_line), 3378 creation_flags, environment, debugstr_w(current_directory), 3379 startup_info, process_information); 3380 3381 /* FIXME: check if handles should be inherited */ 3382 return CreateProcessW( application_name, command_line, NULL, NULL, FALSE, creation_flags, environment, 3383 current_directory, startup_info, process_information ); 3384 } 3385 3386 /* 3387 * @implemented 3388 */ 3389 BOOL WINAPI 3390 DuplicateTokenEx(IN HANDLE ExistingTokenHandle, 3391 IN DWORD dwDesiredAccess, 3392 IN LPSECURITY_ATTRIBUTES lpTokenAttributes OPTIONAL, 3393 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, 3394 IN TOKEN_TYPE TokenType, 3395 OUT PHANDLE DuplicateTokenHandle) 3396 { 3397 OBJECT_ATTRIBUTES ObjectAttributes; 3398 NTSTATUS Status; 3399 SECURITY_QUALITY_OF_SERVICE Sqos; 3400 3401 TRACE("%p 0x%08x 0x%08x 0x%08x %p\n", ExistingTokenHandle, dwDesiredAccess, 3402 ImpersonationLevel, TokenType, DuplicateTokenHandle); 3403 3404 Sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); 3405 Sqos.ImpersonationLevel = ImpersonationLevel; 3406 Sqos.ContextTrackingMode = 0; 3407 Sqos.EffectiveOnly = FALSE; 3408 3409 if (lpTokenAttributes != NULL) 3410 { 3411 InitializeObjectAttributes(&ObjectAttributes, 3412 NULL, 3413 lpTokenAttributes->bInheritHandle ? OBJ_INHERIT : 0, 3414 NULL, 3415 lpTokenAttributes->lpSecurityDescriptor); 3416 } 3417 else 3418 { 3419 InitializeObjectAttributes(&ObjectAttributes, 3420 NULL, 3421 0, 3422 NULL, 3423 NULL); 3424 } 3425 3426 ObjectAttributes.SecurityQualityOfService = &Sqos; 3427 3428 Status = NtDuplicateToken(ExistingTokenHandle, 3429 dwDesiredAccess, 3430 &ObjectAttributes, 3431 FALSE, 3432 TokenType, 3433 DuplicateTokenHandle); 3434 if (!NT_SUCCESS(Status)) 3435 { 3436 ERR("NtDuplicateToken failed: Status %08x\n", Status); 3437 SetLastError(RtlNtStatusToDosError(Status)); 3438 return FALSE; 3439 } 3440 3441 TRACE("Returning token %p.\n", *DuplicateTokenHandle); 3442 3443 return TRUE; 3444 } 3445 3446 /* 3447 * @implemented 3448 */ 3449 BOOL WINAPI 3450 DuplicateToken(IN HANDLE ExistingTokenHandle, 3451 IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, 3452 OUT PHANDLE DuplicateTokenHandle) 3453 { 3454 return DuplicateTokenEx(ExistingTokenHandle, 3455 TOKEN_IMPERSONATE | TOKEN_QUERY, 3456 NULL, 3457 ImpersonationLevel, 3458 TokenImpersonation, 3459 DuplicateTokenHandle); 3460 } 3461 3462 /****************************************************************************** 3463 * ComputeStringSidSize 3464 */ 3465 static DWORD ComputeStringSidSize(LPCWSTR StringSid) 3466 { 3467 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */ 3468 { 3469 int ctok = 0; 3470 while (*StringSid) 3471 { 3472 if (*StringSid == '-') 3473 ctok++; 3474 StringSid++; 3475 } 3476 3477 if (ctok >= 3) 3478 return GetSidLengthRequired(ctok - 2); 3479 } 3480 else /* String constant format - Only available in winxp and above */ 3481 { 3482 unsigned int i; 3483 3484 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) 3485 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2)) 3486 return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount); 3487 3488 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++) 3489 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2)) 3490 { 3491 MAX_SID local; 3492 ADVAPI_GetComputerSid(&local); 3493 return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1); 3494 } 3495 3496 } 3497 3498 return GetSidLengthRequired(0); 3499 } 3500 3501 /****************************************************************************** 3502 * ParseStringSidToSid 3503 */ 3504 static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes) 3505 { 3506 BOOL bret = FALSE; 3507 SID* pisid=pSid; 3508 3509 TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes); 3510 if (!StringSid) 3511 { 3512 SetLastError(ERROR_INVALID_PARAMETER); 3513 TRACE("StringSid is NULL, returning FALSE\n"); 3514 return FALSE; 3515 } 3516 3517 while (*StringSid == ' ') 3518 StringSid++; 3519 3520 if (!*StringSid) 3521 goto lend; /* ERROR_INVALID_SID */ 3522 3523 *cBytes = ComputeStringSidSize(StringSid); 3524 if (!pisid) /* Simply compute the size */ 3525 { 3526 TRACE("only size requested, returning TRUE with %d\n", *cBytes); 3527 return TRUE; 3528 } 3529 3530 if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */ 3531 { 3532 DWORD i = 0, identAuth; 3533 DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD)); 3534 3535 StringSid += 2; /* Advance to Revision */ 3536 pisid->Revision = atoiW(StringSid); 3537 3538 if (pisid->Revision != SDDL_REVISION) 3539 { 3540 TRACE("Revision %d is unknown\n", pisid->Revision); 3541 goto lend; /* ERROR_INVALID_SID */ 3542 } 3543 if (csubauth == 0) 3544 { 3545 TRACE("SubAuthorityCount is 0\n"); 3546 goto lend; /* ERROR_INVALID_SID */ 3547 } 3548 3549 pisid->SubAuthorityCount = csubauth; 3550 3551 /* Advance to identifier authority */ 3552 while (*StringSid && *StringSid != '-') 3553 StringSid++; 3554 if (*StringSid == '-') 3555 StringSid++; 3556 3557 /* MS' implementation can't handle values greater than 2^32 - 1, so 3558 * we don't either; assume most significant bytes are always 0 3559 */ 3560 pisid->IdentifierAuthority.Value[0] = 0; 3561 pisid->IdentifierAuthority.Value[1] = 0; 3562 identAuth = atoiW(StringSid); 3563 pisid->IdentifierAuthority.Value[5] = identAuth & 0xff; 3564 pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8; 3565 pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16; 3566 pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24; 3567 3568 /* Advance to first sub authority */ 3569 while (*StringSid && *StringSid != '-') 3570 StringSid++; 3571 if (*StringSid == '-') 3572 StringSid++; 3573 3574 while (*StringSid) 3575 { 3576 pisid->SubAuthority[i++] = atoiW(StringSid); 3577 3578 while (*StringSid && *StringSid != '-') 3579 StringSid++; 3580 if (*StringSid == '-') 3581 StringSid++; 3582 } 3583 3584 if (i != pisid->SubAuthorityCount) 3585 goto lend; /* ERROR_INVALID_SID */ 3586 3587 bret = TRUE; 3588 } 3589 else /* String constant format - Only available in winxp and above */ 3590 { 3591 unsigned int i; 3592 pisid->Revision = SDDL_REVISION; 3593 3594 for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) 3595 if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2)) 3596 { 3597 DWORD j; 3598 pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount; 3599 pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority; 3600 for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++) 3601 pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j]; 3602 bret = TRUE; 3603 } 3604 3605 for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++) 3606 if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2)) 3607 { 3608 ADVAPI_GetComputerSid(pisid); 3609 pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid; 3610 pisid->SubAuthorityCount++; 3611 bret = TRUE; 3612 } 3613 3614 if (!bret) 3615 FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2)); 3616 } 3617 3618 lend: 3619 if (!bret) 3620 SetLastError(ERROR_INVALID_SID); 3621 3622 TRACE("returning %s\n", bret ? "TRUE" : "FALSE"); 3623 return bret; 3624 } 3625 3626 /********************************************************************** 3627 * GetNamedSecurityInfoA EXPORTED 3628 * 3629 * @implemented 3630 */ 3631 DWORD 3632 WINAPI 3633 GetNamedSecurityInfoA(LPSTR pObjectName, 3634 SE_OBJECT_TYPE ObjectType, 3635 SECURITY_INFORMATION SecurityInfo, 3636 PSID *ppsidOwner, 3637 PSID *ppsidGroup, 3638 PACL *ppDacl, 3639 PACL *ppSacl, 3640 PSECURITY_DESCRIPTOR *ppSecurityDescriptor) 3641 { 3642 DWORD len; 3643 LPWSTR wstr = NULL; 3644 DWORD r; 3645 3646 TRACE("%s %d %d %p %p %p %p %p\n", pObjectName, ObjectType, SecurityInfo, 3647 ppsidOwner, ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor); 3648 3649 if( pObjectName ) 3650 { 3651 len = MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, NULL, 0 ); 3652 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR)); 3653 MultiByteToWideChar( CP_ACP, 0, pObjectName, -1, wstr, len ); 3654 } 3655 3656 r = GetNamedSecurityInfoW( wstr, ObjectType, SecurityInfo, ppsidOwner, 3657 ppsidGroup, ppDacl, ppSacl, ppSecurityDescriptor ); 3658 3659 HeapFree( GetProcessHeap(), 0, wstr ); 3660 3661 return r; 3662 } 3663 3664 /****************************************************************************** 3665 * GetWindowsAccountDomainSid [ADVAPI32.@] 3666 */ 3667 BOOL WINAPI GetWindowsAccountDomainSid( PSID sid, PSID domain_sid, DWORD *size ) 3668 { 3669 SID_IDENTIFIER_AUTHORITY domain_ident = { SECURITY_NT_AUTHORITY }; 3670 DWORD required_size; 3671 int i; 3672 3673 FIXME( "(%p %p %p): semi-stub\n", sid, domain_sid, size ); 3674 3675 if (!sid || !IsValidSid( sid )) 3676 { 3677 SetLastError( ERROR_INVALID_SID ); 3678 return FALSE; 3679 } 3680 3681 if (!size) 3682 { 3683 SetLastError( ERROR_INVALID_PARAMETER ); 3684 return FALSE; 3685 } 3686 3687 if (*GetSidSubAuthorityCount( sid ) < 4) 3688 { 3689 SetLastError( ERROR_INVALID_SID ); 3690 return FALSE; 3691 } 3692 3693 required_size = GetSidLengthRequired( 4 ); 3694 if (*size < required_size || !domain_sid) 3695 { 3696 *size = required_size; 3697 SetLastError( domain_sid ? ERROR_INSUFFICIENT_BUFFER : 3698 ERROR_INVALID_PARAMETER ); 3699 return FALSE; 3700 } 3701 3702 InitializeSid( domain_sid, &domain_ident, 4 ); 3703 for (i = 0; i < 4; i++) 3704 *GetSidSubAuthority( domain_sid, i ) = *GetSidSubAuthority( sid, i ); 3705 3706 *size = required_size; 3707 return TRUE; 3708 } 3709 3710 /* 3711 * @unimplemented 3712 */ 3713 BOOL 3714 WINAPI 3715 EqualDomainSid(IN PSID pSid1, 3716 IN PSID pSid2, 3717 OUT BOOL* pfEqual) 3718 { 3719 UNIMPLEMENTED; 3720 return FALSE; 3721 } 3722 3723 /* EOF */ 3724