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 SetLastError(ERROR_SUCCESS); 763 return RtlIdentifierAuthoritySid(pSid); 764 } 765 766 /* 767 * @implemented 768 */ 769 PDWORD 770 WINAPI 771 GetSidSubAuthority(PSID pSid, 772 DWORD nSubAuthority) 773 { 774 SetLastError(ERROR_SUCCESS); 775 return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority); 776 } 777 778 /* 779 * @implemented 780 */ 781 PUCHAR 782 WINAPI 783 GetSidSubAuthorityCount(PSID pSid) 784 { 785 SetLastError(ERROR_SUCCESS); 786 return RtlSubAuthorityCountSid(pSid); 787 } 788 789 /* 790 * @implemented 791 */ 792 DWORD 793 WINAPI 794 GetLengthSid(PSID pSid) 795 { 796 return (DWORD)RtlLengthSid(pSid); 797 } 798 799 /* 800 * @implemented 801 */ 802 BOOL 803 WINAPI 804 InitializeSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor, 805 DWORD dwRevision) 806 { 807 NTSTATUS Status; 808 809 Status = RtlCreateSecurityDescriptor(pSecurityDescriptor, 810 dwRevision); 811 if (!NT_SUCCESS(Status)) 812 { 813 SetLastError(RtlNtStatusToDosError(Status)); 814 return FALSE; 815 } 816 817 return TRUE; 818 } 819 820 /* 821 * @implemented 822 */ 823 BOOL 824 WINAPI 825 MakeAbsoluteSD(PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor, 826 PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor, 827 LPDWORD lpdwAbsoluteSecurityDescriptorSize, 828 PACL pDacl, 829 LPDWORD lpdwDaclSize, 830 PACL pSacl, 831 LPDWORD lpdwSaclSize, 832 PSID pOwner, 833 LPDWORD lpdwOwnerSize, 834 PSID pPrimaryGroup, 835 LPDWORD lpdwPrimaryGroupSize) 836 { 837 NTSTATUS Status; 838 839 Status = RtlSelfRelativeToAbsoluteSD(pSelfRelativeSecurityDescriptor, 840 pAbsoluteSecurityDescriptor, 841 lpdwAbsoluteSecurityDescriptorSize, 842 pDacl, 843 lpdwDaclSize, 844 pSacl, 845 lpdwSaclSize, 846 pOwner, 847 lpdwOwnerSize, 848 pPrimaryGroup, 849 lpdwPrimaryGroupSize); 850 if (!NT_SUCCESS(Status)) 851 { 852 SetLastError(RtlNtStatusToDosError(Status)); 853 return FALSE; 854 } 855 856 return TRUE; 857 } 858 859 /****************************************************************************** 860 * GetKernelObjectSecurity [ADVAPI32.@] 861 */ 862 BOOL WINAPI GetKernelObjectSecurity( 863 HANDLE Handle, 864 SECURITY_INFORMATION RequestedInformation, 865 PSECURITY_DESCRIPTOR pSecurityDescriptor, 866 DWORD nLength, 867 LPDWORD lpnLengthNeeded ) 868 { 869 TRACE("(%p,0x%08x,%p,0x%08x,%p)\n", Handle, RequestedInformation, 870 pSecurityDescriptor, nLength, lpnLengthNeeded); 871 872 return set_ntstatus( NtQuerySecurityObject(Handle, RequestedInformation, pSecurityDescriptor, 873 nLength, lpnLengthNeeded )); 874 } 875 876 /* 877 * @implemented 878 */ 879 BOOL 880 WINAPI 881 InitializeAcl(PACL pAcl, 882 DWORD nAclLength, 883 DWORD dwAclRevision) 884 { 885 NTSTATUS Status; 886 887 Status = RtlCreateAcl(pAcl, 888 nAclLength, 889 dwAclRevision); 890 if (!NT_SUCCESS(Status)) 891 { 892 SetLastError(RtlNtStatusToDosError(Status)); 893 return FALSE; 894 } 895 896 return TRUE; 897 } 898 899 BOOL WINAPI ImpersonateNamedPipeClient( HANDLE hNamedPipe ) 900 { 901 IO_STATUS_BLOCK io_block; 902 903 TRACE("(%p)\n", hNamedPipe); 904 905 return set_ntstatus( NtFsControlFile(hNamedPipe, NULL, NULL, NULL, 906 &io_block, FSCTL_PIPE_IMPERSONATE, NULL, 0, NULL, 0) ); 907 } 908 909 /* 910 * @implemented 911 */ 912 BOOL 913 WINAPI 914 AddAccessAllowedAce(PACL pAcl, 915 DWORD dwAceRevision, 916 DWORD AccessMask, 917 PSID pSid) 918 { 919 NTSTATUS Status; 920 921 Status = RtlAddAccessAllowedAce(pAcl, 922 dwAceRevision, 923 AccessMask, 924 pSid); 925 if (!NT_SUCCESS(Status)) 926 { 927 SetLastError(RtlNtStatusToDosError(Status)); 928 return FALSE; 929 } 930 931 return TRUE; 932 } 933 934 /* 935 * @implemented 936 */ 937 BOOL WINAPI 938 AddAccessAllowedAceEx(PACL pAcl, 939 DWORD dwAceRevision, 940 DWORD AceFlags, 941 DWORD AccessMask, 942 PSID pSid) 943 { 944 NTSTATUS Status; 945 946 Status = RtlAddAccessAllowedAceEx(pAcl, 947 dwAceRevision, 948 AceFlags, 949 AccessMask, 950 pSid); 951 if (!NT_SUCCESS(Status)) 952 { 953 SetLastError(RtlNtStatusToDosError(Status)); 954 return FALSE; 955 } 956 957 return TRUE; 958 } 959 960 /* 961 * @implemented 962 */ 963 BOOL 964 WINAPI 965 AddAccessDeniedAce(PACL pAcl, 966 DWORD dwAceRevision, 967 DWORD AccessMask, 968 PSID pSid) 969 { 970 NTSTATUS Status; 971 972 Status = RtlAddAccessDeniedAce(pAcl, 973 dwAceRevision, 974 AccessMask, 975 pSid); 976 if (!NT_SUCCESS(Status)) 977 { 978 SetLastError(RtlNtStatusToDosError(Status)); 979 return FALSE; 980 } 981 982 return TRUE; 983 } 984 985 /* 986 * @implemented 987 */ 988 BOOL WINAPI 989 AddAccessDeniedAceEx(PACL pAcl, 990 DWORD dwAceRevision, 991 DWORD AceFlags, 992 DWORD AccessMask, 993 PSID pSid) 994 { 995 NTSTATUS Status; 996 997 Status = RtlAddAccessDeniedAceEx(pAcl, 998 dwAceRevision, 999 AceFlags, 1000 AccessMask, 1001 pSid); 1002 if (!NT_SUCCESS(Status)) 1003 { 1004 SetLastError(RtlNtStatusToDosError(Status)); 1005 return FALSE; 1006 } 1007 1008 return TRUE; 1009 } 1010 1011 /* 1012 * @implemented 1013 */ 1014 BOOL 1015 WINAPI 1016 AddAce(PACL pAcl, 1017 DWORD dwAceRevision, 1018 DWORD dwStartingAceIndex, 1019 LPVOID pAceList, 1020 DWORD nAceListLength) 1021 { 1022 NTSTATUS Status; 1023 1024 Status = RtlAddAce(pAcl, 1025 dwAceRevision, 1026 dwStartingAceIndex, 1027 pAceList, 1028 nAceListLength); 1029 if (!NT_SUCCESS(Status)) 1030 { 1031 SetLastError(RtlNtStatusToDosError(Status)); 1032 return FALSE; 1033 } 1034 1035 return TRUE; 1036 } 1037 1038 /****************************************************************************** 1039 * DeleteAce [ADVAPI32.@] 1040 */ 1041 BOOL WINAPI DeleteAce(PACL pAcl, DWORD dwAceIndex) 1042 { 1043 return set_ntstatus(RtlDeleteAce(pAcl, dwAceIndex)); 1044 } 1045 1046 /* 1047 * @implemented 1048 */ 1049 BOOL 1050 WINAPI 1051 FindFirstFreeAce(PACL pAcl, 1052 LPVOID *pAce) 1053 { 1054 return RtlFirstFreeAce(pAcl, 1055 (PACE*)pAce); 1056 } 1057 1058 /****************************************************************************** 1059 * GetAce [ADVAPI32.@] 1060 */ 1061 BOOL WINAPI GetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce ) 1062 { 1063 return set_ntstatus(RtlGetAce(pAcl, dwAceIndex, pAce)); 1064 } 1065 1066 /****************************************************************************** 1067 * GetAclInformation [ADVAPI32.@] 1068 */ 1069 BOOL WINAPI GetAclInformation( 1070 PACL pAcl, 1071 LPVOID pAclInformation, 1072 DWORD nAclInformationLength, 1073 ACL_INFORMATION_CLASS dwAclInformationClass) 1074 { 1075 return set_ntstatus(RtlQueryInformationAcl(pAcl, pAclInformation, 1076 nAclInformationLength, dwAclInformationClass)); 1077 } 1078 1079 /* 1080 * @implemented 1081 */ 1082 BOOL 1083 WINAPI 1084 IsValidAcl(PACL pAcl) 1085 { 1086 return RtlValidAcl (pAcl); 1087 } 1088 1089 /* 1090 * @implemented 1091 */ 1092 BOOL WINAPI 1093 AllocateLocallyUniqueId(PLUID Luid) 1094 { 1095 NTSTATUS Status; 1096 1097 Status = NtAllocateLocallyUniqueId (Luid); 1098 if (!NT_SUCCESS (Status)) 1099 { 1100 SetLastError(RtlNtStatusToDosError(Status)); 1101 return FALSE; 1102 } 1103 1104 return TRUE; 1105 } 1106 1107 /********************************************************************** 1108 * LookupPrivilegeDisplayNameA EXPORTED 1109 * 1110 * @unimplemented 1111 */ 1112 BOOL 1113 WINAPI 1114 LookupPrivilegeDisplayNameA(LPCSTR lpSystemName, 1115 LPCSTR lpName, 1116 LPSTR lpDisplayName, 1117 LPDWORD cchDisplayName, 1118 LPDWORD lpLanguageId) 1119 { 1120 UNICODE_STRING lpSystemNameW; 1121 UNICODE_STRING lpNameW; 1122 BOOL ret; 1123 DWORD wLen = 0; 1124 1125 TRACE("%s %s %p %p %p\n", debugstr_a(lpSystemName), debugstr_a(lpName), lpName, cchDisplayName, lpLanguageId); 1126 1127 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName); 1128 RtlCreateUnicodeStringFromAsciiz(&lpNameW, lpName); 1129 ret = LookupPrivilegeDisplayNameW(lpSystemNameW.Buffer, lpNameW.Buffer, NULL, &wLen, lpLanguageId); 1130 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 1131 { 1132 LPWSTR lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR)); 1133 1134 ret = LookupPrivilegeDisplayNameW(lpSystemNameW.Buffer, lpNameW.Buffer, lpDisplayNameW, 1135 &wLen, lpLanguageId); 1136 if (ret) 1137 { 1138 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, lpDisplayName, 1139 *cchDisplayName, NULL, NULL); 1140 1141 if (len == 0) 1142 { 1143 /* WideCharToMultiByte failed */ 1144 ret = FALSE; 1145 } 1146 else if (len > *cchDisplayName) 1147 { 1148 *cchDisplayName = len; 1149 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1150 ret = FALSE; 1151 } 1152 else 1153 { 1154 /* WideCharToMultiByte succeeded, output length needs to be 1155 * length not including NULL terminator 1156 */ 1157 *cchDisplayName = len - 1; 1158 } 1159 } 1160 HeapFree(GetProcessHeap(), 0, lpDisplayNameW); 1161 } 1162 RtlFreeUnicodeString(&lpSystemNameW); 1163 RtlFreeUnicodeString(&lpNameW); 1164 return ret; 1165 } 1166 1167 /********************************************************************** 1168 * LookupPrivilegeNameA EXPORTED 1169 * 1170 * @implemented 1171 */ 1172 BOOL 1173 WINAPI 1174 LookupPrivilegeNameA(LPCSTR lpSystemName, 1175 PLUID lpLuid, 1176 LPSTR lpName, 1177 LPDWORD cchName) 1178 { 1179 UNICODE_STRING lpSystemNameW; 1180 BOOL ret; 1181 DWORD wLen = 0; 1182 1183 TRACE("%s %p %p %p\n", debugstr_a(lpSystemName), lpLuid, lpName, cchName); 1184 1185 RtlCreateUnicodeStringFromAsciiz(&lpSystemNameW, lpSystemName); 1186 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, NULL, &wLen); 1187 if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) 1188 { 1189 LPWSTR lpNameW = HeapAlloc(GetProcessHeap(), 0, wLen * sizeof(WCHAR)); 1190 1191 ret = LookupPrivilegeNameW(lpSystemNameW.Buffer, lpLuid, lpNameW, 1192 &wLen); 1193 if (ret) 1194 { 1195 /* Windows crashes if cchName is NULL, so will I */ 1196 unsigned int len = WideCharToMultiByte(CP_ACP, 0, lpNameW, -1, lpName, 1197 *cchName, NULL, NULL); 1198 1199 if (len == 0) 1200 { 1201 /* WideCharToMultiByte failed */ 1202 ret = FALSE; 1203 } 1204 else if (len > *cchName) 1205 { 1206 *cchName = len; 1207 SetLastError(ERROR_INSUFFICIENT_BUFFER); 1208 ret = FALSE; 1209 } 1210 else 1211 { 1212 /* WideCharToMultiByte succeeded, output length needs to be 1213 * length not including NULL terminator 1214 */ 1215 *cchName = len - 1; 1216 } 1217 } 1218 HeapFree(GetProcessHeap(), 0, lpNameW); 1219 } 1220 RtlFreeUnicodeString(&lpSystemNameW); 1221 return ret; 1222 } 1223 1224 /****************************************************************************** 1225 * GetFileSecurityA [ADVAPI32.@] 1226 * 1227 * Obtains Specified information about the security of a file or directory. 1228 * 1229 * PARAMS 1230 * lpFileName [I] Name of the file to get info for 1231 * RequestedInformation [I] SE_ flags from "winnt.h" 1232 * pSecurityDescriptor [O] Destination for security information 1233 * nLength [I] Length of pSecurityDescriptor 1234 * lpnLengthNeeded [O] Destination for length of returned security information 1235 * 1236 * RETURNS 1237 * Success: TRUE. pSecurityDescriptor contains the requested information. 1238 * Failure: FALSE. lpnLengthNeeded contains the required space to return the info. 1239 * 1240 * NOTES 1241 * The information returned is constrained by the callers access rights and 1242 * privileges. 1243 * 1244 * @implemented 1245 */ 1246 BOOL 1247 WINAPI 1248 GetFileSecurityA(LPCSTR lpFileName, 1249 SECURITY_INFORMATION RequestedInformation, 1250 PSECURITY_DESCRIPTOR pSecurityDescriptor, 1251 DWORD nLength, 1252 LPDWORD lpnLengthNeeded) 1253 { 1254 UNICODE_STRING FileName; 1255 BOOL bResult; 1256 1257 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName)) 1258 { 1259 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1260 return FALSE; 1261 } 1262 1263 bResult = GetFileSecurityW(FileName.Buffer, 1264 RequestedInformation, 1265 pSecurityDescriptor, 1266 nLength, 1267 lpnLengthNeeded); 1268 1269 RtlFreeUnicodeString(&FileName); 1270 1271 return bResult; 1272 } 1273 1274 /* 1275 * @implemented 1276 */ 1277 BOOL 1278 WINAPI 1279 GetFileSecurityW(LPCWSTR lpFileName, 1280 SECURITY_INFORMATION RequestedInformation, 1281 PSECURITY_DESCRIPTOR pSecurityDescriptor, 1282 DWORD nLength, 1283 LPDWORD lpnLengthNeeded) 1284 { 1285 OBJECT_ATTRIBUTES ObjectAttributes; 1286 IO_STATUS_BLOCK StatusBlock; 1287 UNICODE_STRING FileName; 1288 ULONG AccessMask = 0; 1289 HANDLE FileHandle; 1290 NTSTATUS Status; 1291 1292 TRACE("GetFileSecurityW() called\n"); 1293 1294 QuerySecurityAccessMask(RequestedInformation, &AccessMask); 1295 1296 if (!RtlDosPathNameToNtPathName_U(lpFileName, 1297 &FileName, 1298 NULL, 1299 NULL)) 1300 { 1301 ERR("Invalid path\n"); 1302 SetLastError(ERROR_INVALID_NAME); 1303 return FALSE; 1304 } 1305 1306 InitializeObjectAttributes(&ObjectAttributes, 1307 &FileName, 1308 OBJ_CASE_INSENSITIVE, 1309 NULL, 1310 NULL); 1311 1312 Status = NtOpenFile(&FileHandle, 1313 AccessMask, 1314 &ObjectAttributes, 1315 &StatusBlock, 1316 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 1317 0); 1318 1319 RtlFreeHeap(RtlGetProcessHeap(), 1320 0, 1321 FileName.Buffer); 1322 1323 if (!NT_SUCCESS(Status)) 1324 { 1325 ERR("NtOpenFile() failed (Status %lx)\n", Status); 1326 SetLastError(RtlNtStatusToDosError(Status)); 1327 return FALSE; 1328 } 1329 1330 Status = NtQuerySecurityObject(FileHandle, 1331 RequestedInformation, 1332 pSecurityDescriptor, 1333 nLength, 1334 lpnLengthNeeded); 1335 NtClose(FileHandle); 1336 if (!NT_SUCCESS(Status)) 1337 { 1338 ERR("NtQuerySecurityObject() failed (Status %lx)\n", Status); 1339 SetLastError(RtlNtStatusToDosError(Status)); 1340 return FALSE; 1341 } 1342 1343 return TRUE; 1344 } 1345 1346 /****************************************************************************** 1347 * SetFileSecurityA [ADVAPI32.@] 1348 * Sets the security of a file or directory 1349 * 1350 * @implemented 1351 */ 1352 BOOL 1353 WINAPI 1354 SetFileSecurityA(LPCSTR lpFileName, 1355 SECURITY_INFORMATION SecurityInformation, 1356 PSECURITY_DESCRIPTOR pSecurityDescriptor) 1357 { 1358 UNICODE_STRING FileName; 1359 BOOL bResult; 1360 1361 if (!RtlCreateUnicodeStringFromAsciiz(&FileName, lpFileName)) 1362 { 1363 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 1364 return FALSE; 1365 } 1366 1367 bResult = SetFileSecurityW(FileName.Buffer, 1368 SecurityInformation, 1369 pSecurityDescriptor); 1370 1371 RtlFreeUnicodeString(&FileName); 1372 1373 return bResult; 1374 } 1375 1376 /****************************************************************************** 1377 * SetFileSecurityW [ADVAPI32.@] 1378 * Sets the security of a file or directory 1379 * 1380 * @implemented 1381 */ 1382 BOOL 1383 WINAPI 1384 SetFileSecurityW(LPCWSTR lpFileName, 1385 SECURITY_INFORMATION SecurityInformation, 1386 PSECURITY_DESCRIPTOR pSecurityDescriptor) 1387 { 1388 OBJECT_ATTRIBUTES ObjectAttributes; 1389 IO_STATUS_BLOCK StatusBlock; 1390 UNICODE_STRING FileName; 1391 ULONG AccessMask = 0; 1392 HANDLE FileHandle; 1393 NTSTATUS Status; 1394 1395 TRACE("SetFileSecurityW() called\n"); 1396 1397 SetSecurityAccessMask(SecurityInformation, &AccessMask); 1398 1399 if (!RtlDosPathNameToNtPathName_U(lpFileName, 1400 &FileName, 1401 NULL, 1402 NULL)) 1403 { 1404 ERR("Invalid path\n"); 1405 SetLastError(ERROR_INVALID_NAME); 1406 return FALSE; 1407 } 1408 1409 InitializeObjectAttributes(&ObjectAttributes, 1410 &FileName, 1411 OBJ_CASE_INSENSITIVE, 1412 NULL, 1413 NULL); 1414 1415 Status = NtOpenFile(&FileHandle, 1416 AccessMask, 1417 &ObjectAttributes, 1418 &StatusBlock, 1419 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 1420 0); 1421 1422 RtlFreeHeap(RtlGetProcessHeap(), 1423 0, 1424 FileName.Buffer); 1425 1426 if (!NT_SUCCESS(Status)) 1427 { 1428 ERR("NtOpenFile() failed (Status %lx)\n", Status); 1429 SetLastError(RtlNtStatusToDosError(Status)); 1430 return FALSE; 1431 } 1432 1433 Status = NtSetSecurityObject(FileHandle, 1434 SecurityInformation, 1435 pSecurityDescriptor); 1436 NtClose(FileHandle); 1437 1438 if (!NT_SUCCESS(Status)) 1439 { 1440 ERR("NtSetSecurityObject() failed (Status %lx)\n", Status); 1441 SetLastError(RtlNtStatusToDosError(Status)); 1442 return FALSE; 1443 } 1444 1445 return TRUE; 1446 } 1447 1448 /****************************************************************************** 1449 * QueryWindows31FilesMigration [ADVAPI32.@] 1450 * 1451 * PARAMS 1452 * x1 [] 1453 */ 1454 BOOL WINAPI 1455 QueryWindows31FilesMigration( DWORD x1 ) 1456 { 1457 FIXME("(%d):stub\n",x1); 1458 return TRUE; 1459 } 1460 1461 /****************************************************************************** 1462 * SynchronizeWindows31FilesAndWindowsNTRegistry [ADVAPI32.@] 1463 * 1464 * PARAMS 1465 * x1 [] 1466 * x2 [] 1467 * x3 [] 1468 * x4 [] 1469 */ 1470 BOOL WINAPI 1471 SynchronizeWindows31FilesAndWindowsNTRegistry( DWORD x1, DWORD x2, DWORD x3, 1472 DWORD x4 ) 1473 { 1474 FIXME("(0x%08x,0x%08x,0x%08x,0x%08x):stub\n",x1,x2,x3,x4); 1475 return TRUE; 1476 } 1477 1478 /* 1479 * @implemented 1480 */ 1481 BOOL 1482 WINAPI 1483 RevertToSelf(VOID) 1484 { 1485 NTSTATUS Status; 1486 HANDLE Token = NULL; 1487 1488 Status = NtSetInformationThread(NtCurrentThread(), 1489 ThreadImpersonationToken, 1490 &Token, 1491 sizeof(HANDLE)); 1492 if (!NT_SUCCESS(Status)) 1493 { 1494 SetLastError(RtlNtStatusToDosError(Status)); 1495 return FALSE; 1496 } 1497 1498 return TRUE; 1499 } 1500 1501 /* 1502 * @implemented 1503 */ 1504 BOOL 1505 WINAPI 1506 ImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel) 1507 { 1508 NTSTATUS Status; 1509 1510 Status = RtlImpersonateSelf(ImpersonationLevel); 1511 if (!NT_SUCCESS(Status)) 1512 { 1513 SetLastError(RtlNtStatusToDosError(Status)); 1514 return FALSE; 1515 } 1516 1517 return TRUE; 1518 } 1519 1520 /* 1521 * @implemented 1522 */ 1523 BOOL 1524 WINAPI 1525 AccessCheck(IN PSECURITY_DESCRIPTOR pSecurityDescriptor, 1526 IN HANDLE ClientToken, 1527 IN DWORD DesiredAccess, 1528 IN PGENERIC_MAPPING GenericMapping, 1529 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL, 1530 IN OUT LPDWORD PrivilegeSetLength, 1531 OUT LPDWORD GrantedAccess, 1532 OUT LPBOOL AccessStatus) 1533 { 1534 NTSTATUS Status; 1535 NTSTATUS NtAccessStatus; 1536 1537 /* Do the access check */ 1538 Status = NtAccessCheck(pSecurityDescriptor, 1539 ClientToken, 1540 DesiredAccess, 1541 GenericMapping, 1542 PrivilegeSet, 1543 (PULONG)PrivilegeSetLength, 1544 (PACCESS_MASK)GrantedAccess, 1545 &NtAccessStatus); 1546 1547 /* See if the access check operation succeeded */ 1548 if (!NT_SUCCESS(Status)) 1549 { 1550 /* Check failed */ 1551 SetLastError(RtlNtStatusToDosError(Status)); 1552 return FALSE; 1553 } 1554 1555 /* Now check the access status */ 1556 if (!NT_SUCCESS(NtAccessStatus)) 1557 { 1558 /* Access denied */ 1559 SetLastError(RtlNtStatusToDosError(NtAccessStatus)); 1560 *AccessStatus = FALSE; 1561 } 1562 else 1563 { 1564 /* Access granted */ 1565 *AccessStatus = TRUE; 1566 } 1567 1568 /* Check succeeded */ 1569 return TRUE; 1570 } 1571 1572 /* 1573 * @unimplemented 1574 */ 1575 BOOL WINAPI AccessCheckByType( 1576 PSECURITY_DESCRIPTOR pSecurityDescriptor, 1577 PSID PrincipalSelfSid, 1578 HANDLE ClientToken, 1579 DWORD DesiredAccess, 1580 POBJECT_TYPE_LIST ObjectTypeList, 1581 DWORD ObjectTypeListLength, 1582 PGENERIC_MAPPING GenericMapping, 1583 PPRIVILEGE_SET PrivilegeSet, 1584 LPDWORD PrivilegeSetLength, 1585 LPDWORD GrantedAccess, 1586 LPBOOL AccessStatus) 1587 { 1588 FIXME("stub\n"); 1589 1590 *AccessStatus = TRUE; 1591 1592 return !*AccessStatus; 1593 } 1594 1595 /* 1596 * @implemented 1597 */ 1598 BOOL 1599 WINAPI 1600 SetKernelObjectSecurity(HANDLE Handle, 1601 SECURITY_INFORMATION SecurityInformation, 1602 PSECURITY_DESCRIPTOR SecurityDescriptor) 1603 { 1604 NTSTATUS Status; 1605 1606 Status = NtSetSecurityObject(Handle, 1607 SecurityInformation, 1608 SecurityDescriptor); 1609 if (!NT_SUCCESS(Status)) 1610 { 1611 SetLastError(RtlNtStatusToDosError(Status)); 1612 return FALSE; 1613 } 1614 1615 return TRUE; 1616 } 1617 1618 /* 1619 * @implemented 1620 */ 1621 BOOL 1622 WINAPI 1623 AddAuditAccessAce(PACL pAcl, 1624 DWORD dwAceRevision, 1625 DWORD dwAccessMask, 1626 PSID pSid, 1627 BOOL bAuditSuccess, 1628 BOOL bAuditFailure) 1629 { 1630 NTSTATUS Status; 1631 1632 Status = RtlAddAuditAccessAce(pAcl, 1633 dwAceRevision, 1634 dwAccessMask, 1635 pSid, 1636 bAuditSuccess, 1637 bAuditFailure); 1638 if (!NT_SUCCESS(Status)) 1639 { 1640 SetLastError(RtlNtStatusToDosError(Status)); 1641 return FALSE; 1642 } 1643 1644 return TRUE; 1645 } 1646 1647 /* 1648 * @implemented 1649 */ 1650 BOOL WINAPI 1651 AddAuditAccessAceEx(PACL pAcl, 1652 DWORD dwAceRevision, 1653 DWORD AceFlags, 1654 DWORD dwAccessMask, 1655 PSID pSid, 1656 BOOL bAuditSuccess, 1657 BOOL bAuditFailure) 1658 { 1659 NTSTATUS Status; 1660 1661 Status = RtlAddAuditAccessAceEx(pAcl, 1662 dwAceRevision, 1663 AceFlags, 1664 dwAccessMask, 1665 pSid, 1666 bAuditSuccess, 1667 bAuditFailure); 1668 if (!NT_SUCCESS(Status)) 1669 { 1670 SetLastError(RtlNtStatusToDosError(Status)); 1671 return FALSE; 1672 } 1673 1674 return TRUE; 1675 } 1676 1677 /****************************************************************************** 1678 * LookupAccountNameA [ADVAPI32.@] 1679 * 1680 * @implemented 1681 */ 1682 BOOL 1683 WINAPI 1684 LookupAccountNameA(LPCSTR SystemName, 1685 LPCSTR AccountName, 1686 PSID Sid, 1687 LPDWORD SidLength, 1688 LPSTR ReferencedDomainName, 1689 LPDWORD hReferencedDomainNameLength, 1690 PSID_NAME_USE SidNameUse) 1691 { 1692 BOOL ret; 1693 UNICODE_STRING lpSystemW; 1694 UNICODE_STRING lpAccountW; 1695 LPWSTR lpReferencedDomainNameW = NULL; 1696 1697 RtlCreateUnicodeStringFromAsciiz(&lpSystemW, SystemName); 1698 RtlCreateUnicodeStringFromAsciiz(&lpAccountW, AccountName); 1699 1700 if (ReferencedDomainName) 1701 lpReferencedDomainNameW = HeapAlloc(GetProcessHeap(), 1702 0, 1703 *hReferencedDomainNameLength * sizeof(WCHAR)); 1704 1705 ret = LookupAccountNameW(lpSystemW.Buffer, 1706 lpAccountW.Buffer, 1707 Sid, 1708 SidLength, 1709 lpReferencedDomainNameW, 1710 hReferencedDomainNameLength, 1711 SidNameUse); 1712 1713 if (ret && lpReferencedDomainNameW) 1714 { 1715 WideCharToMultiByte(CP_ACP, 1716 0, 1717 lpReferencedDomainNameW, 1718 *hReferencedDomainNameLength + 1, 1719 ReferencedDomainName, 1720 *hReferencedDomainNameLength + 1, 1721 NULL, 1722 NULL); 1723 } 1724 1725 RtlFreeUnicodeString(&lpSystemW); 1726 RtlFreeUnicodeString(&lpAccountW); 1727 HeapFree(GetProcessHeap(), 0, lpReferencedDomainNameW); 1728 1729 return ret; 1730 } 1731 1732 /********************************************************************** 1733 * PrivilegeCheck EXPORTED 1734 * 1735 * @implemented 1736 */ 1737 BOOL WINAPI 1738 PrivilegeCheck(HANDLE ClientToken, 1739 PPRIVILEGE_SET RequiredPrivileges, 1740 LPBOOL pfResult) 1741 { 1742 BOOLEAN Result; 1743 NTSTATUS Status; 1744 1745 Status = NtPrivilegeCheck(ClientToken, 1746 RequiredPrivileges, 1747 &Result); 1748 if (!NT_SUCCESS(Status)) 1749 { 1750 SetLastError(RtlNtStatusToDosError(Status)); 1751 return FALSE; 1752 } 1753 1754 *pfResult = (BOOL)Result; 1755 1756 return TRUE; 1757 } 1758 1759 /****************************************************************************** 1760 * GetSecurityInfoExW EXPORTED 1761 */ 1762 DWORD 1763 WINAPI 1764 GetSecurityInfoExA(HANDLE hObject, 1765 SE_OBJECT_TYPE ObjectType, 1766 SECURITY_INFORMATION SecurityInfo, 1767 LPCSTR lpProvider, 1768 LPCSTR lpProperty, 1769 PACTRL_ACCESSA *ppAccessList, 1770 PACTRL_AUDITA *ppAuditList, 1771 LPSTR *lppOwner, 1772 LPSTR *lppGroup) 1773 { 1774 FIXME("%s() not implemented!\n", __FUNCTION__); 1775 return ERROR_BAD_PROVIDER; 1776 } 1777 1778 1779 /****************************************************************************** 1780 * GetSecurityInfoExW EXPORTED 1781 */ 1782 DWORD 1783 WINAPI 1784 GetSecurityInfoExW(HANDLE hObject, 1785 SE_OBJECT_TYPE ObjectType, 1786 SECURITY_INFORMATION SecurityInfo, 1787 LPCWSTR lpProvider, 1788 LPCWSTR lpProperty, 1789 PACTRL_ACCESSW *ppAccessList, 1790 PACTRL_AUDITW *ppAuditList, 1791 LPWSTR *lppOwner, 1792 LPWSTR *lppGroup) 1793 { 1794 FIXME("%s() not implemented!\n", __FUNCTION__); 1795 return ERROR_BAD_PROVIDER; 1796 } 1797 1798 /****************************************************************************** 1799 * BuildExplicitAccessWithNameA [ADVAPI32.@] 1800 */ 1801 VOID WINAPI 1802 BuildExplicitAccessWithNameA(PEXPLICIT_ACCESSA pExplicitAccess, 1803 LPSTR pTrusteeName, 1804 DWORD AccessPermissions, 1805 ACCESS_MODE AccessMode, 1806 DWORD Inheritance) 1807 { 1808 pExplicitAccess->grfAccessPermissions = AccessPermissions; 1809 pExplicitAccess->grfAccessMode = AccessMode; 1810 pExplicitAccess->grfInheritance = Inheritance; 1811 1812 pExplicitAccess->Trustee.pMultipleTrustee = NULL; 1813 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1814 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME; 1815 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; 1816 pExplicitAccess->Trustee.ptstrName = pTrusteeName; 1817 } 1818 1819 1820 /****************************************************************************** 1821 * BuildExplicitAccessWithNameW [ADVAPI32.@] 1822 */ 1823 VOID WINAPI 1824 BuildExplicitAccessWithNameW(PEXPLICIT_ACCESSW pExplicitAccess, 1825 LPWSTR pTrusteeName, 1826 DWORD AccessPermissions, 1827 ACCESS_MODE AccessMode, 1828 DWORD Inheritance) 1829 { 1830 pExplicitAccess->grfAccessPermissions = AccessPermissions; 1831 pExplicitAccess->grfAccessMode = AccessMode; 1832 pExplicitAccess->grfInheritance = Inheritance; 1833 1834 pExplicitAccess->Trustee.pMultipleTrustee = NULL; 1835 pExplicitAccess->Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1836 pExplicitAccess->Trustee.TrusteeForm = TRUSTEE_IS_NAME; 1837 pExplicitAccess->Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; 1838 pExplicitAccess->Trustee.ptstrName = pTrusteeName; 1839 } 1840 1841 /****************************************************************************** 1842 * BuildTrusteeWithObjectsAndNameA [ADVAPI32.@] 1843 */ 1844 VOID WINAPI BuildTrusteeWithObjectsAndNameA( PTRUSTEEA pTrustee, POBJECTS_AND_NAME_A pObjName, 1845 SE_OBJECT_TYPE ObjectType, LPSTR ObjectTypeName, 1846 LPSTR InheritedObjectTypeName, LPSTR Name ) 1847 { 1848 DWORD ObjectsPresent = 0; 1849 1850 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName, 1851 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_a(Name)); 1852 1853 /* Fill the OBJECTS_AND_NAME structure */ 1854 pObjName->ObjectType = ObjectType; 1855 if (ObjectTypeName != NULL) 1856 { 1857 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT; 1858 } 1859 1860 pObjName->InheritedObjectTypeName = InheritedObjectTypeName; 1861 if (InheritedObjectTypeName != NULL) 1862 { 1863 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT; 1864 } 1865 1866 pObjName->ObjectsPresent = ObjectsPresent; 1867 pObjName->ptstrName = Name; 1868 1869 /* Fill the TRUSTEE structure */ 1870 pTrustee->pMultipleTrustee = NULL; 1871 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1872 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME; 1873 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 1874 pTrustee->ptstrName = (LPSTR)pObjName; 1875 } 1876 1877 /****************************************************************************** 1878 * BuildTrusteeWithObjectsAndNameW [ADVAPI32.@] 1879 */ 1880 VOID WINAPI BuildTrusteeWithObjectsAndNameW( PTRUSTEEW pTrustee, POBJECTS_AND_NAME_W pObjName, 1881 SE_OBJECT_TYPE ObjectType, LPWSTR ObjectTypeName, 1882 LPWSTR InheritedObjectTypeName, LPWSTR Name ) 1883 { 1884 DWORD ObjectsPresent = 0; 1885 1886 TRACE("%p %p 0x%08x %p %p %s\n", pTrustee, pObjName, 1887 ObjectType, ObjectTypeName, InheritedObjectTypeName, debugstr_w(Name)); 1888 1889 /* Fill the OBJECTS_AND_NAME structure */ 1890 pObjName->ObjectType = ObjectType; 1891 if (ObjectTypeName != NULL) 1892 { 1893 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT; 1894 } 1895 1896 pObjName->InheritedObjectTypeName = InheritedObjectTypeName; 1897 if (InheritedObjectTypeName != NULL) 1898 { 1899 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT; 1900 } 1901 1902 pObjName->ObjectsPresent = ObjectsPresent; 1903 pObjName->ptstrName = Name; 1904 1905 /* Fill the TRUSTEE structure */ 1906 pTrustee->pMultipleTrustee = NULL; 1907 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1908 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_NAME; 1909 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 1910 pTrustee->ptstrName = (LPWSTR)pObjName; 1911 } 1912 1913 /****************************************************************************** 1914 * BuildTrusteeWithObjectsAndSidA [ADVAPI32.@] 1915 */ 1916 VOID WINAPI 1917 BuildTrusteeWithObjectsAndSidA(PTRUSTEEA pTrustee, 1918 POBJECTS_AND_SID pObjSid, 1919 GUID *pObjectGuid, 1920 GUID *pInheritedObjectGuid, 1921 PSID pSid) 1922 { 1923 DWORD ObjectsPresent = 0; 1924 1925 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid); 1926 1927 /* Fill the OBJECTS_AND_SID structure */ 1928 if (pObjectGuid != NULL) 1929 { 1930 pObjSid->ObjectTypeGuid = *pObjectGuid; 1931 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT; 1932 } 1933 else 1934 { 1935 ZeroMemory(&pObjSid->ObjectTypeGuid, 1936 sizeof(GUID)); 1937 } 1938 1939 if (pInheritedObjectGuid != NULL) 1940 { 1941 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid; 1942 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT; 1943 } 1944 else 1945 { 1946 ZeroMemory(&pObjSid->InheritedObjectTypeGuid, 1947 sizeof(GUID)); 1948 } 1949 1950 pObjSid->ObjectsPresent = ObjectsPresent; 1951 pObjSid->pSid = pSid; 1952 1953 /* Fill the TRUSTEE structure */ 1954 pTrustee->pMultipleTrustee = NULL; 1955 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1956 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID; 1957 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 1958 pTrustee->ptstrName = (LPSTR) pObjSid; 1959 } 1960 1961 1962 /****************************************************************************** 1963 * BuildTrusteeWithObjectsAndSidW [ADVAPI32.@] 1964 */ 1965 VOID WINAPI 1966 BuildTrusteeWithObjectsAndSidW(PTRUSTEEW pTrustee, 1967 POBJECTS_AND_SID pObjSid, 1968 GUID *pObjectGuid, 1969 GUID *pInheritedObjectGuid, 1970 PSID pSid) 1971 { 1972 DWORD ObjectsPresent = 0; 1973 1974 TRACE("%p %p %p %p %p\n", pTrustee, pObjSid, pObjectGuid, pInheritedObjectGuid, pSid); 1975 1976 /* Fill the OBJECTS_AND_SID structure */ 1977 if (pObjectGuid != NULL) 1978 { 1979 pObjSid->ObjectTypeGuid = *pObjectGuid; 1980 ObjectsPresent |= ACE_OBJECT_TYPE_PRESENT; 1981 } 1982 else 1983 { 1984 ZeroMemory(&pObjSid->ObjectTypeGuid, 1985 sizeof(GUID)); 1986 } 1987 1988 if (pInheritedObjectGuid != NULL) 1989 { 1990 pObjSid->InheritedObjectTypeGuid = *pInheritedObjectGuid; 1991 ObjectsPresent |= ACE_INHERITED_OBJECT_TYPE_PRESENT; 1992 } 1993 else 1994 { 1995 ZeroMemory(&pObjSid->InheritedObjectTypeGuid, 1996 sizeof(GUID)); 1997 } 1998 1999 pObjSid->ObjectsPresent = ObjectsPresent; 2000 pObjSid->pSid = pSid; 2001 2002 /* Fill the TRUSTEE structure */ 2003 pTrustee->pMultipleTrustee = NULL; 2004 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2005 pTrustee->TrusteeForm = TRUSTEE_IS_OBJECTS_AND_SID; 2006 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2007 pTrustee->ptstrName = (LPWSTR) pObjSid; 2008 } 2009 2010 /****************************************************************************** 2011 * BuildTrusteeWithSidA [ADVAPI32.@] 2012 */ 2013 VOID WINAPI 2014 BuildTrusteeWithSidA(PTRUSTEE_A pTrustee, 2015 PSID pSid) 2016 { 2017 TRACE("%p %p\n", pTrustee, pSid); 2018 2019 pTrustee->pMultipleTrustee = NULL; 2020 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2021 pTrustee->TrusteeForm = TRUSTEE_IS_SID; 2022 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2023 pTrustee->ptstrName = (LPSTR) pSid; 2024 } 2025 2026 2027 /****************************************************************************** 2028 * BuildTrusteeWithSidW [ADVAPI32.@] 2029 */ 2030 VOID WINAPI 2031 BuildTrusteeWithSidW(PTRUSTEE_W pTrustee, 2032 PSID pSid) 2033 { 2034 TRACE("%p %p\n", pTrustee, pSid); 2035 2036 pTrustee->pMultipleTrustee = NULL; 2037 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2038 pTrustee->TrusteeForm = TRUSTEE_IS_SID; 2039 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2040 pTrustee->ptstrName = (LPWSTR) pSid; 2041 } 2042 2043 /****************************************************************************** 2044 * BuildTrusteeWithNameA [ADVAPI32.@] 2045 */ 2046 VOID WINAPI 2047 BuildTrusteeWithNameA(PTRUSTEE_A pTrustee, 2048 LPSTR name) 2049 { 2050 TRACE("%p %s\n", pTrustee, name); 2051 2052 pTrustee->pMultipleTrustee = NULL; 2053 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2054 pTrustee->TrusteeForm = TRUSTEE_IS_NAME; 2055 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2056 pTrustee->ptstrName = name; 2057 } 2058 2059 /****************************************************************************** 2060 * BuildTrusteeWithNameW [ADVAPI32.@] 2061 */ 2062 VOID WINAPI 2063 BuildTrusteeWithNameW(PTRUSTEE_W pTrustee, 2064 LPWSTR name) 2065 { 2066 TRACE("%p %s\n", pTrustee, name); 2067 2068 pTrustee->pMultipleTrustee = NULL; 2069 pTrustee->MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 2070 pTrustee->TrusteeForm = TRUSTEE_IS_NAME; 2071 pTrustee->TrusteeType = TRUSTEE_IS_UNKNOWN; 2072 pTrustee->ptstrName = name; 2073 } 2074 2075 /****************************************************************************** 2076 * GetTrusteeFormA [ADVAPI32.@] 2077 */ 2078 TRUSTEE_FORM WINAPI GetTrusteeFormA(PTRUSTEEA pTrustee) 2079 { 2080 TRACE("(%p)\n", pTrustee); 2081 2082 if (!pTrustee) 2083 return TRUSTEE_BAD_FORM; 2084 2085 return pTrustee->TrusteeForm; 2086 } 2087 2088 /****************************************************************************** 2089 * GetTrusteeFormW [ADVAPI32.@] 2090 */ 2091 TRUSTEE_FORM WINAPI GetTrusteeFormW(PTRUSTEEW pTrustee) 2092 { 2093 TRACE("(%p)\n", pTrustee); 2094 2095 if (!pTrustee) 2096 return TRUSTEE_BAD_FORM; 2097 2098 return pTrustee->TrusteeForm; 2099 } 2100 2101 /****************************************************************************** 2102 * GetTrusteeNameA [ADVAPI32.@] 2103 */ 2104 LPSTR WINAPI 2105 GetTrusteeNameA(PTRUSTEE_A pTrustee) 2106 { 2107 return pTrustee->ptstrName; 2108 } 2109 2110 2111 /****************************************************************************** 2112 * GetTrusteeNameW [ADVAPI32.@] 2113 */ 2114 LPWSTR WINAPI 2115 GetTrusteeNameW(PTRUSTEE_W pTrustee) 2116 { 2117 return pTrustee->ptstrName; 2118 } 2119 2120 /****************************************************************************** 2121 * GetTrusteeTypeA [ADVAPI32.@] 2122 */ 2123 TRUSTEE_TYPE WINAPI 2124 GetTrusteeTypeA(PTRUSTEE_A pTrustee) 2125 { 2126 return pTrustee->TrusteeType; 2127 } 2128 2129 /****************************************************************************** 2130 * GetTrusteeTypeW [ADVAPI32.@] 2131 */ 2132 TRUSTEE_TYPE WINAPI 2133 GetTrusteeTypeW(PTRUSTEE_W pTrustee) 2134 { 2135 return pTrustee->TrusteeType; 2136 } 2137 2138 /* 2139 * @implemented 2140 */ 2141 BOOL 2142 WINAPI 2143 SetAclInformation(PACL pAcl, 2144 LPVOID pAclInformation, 2145 DWORD nAclInformationLength, 2146 ACL_INFORMATION_CLASS dwAclInformationClass) 2147 { 2148 NTSTATUS Status; 2149 2150 Status = RtlSetInformationAcl(pAcl, 2151 pAclInformation, 2152 nAclInformationLength, 2153 dwAclInformationClass); 2154 if (!NT_SUCCESS(Status)) 2155 { 2156 SetLastError(RtlNtStatusToDosError(Status)); 2157 return FALSE; 2158 } 2159 2160 return TRUE; 2161 } 2162 2163 /********************************************************************** 2164 * SetNamedSecurityInfoA EXPORTED 2165 * 2166 * @implemented 2167 */ 2168 DWORD 2169 WINAPI 2170 SetNamedSecurityInfoA(LPSTR pObjectName, 2171 SE_OBJECT_TYPE ObjectType, 2172 SECURITY_INFORMATION SecurityInfo, 2173 PSID psidOwner, 2174 PSID psidGroup, 2175 PACL pDacl, 2176 PACL pSacl) 2177 { 2178 UNICODE_STRING ObjectName; 2179 DWORD Ret; 2180 2181 if (!RtlCreateUnicodeStringFromAsciiz(&ObjectName, pObjectName)) 2182 { 2183 return ERROR_NOT_ENOUGH_MEMORY; 2184 } 2185 2186 Ret = SetNamedSecurityInfoW(ObjectName.Buffer, 2187 ObjectType, 2188 SecurityInfo, 2189 psidOwner, 2190 psidGroup, 2191 pDacl, 2192 pSacl); 2193 2194 RtlFreeUnicodeString(&ObjectName); 2195 2196 return Ret; 2197 } 2198 2199 /* 2200 * @implemented 2201 */ 2202 BOOL 2203 WINAPI 2204 AreAllAccessesGranted(DWORD GrantedAccess, 2205 DWORD DesiredAccess) 2206 { 2207 return (BOOL)RtlAreAllAccessesGranted(GrantedAccess, 2208 DesiredAccess); 2209 } 2210 2211 /* 2212 * @implemented 2213 */ 2214 BOOL 2215 WINAPI 2216 AreAnyAccessesGranted(DWORD GrantedAccess, 2217 DWORD DesiredAccess) 2218 { 2219 return (BOOL)RtlAreAnyAccessesGranted(GrantedAccess, 2220 DesiredAccess); 2221 } 2222 2223 /****************************************************************************** 2224 * ParseAclStringFlags 2225 */ 2226 static DWORD ParseAclStringFlags(LPCWSTR* StringAcl) 2227 { 2228 DWORD flags = 0; 2229 LPCWSTR szAcl = *StringAcl; 2230 2231 while (*szAcl && *szAcl != '(') 2232 { 2233 if (*szAcl == 'P') 2234 { 2235 flags |= SE_DACL_PROTECTED; 2236 } 2237 else if (*szAcl == 'A') 2238 { 2239 szAcl++; 2240 if (*szAcl == 'R') 2241 flags |= SE_DACL_AUTO_INHERIT_REQ; 2242 else if (*szAcl == 'I') 2243 flags |= SE_DACL_AUTO_INHERITED; 2244 } 2245 szAcl++; 2246 } 2247 2248 *StringAcl = szAcl; 2249 return flags; 2250 } 2251 2252 /****************************************************************************** 2253 * ParseAceStringType 2254 */ 2255 static const ACEFLAG AceType[] = 2256 { 2257 { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE }, 2258 { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE }, 2259 { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE }, 2260 { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE }, 2261 { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE }, 2262 /* 2263 { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE }, 2264 { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE }, 2265 { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE }, 2266 { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE }, 2267 */ 2268 { NULL, 0 }, 2269 }; 2270 2271 static BYTE ParseAceStringType(LPCWSTR* StringAcl) 2272 { 2273 UINT len = 0; 2274 LPCWSTR szAcl = *StringAcl; 2275 const ACEFLAG *lpaf = AceType; 2276 2277 while (*szAcl == ' ') 2278 szAcl++; 2279 2280 while (lpaf->wstr && 2281 (len = strlenW(lpaf->wstr)) && 2282 strncmpW(lpaf->wstr, szAcl, len)) 2283 lpaf++; 2284 2285 if (!lpaf->wstr) 2286 return 0; 2287 2288 *StringAcl = szAcl + len; 2289 return lpaf->value; 2290 } 2291 2292 2293 /****************************************************************************** 2294 * ParseAceStringFlags 2295 */ 2296 static const ACEFLAG AceFlags[] = 2297 { 2298 { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE }, 2299 { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG }, 2300 { SDDL_INHERITED, INHERITED_ACE }, 2301 { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE }, 2302 { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE }, 2303 { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE }, 2304 { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG }, 2305 { NULL, 0 }, 2306 }; 2307 2308 static BYTE ParseAceStringFlags(LPCWSTR* StringAcl) 2309 { 2310 UINT len = 0; 2311 BYTE flags = 0; 2312 LPCWSTR szAcl = *StringAcl; 2313 2314 while (*szAcl == ' ') 2315 szAcl++; 2316 2317 while (*szAcl != ';') 2318 { 2319 const ACEFLAG *lpaf = AceFlags; 2320 2321 while (lpaf->wstr && 2322 (len = strlenW(lpaf->wstr)) && 2323 strncmpW(lpaf->wstr, szAcl, len)) 2324 lpaf++; 2325 2326 if (!lpaf->wstr) 2327 return 0; 2328 2329 flags |= lpaf->value; 2330 szAcl += len; 2331 } 2332 2333 *StringAcl = szAcl; 2334 return flags; 2335 } 2336 2337 2338 /****************************************************************************** 2339 * ParseAceStringRights 2340 */ 2341 static const ACEFLAG AceRights[] = 2342 { 2343 { SDDL_GENERIC_ALL, GENERIC_ALL }, 2344 { SDDL_GENERIC_READ, GENERIC_READ }, 2345 { SDDL_GENERIC_WRITE, GENERIC_WRITE }, 2346 { SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE }, 2347 2348 { SDDL_READ_CONTROL, READ_CONTROL }, 2349 { SDDL_STANDARD_DELETE, DELETE }, 2350 { SDDL_WRITE_DAC, WRITE_DAC }, 2351 { SDDL_WRITE_OWNER, WRITE_OWNER }, 2352 2353 { SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP}, 2354 { SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP}, 2355 { SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD}, 2356 { SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD}, 2357 { SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST}, 2358 { SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF}, 2359 { SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT}, 2360 { SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE}, 2361 { SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS}, 2362 2363 { SDDL_FILE_ALL, FILE_ALL_ACCESS }, 2364 { SDDL_FILE_READ, FILE_GENERIC_READ }, 2365 { SDDL_FILE_WRITE, FILE_GENERIC_WRITE }, 2366 { SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE }, 2367 2368 { SDDL_KEY_ALL, KEY_ALL_ACCESS }, 2369 { SDDL_KEY_READ, KEY_READ }, 2370 { SDDL_KEY_WRITE, KEY_WRITE }, 2371 { SDDL_KEY_EXECUTE, KEY_EXECUTE }, 2372 2373 { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP }, 2374 { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP }, 2375 { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP }, 2376 { NULL, 0 }, 2377 }; 2378 2379 static DWORD ParseAceStringRights(LPCWSTR* StringAcl) 2380 { 2381 UINT len = 0; 2382 DWORD rights = 0; 2383 LPCWSTR szAcl = *StringAcl; 2384 2385 while (*szAcl == ' ') 2386 szAcl++; 2387 2388 if ((*szAcl == '0') && (*(szAcl + 1) == 'x')) 2389 { 2390 LPCWSTR p = szAcl; 2391 2392 while (*p && *p != ';') 2393 p++; 2394 2395 if (p - szAcl <= 10 /* 8 hex digits + "0x" */ ) 2396 { 2397 rights = strtoulW(szAcl, NULL, 16); 2398 szAcl = p; 2399 } 2400 else 2401 WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl)); 2402 } 2403 else 2404 { 2405 while (*szAcl != ';') 2406 { 2407 const ACEFLAG *lpaf = AceRights; 2408 2409 while (lpaf->wstr && 2410 (len = strlenW(lpaf->wstr)) && 2411 strncmpW(lpaf->wstr, szAcl, len)) 2412 { 2413 lpaf++; 2414 } 2415 2416 if (!lpaf->wstr) 2417 return 0; 2418 2419 rights |= lpaf->value; 2420 szAcl += len; 2421 } 2422 } 2423 2424 *StringAcl = szAcl; 2425 return rights; 2426 } 2427 2428 2429 /****************************************************************************** 2430 * ParseStringAclToAcl 2431 * 2432 * dacl_flags(string_ace1)(string_ace2)... (string_acen) 2433 */ 2434 static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, 2435 PACL pAcl, LPDWORD cBytes) 2436 { 2437 DWORD val; 2438 DWORD sidlen; 2439 DWORD length = sizeof(ACL); 2440 DWORD acesize = 0; 2441 DWORD acecount = 0; 2442 PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */ 2443 DWORD error = ERROR_INVALID_ACL; 2444 2445 TRACE("%s\n", debugstr_w(StringAcl)); 2446 2447 if (!StringAcl) 2448 return FALSE; 2449 2450 if (pAcl) /* pAce is only useful if we're setting values */ 2451 pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1); 2452 2453 /* Parse ACL flags */ 2454 *lpdwFlags = ParseAclStringFlags(&StringAcl); 2455 2456 /* Parse ACE */ 2457 while (*StringAcl == '(') 2458 { 2459 StringAcl++; 2460 2461 /* Parse ACE type */ 2462 val = ParseAceStringType(&StringAcl); 2463 if (pAce) 2464 pAce->Header.AceType = (BYTE) val; 2465 if (*StringAcl != ';') 2466 { 2467 error = RPC_S_INVALID_STRING_UUID; 2468 goto lerr; 2469 } 2470 StringAcl++; 2471 2472 /* Parse ACE flags */ 2473 val = ParseAceStringFlags(&StringAcl); 2474 if (pAce) 2475 pAce->Header.AceFlags = (BYTE) val; 2476 if (*StringAcl != ';') 2477 goto lerr; 2478 StringAcl++; 2479 2480 /* Parse ACE rights */ 2481 val = ParseAceStringRights(&StringAcl); 2482 if (pAce) 2483 pAce->Mask = val; 2484 if (*StringAcl != ';') 2485 goto lerr; 2486 StringAcl++; 2487 2488 /* Parse ACE object guid */ 2489 while (*StringAcl == ' ') 2490 StringAcl++; 2491 if (*StringAcl != ';') 2492 { 2493 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); 2494 goto lerr; 2495 } 2496 StringAcl++; 2497 2498 /* Parse ACE inherit object guid */ 2499 while (*StringAcl == ' ') 2500 StringAcl++; 2501 if (*StringAcl != ';') 2502 { 2503 FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); 2504 goto lerr; 2505 } 2506 StringAcl++; 2507 2508 /* Parse ACE account sid */ 2509 if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen)) 2510 { 2511 while (*StringAcl && *StringAcl != ')') 2512 StringAcl++; 2513 } 2514 2515 if (*StringAcl != ')') 2516 goto lerr; 2517 StringAcl++; 2518 2519 acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen; 2520 length += acesize; 2521 if (pAce) 2522 { 2523 pAce->Header.AceSize = acesize; 2524 pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize); 2525 } 2526 acecount++; 2527 } 2528 2529 *cBytes = length; 2530 2531 if (length > 0xffff) 2532 { 2533 ERR("ACL too large\n"); 2534 goto lerr; 2535 } 2536 2537 if (pAcl) 2538 { 2539 pAcl->AclRevision = ACL_REVISION; 2540 pAcl->Sbz1 = 0; 2541 pAcl->AclSize = length; 2542 pAcl->AceCount = acecount; 2543 pAcl->Sbz2 = 0; 2544 } 2545 return TRUE; 2546 2547 lerr: 2548 SetLastError(error); 2549 WARN("Invalid ACE string format\n"); 2550 return FALSE; 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_RELATIVE); 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