shlwapi: Implement GetShellSecurityDescriptor and test for it.
This commit is contained in:
parent
def7df305e
commit
5151c81a23
|
@ -4453,3 +4453,151 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID
|
|||
}
|
||||
fn(wEventId, uFlags, dwItem1, dwItem2);
|
||||
}
|
||||
|
||||
typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
|
||||
SID_IDENTIFIER_AUTHORITY sidAuthority;
|
||||
DWORD dwUserGroupID;
|
||||
DWORD dwUserID;
|
||||
} SHELL_USER_SID, *PSHELL_USER_SID;
|
||||
|
||||
typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
|
||||
SHELL_USER_SID susID;
|
||||
DWORD dwAccessType;
|
||||
BOOL fInherit;
|
||||
DWORD dwAccessMask;
|
||||
DWORD dwInheritMask;
|
||||
DWORD dwInheritAccessMask;
|
||||
} SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
|
||||
|
||||
/***********************************************************************
|
||||
* GetShellSecurityDescriptor [SHLWAPI.475]
|
||||
*
|
||||
* prepares SECURITY_DESCRIPTOR from a set of ACEs
|
||||
*
|
||||
* PARAMS
|
||||
* apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
|
||||
* each of which describes permissions to apply
|
||||
* cUserPerm [I] number of entries in apUserPerm array
|
||||
*
|
||||
* RETURNS
|
||||
* success: pointer to SECURITY_DESCRIPTOR
|
||||
* failure: NULL
|
||||
*
|
||||
* NOTES
|
||||
* Call should free returned descriptor with LocalFree
|
||||
*/
|
||||
SECURITY_DESCRIPTOR * WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
|
||||
{
|
||||
PSID *sidlist;
|
||||
PSID cur_user = NULL;
|
||||
BYTE tuUser[2000];
|
||||
DWORD acl_size;
|
||||
int sid_count, i;
|
||||
PSECURITY_DESCRIPTOR psd = NULL;
|
||||
|
||||
TRACE("%p %d\n", apUserPerm, cUserPerm);
|
||||
|
||||
if (apUserPerm == NULL || cUserPerm <= 0)
|
||||
return NULL;
|
||||
|
||||
sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
|
||||
if (!sidlist)
|
||||
return NULL;
|
||||
|
||||
acl_size = sizeof(ACL);
|
||||
|
||||
for(sid_count = 0; sid_count < cUserPerm; sid_count++)
|
||||
{
|
||||
static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
|
||||
PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
|
||||
PSHELL_USER_SID sid = &perm->susID;
|
||||
PSID pSid;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
|
||||
{ /* current user's SID */
|
||||
if (!cur_user)
|
||||
{
|
||||
HANDLE Token;
|
||||
DWORD bufsize = sizeof(tuUser);
|
||||
|
||||
ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
|
||||
if (ret)
|
||||
{
|
||||
ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
|
||||
if (ret)
|
||||
cur_user = ((PTOKEN_USER)&tuUser)->User.Sid;
|
||||
CloseHandle(Token);
|
||||
}
|
||||
}
|
||||
pSid = cur_user;
|
||||
} else if (sid->dwUserID==0) /* one sub-authority */
|
||||
ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
|
||||
0, 0, 0, 0, 0, 0, &pSid);
|
||||
else
|
||||
ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
|
||||
0, 0, 0, 0, 0, 0, &pSid);
|
||||
if (!ret)
|
||||
goto free_sids;
|
||||
|
||||
sidlist[sid_count] = pSid;
|
||||
/* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
|
||||
acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
|
||||
}
|
||||
|
||||
psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
|
||||
|
||||
if (psd != NULL)
|
||||
{
|
||||
PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
|
||||
|
||||
if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
|
||||
goto error;
|
||||
|
||||
if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
|
||||
goto error;
|
||||
|
||||
for(i = 0; i < sid_count; i++)
|
||||
{
|
||||
PSHELL_USER_PERMISSION sup = apUserPerm[i];
|
||||
PSID sid = sidlist[i];
|
||||
|
||||
switch(sup->dwAccessType)
|
||||
{
|
||||
case ACCESS_ALLOWED_ACE_TYPE:
|
||||
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
|
||||
goto error;
|
||||
if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
|
||||
(BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
|
||||
goto error;
|
||||
break;
|
||||
case ACCESS_DENIED_ACE_TYPE:
|
||||
if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
|
||||
goto error;
|
||||
if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
|
||||
(BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
|
||||
goto error;
|
||||
break;
|
||||
default:
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
|
||||
goto error;
|
||||
}
|
||||
goto free_sids;
|
||||
|
||||
error:
|
||||
LocalFree(psd);
|
||||
psd = NULL;
|
||||
free_sids:
|
||||
for(i = 0; i < sid_count; i++)
|
||||
{
|
||||
if (!cur_user || sidlist[i] != cur_user)
|
||||
FreeSid(sidlist[i]);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, sidlist);
|
||||
|
||||
return psd;
|
||||
}
|
||||
|
|
|
@ -472,7 +472,7 @@
|
|||
472 stub -noname SHCreatePropertyBagOnProfileSelections
|
||||
473 stub -noname SHGetIniStringUTF7W
|
||||
474 stub -noname SHSetIniStringUTF7W
|
||||
475 stub -noname GetShellSecurityDescriptor
|
||||
475 stdcall -noname GetShellSecurityDescriptor(ptr long)
|
||||
476 stub -noname SHGetObjectCompatFlags
|
||||
477 stub -noname SHCreatePropertyBagOnMemory
|
||||
478 stdcall -noname IUnknown_TranslateAcceleratorIO(ptr ptr)
|
||||
|
|
|
@ -327,6 +327,110 @@ static void test_fdsa(void)
|
|||
HeapFree(GetProcessHeap(), 0, mem);
|
||||
}
|
||||
|
||||
|
||||
typedef struct SHELL_USER_SID {
|
||||
SID_IDENTIFIER_AUTHORITY sidAuthority;
|
||||
DWORD dwUserGroupID;
|
||||
DWORD dwUserID;
|
||||
} SHELL_USER_SID, *PSHELL_USER_SID;
|
||||
typedef struct SHELL_USER_PERMISSION {
|
||||
SHELL_USER_SID susID;
|
||||
DWORD dwAccessType;
|
||||
BOOL fInherit;
|
||||
DWORD dwAccessMask;
|
||||
DWORD dwInheritMask;
|
||||
DWORD dwInheritAccessMask;
|
||||
} SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
|
||||
static void test_GetShellSecurityDescriptor(void)
|
||||
{
|
||||
SHELL_USER_PERMISSION supCurrentUserFull = {
|
||||
{ {SECURITY_NULL_SID_AUTHORITY}, 0, 0 },
|
||||
ACCESS_ALLOWED_ACE_TYPE, FALSE,
|
||||
GENERIC_ALL, 0, 0 };
|
||||
#define MY_INHERITANCE 0xBE /* invalid value to proof behavior */
|
||||
SHELL_USER_PERMISSION supEveryoneDenied = {
|
||||
{ {SECURITY_WORLD_SID_AUTHORITY}, SECURITY_WORLD_RID, 0 },
|
||||
ACCESS_DENIED_ACE_TYPE, TRUE,
|
||||
GENERIC_WRITE, MY_INHERITANCE | 0xDEADBA00, GENERIC_READ };
|
||||
PSHELL_USER_PERMISSION rgsup[2] = {
|
||||
&supCurrentUserFull, &supEveryoneDenied,
|
||||
};
|
||||
SECURITY_DESCRIPTOR* psd;
|
||||
SECURITY_DESCRIPTOR* (WINAPI*pGetShellSecurityDescriptor)(PSHELL_USER_PERMISSION*,int);
|
||||
|
||||
pGetShellSecurityDescriptor=(void*)GetProcAddress(hShlwapi,(char*)475);
|
||||
|
||||
psd = pGetShellSecurityDescriptor(NULL, 2);
|
||||
ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
|
||||
psd = pGetShellSecurityDescriptor(rgsup, 0);
|
||||
ok(psd==NULL, "GetShellSecurityDescriptor should fail\n");
|
||||
|
||||
psd = pGetShellSecurityDescriptor(rgsup, 2);
|
||||
ok(psd!=NULL, "GetShellSecurityDescriptor failed\n");
|
||||
if (psd!=NULL)
|
||||
{
|
||||
BOOL bHasDacl = FALSE, bDefaulted;
|
||||
PACL pAcl;
|
||||
DWORD dwRev;
|
||||
SECURITY_DESCRIPTOR_CONTROL control;
|
||||
|
||||
ok(IsValidSecurityDescriptor(psd), "returned value is not valid SD\n");
|
||||
|
||||
ok(GetSecurityDescriptorControl(psd, &control, &dwRev),
|
||||
"GetSecurityDescriptorControl failed with error %d\n", GetLastError());
|
||||
ok(0 == (control & SE_SELF_RELATIVE), "SD should be absolute\n");
|
||||
|
||||
ok(GetSecurityDescriptorDacl(psd, &bHasDacl, &pAcl, &bDefaulted),
|
||||
"GetSecurityDescriptorDacl failed with error %d\n", GetLastError());
|
||||
|
||||
ok(bHasDacl, "SD has no DACL\n");
|
||||
if (bHasDacl)
|
||||
{
|
||||
ok(!bDefaulted, "DACL should not be defaulted\n");
|
||||
|
||||
ok(pAcl != NULL, "NULL DACL!\n");
|
||||
if (pAcl != NULL)
|
||||
{
|
||||
ACL_SIZE_INFORMATION asiSize;
|
||||
|
||||
ok(IsValidAcl(pAcl), "DACL is not valid\n");
|
||||
|
||||
ok(GetAclInformation(pAcl, &asiSize, sizeof(asiSize), AclSizeInformation),
|
||||
"GetAclInformation failed with error %d\n", GetLastError());
|
||||
|
||||
ok(asiSize.AceCount == 3, "Incorrect number of ACEs: %d entries\n", asiSize.AceCount);
|
||||
if (asiSize.AceCount == 3)
|
||||
{
|
||||
ACCESS_ALLOWED_ACE *paaa; /* will use for DENIED too */
|
||||
|
||||
ok(GetAce(pAcl, 0, (LPVOID*)&paaa), "GetAce failed with error %d\n", GetLastError());
|
||||
ok(paaa->Header.AceType == ACCESS_ALLOWED_ACE_TYPE,
|
||||
"Invalid ACE type %d\n", paaa->Header.AceType);
|
||||
ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
|
||||
ok(paaa->Mask == GENERIC_ALL, "Invalid ACE mask %x\n", paaa->Mask);
|
||||
|
||||
ok(GetAce(pAcl, 1, (LPVOID*)&paaa), "GetAce failed with error %d\n", GetLastError());
|
||||
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
|
||||
"Invalid ACE type %d\n", paaa->Header.AceType);
|
||||
/* first one of two ACEs generated from inheritable entry - without inheritance */
|
||||
ok(paaa->Header.AceFlags == 0, "Invalid ACE flags %x\n", paaa->Header.AceFlags);
|
||||
ok(paaa->Mask == GENERIC_WRITE, "Invalid ACE mask %x\n", paaa->Mask);
|
||||
|
||||
ok(GetAce(pAcl, 2, (LPVOID*)&paaa), "GetAce failed with error %d\n", GetLastError());
|
||||
ok(paaa->Header.AceType == ACCESS_DENIED_ACE_TYPE,
|
||||
"Invalid ACE type %d\n", paaa->Header.AceType);
|
||||
/* second ACE - with inheritance */
|
||||
ok(paaa->Header.AceFlags == MY_INHERITANCE,
|
||||
"Invalid ACE flags %x\n", paaa->Header.AceFlags);
|
||||
ok(paaa->Mask == GENERIC_READ, "Invalid ACE mask %x\n", paaa->Mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LocalFree(psd);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(ordinal)
|
||||
{
|
||||
hShlwapi = LoadLibraryA("shlwapi.dll");
|
||||
|
@ -345,6 +449,7 @@ START_TEST(ordinal)
|
|||
test_SHSearchMapInt();
|
||||
test_alloc_shared();
|
||||
test_fdsa();
|
||||
test_GetShellSecurityDescriptor();
|
||||
|
||||
FreeLibrary(hShlwapi);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue