上次使用简单的Win32窗口函数来捕获用户修改文件夹权限的动作,这次要把那段代码集成到服务中,在后台运行。这样,问题就又出来了。服务默认是运行在LocalSystem账户下的,在这个账户下是不能直接访问用户桌面的,这样我原来的代码放到服务里就失效了。怎么样才能在服务里访问用户桌面呢?在Internet和MSDN中只能找到这样的信息:http://support.microsoft.com/default.aspx?scid=kb;en-us;115825。但是我要的是能够查找用户桌面上的窗口,而不仅仅是能够在服务中弹出对话框让用户能够看到。网上继续查找资料,还是一无所获。最后,翻翻
Jeffrey Richter
的书《Programming Server-Side Applications for MS Windows》的Security部分,发现他早已解决了这个问题,而且还列出了全部的代码。实在太好了。
下面就是他的代码:给要访问桌面的账户添加相应的权限。下面代码中调用的函数在他的书中都能够找到。
BOOL AllowAccessToDesktop(PSID psidTrustee, HDESK hDesk)
{
BOOL fReturn = FALSE;
PSECURITY_DESCRIPTOR psdDesk = NULL;
PACE_UNION pACENew = NULL;
// Get the DACL for the desktop
PACL pDACLDesk;
if(GetSecurityInfo(hDesk, SE_WINDOW_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACLDesk, NULL, &psdDesk) != ERROR_SUCCESS)
goto leave;
// This is the access awarded to a user who logged on interactively
PACE_UNION pACENew = AllocateACE(ACCESS_ALLOWED_ACE_TYPE, 0,
DELETE|WRITE_OWNER|WRITE_DAC|READ_CONTROL|
DESKTOP_READOBJECTS|DESKTOP_CREATEWINDOW|
DESKTOP_CREATEMENU|DESKTOP_HOOKCONTROL|
DESKTOP_JOURNALRECORD|DESKTOP_JOURNALPLAYBACK|
DESKTOP_ENUMERATE|DESKTOP_WRITEOBJECTS|DESKTOP_SWITCHDESKTOP,
psidTrustee);
if (FindACEInACL(pDACLDesk, pACENew) == -1){
// If not, calculate new DACL size
ULONG lNewACL = CalculateACLSize( pDACLDesk, NULL, 0,
&pACENew, 1 );
PACL pNewDACL = (PACL)_alloca(lNewACL);
if (pNewDACL == NULL)
goto leave;
if (!InitializeAcl(pNewDACL, lNewACL, ACL_REVISION))
goto leave;
if (!CopyACL(pNewDACL, pDACLDesk))
goto leave;
ULONG lIndex = GetACEInsertionIndex(pNewDACL, pACENew);
if (!AddAce(pNewDACL, ACL_REVISION, lIndex, pACENew, pACENew->aceHeader.AceSize))
goto leave;
if (SetSecurityInfo(hDesk, SE_WINDOW_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL)!=ERROR_SUCCESS)
goto leave;
}
fReturn = TRUE;
leave:;
}catch(...){
}
// Clean up
if(pACENew != NULL)
LocalFree(pACENew);
if(psdDesk != NULL)
LocalFree(psdDesk);
return (fReturn);
}
{
BOOL fReturn = FALSE;
PSECURITY_DESCRIPTOR psdDesk = NULL;
PACE_UNION pACENew = NULL;
try{
// Get the DACL for the desktop
PACL pDACLDesk;
if(GetSecurityInfo(hDesk, SE_WINDOW_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDACLDesk, NULL, &psdDesk) != ERROR_SUCCESS)
goto leave;
// Allocate our new ACE
// This is the access awarded to a user who logged on interactively
PACE_UNION pACENew = AllocateACE(ACCESS_ALLOWED_ACE_TYPE, 0,
DELETE|WRITE_OWNER|WRITE_DAC|READ_CONTROL|
DESKTOP_READOBJECTS|DESKTOP_CREATEWINDOW|
DESKTOP_CREATEMENU|DESKTOP_HOOKCONTROL|
DESKTOP_JOURNALRECORD|DESKTOP_JOURNALPLAYBACK|
DESKTOP_ENUMERATE|DESKTOP_WRITEOBJECTS|DESKTOP_SWITCHDESKTOP,
psidTrustee);
// Is the ACE already in the DACL?
if (FindACEInACL(pDACLDesk, pACENew) == -1){
// If not, calculate new DACL size
ULONG lNewACL = CalculateACLSize( pDACLDesk, NULL, 0,
&pACENew, 1 );
// Allocate memory for the new DACL
PACL pNewDACL = (PACL)_alloca(lNewACL);
if (pNewDACL == NULL)
goto leave;
// Initialize the ACL
if (!InitializeAcl(pNewDACL, lNewACL, ACL_REVISION))
goto leave;
// Copy the ACL
if (!CopyACL(pNewDACL, pDACLDesk))
goto leave;
// Get location for new ACE
ULONG lIndex = GetACEInsertionIndex(pNewDACL, pACENew);
// Add the new ACE
if (!AddAce(pNewDACL, ACL_REVISION, lIndex, pACENew, pACENew->aceHeader.AceSize))
goto leave;
// Set the DACL back to the window station
if (SetSecurityInfo(hDesk, SE_WINDOW_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDACL, NULL)!=ERROR_SUCCESS)
goto leave;
}
fReturn = TRUE;
leave:;
}catch(...){
}
// Clean up
if(pACENew != NULL)
LocalFree(pACENew);
if(psdDesk != NULL)
LocalFree(psdDesk);
return (fReturn);
}