|
|
//+---------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993 - 1997.
//
// File: datapkt.cpp
//
// Contents: Implements the class CDataPacket to manages diverse data
// packets needing to be written to various databases
//
// Classes:
//
// Methods: CDataPacket::CDataPacket (x 7)
// CDataPacket::~CDataPacket
// CDataPacket::ChgSzValue
// CDataPacket::ChgDwordValue
// CDataPacket::ChgACL
// CDataPacket::ChgPassword
// CDataPacket::ChgSrvIdentity
//
// History: 23-Apr-96 BruceMa Created.
// 12-Dec-96 RonanS Added copy constructor to CDataPacket
// to get around bugs when copying CDataPacket.
// Fixed memory leaks in destructor.
// Simplified constructor code.
// 09-Jan-97 SteveBl Modified to support IAccessControl.
//
//----------------------------------------------------------------------
#include "stdafx.h"
#include "assert.h"
#include "datapkt.h"
#if !defined(STANDALONE_BUILD)
extern "C" { #include <getuser.h>
} #endif
#include "util.h"
static TCHAR * TStrDup(const TCHAR *lpszString) { TCHAR * lpszTmp = NULL; int nStrlen = 0;
if (lpszString ) { lpszTmp = new TCHAR[_tcslen(lpszString) + 1]; ASSERT(lpszTmp);
_tcscpy(lpszTmp, lpszString); }
return lpszTmp; }
CDataPacket::CDataPacket(void) { m_tagType = Empty; m_fDelete = FALSE; m_fDeleteHive = FALSE; m_hRoot = 0; SetModified(TRUE); }
CDataPacket::CDataPacket(HKEY hRoot, TCHAR *szKeyPath, TCHAR *szValueName, DWORD dwValue) :m_szKeyPath(szKeyPath), m_szValueName(szValueName) { m_tagType = NamedValueDword; m_hRoot = hRoot; pkt.nvdw.dwValue = dwValue; SetModified(TRUE); m_fDelete = FALSE; m_fDeleteHive = FALSE; }
CDataPacket::CDataPacket(HKEY hRoot, TCHAR *szKeyPath, TCHAR *szValueName, SECURITY_DESCRIPTOR *pSec, BOOL fSelfRelative) :m_szKeyPath(szKeyPath), m_szValueName(szValueName) { int err; ULONG cbLen; SECURITY_DESCRIPTOR *pSD;
m_tagType = SingleACL; m_hRoot = hRoot;
// Get the security descriptor into self relative form so we
// can cache it
// Force first call to fail so we can get the real size needed
if (!fSelfRelative) { cbLen = 1; if (!MakeSelfRelativeSD(pSec, NULL, &cbLen)) { err = GetLastError(); }
// Now really do it
pSD = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED, cbLen); if (!pSD) { ReportOutOfMemAndTerminate(); // will never get here
return; } if (!MakeSelfRelativeSD(pSec, pSD, &cbLen)) { err = GetLastError(); } pkt.acl.pSec = pSD; } else { // The security descriptor is aready in self relative form
// as it was read directly from the registry. However, we still
// have to copy the it.
g_util.CopySD(pSec, &pkt.acl.pSec); }
SetModified(TRUE); m_fDelete = FALSE; m_fDeleteHive = FALSE; }
CDataPacket::CDataPacket(HKEY hKey, HKEY *phClsids, unsigned cClsids, TCHAR *szTitle, SECURITY_DESCRIPTOR *pSecOrig, SECURITY_DESCRIPTOR *pSec, BOOL fSelfRelative) { ULONG cbLen; SECURITY_DESCRIPTOR *pSD;
m_tagType = RegKeyACL; m_hRoot = hKey;
pkt.racl.phClsids = phClsids; pkt.racl.cClsids = cClsids; pkt.racl.szTitle = TStrDup(szTitle);
// Get the new security descriptor into self relative form so we
// can cache it (if we have to)
if (!fSelfRelative) { // Force first call to fail so we can get the real size needed
cbLen = 1; MakeSelfRelativeSD(pSec, NULL, &cbLen);
// Now really do it
pSD = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED, cbLen); if (!pSD) { ReportOutOfMemAndTerminate(); // will never get here
return; } MakeSelfRelativeSD(pSec, pSD, &cbLen); pkt.racl.pSec = pSD; } else { g_util.CopySD(pSec, &pkt.racl.pSec); }
// The original security descriptor is aready in self relative form
// as it was read directly from the registry. (The edited SD from the
// ACL editor is in absolute form.) However, we still have to copy the
// original SD.
g_util.CopySD(pSecOrig, &pkt.racl.pSecOrig);
SetModified(TRUE); m_fDelete = FALSE; m_fDeleteHive = FALSE; }
CDataPacket::CDataPacket(TCHAR *szPassword, CLSID appid) { m_tagType = Password; pkt.pw.szPassword = TStrDup(szPassword); pkt.pw.appid = appid; SetModified(TRUE); m_fDelete = FALSE; m_hRoot = 0; m_fDeleteHive = FALSE; }
CDataPacket::CDataPacket(TCHAR *szServiceName, TCHAR *szIdentity) { m_hRoot = 0; m_tagType = ServiceIdentity; pkt.si.szServiceName = TStrDup(szServiceName); pkt.si.szIdentity = TStrDup(szIdentity); SetModified(TRUE); m_fDelete = FALSE; m_fDeleteHive = FALSE; }
CRegSzNamedValueDp::CRegSzNamedValueDp(const CRegSzNamedValueDp& rDataPacket) : CDataPacket((const CDataPacket & ) rDataPacket) { m_szValue = rDataPacket.m_szValue; }
CDataPacket::CDataPacket( const CDataPacket & rDataPacket) :m_szKeyPath (rDataPacket.m_szKeyPath), m_szValueName(rDataPacket.m_szValueName) { m_tagType = rDataPacket.m_tagType; m_fModified = rDataPacket.m_fModified; m_fDelete = rDataPacket.m_fDelete; m_hRoot = rDataPacket.m_hRoot;
switch (m_tagType) { case NamedValueSz: // handled by derived class
break; case NamedValueDword: pkt.nvdw.dwValue = rDataPacket.pkt.nvdw.dwValue; break;
case SingleACL: // Get the security descriptor into self relative form so we
g_util.CopySD(rDataPacket.pkt.acl.pSec, &pkt.acl.pSec); break;
case RegKeyACL: pkt.racl.phClsids = rDataPacket.pkt.racl.phClsids; pkt.racl.cClsids = rDataPacket.pkt.racl.cClsids; pkt.racl.szTitle = TStrDup(rDataPacket.pkt.racl.szTitle); g_util.CopySD(rDataPacket.pkt.racl.pSec, &pkt.racl.pSec); g_util.CopySD(rDataPacket.pkt.racl.pSecOrig, &pkt.racl.pSecOrig); break;
case Password: pkt.pw.szPassword = TStrDup(rDataPacket.pkt.pw.szPassword); pkt.pw.appid = rDataPacket.pkt.pw.appid; break;
case ServiceIdentity: pkt.si.szServiceName = TStrDup(rDataPacket.pkt.si.szServiceName); pkt.si.szIdentity = TStrDup(rDataPacket.pkt.si.szIdentity); break;
case Empty: break; } }
CDataPacket::~CDataPacket() {
switch (m_tagType) { case NamedValueSz: // handled by derived class
break;
case NamedValueDword: break;
case SingleACL: if (pkt.acl.pSec) GlobalFree(pkt.acl.pSec); break;
case RegKeyACL: if (pkt.racl.szTitle) delete pkt.racl.szTitle; if (pkt.racl.pSec) GlobalFree(pkt.racl.pSec); if (pkt.racl.pSecOrig) GlobalFree(pkt.racl.pSecOrig); break;
case Password: if (pkt.pw.szPassword) delete pkt.pw.szPassword; break;
case ServiceIdentity: if (pkt.si.szServiceName) delete pkt.si.szServiceName; if (pkt.si.szIdentity) delete pkt.si.szIdentity; break; } }
void CRegSzNamedValueDp::ChgSzValue(TCHAR *szValue) { assert(m_tagType == NamedValueSz); m_szValue = szValue; SetModified(TRUE); }
void CDataPacket::ChgDwordValue(DWORD dwValue) { assert(m_tagType == NamedValueDword); pkt.nvdw.dwValue = dwValue; SetModified(TRUE); }
void CDataPacket::ChgACL(SECURITY_DESCRIPTOR *pSec, BOOL fSelfRelative) { ULONG cbLen; SECURITY_DESCRIPTOR *pSD;
assert(m_tagType == SingleACL || m_tagType == RegKeyACL);
// Remove the previous security descriptor
if (m_tagType == SingleACL) { GlobalFree(pkt.acl.pSec); pkt.acl.pSec = NULL; } else { GlobalFree(pkt.racl.pSec); pkt.racl.pSec = NULL; }
// Put into self relative form (if necessary)
if (!fSelfRelative) { cbLen = 1; MakeSelfRelativeSD(pSec, NULL, &cbLen);
// Now really do it
pSD = (SECURITY_DESCRIPTOR *) GlobalAlloc(GMEM_FIXED, cbLen); if (!pSD) { ReportOutOfMemAndTerminate(); // will never get here
return; } MakeSelfRelativeSD(pSec, pSD, &cbLen);
// Store it
if (m_tagType == SingleACL) { pkt.acl.pSec = pSD; } else { pkt.racl.pSec = pSD; } } else { if (m_tagType == SingleACL) { g_util.CopySD(pSec, &pkt.acl.pSec); } else { g_util.CopySD(pSec, &pkt.racl.pSec); } } SetModified(TRUE); }
void CDataPacket::ChgPassword(TCHAR *szPassword) { if (m_tagType != Password) return; if (pkt.pw.szPassword) delete pkt.pw.szPassword; pkt.pw.szPassword = TStrDup(szPassword); SetModified(TRUE); }
void CDataPacket::ChgSrvIdentity(TCHAR *szIdentity) { assert(m_tagType == ServiceIdentity); if (pkt.si.szIdentity) delete pkt.si.szIdentity; pkt.si.szIdentity = TStrDup(szIdentity); SetModified(TRUE); }
void CDataPacket::MarkForDeletion(BOOL bDelete) { m_fDelete = bDelete; SetModified(TRUE); }
void CDataPacket::MarkHiveForDeletion(BOOL bDelete) { m_fDelete = bDelete; m_fDeleteHive = bDelete; SetModified(TRUE); }
int CDataPacket::Apply() { int err = ERROR_SUCCESS;
if (m_fModified) { if (m_fDelete) err = Remove(); else err = Update(); }
// Cleanup work
if (err == ERROR_SUCCESS) { m_fModified = FALSE; } else { if (err == ERROR_ACCESS_DENIED) { g_util.CkForAccessDenied(ERROR_ACCESS_DENIED); } else { g_util.PostErrorMessage(); } }
return err;
}
int CDataPacket::Update() { int err = ERROR_SUCCESS;
ASSERT(m_fModified); switch (m_tagType) { case Empty: break;
case NamedValueSz: ASSERT(FALSE); // we should never reach here
break;
case NamedValueDword: { err = g_util.WriteRegDwordNamedValue(m_hRoot, (LPCTSTR)m_szKeyPath, (LPCTSTR)m_szValueName, pkt.nvdw.dwValue); } break;
case SingleACL: { err = g_util.WriteRegSingleACL(m_hRoot, (LPCTSTR)m_szKeyPath, (LPCTSTR)m_szValueName, pkt.acl.pSec); } break;
case RegKeyACL: err = g_util.WriteRegKeyACL(m_hRoot, pkt.racl.phClsids, pkt.racl.cClsids, pkt.racl.pSec, pkt.racl.pSecOrig); break;
case Password: err = g_util.WriteLsaPassword(pkt.pw.appid, pkt.pw.szPassword); break;
case ServiceIdentity: err = g_util.WriteSrvIdentity(pkt.si.szServiceName, pkt.si.szIdentity); break; }
return err; }
long CDataPacket::Read(HKEY hKey) { return 0; }
int CDataPacket::Remove() { int err = ERROR_SUCCESS;
if (m_fModified && m_fDelete) { switch (m_tagType) { case Empty: break;
case SingleACL: case NamedValueDword: case NamedValueSz: case NamedValueMultiSz: if (m_fDeleteHive) g_util.DeleteRegKey(m_hRoot,(LPCTSTR)m_szKeyPath); else g_util.DeleteRegValue(m_hRoot, (LPCTSTR)m_szKeyPath, (LPCTSTR)m_szValueName); break;
case RegKeyACL: err = g_util.WriteRegKeyACL(m_hRoot, pkt.racl.phClsids, pkt.racl.cClsids, pkt.racl.pSec, pkt.racl.pSecOrig); break;
case Password: err = g_util.WriteLsaPassword(pkt.pw.appid, pkt.pw.szPassword); break;
case ServiceIdentity: err = g_util.WriteSrvIdentity(pkt.si.szServiceName, pkt.si.szIdentity); break; } }
return err; }
//
// ReportOutOfMemAndTerminate
//
// Dcomcnfg was not coded very well to handle out-of-memory
// errors in certain spots. Rather than rip out and replace
// lots of code to fix this properly, I am simply going to report
// an error and terminate the process when this occurs. Dcomnfg
// as of now only ships in the reskit, not in the os.
//
void CDataPacket::ReportOutOfMemAndTerminate() { CString sTitle; CString sMessage;
if (sTitle.LoadString(IDS_FATALOUTOFMEMORYTITLE)) { if (sMessage.LoadString(IDS_FATALOUTOFMEMORY)) { MessageBoxW(NULL, sMessage, sTitle, MB_ICONWARNING | MB_OK | MB_TASKMODAL); } }
TerminateProcess(GetCurrentProcess(), ERROR_NOT_ENOUGH_MEMORY);
// will never get here
return; }
//*****************************************************************************
//
// class CRegSzNamedValueDp
//
// data packet for RegSZ named value
//
//*****************************************************************************
int CRegSzNamedValueDp::Update() { int err = ERROR_SUCCESS;
ASSERT(m_tagType == NamedValueSz); ASSERT(m_fModified);
err = g_util.WriteRegSzNamedValue(m_hRoot, (LPCTSTR)m_szKeyPath, (LPCTSTR)m_szValueName, (LPCTSTR)m_szValue, m_szValue.GetLength() + 1); return err; }
long CRegSzNamedValueDp::Read(HKEY hkey) { return 0; }
CString CRegSzNamedValueDp::Value() { return m_szValue; }
CRegSzNamedValueDp::CRegSzNamedValueDp(HKEY hRoot, TCHAR *szKeyPath, TCHAR *szValueName, TCHAR *szValue) : m_szValue(szValue) { m_tagType = NamedValueSz; m_hRoot = hRoot; m_szKeyPath = szKeyPath; m_szValueName = szValueName; }
BOOL CDataPacket::IsIdentifiedBy(HKEY hRoot, TCHAR *szKeyPath, TCHAR *szValueName) { if (((m_tagType == NamedValueSz) && (m_hRoot == hRoot) && (m_szKeyPath == szKeyPath) && (m_szValueName == szValueName)) || ((m_tagType == NamedValueDword) && (m_hRoot == hRoot) && (m_szKeyPath == szKeyPath) && (m_szValueName == szValueName) )) return TRUE;
return FALSE; }
BOOL CRegSzNamedValueDp::IsIdentifiedBy(HKEY hRoot, TCHAR * szKeyPath, TCHAR * szValueName) { if (((m_tagType == NamedValueSz) && (m_hRoot == hRoot) && (m_szKeyPath == szKeyPath) && (m_szValueName == szValueName))) return TRUE;
return FALSE; }
//////////////////////////////////////////////////////////////////////
// CRegMultiSzNamedValueDp Class
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CRegMultiSzNamedValueDp::CRegMultiSzNamedValueDp(HKEY hRoot, TCHAR *szKeyPath, TCHAR *szValueName) { m_tagType = NamedValueMultiSz; m_hRoot = hRoot; m_szKeyPath = szKeyPath; m_szValueName = szValueName; }
CRegMultiSzNamedValueDp::~CRegMultiSzNamedValueDp() {
}
BOOL CRegMultiSzNamedValueDp::IsIdentifiedBy(HKEY hRoot, TCHAR * szKeyPath, TCHAR * szValueName) { if (((m_tagType == NamedValueMultiSz) && (m_hRoot == hRoot) && (m_szKeyPath == szKeyPath) && (m_szValueName == szValueName))) return TRUE;
return FALSE; }
int CRegMultiSzNamedValueDp::Update() { int err = ERROR_SUCCESS;
ASSERT(m_tagType == NamedValueMultiSz); ASSERT(m_fModified);
// build up string to save
// calculate size of string
int nSize=0, nIndex = 0;
for (nIndex = 0; nIndex < m_strValues.GetSize(); nIndex ++) { CString sTmp = m_strValues.GetAt(nIndex); nSize += sTmp.GetLength()+1; } nSize += 2;
// build up string to save
TCHAR* lpszTmp = new TCHAR[nSize]; if (lpszTmp) { int nOffset = 0; for (nIndex = 0; nIndex < m_strValues.GetSize(); nIndex ++) { CString sTmp = m_strValues.GetAt(nIndex); _tcscpy((TCHAR*)(&lpszTmp[nOffset]), (LPCTSTR) sTmp); nOffset += sTmp.GetLength()+1; }
// finish with two nulls
lpszTmp[nOffset++] = TEXT('\0'); lpszTmp[nOffset++] = TEXT('\0'); err = g_util.WriteRegMultiSzNamedValue(m_hRoot, (LPCTSTR)m_szKeyPath, (LPCTSTR)m_szValueName, lpszTmp, nOffset); delete lpszTmp; }
return err; }
void CRegMultiSzNamedValueDp::Clear() { m_strValues.RemoveAll(); }
long CRegMultiSzNamedValueDp::Read(HKEY hKey) { ASSERT(hKey != NULL);
HKEY hkEndpoints = NULL;
DWORD dwType = REG_MULTI_SZ; DWORD dwcbBuffer = 1024; TCHAR* pszBuffer = new TCHAR[1024];
ASSERT(pszBuffer != NULL);
// try to read values into default sized buffer
LONG lErr = RegQueryValueEx(hKey, (LPCTSTR)m_szValueName, 0, &dwType, (LPBYTE)pszBuffer, &dwcbBuffer);
// if buffer is not big enough, extend it and reread
if (lErr == ERROR_MORE_DATA) { delete pszBuffer; DWORD dwNewSize = (dwcbBuffer + 1 / sizeof(TCHAR)); pszBuffer = new TCHAR[dwNewSize]; if (pszBuffer) dwcbBuffer = dwNewSize; lErr = RegQueryValueEx(m_hRoot, (LPCTSTR)m_szValueName, 0, &dwType, (LPBYTE)pszBuffer, &dwcbBuffer); }
if ((lErr == ERROR_SUCCESS) && (dwcbBuffer > 0) && (dwType == REG_MULTI_SZ)) { // parse each string
TCHAR * lpszRegEntry = pszBuffer;
while(lpszRegEntry && *lpszRegEntry) { // caclulate length of entry
CString sTmp(lpszRegEntry); int nLenEntry = sTmp.GetLength(); m_strValues.Add(sTmp);
lpszRegEntry += nLenEntry+1; } } else if ((lErr != ERROR_SUCCESS) && (lErr != ERROR_FILE_NOT_FOUND)) g_util.PostErrorMessage();
delete pszBuffer; SetModified(FALSE);
return lErr; }
|