diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index 6afcc42df5e..6c1cdf1d3b4 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -3919,9 +3919,41 @@ DWORD WINAPI SetNamedSecurityInfoW(LPWSTR pObjectName, SE_OBJECT_TYPE ObjectType, SECURITY_INFORMATION SecurityInfo, PSID psidOwner, PSID psidGroup, PACL pDacl, PACL pSacl) { - FIXME("%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType, + OBJECT_ATTRIBUTES attr; + UNICODE_STRING nameW; + IO_STATUS_BLOCK io; + DWORD access = 0; + HANDLE hFile; + DWORD status; + + TRACE( "%s %d %d %p %p %p %p\n", debugstr_w(pObjectName), ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl); - return ERROR_SUCCESS; + + if (!pObjectName) return ERROR_INVALID_PARAMETER; + if (!RtlDosPathNameToNtPathName_U( pObjectName, &nameW, NULL, NULL )) + return ERROR_PATH_NOT_FOUND; + + if (SecurityInfo & (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION)) + access |= WRITE_OWNER; + if (SecurityInfo & DACL_SECURITY_INFORMATION) + access |= WRITE_DAC; + if (SecurityInfo & SACL_SECURITY_INFORMATION) + access |= ACCESS_SYSTEM_SECURITY; + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &nameW; + attr.SecurityDescriptor = NULL; + + status = NtCreateFile( &hFile, access, &attr, &io, NULL, FILE_FLAG_BACKUP_SEMANTICS, + FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, + FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0 ); + RtlFreeUnicodeString( &nameW ); + if (status != STATUS_SUCCESS) + return RtlNtStatusToDosError( status ); + status = SetSecurityInfo( hFile, ObjectType, SecurityInfo, psidOwner, psidGroup, pDacl, pSacl ); + CloseHandle( hFile ); + return status; } /****************************************************************************** diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c index da5af045ecb..2a4df4dfa4f 100644 --- a/dlls/advapi32/tests/security.c +++ b/dlls/advapi32/tests/security.c @@ -101,6 +101,8 @@ static BOOL (WINAPI *pSetFileSecurityA)(LPCSTR, SECURITY_INFORMATION, static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*); +static DWORD (WINAPI *pSetNamedSecurityInfoA)(LPTSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, + PSID, PSID, PACL, PACL); static PDWORD (WINAPI *pGetSidSubAuthority)(PSID, DWORD); static PUCHAR (WINAPI *pGetSidSubAuthorityCount)(PSID); static BOOL (WINAPI *pIsValidSid)(PSID); @@ -170,6 +172,7 @@ static void init(void) pSetFileSecurityA = (void *)GetProcAddress(hmod, "SetFileSecurityA" ); pCreateWellKnownSid = (void *)GetProcAddress( hmod, "CreateWellKnownSid" ); pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA"); + pSetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "SetNamedSecurityInfoA"); pGetSidSubAuthority = (void *)GetProcAddress(hmod, "GetSidSubAuthority"); pGetSidSubAuthorityCount = (void *)GetProcAddress(hmod, "GetSidSubAuthorityCount"); pIsValidSid = (void *)GetProcAddress(hmod, "IsValidSid"); @@ -3002,6 +3005,7 @@ static void test_SetEntriesInAclA(void) static void test_GetNamedSecurityInfoA(void) { + char invalid_path[] = "/an invalid file path"; PSECURITY_DESCRIPTOR pSecDesc; DWORD revision; SECURITY_DESCRIPTOR_CONTROL control; @@ -3014,9 +3018,9 @@ static void test_GetNamedSecurityInfoA(void) BOOL ret, isNT4; CHAR windows_dir[MAX_PATH]; - if (!pGetNamedSecurityInfoA) + if (!pGetNamedSecurityInfoA || !pSetNamedSecurityInfoA) { - win_skip("GetNamedSecurityInfoA is not available\n"); + win_skip("[Get|Set]NamedSecurityInfoA is not available\n"); return; } @@ -3072,6 +3076,13 @@ static void test_GetNamedSecurityInfoA(void) error = pGetNamedSecurityInfoA(windows_dir, SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION, NULL, NULL, &dacl, NULL, NULL); ok(error==ERROR_INVALID_PARAMETER, "GetNamedSecurityInfo failed with error %d\n", error); + + /* Test behavior of SetNamedSecurityInfo with an invalid path */ + SetLastError(0xdeadbeef); + error = pSetNamedSecurityInfoA(invalid_path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, + NULL, NULL, NULL); + ok(error == ERROR_FILE_NOT_FOUND, "Unexpected error returned: 0x%x\n", error); + ok(GetLastError() == 0xdeadbeef, "Expected last error to remain unchanged.\n"); } static void test_ConvertStringSecurityDescriptor(void)