2006-01-23 08:47:05 +00:00
|
|
|
// Berkeley Open Infrastructure for Network Computing
|
|
|
|
// http://boinc.berkeley.edu
|
2006-12-14 16:59:28 +00:00
|
|
|
// Copyright (C) 2006 University of California
|
2006-01-23 08:47:05 +00:00
|
|
|
//
|
|
|
|
// This is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
|
|
// License as published by the Free Software Foundation;
|
|
|
|
// either version 2.1 of the License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This software is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
// See the GNU Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// To view the GNU Lesser General Public License visit
|
|
|
|
// http://www.gnu.org/copyleft/lesser.html
|
|
|
|
// or write to the Free Software Foundation, Inc.,
|
2007-10-09 11:35:47 +00:00
|
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
2006-01-23 08:47:05 +00:00
|
|
|
|
|
|
|
|
2006-12-14 18:15:22 +00:00
|
|
|
#ifdef _BOINC_DLL
|
2006-01-23 08:47:05 +00:00
|
|
|
#include "stdafx.h"
|
2006-12-14 18:15:22 +00:00
|
|
|
#else
|
|
|
|
#include "boinc_win.h"
|
|
|
|
#endif
|
|
|
|
#include "win_util.h"
|
|
|
|
|
2006-01-23 08:47:05 +00:00
|
|
|
|
2008-02-15 15:52:16 +00:00
|
|
|
#define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \
|
|
|
|
DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALRECORD | \
|
|
|
|
DESKTOP_JOURNALPLAYBACK | DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \
|
|
|
|
DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED)
|
|
|
|
|
|
|
|
#define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \
|
|
|
|
WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \
|
|
|
|
WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \
|
|
|
|
WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | WINSTA_READSCREEN | \
|
|
|
|
STANDARD_RIGHTS_REQUIRED)
|
|
|
|
|
|
|
|
#define GENERIC_ACCESS (GENERIC_READ | GENERIC_WRITE | \
|
|
|
|
GENERIC_EXECUTE | GENERIC_ALL)
|
|
|
|
|
2006-01-23 08:47:05 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Find out if we are on a Windows 2000 compatible system
|
|
|
|
**/
|
2006-12-14 16:59:28 +00:00
|
|
|
BOOL IsWindows2000Compatible() {
|
2006-01-23 08:47:05 +00:00
|
|
|
OSVERSIONINFO osvi;
|
|
|
|
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
|
|
|
|
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return (osvi.dwMajorVersion >= 5);
|
|
|
|
}
|
|
|
|
|
2006-12-28 18:48:42 +00:00
|
|
|
/**
|
|
|
|
* Define these if they aren't defined. They are normally found in
|
|
|
|
* winnt.h, but some compilers don't have them.
|
|
|
|
**/
|
|
|
|
#ifndef VER_AND
|
|
|
|
#define VER_AND 6
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef VER_SUITENAME
|
|
|
|
#define VER_SUITENAME 0x0000040
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef VER_SUITE_SINGLEUSERTS
|
|
|
|
#define VER_SUITE_SINGLEUSERTS 0x00000100
|
|
|
|
#endif
|
|
|
|
|
2006-01-23 08:47:05 +00:00
|
|
|
/**
|
|
|
|
* This function performs the basic check to see if
|
|
|
|
* the platform on which it is running is Terminal
|
|
|
|
* services enabled. Note, this code is compatible on
|
|
|
|
* all Win32 platforms. For the Windows 2000 platform
|
|
|
|
* we perform a "lazy" bind to the new product suite
|
|
|
|
* APIs that were first introduced on that platform.
|
|
|
|
**/
|
2006-12-14 16:59:28 +00:00
|
|
|
BOOL IsTerminalServicesEnabled() {
|
2006-01-23 08:47:05 +00:00
|
|
|
BOOL bResult = FALSE; // assume Terminal Services is not enabled
|
|
|
|
|
|
|
|
DWORD dwVersion;
|
|
|
|
OSVERSIONINFOEXA osVersionInfo;
|
|
|
|
DWORDLONG dwlConditionMask = 0;
|
|
|
|
HMODULE hmodK32 = NULL;
|
|
|
|
HMODULE hmodNtDll = NULL;
|
|
|
|
typedef ULONGLONG (WINAPI *PFnVerSetConditionMask)(ULONGLONG,ULONG,UCHAR);
|
|
|
|
typedef BOOL (WINAPI *PFnVerifyVersionInfoA)(POSVERSIONINFOEXA, DWORD, DWORDLONG);
|
|
|
|
PFnVerSetConditionMask pfnVerSetConditionMask;
|
|
|
|
PFnVerifyVersionInfoA pfnVerifyVersionInfoA;
|
|
|
|
|
|
|
|
dwVersion = GetVersion();
|
|
|
|
|
|
|
|
// are we running NT ?
|
|
|
|
if (!(dwVersion & 0x80000000))
|
|
|
|
{
|
|
|
|
// Is it Windows 2000 (NT 5.0) or greater ?
|
|
|
|
if (LOBYTE(LOWORD(dwVersion)) > 4)
|
|
|
|
{
|
|
|
|
// In Windows 2000 we need to use the Product Suite APIs
|
|
|
|
// Don't static link because it won't load on non-Win2000 systems
|
|
|
|
hmodNtDll = GetModuleHandle( "NTDLL.DLL" );
|
|
|
|
if (hmodNtDll != NULL)
|
|
|
|
{
|
|
|
|
pfnVerSetConditionMask = (PFnVerSetConditionMask )GetProcAddress( hmodNtDll, "VerSetConditionMask");
|
|
|
|
if (pfnVerSetConditionMask != NULL)
|
|
|
|
{
|
|
|
|
dwlConditionMask = (*pfnVerSetConditionMask)( dwlConditionMask, VER_SUITENAME, VER_AND );
|
|
|
|
hmodK32 = GetModuleHandle( "KERNEL32.DLL" );
|
|
|
|
if (hmodK32 != NULL)
|
|
|
|
{
|
|
|
|
pfnVerifyVersionInfoA = (PFnVerifyVersionInfoA)GetProcAddress( hmodK32, "VerifyVersionInfoA") ;
|
|
|
|
if (pfnVerifyVersionInfoA != NULL)
|
|
|
|
{
|
|
|
|
ZeroMemory(&osVersionInfo, sizeof(osVersionInfo));
|
|
|
|
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
|
|
|
|
osVersionInfo.wSuiteMask = VER_SUITE_TERMINAL | VER_SUITE_SINGLEUSERTS;
|
|
|
|
bResult = (*pfnVerifyVersionInfoA)(
|
|
|
|
&osVersionInfo,
|
|
|
|
VER_SUITENAME,
|
|
|
|
dwlConditionMask);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// This is NT 4.0 or older
|
|
|
|
bResult = ValidateProductSuite( "Terminal Server" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return bResult;
|
|
|
|
}
|
|
|
|
|
2007-02-20 16:27:15 +00:00
|
|
|
|
2006-01-23 08:47:05 +00:00
|
|
|
/**
|
|
|
|
* This function compares the passed in "suite name" string
|
|
|
|
* to the product suite information stored in the registry.
|
|
|
|
* This only works on the Terminal Server 4.0 platform.
|
|
|
|
**/
|
2006-12-14 16:59:28 +00:00
|
|
|
BOOL ValidateProductSuite (LPSTR SuiteName) {
|
2006-01-23 08:47:05 +00:00
|
|
|
BOOL rVal = FALSE;
|
|
|
|
LONG Rslt;
|
|
|
|
HKEY hKey = NULL;
|
|
|
|
DWORD Type = 0;
|
|
|
|
DWORD Size = 0;
|
|
|
|
LPSTR ProductSuite = NULL;
|
|
|
|
LPSTR p;
|
|
|
|
|
|
|
|
Rslt = RegOpenKeyA(
|
|
|
|
HKEY_LOCAL_MACHINE,
|
|
|
|
"System\\CurrentControlSet\\Control\\ProductOptions",
|
|
|
|
&hKey
|
|
|
|
);
|
|
|
|
|
|
|
|
if (Rslt != ERROR_SUCCESS)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
Rslt = RegQueryValueExA( hKey, "ProductSuite", NULL, &Type, NULL, &Size );
|
|
|
|
if (Rslt != ERROR_SUCCESS || !Size)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
ProductSuite = (LPSTR) LocalAlloc( LPTR, Size );
|
|
|
|
if (!ProductSuite)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
Rslt = RegQueryValueExA( hKey, "ProductSuite", NULL, &Type,
|
|
|
|
(LPBYTE) ProductSuite, &Size );
|
|
|
|
if (Rslt != ERROR_SUCCESS || Type != REG_MULTI_SZ)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
p = ProductSuite;
|
|
|
|
while (*p)
|
|
|
|
{
|
|
|
|
if (lstrcmpA( p, SuiteName ) == 0)
|
|
|
|
{
|
|
|
|
rVal = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p += (lstrlenA( p ) + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
if (ProductSuite)
|
|
|
|
LocalFree( ProductSuite );
|
|
|
|
|
|
|
|
if (hKey)
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
|
|
|
|
return rVal;
|
|
|
|
}
|
2007-02-20 16:27:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function terminates a process by process id instead of a handle.
|
|
|
|
**/
|
|
|
|
BOOL TerminateProcessById( DWORD dwProcessID ) {
|
|
|
|
HANDLE hProcess;
|
|
|
|
BOOL bRetVal = FALSE;
|
|
|
|
|
|
|
|
hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, dwProcessID );
|
|
|
|
|
|
|
|
if (hProcess) {
|
|
|
|
bRetVal = TerminateProcess(hProcess, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
CloseHandle( hProcess );
|
|
|
|
|
|
|
|
return bRetVal;
|
|
|
|
}
|
|
|
|
|
2008-02-15 15:52:16 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* This function adjusts the specified WindowStation to include the specfied
|
|
|
|
* user.
|
|
|
|
*
|
|
|
|
* See: http://msdn2.microsoft.com/en-us/library/aa379608(VS.85).aspx
|
|
|
|
**/
|
|
|
|
BOOL AddAceToWindowStation(HWINSTA hwinsta, PSID psid)
|
|
|
|
{
|
|
|
|
ACCESS_ALLOWED_ACE *pace = NULL;
|
|
|
|
ACL_SIZE_INFORMATION aclSizeInfo;
|
|
|
|
BOOL bDaclExist;
|
|
|
|
BOOL bDaclPresent;
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
DWORD dwNewAclSize;
|
|
|
|
DWORD dwSidSize = 0;
|
|
|
|
DWORD dwSdSizeNeeded;
|
|
|
|
PACL pacl = NULL;
|
|
|
|
PACL pNewAcl = NULL;
|
|
|
|
PSECURITY_DESCRIPTOR psd = NULL;
|
|
|
|
PSECURITY_DESCRIPTOR psdNew = NULL;
|
|
|
|
PVOID pTempAce;
|
|
|
|
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
__try
|
|
|
|
{
|
|
|
|
// Obtain the DACL for the window station.
|
|
|
|
|
|
|
|
if (!GetUserObjectSecurity(
|
|
|
|
hwinsta,
|
|
|
|
&si,
|
|
|
|
psd,
|
|
|
|
dwSidSize,
|
|
|
|
&dwSdSizeNeeded)
|
|
|
|
)
|
|
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
{
|
|
|
|
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
|
|
|
|
GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwSdSizeNeeded);
|
|
|
|
|
|
|
|
if (psd == NULL)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
|
|
|
|
GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwSdSizeNeeded);
|
|
|
|
|
|
|
|
if (psdNew == NULL)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
dwSidSize = dwSdSizeNeeded;
|
|
|
|
|
|
|
|
if (!GetUserObjectSecurity(
|
|
|
|
hwinsta,
|
|
|
|
&si,
|
|
|
|
psd,
|
|
|
|
dwSidSize,
|
|
|
|
&dwSdSizeNeeded)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Create a new DACL.
|
|
|
|
|
|
|
|
if (!InitializeSecurityDescriptor(
|
|
|
|
psdNew,
|
|
|
|
SECURITY_DESCRIPTOR_REVISION)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Get the DACL from the security descriptor.
|
|
|
|
|
|
|
|
if (!GetSecurityDescriptorDacl(
|
|
|
|
psd,
|
|
|
|
&bDaclPresent,
|
|
|
|
&pacl,
|
|
|
|
&bDaclExist)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Initialize the ACL.
|
|
|
|
|
|
|
|
ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
|
|
|
|
aclSizeInfo.AclBytesInUse = sizeof(ACL);
|
|
|
|
|
|
|
|
// Call only if the DACL is not NULL.
|
|
|
|
|
|
|
|
if (pacl != NULL)
|
|
|
|
{
|
|
|
|
// get the file ACL size info
|
|
|
|
if (!GetAclInformation(
|
|
|
|
pacl,
|
|
|
|
(LPVOID)&aclSizeInfo,
|
|
|
|
sizeof(ACL_SIZE_INFORMATION),
|
|
|
|
AclSizeInformation)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the size of the new ACL.
|
|
|
|
|
|
|
|
dwNewAclSize = aclSizeInfo.AclBytesInUse +
|
|
|
|
(2*sizeof(ACCESS_ALLOWED_ACE)) + (2*GetLengthSid(psid)) -
|
|
|
|
(2*sizeof(DWORD));
|
|
|
|
|
|
|
|
// Allocate memory for the new ACL.
|
|
|
|
|
|
|
|
pNewAcl = (PACL)HeapAlloc(
|
|
|
|
GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwNewAclSize);
|
|
|
|
|
|
|
|
if (pNewAcl == NULL)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Initialize the new DACL.
|
|
|
|
|
|
|
|
if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// If DACL is present, copy it to a new DACL.
|
|
|
|
|
|
|
|
if (bDaclPresent)
|
|
|
|
{
|
|
|
|
// Copy the ACEs to the new ACL.
|
|
|
|
if (aclSizeInfo.AceCount)
|
|
|
|
{
|
|
|
|
for (i=0; i < aclSizeInfo.AceCount; i++)
|
|
|
|
{
|
|
|
|
// Get an ACE.
|
|
|
|
if (!GetAce(pacl, i, &pTempAce))
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Add the ACE to the new ACL.
|
|
|
|
if (!AddAce(
|
|
|
|
pNewAcl,
|
|
|
|
ACL_REVISION,
|
|
|
|
MAXDWORD,
|
|
|
|
pTempAce,
|
|
|
|
((PACE_HEADER)pTempAce)->AceSize)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add the first ACE to the window station.
|
|
|
|
|
|
|
|
pace = (ACCESS_ALLOWED_ACE *)HeapAlloc(
|
|
|
|
GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psid) -
|
|
|
|
sizeof(DWORD));
|
|
|
|
|
|
|
|
if (pace == NULL)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
|
|
|
|
pace->Header.AceFlags = CONTAINER_INHERIT_ACE |
|
|
|
|
INHERIT_ONLY_ACE | OBJECT_INHERIT_ACE;
|
|
|
|
pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) +
|
|
|
|
GetLengthSid(psid) - sizeof(DWORD);
|
|
|
|
pace->Mask = GENERIC_ACCESS;
|
|
|
|
|
|
|
|
if (!CopySid(GetLengthSid(psid), &pace->SidStart, psid))
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
if (!AddAce(
|
|
|
|
pNewAcl,
|
|
|
|
ACL_REVISION,
|
|
|
|
MAXDWORD,
|
|
|
|
(LPVOID)pace,
|
|
|
|
pace->Header.AceSize)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Add the second ACE to the window station.
|
|
|
|
|
|
|
|
pace->Header.AceFlags = NO_PROPAGATE_INHERIT_ACE;
|
|
|
|
pace->Mask = WINSTA_ALL;
|
|
|
|
|
|
|
|
if (!AddAce(
|
|
|
|
pNewAcl,
|
|
|
|
ACL_REVISION,
|
|
|
|
MAXDWORD,
|
|
|
|
(LPVOID)pace,
|
|
|
|
pace->Header.AceSize)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Set a new DACL for the security descriptor.
|
|
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(
|
|
|
|
psdNew,
|
|
|
|
TRUE,
|
|
|
|
pNewAcl,
|
|
|
|
FALSE)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Set the new security descriptor for the window station.
|
|
|
|
|
|
|
|
if (!SetUserObjectSecurity(hwinsta, &si, psdNew))
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Indicate success.
|
|
|
|
|
|
|
|
bSuccess = TRUE;
|
|
|
|
}
|
|
|
|
__finally
|
|
|
|
{
|
|
|
|
// Free the allocated buffers.
|
|
|
|
|
|
|
|
if (pace != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pace);
|
|
|
|
|
|
|
|
if (pNewAcl != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);
|
|
|
|
|
|
|
|
if (psd != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
|
|
|
|
|
|
|
|
if (psdNew != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
|
|
|
|
}
|
|
|
|
|
|
|
|
return bSuccess;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This function adjusts the specified Desktop to include the specfied
|
|
|
|
* user.
|
|
|
|
*
|
|
|
|
* See: http://msdn2.microsoft.com/en-us/library/aa379608(VS.85).aspx
|
|
|
|
**/
|
|
|
|
BOOL AddAceToDesktop(HDESK hdesk, PSID psid)
|
|
|
|
{
|
|
|
|
ACL_SIZE_INFORMATION aclSizeInfo;
|
|
|
|
BOOL bDaclExist;
|
|
|
|
BOOL bDaclPresent;
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
DWORD dwNewAclSize;
|
|
|
|
DWORD dwSidSize = 0;
|
|
|
|
DWORD dwSdSizeNeeded;
|
|
|
|
PACL pacl = NULL;
|
|
|
|
PACL pNewAcl = NULL;
|
|
|
|
PSECURITY_DESCRIPTOR psd = NULL;
|
|
|
|
PSECURITY_DESCRIPTOR psdNew = NULL;
|
|
|
|
PVOID pTempAce;
|
|
|
|
SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION;
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
__try
|
|
|
|
{
|
|
|
|
// Obtain the security descriptor for the desktop object.
|
|
|
|
|
|
|
|
if (!GetUserObjectSecurity(
|
|
|
|
hdesk,
|
|
|
|
&si,
|
|
|
|
psd,
|
|
|
|
dwSidSize,
|
|
|
|
&dwSdSizeNeeded))
|
|
|
|
{
|
|
|
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
{
|
|
|
|
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(
|
|
|
|
GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwSdSizeNeeded );
|
|
|
|
|
|
|
|
if (psd == NULL)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
psdNew = (PSECURITY_DESCRIPTOR)HeapAlloc(
|
|
|
|
GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwSdSizeNeeded);
|
|
|
|
|
|
|
|
if (psdNew == NULL)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
dwSidSize = dwSdSizeNeeded;
|
|
|
|
|
|
|
|
if (!GetUserObjectSecurity(
|
|
|
|
hdesk,
|
|
|
|
&si,
|
|
|
|
psd,
|
|
|
|
dwSidSize,
|
|
|
|
&dwSdSizeNeeded)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new security descriptor.
|
|
|
|
|
|
|
|
if (!InitializeSecurityDescriptor(
|
|
|
|
psdNew,
|
|
|
|
SECURITY_DESCRIPTOR_REVISION)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Obtain the DACL from the security descriptor.
|
|
|
|
|
|
|
|
if (!GetSecurityDescriptorDacl(
|
|
|
|
psd,
|
|
|
|
&bDaclPresent,
|
|
|
|
&pacl,
|
|
|
|
&bDaclExist)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Initialize.
|
|
|
|
|
|
|
|
ZeroMemory(&aclSizeInfo, sizeof(ACL_SIZE_INFORMATION));
|
|
|
|
aclSizeInfo.AclBytesInUse = sizeof(ACL);
|
|
|
|
|
|
|
|
// Call only if NULL DACL.
|
|
|
|
|
|
|
|
if (pacl != NULL)
|
|
|
|
{
|
|
|
|
// Determine the size of the ACL information.
|
|
|
|
|
|
|
|
if (!GetAclInformation(
|
|
|
|
pacl,
|
|
|
|
(LPVOID)&aclSizeInfo,
|
|
|
|
sizeof(ACL_SIZE_INFORMATION),
|
|
|
|
AclSizeInformation)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the size of the new ACL.
|
|
|
|
|
|
|
|
dwNewAclSize = aclSizeInfo.AclBytesInUse +
|
|
|
|
sizeof(ACCESS_ALLOWED_ACE) +
|
|
|
|
GetLengthSid(psid) - sizeof(DWORD);
|
|
|
|
|
|
|
|
// Allocate buffer for the new ACL.
|
|
|
|
|
|
|
|
pNewAcl = (PACL)HeapAlloc(
|
|
|
|
GetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
dwNewAclSize);
|
|
|
|
|
|
|
|
if (pNewAcl == NULL)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Initialize the new ACL.
|
|
|
|
|
|
|
|
if (!InitializeAcl(pNewAcl, dwNewAclSize, ACL_REVISION))
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// If DACL is present, copy it to a new DACL.
|
|
|
|
|
|
|
|
if (bDaclPresent)
|
|
|
|
{
|
|
|
|
// Copy the ACEs to the new ACL.
|
|
|
|
if (aclSizeInfo.AceCount)
|
|
|
|
{
|
|
|
|
for (i=0; i < aclSizeInfo.AceCount; i++)
|
|
|
|
{
|
|
|
|
// Get an ACE.
|
|
|
|
if (!GetAce(pacl, i, &pTempAce))
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Add the ACE to the new ACL.
|
|
|
|
if (!AddAce(
|
|
|
|
pNewAcl,
|
|
|
|
ACL_REVISION,
|
|
|
|
MAXDWORD,
|
|
|
|
pTempAce,
|
|
|
|
((PACE_HEADER)pTempAce)->AceSize)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add ACE to the DACL.
|
|
|
|
|
|
|
|
if (!AddAccessAllowedAce(
|
|
|
|
pNewAcl,
|
|
|
|
ACL_REVISION,
|
|
|
|
DESKTOP_ALL,
|
|
|
|
psid)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Set new DACL to the new security descriptor.
|
|
|
|
|
|
|
|
if (!SetSecurityDescriptorDacl(
|
|
|
|
psdNew,
|
|
|
|
TRUE,
|
|
|
|
pNewAcl,
|
|
|
|
FALSE)
|
|
|
|
)
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Set the new security descriptor for the desktop object.
|
|
|
|
|
|
|
|
if (!SetUserObjectSecurity(hdesk, &si, psdNew))
|
|
|
|
__leave;
|
|
|
|
|
|
|
|
// Indicate success.
|
|
|
|
|
|
|
|
bSuccess = TRUE;
|
|
|
|
}
|
|
|
|
__finally
|
|
|
|
{
|
|
|
|
// Free buffers.
|
|
|
|
|
|
|
|
if (pNewAcl != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pNewAcl);
|
|
|
|
|
|
|
|
if (psd != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
|
|
|
|
|
|
|
|
if (psdNew != NULL)
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)psdNew);
|
|
|
|
}
|
|
|
|
|
|
|
|
return bSuccess;
|
|
|
|
}
|
|
|
|
|