Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2107 lines
62 KiB

/**************************************************************************
Folder Properties, Security page for Win9X
Author: Yury Polyakovsky
Copyright 1998 Microsoft Corporation. All Rights Reserved.
**************************************************************************/
/**************************************************************************
File: PropSheet.cpp
Description:
**************************************************************************/
#include "PropSheet.h"
#include "CHString.h"
/**************************************************************************
private function prototypes
**************************************************************************/
int WideCharToLocal(LPTSTR, LPWSTR, DWORD);
int LocalToWideChar(LPWSTR, LPTSTR, DWORD);
void StringFromSid( PSID psid, CHString& str );
PSID StrToSID(const CHString& sid);
BOOL WINAPI RtlAllocateAndInitializeSid(
PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
UCHAR SubAuthorityCount,
ULONG SubAuthority0,
ULONG SubAuthority1,
ULONG SubAuthority2,
ULONG SubAuthority3,
ULONG SubAuthority4,
ULONG SubAuthority5,
ULONG SubAuthority6,
ULONG SubAuthority7,
OUT PSID *Sid);
WINADVAPI PSID_IDENTIFIER_AUTHORITY WINAPI RtlGetSidIdentifierAuthority(PSID pSid);
PUCHAR WINAPI RtlGetSidSubAuthorityCount (PSID pSid);
PDWORD WINAPI RtlGetSidSubAuthority (PSID pSid, DWORD nSubAuthority);
BOOL IsNT();
/**************************************************************************
global variables and definitions
**************************************************************************/
#define INITGUID
#include <initguid.h>
//#include <shlguid.h>
// {E3B33E82-7B11-11d2-9274-00105A24ED29}
DEFINE_GUID( CLSID_PropSheetExt,
0x48a02841,
0x39f1,
0x150b,
0x92,
0x74,
0x0,
0x10,
0x5a,
0x24,
0xed,
0x29);
HINSTANCE g_hInst;
UINT g_DllRefCount;
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
//SID_IDENTIFIER_AUTHORITY g_siaEveryone = {0x80,0,1,0,0,0};
//BYTE bSubAuthorityCount = 0;
//SID_IDENTIFIER_AUTHORITY g_siaEveryone = SECURITY_WORLD_SID_AUTHORITY;
//SID_IDENTIFIER_AUTHORITY g_siaDomainUsers = SECURITY_WORLD_SID_AUTHORITY;
//BYTE bSubAuthorityCount = 1;
TCHAR tszSubKey[] = TEXT("Software\\Microsoft\\ServerAppliance");
LPTSTR ptszValue[] =
{
TEXT("DomainName"),
TEXT("ServerName"),
TEXT("Documents"),
TEXT("Share"),
};
LPTSTR ptszData[] =
{
TEXT(DOMAIN_NAME),
TEXT(DOMAIN_SERVER),
TEXT(DOCUMENTS_FOLDER), // Local path at server in C format
TEXT(CHAMELEON_SHARE) // in C format
};
/**************************************************************************
DllMain
**************************************************************************/
extern "C" BOOL WINAPI DllMain( HINSTANCE hInstance,
DWORD dwReason,
LPVOID lpReserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
InitCommonControls();
g_hInst = hInstance;
break;
case DLL_PROCESS_DETACH:
g_hInst = hInstance;
break;
}
return TRUE;
}
/**************************************************************************
DllCanUnloadNow
**************************************************************************/
STDAPI DllCanUnloadNow(void)
{
int i;
i = 1;
return (g_DllRefCount == 0) ? S_OK : S_FALSE;
}
/**************************************************************************
DllGetClassObject
**************************************************************************/
STDAPI DllGetClassObject( REFCLSID rclsid,
REFIID riid,
LPVOID *ppReturn)
{
*ppReturn = NULL;
//if we don't support this classid, return the proper error code
if(!IsEqualCLSID(rclsid, CLSID_PropSheetExt))
return CLASS_E_CLASSNOTAVAILABLE;
//create a CClassFactory object and check it for validity
CClassFactory *pClassFactory = new CClassFactory();
if(NULL == pClassFactory)
return E_OUTOFMEMORY;
//get the QueryInterface return for our return value
HRESULT hResult = pClassFactory->QueryInterface(riid, ppReturn);
//call Release to decement the ref count - creating the object set it to one
//and QueryInterface incremented it - since its being used externally (not by
//us), we only want the ref count to be 1
pClassFactory->Release();
//return the result from QueryInterface
return hResult;
}
/**************************************************************************
DllRegisterServer
**************************************************************************/
typedef struct{
HKEY hRootKey;
LPTSTR lpszSubKey;
LPTSTR lpszValueName;
LPTSTR lpszData;
}REGSTRUCT, *LPREGSTRUCT;
//register the CLSID entries
REGSTRUCT ClsidEntries[] = { HKEY_CLASSES_ROOT, TEXT("CLSID\\%s"), NULL, TEXT("Security Context Menu Extension"),
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\InprocServer32"), NULL, TEXT("%s"),
HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\InprocServer32"), TEXT("ThreadingModel"), TEXT("Apartment"),
// HKEY_CLASSES_ROOT, TEXT(".ext"), NULL, TEXT("StrFile"), Specific extension
// HKEY_CLASSES_ROOT, TEXT("*\\ShellEx\\PropertySheetHandlers\\%s"), NULL, TEXT(""), All files
HKEY_CLASSES_ROOT, TEXT("Directory\\ShellEx\\PropertySheetHandlers\\%s"), NULL, TEXT(""),
NULL, NULL, NULL, NULL};
STDAPI DllRegisterServer(void)
{
int i;
HKEY hKey;
LRESULT lResult;
DWORD dwDisp;
TCHAR szSubKey[MAX_PATH];
TCHAR szCLSID[MAX_PATH];
TCHAR szModule[MAX_PATH];
LPWSTR pwsz;
//get the CLSID in string form
StringFromIID(CLSID_PropSheetExt, &pwsz);
if(pwsz)
{
WideCharToLocal(szCLSID, pwsz, ARRAYSIZE(szCLSID));
//free the string
LPMALLOC pMalloc;
CoGetMalloc(1, &pMalloc);
if(pMalloc)
{
pMalloc->Free(pwsz);
pMalloc->Release();
}
}
//get this DLL's path and file name
GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule));
for(i = 0; ClsidEntries[i].hRootKey; i++)
{
//Create the sub key string.
wsprintf(szSubKey, ClsidEntries[i].lpszSubKey, szCLSID);
lResult = RegCreateKeyEx( ClsidEntries[i].hRootKey,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisp);
if(NOERROR == lResult)
{
TCHAR szData[MAX_PATH] = TEXT("");
//if necessary, create the value string
wsprintf(szData, ClsidEntries[i].lpszData, szModule);
lResult = RegSetValueEx( hKey,
ClsidEntries[i].lpszValueName,
0,
REG_SZ,
(LPBYTE)szData,
lstrlen(szData) + 1);
RegCloseKey(hKey);
}
else
return SELFREG_E_CLASS;
}
//If running on NT, register the extension as approved.
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
{
lstrcpy(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"));
lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisp);
if(NOERROR == lResult)
{
TCHAR szData[MAX_PATH];
//Create the value string.
lstrcpy(szData, TEXT("Security Context Menu Extension"));
lResult = RegSetValueEx( hKey,
szCLSID,
0,
REG_SZ,
(LPBYTE)szData,
lstrlen(szData) + 1);
RegCloseKey(hKey);
}
else
return SELFREG_E_CLASS;
}
// Chameleon Server constants
lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
tszSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
&dwDisp);
if(NOERROR == lResult)
{
for (int ind = 0; ind < sizeof(ptszValue) / sizeof(ptszValue[0]); ind++)
{
lResult = RegSetValueEx(hKey,
ptszValue[ind],
0,
REG_SZ,
(LPBYTE)ptszData[ind],
lstrlen(ptszData[ind]) + 1);
}
RegCloseKey(hKey);
}
else
return SELFREG_E_CLASS;
return S_OK;
}
STDAPI DllUnregisterServer(void)
{
int i;
LRESULT lResult;
TCHAR szSubKey[MAX_PATH];
TCHAR szCLSID[MAX_PATH];
TCHAR szModule[MAX_PATH];
LPWSTR pwsz;
//get the CLSID in string form
StringFromIID(CLSID_PropSheetExt, &pwsz);
if(pwsz)
{
WideCharToLocal(szCLSID, pwsz, ARRAYSIZE(szCLSID));
//free the string
LPMALLOC pMalloc;
CoGetMalloc(1, &pMalloc);
if(pMalloc)
{
pMalloc->Free(pwsz);
pMalloc->Release();
}
}
//get this DLL's path and file name
GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule));
for(i = 0; ClsidEntries[i].hRootKey; i++)
{
//Create the sub key string.
wsprintf(szSubKey, ClsidEntries[i].lpszSubKey, szCLSID);
lResult = RegDeleteKey( ClsidEntries[i].hRootKey,
szSubKey); // Review Yury: In case we want to run it on NT we have to recursively enumerate the subkeys and delete them individually
if(NOERROR != lResult)
return SELFREG_E_CLASS;
}
//Review Yury: If running on NT, unregister the extension as approved.
// Chameleon Server constants
lResult = RegDeleteKey( HKEY_LOCAL_MACHINE,
tszSubKey);
if(NOERROR != lResult)
return SELFREG_E_CLASS;
return S_OK;
}
///////////////////////////////////////////////////////////////////////////
//
// IClassFactory implementation
//
/**************************************************************************
CClassFactory::CClassFactory
**************************************************************************/
CClassFactory::CClassFactory()
{
m_ObjRefCount = 1;
g_DllRefCount++;
}
/**************************************************************************
CClassFactory::~CClassFactory
**************************************************************************/
CClassFactory::~CClassFactory()
{
g_DllRefCount--;
}
/**************************************************************************
CClassFactory::QueryInterface
**************************************************************************/
STDMETHODIMP CClassFactory::QueryInterface( REFIID riid,
LPVOID FAR * ppReturn)
{
*ppReturn = NULL;
if(IsEqualIID(riid, IID_IUnknown))
{
*ppReturn = (LPUNKNOWN)(LPCLASSFACTORY)this;
}
if(IsEqualIID(riid, IID_IClassFactory))
{
*ppReturn = (LPCLASSFACTORY)this;
}
if(*ppReturn)
{
(*(LPUNKNOWN*)ppReturn)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/**************************************************************************
CClassFactory::AddRef
**************************************************************************/
STDMETHODIMP_(DWORD) CClassFactory::AddRef()
{
return ++m_ObjRefCount;
}
/**************************************************************************
CClassFactory::Release
**************************************************************************/
STDMETHODIMP_(DWORD) CClassFactory::Release()
{
if(--m_ObjRefCount == 0)
delete this;
return m_ObjRefCount;
}
/**************************************************************************
CClassFactory::CreateInstance
**************************************************************************/
STDMETHODIMP CClassFactory::CreateInstance( LPUNKNOWN pUnknown,
REFIID riid,
LPVOID FAR * ppObject)
{
*ppObject = NULL;
if(pUnknown != NULL)
return CLASS_E_NOAGGREGATION;
//add implementation specific code here
CShellPropSheetExt *pShellExt = new CShellPropSheetExt;
if(NULL == pShellExt)
return E_OUTOFMEMORY;
//get the QueryInterface return for our return value
HRESULT hResult = pShellExt->QueryInterface(riid, ppObject);
//call Release to decement the ref count
pShellExt->Release();
//return the result from QueryInterface
return hResult;
}
/**************************************************************************
CClassFactory::LockServer
**************************************************************************/
STDMETHODIMP CClassFactory::LockServer(BOOL)
{
return E_NOTIMPL;
}
/**************************************************************************
CShellPropSheetExt::CShellPropSheetExt()
**************************************************************************/
CShellPropSheetExt::CShellPropSheetExt()
{
m_uiUser = 0;
m_ObjRefCount = 1;
g_DllRefCount++;
m_pSAUserInfo = NULL;// m_pIWbemServices = NULL;
m_fEveryone = FALSE;
m_szPath[0] = _T('\0');
m_fChanged = FALSE;
m_fHasAccess = FALSE;
}
/**************************************************************************
CShellPropSheetExt::~CShellPropSheetExt()
**************************************************************************/
CShellPropSheetExt::~CShellPropSheetExt()
{
g_DllRefCount--;
}
///////////////////////////////////////////////////////////////////////////
//
// IUnknown Implementation
//
/**************************************************************************
CShellPropSheetExt::QueryInterface
**************************************************************************/
STDMETHODIMP CShellPropSheetExt::QueryInterface( REFIID riid,
LPVOID FAR * ppReturn)
{
*ppReturn = NULL;
//IUnknown
if(IsEqualIID(riid, IID_IUnknown))
{
*ppReturn = (LPVOID)this;
}
//IShellExtInit
if(IsEqualIID(riid, IID_IShellExtInit))
{
*ppReturn = (LPSHELLEXTINIT)this;
}
//IShellPropSheetExt
if(IsEqualIID(riid, IID_IShellPropSheetExt))
{
*ppReturn = (LPSHELLPROPSHEETEXT)this;
}
if(*ppReturn)
{
(*(LPUNKNOWN*)ppReturn)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/**************************************************************************
CShellPropSheetExt::AddRef
**************************************************************************/
STDMETHODIMP_(DWORD) CShellPropSheetExt::AddRef()
{
return ++m_ObjRefCount;
}
/**************************************************************************
CShellPropSheetExt::Release
**************************************************************************/
STDMETHODIMP_(DWORD) CShellPropSheetExt::Release()
{
if(--m_ObjRefCount == 0)
delete this;
return m_ObjRefCount;
}
///////////////////////////////////////////////////////////////////////////
//
// IShellExtInit Implementation
//
/**************************************************************************
CShellPropSheetExt::EnumUsers()
**************************************************************************/
void CShellPropSheetExt::EnumUsers(HWND hWnd)
{
if (!m_pSAUserInfo)
return;
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
HRESULT hRes;
BSTR *lpbstrSAUserNames;
VARIANT_BOOL *vboolIsSAUserAdmin;
PSID *ppsidSAUsers;
LONG *ppsidSAUsersLength;
DWORD dwNumSAUsers;
dwNumSAUsers = 0;
hRes = GetUserList(m_pSAUserInfo,
&lpbstrSAUserNames,
&vboolIsSAUserAdmin,
&ppsidSAUsers,
&ppsidSAUsersLength,
&dwNumSAUsers);
_ASSERTE(SUCCEEDED(hRes)) ;
if (!(SUCCEEDED(hRes)))
return ;
TCHAR tcName[100]; // Review Yury: What is size of the name
TCHAR szPathChank[MAX_PATH];
_bstr_t bsDirPath("");
// bsDirPath += "\"";
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\ServerAppliance"),
0,
KEY_READ,
&hKey) != ERROR_SUCCESS)
return ;
DWORD dwcData = sizeof(m_tszDocuments);
if (RegQueryValueEx(hKey,
"Documents",
0,
NULL,
(LPBYTE)m_tszDocuments,
&dwcData) != ERROR_SUCCESS)
return ;
dwcData = sizeof(m_tszShare);
if (RegQueryValueEx(hKey,
"Share",
0,
NULL,
(LPBYTE)m_tszShare,
&dwcData) != ERROR_SUCCESS)
return ;
RegCloseKey(hKey);
// Convert share to local server path
bsDirPath += m_tszDocuments; // Temporary, till I know how to get local path for the share
LPTSTR szPath;
if (_tcsnccmp(m_szPath, TEXT("\\\\"), 2))
szPath = m_szPath + sizeof(_T("G:")); // Skip network dis name
else
szPath = m_szPath + lstrlen(m_tszShare); // Skip share name
for (LPTSTR ptWack = szPath, ptWackTmp = szPath; ptWack; )
{
ptWackTmp = ptWack;
ptWack = _tcschr(ptWack, _T('\\'));
if (!ptWack)
{
_tcscpy(szPathChank, ptWackTmp);
bsDirPath += "\\";
bsDirPath += szPathChank;
}
else
{
_tcsncpy(szPathChank, ptWackTmp, ptWack - ptWackTmp);
szPathChank[ptWack - ptWackTmp] = _T('\0');
ptWack++;
bsDirPath += "\\";
bsDirPath += szPathChank;
}
}
m_bsPath = bsDirPath;
VARIANT_BOOL vboolRetVal;
HRESULT hResAccess;
hResAccess = m_pSAUserInfo->DoIHaveAccess(m_bsPath, &vboolRetVal);
if (FAILED(hResAccess))
// if (hResAccess == E_ACCESSDENIED && vboolRetVal == VARIANT_FALSE)
m_fHasAccess = FALSE;
else
m_fHasAccess = TRUE;
for (int indGroup = 0; indGroup <= 1; indGroup++)
{
for (DWORD indUser = 0; indUser < dwNumSAUsers; indUser++)
{
if (indGroup > 0)
{
// Set the administrator's checkmarks
if (vboolIsSAUserAdmin[indUser])
{
// Set grayed checked box
m_CheckList.Mark(hWndList, indUser, GRAYCHECKED);
}
}
else if (SUCCEEDED(hRes))
{
// Add the user to the output listbox.
WideCharToLocal(tcName,lpbstrSAUserNames[indUser], ARRAYSIZE(tcName));
if (_tcsicmp(tcName, TEXT("Domain Users")))
{
// Eliminate Domain Users. Review Yury: Use m_pSidDomainUsers to do that after StringFromSid is fixed.
m_CheckList.AddString(hWndList, tcName, ppsidSAUsers[indUser], ppsidSAUsersLength[indUser], BLANK);
}
}
}
if (indGroup == 0)
{
// Set checkmarks
hRes = GetFilePermissions(hWnd);
_ASSERTE(SUCCEEDED(hRes));
if (!SUCCEEDED(hRes))
return;
}
} // end of groups
// Clean up
BOOL fRes = FALSE;
fRes = HeapFree(GetProcessHeap(), 0, ppsidSAUsers);
_ASSERTE(fRes);
fRes = HeapFree(GetProcessHeap(), 0, ppsidSAUsersLength);
_ASSERTE(fRes);
fRes = HeapFree(GetProcessHeap(), 0, lpbstrSAUserNames);
_ASSERTE(fRes);
fRes = HeapFree(GetProcessHeap(), 0, vboolIsSAUserAdmin);
_ASSERTE(fRes);
// If we user has no access show only admins
int cUserCount = ListView_GetItemCount(hWndList);
for (int indUser = 0; !m_fHasAccess && indUser < cUserCount; indUser++)
{
if (m_CheckList.GetState(hWndList, indUser) == BLANK)
{
ListView_DeleteItem(hWndList, indUser);
indUser--;
cUserCount--;
}
}
m_CheckList.InitFinish(hWndList);
// Done with this enumerator.
}
/**************************************************************************
CShellPropSheetExt::GetFilePermissions()
**************************************************************************/
HRESULT CShellPropSheetExt::GetFilePermissions(HWND hWnd)
{
if (!m_pSAUserInfo)
return E_FAIL;
PSID *ppsidAAUsers;
LONG *ppsidAAUsersLength;
DWORD dwNumAASids;
SAFEARRAY *psaAASids;
VARIANT_BOOL vboolRes;
VARIANT vAASids;
LONG lStartAASids, lEndAASids, lCurrent;
HRESULT hr;
dwNumAASids = 0;
VariantInit(&vAASids);
hr = m_pSAUserInfo->GetFileAccessAllowedAces(m_bsPath,
&vAASids,
&vboolRes);
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
return hr;
psaAASids = V_ARRAY(&vAASids);
_ASSERTE(V_VT(&vAASids) == (VT_ARRAY | VT_VARIANT));
if (V_VT(&vAASids) != (VT_ARRAY | VT_VARIANT))
return E_INVALIDARG;
hr = SafeArrayGetLBound( psaAASids, 1, &lStartAASids );
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
return hr;
hr = SafeArrayGetUBound( psaAASids, 1, &lEndAASids );
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
return hr;
dwNumAASids = lEndAASids - lStartAASids + 1;
ppsidAAUsers = (PSID *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNumAASids * sizeof(PSID));
_ASSERTE(ppsidAAUsers);
if (ppsidAAUsers == NULL)
return E_OUTOFMEMORY;
ppsidAAUsersLength = (LONG *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwNumAASids * sizeof(LONG));
_ASSERTE(ppsidAAUsersLength);
if (ppsidAAUsersLength == NULL)
return E_OUTOFMEMORY;
VARIANT vAASid;
for(lCurrent = lStartAASids; lCurrent <= lEndAASids; lCurrent++)
{
VariantInit(&vAASid);
hr = SafeArrayGetElement( psaAASids, &lCurrent, &vAASid );
_ASSERTE(!FAILED(hr));
if( FAILED(hr) )
return hr;
hr = UnpackSidFromVariant(&vAASid, &(ppsidAAUsers)[lCurrent], &(ppsidAAUsersLength[lCurrent]));
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
return hr;
// BOOL fRes = IsValidSid((*ppsidAAUsers)[lCurrent]);
// _ASSERTE(fRes);
// if (fRes == FALSE)
// return E_INVALIDARG;
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
PSID pSID;
LONG lenghSid;
DWORD dwNumSAUsers = ListView_GetItemCount(hWndList);
for (DWORD indUser = 0; indUser < dwNumSAUsers; indUser++)
{
m_CheckList.GetSID(hWndList, indUser, &pSID, &lenghSid);
if (UserSidFound(pSID, lenghSid, ppsidAAUsers, ppsidAAUsersLength, dwNumAASids) == VARIANT_TRUE)
m_CheckList.Mark(hWndList, indUser, CHECKED);
}
// Check if Everybody sid is set
if (UserSidFound(g_pSidEverybody, g_pSidEverybodyLenght, ppsidAAUsers, ppsidAAUsersLength, dwNumAASids) == VARIANT_TRUE)
m_fEveryone = TRUE;
}
// Clean up
BOOL fRes = FALSE;
for(DWORD i=0; i<dwNumAASids; i++)
{
fRes = HeapFree(GetProcessHeap(), 0, ppsidAAUsers[i]);
_ASSERTE(fRes);
}
fRes = HeapFree(GetProcessHeap(), 0, ppsidAAUsers);
_ASSERTE(fRes);
return S_OK;
}
/**************************************************************************
CShellPropSheetExt::SetFilePermissions()
**************************************************************************/
HRESULT CShellPropSheetExt::SetFilePermissions(HWND hWnd)
{
DWORD indUser, indUserAcess;
DWORD dwNumSAUsers = 0;
VARIANT vArrSids;
HRESULT hr;
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
dwNumSAUsers = ListView_GetItemCount(hWndList);
VariantInit(&vArrSids);
V_VT(&vArrSids) = VT_ARRAY | VT_VARIANT;
SAFEARRAYBOUND bounds;
bounds.cElements = (ULONG)dwNumSAUsers + 2;
bounds.lLbound = 0;
SAFEARRAY *psaSids = NULL;
SAFEARRAY *psaUserSid = NULL;
psaSids = SafeArrayCreate(VT_VARIANT, 1, &bounds);
_ASSERTE(psaSids);
if (psaSids == NULL)
return E_OUTOFMEMORY;
for(indUser=0, indUserAcess = 0; indUser < dwNumSAUsers; indUser++)
{
if (m_CheckList.GetState(hWndList, indUser) == CHECKED)
{
VARIANT *pVarSid = NULL;
PSID pSID = NULL;
LONG lengthSID;
m_CheckList.GetSID(hWndList, indUser, &pSID, &lengthSID);
hr = PackSidInVariant(&pVarSid, pSID, lengthSID);
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
{
SafeArrayDestroy(psaSids);
psaUserSid = V_ARRAY(pVarSid);
SafeArrayDestroy(psaUserSid);
HeapFree(GetProcessHeap(), 0, pVarSid);
return hr;
}
hr = SafeArrayPutElement(psaSids, (LONG *)&indUserAcess, (LPVOID)pVarSid);
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
{
SafeArrayDestroy(psaSids);
psaUserSid = V_ARRAY(pVarSid);
SafeArrayDestroy(psaUserSid);
HeapFree(GetProcessHeap(), 0, pVarSid);
return hr;
}
psaUserSid = V_ARRAY(pVarSid);
SafeArrayDestroy(psaUserSid);
HeapFree(GetProcessHeap(), 0, pVarSid);
indUserAcess++;
}
}
VARIANT *pVarSid = NULL;
if (m_fEveryone)
{
hr = PackSidInVariant(&pVarSid, g_pSidEverybody, g_pSidEverybodyLenght/*ppsidSAUsers[dwNumSAUsers+1]*/);
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
{
SafeArrayDestroy(psaSids);
HeapFree(GetProcessHeap(), 0, pVarSid);
return hr;
}
hr = SafeArrayPutElement(psaSids, (LONG *)&indUserAcess, (LPVOID)pVarSid);
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
{
SafeArrayDestroy(psaSids);
HeapFree(GetProcessHeap(), 0, pVarSid);
return hr;
}
HeapFree(GetProcessHeap(), 0, pVarSid);
indUserAcess++;
}
// Administrators always should have access
hr = PackSidInVariant(&pVarSid, g_pSidAdmins, g_pSidAdminsLenght/*ppsidSAUsers[dwNumSAUsers+1]*/);
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
{
SafeArrayDestroy(psaSids);
HeapFree(GetProcessHeap(), 0, pVarSid);
return hr;
}
hr = SafeArrayPutElement(psaSids, (LONG *)&indUserAcess, (LPVOID)pVarSid);
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
{
SafeArrayDestroy(psaSids);
HeapFree(GetProcessHeap(), 0, pVarSid);
return hr;
}
HeapFree(GetProcessHeap(), 0, pVarSid);
indUserAcess++;
bounds.cElements = (ULONG)indUserAcess;
SafeArrayRedim(psaSids, &bounds);
V_ARRAY(&vArrSids) = psaSids;
VARIANT_BOOL vboolRetVal;
hr = m_pSAUserInfo->SetFileAccessAllowedAces(m_bsPath,
&vArrSids,
&vboolRetVal);
_ASSERTE(!FAILED(hr));
if (FAILED(hr))
return hr;
else
m_fChanged = FALSE;
SafeArrayDestroy(psaSids);
VariantClear(&vArrSids);
return S_OK;
}
/**************************************************************************
CShellPropSheetExt::Connect()
**************************************************************************/
BOOL CShellPropSheetExt::Connect()
{
BOOL bRet = FALSE;
HRESULT hRes;
HKEY hKey = 0;
DWORD dwType = 0;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\ServerAppliance"),
0,
KEY_READ,
&hKey) != ERROR_SUCCESS)
return FALSE;
DWORD dwcData = sizeof(m_tszDomainServer);
if (RegQueryValueEx(hKey,
TEXT("ServerName"),
0,
&dwType,
(LPBYTE)m_tszDomainServer,
&dwcData) != ERROR_SUCCESS)
return FALSE;
RegCloseKey(hKey);
COSERVERINFO serverInfo;
CoInitialize(NULL);
serverInfo.dwReserved1 = 0;
serverInfo.dwReserved2 = 0;
_bstr_t bsDomainSevrer("\\\\");
bsDomainSevrer += m_tszDomainServer;
serverInfo.pwszName = bsDomainSevrer.copy();//SysAllocString(L"\\\\BALAJIB_1");
serverInfo.pAuthInfo = NULL;
MULTI_QI qi = {&IID_ISAUserInfo, NULL, 0};
hRes = CoCreateInstanceEx(CLSID_SAUserInfo,
NULL,
CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
&serverInfo,
1,
&qi);
_ASSERTE(SUCCEEDED(hRes) && SUCCEEDED(qi.hr));
if (SUCCEEDED(hRes) && SUCCEEDED(qi.hr))
{
m_pSAUserInfo = (ISAUserInfo *)qi.pItf;
hRes = CoSetProxyBlanket((IUnknown*)m_pSAUserInfo,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE);
if (SUCCEEDED(hRes))
bRet = TRUE;
}
return bRet;
}
/**************************************************************************
CShellPropSheetExt::Save()
**************************************************************************/
void CShellPropSheetExt::Save(HWND hWnd)
{
HRESULT hr;
hr = SetFilePermissions(hWnd);
_ASSERTE (!FAILED(hr));
}
/**************************************************************************
CShellPropSheetExt::CleanUp
**************************************************************************/
void CShellPropSheetExt::CleanUp()
{
BOOL fRes = FALSE;
m_pSAUserInfo->Release();
if (g_pSidEverybody)
{
fRes = HeapFree(GetProcessHeap(), 0, g_pSidEverybody);
_ASSERTE(fRes);
g_pSidEverybody = NULL;
}
if (g_pSidAdmins)
{
fRes = HeapFree(GetProcessHeap(), 0, g_pSidAdmins);
_ASSERTE(fRes);
g_pSidAdmins = NULL;
}
}
/**************************************************************************
CShellPropSheetExt::IsChamelon()
**************************************************************************/
BOOL CShellPropSheetExt::IsChamelon(LPTSTR szPath)
{
// Review Yury: use WNetGetConnection instead.
TCHAR szPathTmp[MAX_PATH];
// TCHAR szNetwork[MAX_PATH + 4] = "Network\\";
TCHAR szSubKeyRemotePathNT[MAX_PATH] = TEXT("Network\\");
TCHAR szSubKeyRemotePathWindows[MAX_PATH] = TEXT("Network\\Persistent\\");
_tcsncpy(szPathTmp, szPath, ARRAYSIZE(szPathTmp));
if (PathStripToRoot(szPathTmp) && GetDriveType(szPathTmp) == DRIVE_REMOTE)
{
HKEY hKey;
LRESULT lResult = ERROR_SUCCESS;
LPTSTR pszSubKey = NULL;
szPathTmp[1] = _T('\0'); // We need only letter
if (IsNT())
pszSubKey = szSubKeyRemotePathNT;
else
pszSubKey = szSubKeyRemotePathWindows;
_tcscat(pszSubKey, szPathTmp);
lResult = RegOpenKeyEx(HKEY_CURRENT_USER,
pszSubKey,
0,
KEY_READ,
&hKey);
_ASSERTE(lResult == ERROR_SUCCESS);
if(lResult != ERROR_SUCCESS)
return FALSE;
//create an array to put our data in
TCHAR szShare[MAX_PATH];
DWORD dwType;
DWORD dwSize = sizeof(szShare);
lResult = RegQueryValueEx( hKey,
TEXT("RemotePath"),
NULL,
&dwType,
(LPBYTE)szShare,
&dwSize);
_ASSERTE(lResult == ERROR_SUCCESS);
RegCloseKey(hKey);
if(lResult != ERROR_SUCCESS)
return FALSE;
if (!_tcsicmp(szShare, TEXT(CHAMELEON_SHARE)))
return TRUE;
else
return FALSE;
}
else if (PathIsUNC(szPath))
{
return TRUE;
}
else
return FALSE;
}
/**************************************************************************
CShellPropSheetExt::Initialize()
**************************************************************************/
STDMETHODIMP CShellPropSheetExt::Initialize( LPCITEMIDLIST pidlFolder,
LPDATAOBJECT lpDataObj,
HKEY hKeyProgId)
{
STGMEDIUM medium;
FORMATETC fe = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT hResult = E_FAIL;
TCHAR szPath[MAX_PATH];
BOOL fResult = FALSE;
// OLE initialization. This is 'lighter' than OleInitialize()
// which also setups DnD, etc.
if(FAILED(CoInitialize(NULL)))
return E_FAIL;
if(NULL == lpDataObj)
return E_INVALIDARG;
if(FAILED(lpDataObj->GetData(&fe, &medium)))
return E_FAIL;
//get the file name from the HDROP
UINT uCount = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0);
DragQueryFile((HDROP)medium.hGlobal, 0, szPath, MAX_PATH);
_tcsncpy(m_szPath, szPath, ARRAYSIZE(m_szPath));
#ifdef USE_FILE_ACCESS_TO_CHECK_PERMISSION
HANDLE hFolder = CreateFile(m_szPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_NORMAL, NULL);
//WIN32_FIND_DATA FindFileData;
//HANDLE hFolder = FindFirstFile(szPath, &FindFileData ); // This doesn't work because we can find the foldre even we don't have permision
if (hFolder != INVALID_HANDLE_VALUE)
{
CloseHandle(hFolder);
m_fHasAccess = TRUE;
}
else
{
DWORD dwError = GetLastError();
if (dwError == ERROR_ACCESS_DENIED)
m_fHasAccess = FALSE;
else
m_fHasAccess = TRUE;
}
#endif USE_FILE_ACCESS_TO_CHECK_PERMISSION
//if(uCount == 1 && ((PathStripToRoot(szPath) && GetDriveType(szPath) == DRIVE_REMOTE) || PathIsUNC(szPath)))
if (uCount == 1 && IsChamelon(szPath))
hResult = S_OK;
else
return E_FAIL;
if (!Connect())
return E_FAIL;
ReleaseStgMedium(&medium);
return hResult;
}
///////////////////////////////////////////////////////////////////////////
//
// IShellPropSheetExt Implementation
//
/**************************************************************************
CShellPropSheetExt::AddPages()
**************************************************************************/
STDMETHODIMP CShellPropSheetExt::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
{
PROPSHEETPAGE psp;
HPROPSHEETPAGE hPage;
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE | PSP_USECALLBACK;
psp.hInstance = g_hInst;
psp.pszTemplate = MAKEINTRESOURCE(IDD_PAGEDLG);
psp.hIcon = 0;
psp.pszTitle = TEXT("Security");
psp.pfnDlgProc = PageDlgProc;
psp.pcRefParent = &g_DllRefCount;
psp.pfnCallback = PageCallbackProc;
psp.lParam = (LPARAM)this;
hPage = CreatePropertySheetPage(&psp);
if(hPage)
{
if(lpfnAddPage(hPage, lParam))
{
//keep this object around until the page is released in PageCallbackProc
this->AddRef();
return S_OK;
}
else
{
DestroyPropertySheetPage(hPage);
}
}
else
{
return E_OUTOFMEMORY;
}
return E_FAIL;
}
/**************************************************************************
CShellPropSheetExt::ReplacePage()
**************************************************************************/
STDMETHODIMP CShellPropSheetExt::ReplacePage( UINT uPageID,
LPFNADDPROPSHEETPAGE lpfnAddPage,
LPARAM lParam)
{
return E_NOTIMPL;
}
/**************************************************************************
CShellPropSheetExt::NoAccessUpdateView()
**************************************************************************/
void CShellPropSheetExt::NoAccessUpdateView(HWND hWnd)
{
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
HWND hWndButGroup = GetDlgItem(hWnd, IDC_BUTTONGROUP);
ShowWindow(hWndButGroup, SW_HIDE);
HWND hWndButEveryone = GetDlgItem(hWnd, IDC_EVERYONE);
ShowWindow(hWndButEveryone, SW_HIDE);
HWND hWndButSelected = GetDlgItem(hWnd, IDC_SELECTUSERS);
ShowWindow(hWndButSelected, SW_HIDE);
HWND hWndAdminMessage = GetDlgItem(hWnd, IDC_ADMIN_MESSAGE);
ShowWindow(hWndAdminMessage, SW_HIDE);
HWND hWndUserMessage = GetDlgItem(hWnd, IDC_USER_MESSAGE);
ShowWindow(hWndUserMessage, SW_SHOW);
EnableWindow(hWndList, FALSE);
}
/**************************************************************************
CShellPropSheetExt::AccessUpdateView()
**************************************************************************/
void CShellPropSheetExt::AccessUpdateView(HWND hWnd)
{
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
HWND hWndButGroup = GetDlgItem(hWnd, IDC_BUTTONGROUP);
ShowWindow(hWndButGroup, SW_SHOW);
HWND hWndButEveryone = GetDlgItem(hWnd, IDC_EVERYONE);
ShowWindow(hWndButEveryone, SW_SHOW);
HWND hWndButSelected = GetDlgItem(hWnd, IDC_SELECTUSERS);
ShowWindow(hWndButSelected, SW_SHOW);
HWND hWndAdminMessage = GetDlgItem(hWnd, IDC_ADMIN_MESSAGE);
ShowWindow(hWndAdminMessage, SW_SHOW);
HWND hWndUserMessage = GetDlgItem(hWnd, IDC_USER_MESSAGE);
ShowWindow(hWndUserMessage, SW_HIDE);
EnableWindow(hWndList, TRUE);
}
/**************************************************************************
PageDlgProc
**************************************************************************/
#define THIS_POINTER_PROP TEXT("ThisPointerProperty")
INT_PTR CALLBACK CShellPropSheetExt::PageDlgProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
LPPROPSHEETPAGE pPage = (LPPROPSHEETPAGE)lParam;
if(pPage)
{
CShellPropSheetExt *pExt = (CShellPropSheetExt*)pPage->lParam;
if(pExt)
{
SetProp(hWnd, THIS_POINTER_PROP, (HANDLE)pExt);
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
pExt->m_CheckList.Init(hWndList);
pExt->EnumUsers(hWnd);
ListView_SetItemState(hWndList, pExt->m_uiUser, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
::SendDlgItemMessage(hWnd, (pExt->m_fEveryone) ? IDC_EVERYONE : IDC_SELECTUSERS, BM_SETCHECK, BST_CHECKED, 0);
if (!pExt->m_fHasAccess)
pExt->NoAccessUpdateView(hWnd);
else
{
pExt->AccessUpdateView(hWnd);
if (pExt->m_fEveryone)
::EnableWindow(hWndList , FALSE);
}
}
}
}
break;
case WM_COMMAND:
{
WORD wNotifyCode;
switch ( wNotifyCode = HIWORD(wParam))
{
case BN_CLICKED:
{
CShellPropSheetExt *pExt = (CShellPropSheetExt*)GetProp(hWnd,THIS_POINTER_PROP);
if(pExt &&
(((int) LOWORD(wParam) == IDC_SELECTUSERS && pExt->m_fEveryone)
|| ((int) LOWORD(wParam) == IDC_EVERYONE && !pExt->m_fEveryone)))
{
pExt->m_fEveryone = !pExt->m_fEveryone;
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
EnableWindow(hWndList , (pExt->m_fEveryone) ? FALSE : TRUE);
PropSheet_Changed(GetParent(hWnd), hWnd);
pExt->m_fChanged = TRUE;
}
}
break;
}
}
break;
case WM_NOTIFY:
{
switch (((NMHDR FAR *)lParam)->code)
{
case LVN_KEYDOWN:
{
LPNMLVKEYDOWN pnm = (LPNMLVKEYDOWN) lParam;
if (pnm->wVKey == VK_SPACE)
{
// Change the access
CShellPropSheetExt *pExt = (CShellPropSheetExt*)GetProp(hWnd,THIS_POINTER_PROP);
if (pExt)
{
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
CHKMARK chk = pExt->m_CheckList.GetState(hWndList, pExt->m_uiUser);
CHKMARK chkNew = BLANK;
switch (chk)
{
case BLANK:
chkNew = CHECKED;
case CHECKED:
PropSheet_Changed(GetParent(hWnd), hWnd);
pExt->m_CheckList.Mark(hWndList, pExt->m_uiUser, chkNew);
pExt->m_fChanged = TRUE;
break;
default:
break;
}
}
}
}
break;
case LVN_ITEMCHANGED:
{
LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
if (pnmv->uChanged == LVIF_STATE && pnmv->uNewState & LVIS_SELECTED)
{
CShellPropSheetExt *pExt = (CShellPropSheetExt*)GetProp(hWnd,THIS_POINTER_PROP);
pExt->m_uiUser = pnmv->iItem;
}
}
break;
case NM_CLICK:
{
LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
CShellPropSheetExt *pExt = (CShellPropSheetExt*)GetProp(hWnd,THIS_POINTER_PROP);
if (pExt)
{
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
RECT recIcon;
if (!ListView_GetItemRect(hWndList, pnmv->iItem, &recIcon, LVIR_ICON))
break;
if (recIcon.right > pnmv->ptAction.x)
{
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
CHKMARK chk = pExt->m_CheckList.GetState(hWndList, pExt->m_uiUser);
CHKMARK chkNew = BLANK;
switch (chk)
{
case BLANK:
chkNew = CHECKED;
case CHECKED:
PropSheet_Changed(GetParent(hWnd), hWnd);
pExt->m_CheckList.Mark(hWndList, pExt->m_uiUser, chkNew);
pExt->m_fChanged = TRUE;
break;
default:
break;
}
}
}
}
break;
case PSN_SETACTIVE:
break;
case PSN_APPLY:
{
//User has clicked the OK or Apply
CShellPropSheetExt *pExt = (CShellPropSheetExt*)GetProp(hWnd,THIS_POINTER_PROP);
if(pExt && pExt->m_fChanged)
{
pExt->Save(hWnd);
if (!pExt->m_fChanged)
{
VARIANT_BOOL vboolRetVal;
HRESULT hResAccess;
if (SUCCEEDED(hResAccess = pExt->m_pSAUserInfo->DoIHaveAccess(pExt->m_bsPath, &vboolRetVal)))
pExt->m_fHasAccess = TRUE;
else
{
// We lost access. Redo the ListView.
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
pExt->m_CheckList.Init(hWndList);
pExt->EnumUsers(hWnd);
pExt->m_fHasAccess = FALSE;
pExt->NoAccessUpdateView(hWnd);
}
}
}
}
break;
case PSN_QUERYCANCEL:
break;
default:
break;
}
}
break;
case WM_DESTROY:
CShellPropSheetExt *pExt = (CShellPropSheetExt*)GetProp(hWnd,THIS_POINTER_PROP);
if (pExt)
{
HWND hWndList = GetDlgItem(hWnd, IDC_FILE_LIST);
// Delete SIDs in here
// _bstr_t *pbsSID;
LV_ITEM lvi;
ZeroMemory(&lvi, sizeof(lvi));
lvi.mask = LVIF_PARAM;
for (int indUser = 0; indUser < ListView_GetItemCount(hWndList); indUser++)
{
lvi.iItem = indUser;
ListView_GetItem(hWndList, &lvi);
// pbsSID = (_bstr_t *)lvi.lParam;
// if (pbsSID)
// {
// delete pbsSID;
// }
}
pExt->m_CheckList.OnDestroy(hWndList);
pExt->m_CheckList.Term();
RemoveProp(hWnd, THIS_POINTER_PROP);
pExt->CleanUp();
}
break;
}
return FALSE;
}
/**************************************************************************
PageCallbackProc()
**************************************************************************/
UINT CALLBACK CShellPropSheetExt::PageCallbackProc( HWND hWnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
switch(uMsg)
{
case PSPCB_CREATE:
return TRUE;
case PSPCB_RELEASE:
{
/*
Release the object. This gets called even if the page dialog was never
actually created.
*/
CShellPropSheetExt *pExt = (CShellPropSheetExt*)ppsp->lParam;
if(pExt)
{
pExt->Release();
}
}
break;
}
return FALSE;
}
/**************************************************************************
WideCharToLocal()
**************************************************************************/
int WideCharToLocal(LPTSTR pLocal, LPWSTR pWide, DWORD dwChars)
{
*pLocal = 0;
#ifdef UNICODE
lstrcpyn(pLocal, pWide, dwChars);
#else
WideCharToMultiByte( CP_ACP,
0,
pWide,
-1,
pLocal,
dwChars,
NULL,
NULL);
#endif
return lstrlen(pLocal);
}
/**************************************************************************
LocalToWideChar()
**************************************************************************/
int LocalToWideChar(LPWSTR pWide, LPTSTR pLocal, DWORD dwChars)
{
*pWide = 0;
#ifdef UNICODE
lstrcpyn(pWide, pLocal, dwChars);
#else
MultiByteToWideChar( CP_ACP,
0,
pLocal,
-1,
pWide,
dwChars);
#endif
return lstrlenW(pWide);
}
#ifdef WE_USE_WBEM
/**************************************************************************
StringFromSid()
Here's a conversion from binary SID to string
We need it because of WBEM inconsitency.
Win32_Account has it as a string and Win32_Trastee as a binary
**************************************************************************/
void StringFromSid( PSID psid, CHString& str )
{
// Initialize m_strSid - human readable form of our SID
SID_IDENTIFIER_AUTHORITY *psia = RtlGetSidIdentifierAuthority( psid );
// We assume that only last byte is used (authorities between 0 and 15).
// Correct this if needed.
_ASSERTE( psia->Value[0] == 0 &&
psia->Value[1] == 0 &&
psia->Value[2] == 0 &&
psia->Value[3] == 0 &&
psia->Value[4] == 0 );
DWORD dwTopAuthority = psia->Value[5];
str.Format( TEXT("S-1-%d"), dwTopAuthority );
CHString strSubAuthority;
UCHAR ucSubAuthorityCount = 0;
UCHAR *pucTemp = RtlGetSidSubAuthorityCount( psid );
ucSubAuthorityCount = *pucTemp;
for ( UCHAR i = 0; i < ucSubAuthorityCount; i++ ) {
DWORD dwSubAuthority = *( RtlGetSidSubAuthority( psid, i ) );
strSubAuthority.Format( TEXT("%d"), dwSubAuthority );
str += "-" + strSubAuthority;
}
}
/**************************************************************************
StrToSID()
Here's a conversion from string to binary SID
We need it because of WBEM inconsitency.
Win32_Account has it as a string and Win32_Trastee as a binary
**************************************************************************/
// for input of the form AAA-BBB-CCC
// will return AAA in token
// and BBB-CCC in str
bool WhackToken(CHString& str, CHString& token)
{
bool bRet = false;
if (bRet = !str.IsEmpty())
{
int index;
index = str.Find('-');
if (index == -1)
{
// all that's left is the token, we're done
token = str;
str.Empty();
}
else
{
token = str.Left(index);
str = str.Mid(index+1);
}
}
return bRet;
}
// helper for StrToSID
// takes a string, converts to a SID_IDENTIFIER_AUTHORITY
// returns false if not a valid SID_IDENTIFIER_AUTHORITY
// contents of identifierAuthority are unreliable on failure
bool StrToIdentifierAuthority(const CHString& str, SID_IDENTIFIER_AUTHORITY& identifierAuthority)
{
bool bRet = false;
memset(&identifierAuthority, '\0', sizeof(SID_IDENTIFIER_AUTHORITY));
DWORD duhWord;
TCHAR* p = NULL;
CHString localStr(str);
// per KB article Q13132, if identifier authority is greater than 2**32, it's in hex
if ((localStr[0] == '0') && localStr.GetLength() > 1 && ((localStr[1] == 'x') || (localStr[1] == 'X')))
// if it looks hexidecimalish...
{
// going to parse this out backwards, chpping two chars off the end at a time
// first, whack off the 0x
localStr = localStr.Mid(2);
CHString token;
int nValue =5;
bRet = true;
while (bRet && localStr.GetLength() && (nValue > 0))
{
token = localStr.Right(2);
localStr = localStr.Left(localStr.GetLength() -2);
duhWord = _tcstoul(token, &p, 16);
// if strtoul succeeds, the pointer is moved
if (p != (LPCTSTR)token)
identifierAuthority.Value[nValue--] = (BYTE)duhWord;
else
bRet = false;
}
}
else
// it looks decimalish
{
duhWord = _tcstoul(localStr, &p, 10);
if (p != (LPCTSTR)localStr)
// conversion succeeded
{
bRet = true;
identifierAuthority.Value[5] = LOBYTE(LOWORD(duhWord));
identifierAuthority.Value[4] = HIBYTE(LOWORD(duhWord));
identifierAuthority.Value[3] = LOBYTE(HIWORD(duhWord));
identifierAuthority.Value[2] = HIBYTE(HIWORD(duhWord));
}
}
return bRet;
}
// a string representation of a SID is assumed to be:
// S-#-####-####-####-####-####-####
// we will enforce only the S ourselves,
// The version is not checked
// everything else will be handed off to the OS
// caller must free the SID returned
PSID StrToSID(const CHString& sid)
{
PSID pSid = NULL;
if (!sid.IsEmpty() && ((sid[0] == 'S')||(sid[0] == 's')) && (sid[1] == '-'))
{
// get a local copy we can play with
// we'll parse this puppy the easy way
// by slicing off each token as we find it
// slow but sure
// start by slicing off the "S-"
CHString str(sid.Mid(2));
CHString token;
SID_IDENTIFIER_AUTHORITY identifierAuthority = {0,0,0,0,0,0};
BYTE nSubAuthorityCount =0; // count of subauthorities
DWORD dwSubAuthority[8] = {0,0,0,0,0,0,0,0}; // subauthorities
// skip version
WhackToken(str, token);
// Grab Authority
if (WhackToken(str, token))
{
DWORD duhWord;
TCHAR* p = NULL;
bool bDoIt = false;
if (StrToIdentifierAuthority(token, identifierAuthority))
// conversion succeeded
{
bDoIt = true;
// now fill up the subauthorities
while (bDoIt && WhackToken(str, token))
{
p = NULL;
duhWord = _tcstoul(token, &p, 10);
if (p != (LPCTSTR)token)
{
dwSubAuthority[nSubAuthorityCount] = duhWord;
bDoIt = (++nSubAuthorityCount <= 8);
}
else
bDoIt = false;
} // end while WhackToken
if (bDoIt)
{
if (IsNT())
AllocateAndInitializeSid(&identifierAuthority,
nSubAuthorityCount,
dwSubAuthority[0],
dwSubAuthority[1],
dwSubAuthority[2],
dwSubAuthority[3],
dwSubAuthority[4],
dwSubAuthority[5],
dwSubAuthority[6],
dwSubAuthority[7],
&pSid);
else
RtlAllocateAndInitializeSid(&identifierAuthority,
nSubAuthorityCount,
dwSubAuthority[0],
dwSubAuthority[1],
dwSubAuthority[2],
dwSubAuthority[3],
dwSubAuthority[4],
dwSubAuthority[5],
dwSubAuthority[6],
dwSubAuthority[7],
&pSid);
}
}
}
}
return pSid;
}
/*++
Routine Description:
This routine returns the length, in bytes, required to store an SID
with the specified number of Sub-Authorities.
Arguments:
SubAuthorityCount - The number of sub-authorities to be stored in the SID.
Return Value:
ULONG - The length, in bytes, required to store the SID.
--*/
ULONG
RtlLengthRequiredSid (ULONG SubAuthorityCount)
{
return (8L + (4 * SubAuthorityCount));
}
BOOL WINAPI
RtlAllocateAndInitializeSid(
PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
UCHAR SubAuthorityCount,
ULONG SubAuthority0,
ULONG SubAuthority1,
ULONG SubAuthority2,
ULONG SubAuthority3,
ULONG SubAuthority4,
ULONG SubAuthority5,
ULONG SubAuthority6,
ULONG SubAuthority7,
OUT PSID *Sid
)
/*++
Routine Description:
This function allocates and initializes a sid with the specified
number of sub-authorities (up to 8). A sid allocated with this
routine must be freed using RtlFreeSid().
Arguments:
IdentifierAuthority - Pointer to the Identifier Authority value to
set in the SID.
SubAuthorityCount - The number of sub-authorities to place in the SID.
This also identifies how many of the SubAuthorityN parameters
have meaningful values. This must contain a value from 0 through
8.
SubAuthority0-7 - Provides the corresponding sub-authority value to
place in the SID. For example, a SubAuthorityCount value of 3
indicates that SubAuthority0, SubAuthority1, and SubAuthority0
have meaningful values and the rest are to be ignored.
Sid - Receives a pointer to the SID data structure to initialize.
Return Value:
STATUS_SUCCESS - The SID has been allocated and initialized.
STATUS_NO_MEMORY - The attempt to allocate memory for the SID
failed.
STATUS_INVALID_SID - The number of sub-authorities specified did
not fall in the valid range for this api (0 through 8).
--*/
{
PISID ISid;
if ( SubAuthorityCount > 8 ) {
return 0;//( STATUS_INVALID_SID );
}
ISid = (PISID)HeapAlloc( GetProcessHeap(), 0,
RtlLengthRequiredSid(SubAuthorityCount)
);
if (ISid == NULL) {
return(STATUS_NO_MEMORY);
}
ISid->SubAuthorityCount = (UCHAR)SubAuthorityCount;
ISid->Revision = 1;
ISid->IdentifierAuthority = *IdentifierAuthority;
switch (SubAuthorityCount) {
case 8:
ISid->SubAuthority[7] = SubAuthority7;
case 7:
ISid->SubAuthority[6] = SubAuthority6;
case 6:
ISid->SubAuthority[5] = SubAuthority5;
case 5:
ISid->SubAuthority[4] = SubAuthority4;
case 4:
ISid->SubAuthority[3] = SubAuthority3;
case 3:
ISid->SubAuthority[2] = SubAuthority2;
case 2:
ISid->SubAuthority[1] = SubAuthority1;
case 1:
ISid->SubAuthority[0] = SubAuthority0;
case 0:
;
}
(*Sid) = ISid;
return 1;//( STATUS_SUCCESS );
}
/*++
Routine Description:
The RtlGetSidIdentifierAuthority function returns the address
of the SID_IDENTIFIER_AUTHORITY structure in a specified security identifier (SID).
Arguments:
pSid - Receives a pointer to the SID data structure to initialize.
Return Value:
PSID_IDENTIFIER_AUTHORITY
--*/
PSID_IDENTIFIER_AUTHORITY WINAPI
RtlGetSidIdentifierAuthority(PSID pSid)
{
PISID ISid = (PISID)pSid;
_ASSERTE( ISid->SubAuthorityCount <= 8 );
return &(ISid->IdentifierAuthority);
}
/*++
Routine Description:
The RtlGetSidSubAuthorityCount function returns the address of the field
in a SID structure containing the subauthority count
Arguments:
pSid - Receives a pointer to the SID data structure to initialize.
Return Value:
pointer to the subauthority count for the specified SID structure
--*/
PUCHAR WINAPI
RtlGetSidSubAuthorityCount (PSID pSid)
{
PISID ISid = (PISID)pSid;
_ASSERTE( ISid->SubAuthorityCount <= 8 );
return &(ISid->SubAuthorityCount);
}
/*++
Routine Description:
The RtlGetSidSubAuthority function returns the address of a specified
subauthority in a SID structure
Arguments:
pSid - Receives a pointer to the SID data structure to initialize.
nSubAuthority - Specifies an index value identifying
the subauthority array element whose address the function will return.
Return Value:
PSID_IDENTIFIER_AUTHORITY
--*/
PDWORD WINAPI
RtlGetSidSubAuthority (PSID pSid, DWORD nSubAuthority)
{
PISID ISid = (PISID)pSid;
_ASSERTE( ISid->SubAuthorityCount <= 8 );
return &(ISid->SubAuthority[nSubAuthority]);
}
#endif WE_USE_WBEM
BOOL IsNT()
{
OSVERSIONINFO OsVersionInfo;
ZeroMemory(&OsVersionInfo, sizeof(OSVERSIONINFO));
OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&OsVersionInfo);
if ((VER_PLATFORM_WIN32_NT == OsVersionInfo.dwPlatformId))// Review Yury: What about Win2000? && (OsVersionInfo.dwMajorVersion == 4))
return TRUE;
else
return FALSE;
}