分类: WINDOWS
2009-09-14 11:14:55
当以一个普通用户的身份把自己制作的安装包装到Windows Vista系统盘的“Program File”目录下时,可能会发现,安装上的可执行程序打不开指定的服务或各种其它进程已创建的对象,读写不了系统盘下“Program File”目录中的文件等等问题。这些问题都是由于Vista下存在用户权限控制(UAC)而引起的。 通过之前一个项目的经验,这里提供一些解决方法,如下:
1. 对于打不开服务的问题, 要想办法降低所打开服务所需的用户权限,下面一段代码就是用来降低某个服务的控制权限的。
BOOL CAgentService::AdjustAccessRights(char *lpszServiceName)
{
BOOL bDaclPresent = FALSE;
BOOL bDaclDefaulted = FALSE;
SC_HANDLE schManager = NULL;
SC_HANDLE schService = NULL;
PACL pacl = NULL;
PACL pnewacl = NULL;
EXPLICIT_ACCESS exa;
DWORD dwSize = 0;
DWORD code = ERROR_SUCCESS;
SECURITY_DESCRIPTOR sd;
PSECURITY_DESCRIPTOR psdesc = NULL;
BOOL bError = FALSE;
memset(&exa, 0, sizeof(exa));
memset(&sd, 0, sizeof(sd));
schManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if(!schManager)
{
bError = TRUE;
}
if(!bError)
{
schService = OpenService(schManager, lpszServiceName, READ_CONTROL | WRITE_DAC);
if(!schService)
{
bError = TRUE;
}
}
if(!bError)
{
if (!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &sd, 0, &dwSize))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
psdesc = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
if (psdesc == NULL)
{
bError = TRUE;
}
if (!QueryServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, psdesc, dwSize, &dwSize))
{
bError = TRUE;
}
}
else
{
bError = TRUE;
}
}
}
if(!bError)
{
if (!GetSecurityDescriptorDacl(psdesc, &bDaclPresent, &pacl, &bDaclDefaulted))
{
bError = TRUE;
}
BuildExplicitAccessWithName(&exa,
"Everyone",
SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL,
SET_ACCESS,
NO_INHERITANCE);
code = SetEntriesInAcl(1, &exa, pacl, &pnewacl);
if(code != ERROR_SUCCESS)
{
bError = TRUE;
}
if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
{
bError = TRUE;
}
if(!SetSecurityDescriptorDacl(&sd, TRUE, pnewacl, FALSE))
{
bError = TRUE;
}
if (!SetServiceObjectSecurity(schService, DACL_SECURITY_INFORMATION, &sd))
{
bError = TRUE;
}
}
if(pnewacl)
{
LocalFree(pnewacl);
}
if(psdesc)
{
HeapFree(GetProcessHeap(), 0, psdesc);
}
if(schService)
{
CloseServiceHandle(schService);
}
if(schManager)
{
CloseServiceHandle(schManager);
}
return bError;
}
2. 对于安装上的可执行文件无法读写系统盘“Program File”目录下的文件的问题,简单的解决办法是在制作安装包时做一定的设置,这里以InstallShiled 12制作安装包为例,
如图选择Direct/LockPermissions, 把右边User一栏填写为“Everyone”。
这样我们做好的安装包,安装到Vista下任意目录下时,任意用户对该安装目录都有读写权限,自然也就不会出现无法读写文件的问题,当然,这种做法有一定的风险。如果大家以后又更好的解决办法,请及时提出来。
3. 对于在Vista一个进程下无法打开其它进程已创建好的事件对象,互斥对象,共享内存,管道等对象的问题,主要是因Vista下提升了对各种对象操作的安全限制,解决的方法就是在创建各种对象之前为其添加”Security Descriptor”,如下:
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
m_bWinVista = GetOSVersion_Vista();
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = &sd;
if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
{
return false; // Handle errors.
}
// Add a NULL DACL to the security descriptor.
if(!SetSecurityDescriptorDacl(&sd, TRUE, (PACL)NULL, FALSE))
{
return false; // Handle errors.
}
接下来用得到的sd创建需要的对象