windows-nt/Source/XPSP1/NT/inetsrv/iis/ui/admin/comprop/setperm.cpp
2020-09-26 16:20:57 +08:00

301 lines
7.4 KiB
C++

/*++
Copyright (c) 1994-1999 Microsoft Corporation
Module Name :
setperm.cpp
Abstract:
IIS Security Wizard helper file
Author:
Sergei Antonov (sergeia)
Project:
Internet Services Manager
Revision History:
7/12/99 created
--*/
//
// Include Files
//
#include "stdafx.h"
#include "comprop.h"
#include <aclapi.h>
#include <ntseapi.h>
#include <shlwapi.h>
static HRESULT
SetSecurityDeep(
LPTSTR *ppszBuffer,
UINT * pcchBuffer,
DWORD dwAttributes,
SECURITY_INFORMATION si,
PACL pDacl,
PACL pSacl
);
static BOOL
PathIsDotOrDotDot(LPCTSTR pszPath)
{
if (TEXT('.') == *pszPath++)
{
if (TEXT('\0') == *pszPath || (TEXT('.') == *pszPath && TEXT('\0') == *(pszPath + 1)))
return TRUE;
}
return FALSE;
}
HRESULT
CPWSummary::SetPermToChildren(
IN CString& FileName,
IN SECURITY_INFORMATION si,
IN PACL pDacl,
IN PACL pSacl
)
{
HRESULT hr = S_OK;
LPTSTR pszBuffer = NULL;
UINT cchBuffer = 0, cchFolder;
HANDLE hFind;
WIN32_FIND_DATA fd;
pszBuffer = (LPTSTR)LocalAlloc(LMEM_FIXED, 2 * MAX_PATH * sizeof(TCHAR));
if (pszBuffer == NULL)
return E_OUTOFMEMORY;
cchBuffer = (UINT)LocalSize(pszBuffer) / sizeof(TCHAR);
lstrcpy(pszBuffer, FileName);
cchFolder = lstrlen(pszBuffer);
// Append a backslash if it's not there already
if (pszBuffer[cchFolder-1] != TEXT('\\'))
{
pszBuffer[cchFolder] = TEXT('\\');
cchFolder++;
}
// Append the '*' wildcard
pszBuffer[cchFolder] = TEXT('*');
pszBuffer[cchFolder+1] = TEXT('\0');
if (INVALID_HANDLE_VALUE != (hFind = FindFirstFile(pszBuffer, &fd)))
{
do
{
if (PathIsDotOrDotDot(fd.cFileName))
continue;
//
// Build full path name and recurse
//
lstrcpyn(pszBuffer + cchFolder, fd.cFileName, cchBuffer - cchFolder);
if (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY)
{
hr = SetSecurityDeep(&pszBuffer,
&cchBuffer,
fd.dwFileAttributes,
si,
pDacl,
pSacl);
}
else
{
hr = HRESULT_FROM_WIN32(SetNamedSecurityInfo(
pszBuffer,
SE_FILE_OBJECT,
si,
NULL,
NULL,
pDacl,
pSacl));
}
}
while (S_OK == hr && FindNextFile(hFind, &fd));
FindClose(hFind);
}
if (pszBuffer != NULL)
LocalFree(pszBuffer);
return hr;
}
static HRESULT
SetSecurityDeep(
LPTSTR *ppszBuffer,
UINT * pcchBuffer,
DWORD dwAttributes,
SECURITY_INFORMATION si,
PACL pDacl,
PACL pSacl
)
{
HRESULT hr = S_OK;
DWORD dwErr = NOERROR;
LPTSTR pszBuffer;
BOOL bWriteDone = FALSE;
pszBuffer = *ppszBuffer;
//
// Recursively apply the new SD to subfolders
//
if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
HANDLE hFind;
WIN32_FIND_DATA fd;
UINT cchFolder;
UINT cchSizeRequired;
cchFolder = lstrlen(pszBuffer);
//
// If the buffer is getting tight, realloc
//
cchSizeRequired = cchFolder + 1 + sizeof(fd.cFileName) / sizeof(TCHAR); // 1 for backslash
if (cchSizeRequired > *pcchBuffer)
{
cchSizeRequired += MAX_PATH; // so we don't realloc as often
pszBuffer = (LPTSTR)LocalReAlloc(*ppszBuffer, cchSizeRequired * sizeof(TCHAR), LMEM_MOVEABLE);
if (pszBuffer)
{
*ppszBuffer = pszBuffer;
*pcchBuffer = cchSizeRequired;
}
else
{
// fd.cFileName typically has some empty space, so we
// may be able to continue
pszBuffer = *ppszBuffer;
if (*pcchBuffer < cchFolder + 3) // backslash, '*', and NULL
return E_OUTOFMEMORY;
}
}
// Append a backslash if it's not there already
if (pszBuffer[cchFolder-1] != TEXT('\\'))
{
pszBuffer[cchFolder] = TEXT('\\');
cchFolder++;
}
// Append the '*' wildcard
pszBuffer[cchFolder] = TEXT('*');
pszBuffer[cchFolder+1] = TEXT('\0');
//
// Enumerate the folder contents
//
hFind = FindFirstFile(pszBuffer, &fd);
if (INVALID_HANDLE_VALUE == hFind)
{
dwErr = GetLastError();
if (ERROR_ACCESS_DENIED == dwErr)
{
// Remove the '*' wildcard
pszBuffer[cchFolder-1] = TEXT('\0');
if (si & DACL_SECURITY_INFORMATION)
{
//
// The user may be granting themselves access, so call
// WriteObjectSecurity and retry FindFirstFile.
//
// Don't blindly call WriteObjectSecurity before FindFirstFile
// since it's possible the user has access now but is removing
// their own access.
//
bWriteDone = TRUE;
hr = HRESULT_FROM_WIN32(SetNamedSecurityInfo(
pszBuffer,
SE_FILE_OBJECT,
si,
NULL,
NULL,
pDacl,
pSacl));
if (SUCCEEDED(hr))
{
// Retry FindFirstFile
pszBuffer[cchFolder-1] = TEXT('\\');
hFind = FindFirstFile(pszBuffer, &fd);
}
}
}
}
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (PathIsDotOrDotDot(fd.cFileName))
continue;
//
// Build full path name and recurse
//
lstrcpyn(pszBuffer + cchFolder, fd.cFileName, *pcchBuffer - cchFolder);
hr = SetSecurityDeep(ppszBuffer,
pcchBuffer,
fd.dwFileAttributes,
si,
pDacl,
pSacl);
// In case the buffer was reallocated
pszBuffer = *ppszBuffer;
}
while (S_OK == hr && FindNextFile(hFind, &fd));
FindClose(hFind);
}
else if (NOERROR != dwErr)
{
hr = S_FALSE; // abort
}
// Truncate the path back to the original length (sans backslash)
pszBuffer[cchFolder-1] = TEXT('\0');
}
//
// Finally, write out the new security descriptor
//
if (!bWriteDone)
{
hr = HRESULT_FROM_WIN32(SetNamedSecurityInfo(
pszBuffer,
SE_FILE_OBJECT,
si,
NULL,
NULL,
pDacl,
pSacl));
}
if (SUCCEEDED(hr))
{
//
// Notify the shell if we change permissions on a folder (48220)
//
if ( (dwAttributes & FILE_ATTRIBUTE_DIRECTORY)
&& (si & DACL_SECURITY_INFORMATION)
)
{
SHChangeNotify(
SHCNE_UPDATEDIR,
SHCNF_PATH | SHCNF_FLUSH | SHCNF_FLUSHNOWAIT,
pszBuffer,
NULL);
}
}
else
{
hr = S_FALSE; // abort
}
return hr;
}