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.
490 lines
11 KiB
490 lines
11 KiB
#include "pch.hxx"
|
|
#include "strconst.h"
|
|
#include <mimeole.h>
|
|
#include <imnact.h>
|
|
#include "imsgcont.h"
|
|
#include <goptions.h>
|
|
#include <thormsgs.h>
|
|
#include "sigs.h"
|
|
#include <shlwapi.h>
|
|
#undef _INC_GOPTIONS_H
|
|
#define DEFINE_OPTION_STRUCTS
|
|
#include <goptions.h>
|
|
#include "demand.h"
|
|
#include "multiusr.h"
|
|
|
|
IOptionBucketEx *g_pOpt = NULL;
|
|
COptNotify *g_pOptNotify = NULL;
|
|
|
|
BOOL g_fBadShutdown = FALSE;
|
|
|
|
static OPTBCKTINIT g_init =
|
|
{
|
|
c_rgOptInfo,
|
|
ARRAYSIZE(c_rgOptInfo),
|
|
|
|
HKEY_CURRENT_USER,
|
|
c_szRegRoot,
|
|
c_rgszOptRegKey,
|
|
COPTREGKEY
|
|
};
|
|
|
|
BOOL InitGlobalOptions(HKEY hkey, LPCSTR szRegOptRoot)
|
|
{
|
|
OPTBCKTINIT init;
|
|
LPCOPTBCKTINIT pinit;
|
|
HRESULT hr;
|
|
|
|
Assert(NULL == g_pOpt);
|
|
Assert(NULL == g_pOptNotify);
|
|
|
|
g_init.hkey = MU_GetCurrentUserHKey();
|
|
|
|
IF_NULLEXIT(g_pOptNotify = new COptNotify);
|
|
|
|
IF_FAILEXIT(hr = CreateOptionBucketEx(&g_pOpt));
|
|
pinit = &g_init;
|
|
|
|
if (NULL != hkey)
|
|
{
|
|
Assert(NULL != szRegOptRoot);
|
|
init = g_init;
|
|
init.hkey = hkey;
|
|
init.pszRegKeyBase = szRegOptRoot;
|
|
pinit = &init;
|
|
}
|
|
|
|
IF_FAILEXIT(hr = g_pOpt->Initialize(pinit));
|
|
IF_FAILEXIT(hr = g_pOpt->SetNotification((IOptionBucketNotify *)g_pOptNotify));
|
|
|
|
// signature manager
|
|
IF_FAILEXIT(hr = InitSignatureManager(pinit->hkey, pinit->pszRegKeyBase));
|
|
|
|
// if the running regkey is still there, we shut down badly
|
|
g_fBadShutdown = DwGetOption(OPT_ATHENA_RUNNING);
|
|
SetDwOption(OPT_ATHENA_RUNNING, TRUE, NULL, 0);
|
|
|
|
exit:
|
|
return (S_OK == hr);
|
|
}
|
|
|
|
void DeInitGlobalOptions(void)
|
|
{
|
|
|
|
if (NULL != g_pOpt)
|
|
{
|
|
SetDwOption(OPT_ATHENA_RUNNING, FALSE, NULL, 0);
|
|
g_pOpt->Release();
|
|
g_pOpt = NULL;
|
|
}
|
|
|
|
if (NULL != g_pOptNotify)
|
|
{
|
|
g_pOptNotify->Release();
|
|
g_pOptNotify = NULL;
|
|
}
|
|
|
|
DeinitSignatureManager();
|
|
}
|
|
|
|
DWORD DwGetOption(PROPID id)
|
|
{
|
|
Assert(NULL != g_pOpt);
|
|
|
|
return(IDwGetOption(g_pOpt, id));
|
|
}
|
|
|
|
DWORD DwGetOptionDefault(PROPID id)
|
|
{
|
|
Assert(NULL != g_pOpt);
|
|
|
|
return(IDwGetOptionDefault(g_pOpt, id));
|
|
}
|
|
|
|
DWORD GetOption(PROPID id, void *pv, DWORD cb)
|
|
{
|
|
Assert(NULL != g_pOpt);
|
|
|
|
return(IGetOption(g_pOpt, id, pv, cb));
|
|
}
|
|
|
|
DWORD IDwGetOption(IOptionBucketEx *pOpt, PROPID id)
|
|
{
|
|
PROPVARIANT var;
|
|
HRESULT hr;
|
|
DWORD dw = 0;
|
|
|
|
Assert(NULL != pOpt);
|
|
|
|
// special case attachment checks to allow for ADM setting of group policy
|
|
if ((id == OPT_SECURITY_ATTACHMENT) || (id == OPT_SECURITY_ATTACHMENT_LOCKED))
|
|
{
|
|
HKEY hkey;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegFlat, 0, KEY_READ, &hkey))
|
|
{
|
|
DWORD dwVal, cb;
|
|
|
|
cb = sizeof(dwVal);
|
|
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szBlockAttachments, 0, NULL, (LPBYTE)&dwVal, &cb))
|
|
{
|
|
// if set then unsafe attachments are both locked and also disallowed
|
|
if (dwVal == 1)
|
|
dw = 1;
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
}
|
|
|
|
if (!dw)
|
|
{
|
|
IF_FAILEXIT(hr = pOpt->GetProperty(MAKEPROPSTRING(id), &var, 0));
|
|
|
|
Assert(VT_UI4 == var.vt);
|
|
dw = var.ulVal;
|
|
}
|
|
|
|
exit:
|
|
return(dw);
|
|
}
|
|
|
|
DWORD IDwGetOptionDefault(IOptionBucketEx *pOpt, PROPID id)
|
|
{
|
|
PROPVARIANT var;
|
|
HRESULT hr;
|
|
DWORD dw = 0;
|
|
|
|
Assert(pOpt != NULL);
|
|
IF_FAILEXIT(hr = pOpt->GetPropertyDefault(id, &var, 0));
|
|
|
|
Assert(var.vt == VT_UI4);
|
|
dw = var.ulVal;
|
|
|
|
exit:
|
|
return(dw);
|
|
}
|
|
|
|
DWORD IGetOption(IOptionBucketEx *pOpt, PROPID id, void *pv, DWORD cb)
|
|
{
|
|
PROPVARIANT var;
|
|
HRESULT hr = S_OK;
|
|
DWORD cbT = 0;
|
|
LPBYTE pByte = NULL;
|
|
|
|
Assert(NULL != pOpt);
|
|
IF_FAILEXIT(hr = pOpt->GetProperty(MAKEPROPSTRING(id), &var, 0));
|
|
|
|
switch (var.vt)
|
|
{
|
|
case VT_LPSTR:
|
|
pByte = (LPBYTE)var.pszVal;
|
|
cbT = lstrlen(var.pszVal) + 1;
|
|
break;
|
|
|
|
case VT_LPWSTR:
|
|
pByte = (LPBYTE)var.pwszVal;
|
|
cbT = (lstrlenW(var.pwszVal) + 1) * sizeof(WCHAR);
|
|
break;
|
|
|
|
case VT_BLOB:
|
|
pByte = (LPBYTE)var.blob.pBlobData;
|
|
cbT = var.blob.cbSize;
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE);
|
|
IF_FAILEXIT(hr = E_FAIL);
|
|
break;
|
|
}
|
|
|
|
if (cb >= cbT && pByte)
|
|
CopyMemory(pv, pByte, cbT);
|
|
else
|
|
IF_FAILEXIT(hr = E_FAIL);
|
|
|
|
exit:
|
|
MemFree(pByte);
|
|
|
|
return (SUCCEEDED(hr) ? cbT : 0);
|
|
}
|
|
|
|
BOOL SetDwOption(PROPID id, DWORD dw, HWND hwnd, DWORD dwFlags)
|
|
{
|
|
Assert(NULL != g_pOpt);
|
|
|
|
return(ISetOption(g_pOpt, id, &dw, sizeof(DWORD), hwnd, dwFlags));
|
|
}
|
|
|
|
BOOL SetOption(PROPID id, void *pv, DWORD cb, HWND hwnd, DWORD dwFlags)
|
|
{
|
|
Assert(NULL != g_pOpt);
|
|
|
|
return(ISetOption(g_pOpt, id, pv, cb, hwnd, dwFlags));
|
|
}
|
|
|
|
BOOL ISetDwOption(IOptionBucketEx *pOpt, PROPID id, DWORD dw, HWND hwnd, DWORD dwFlags)
|
|
{
|
|
Assert(NULL != pOpt);
|
|
|
|
return(ISetOption(pOpt, id, &dw, sizeof(DWORD), hwnd, dwFlags));
|
|
}
|
|
|
|
BOOL ISetOption(IOptionBucketEx *pOpt, PROPID id, void *pv, DWORD cb, HWND hwnd, DWORD dwFlags)
|
|
{
|
|
HRESULT hr;
|
|
PROPINFO info;
|
|
PROPVARIANT var;
|
|
|
|
Assert(NULL != pOpt);
|
|
Assert(NULL != pv);
|
|
|
|
info.cbSize = sizeof(info);
|
|
IF_FAILEXIT(hr = pOpt->GetPropertyInfo(id, &info, 0));
|
|
|
|
var.vt = info.vt;
|
|
|
|
switch(var.vt)
|
|
{
|
|
case VT_UI4:
|
|
var.ulVal = *((DWORD *)pv);
|
|
break;
|
|
|
|
case VT_LPSTR:
|
|
var.pszVal = (LPSTR)pv;
|
|
break;
|
|
|
|
case VT_LPWSTR:
|
|
var.pwszVal = (LPWSTR)pv;
|
|
break;
|
|
|
|
case VT_BLOB:
|
|
var.blob.cbSize = cb;
|
|
var.blob.pBlobData = (BYTE *)pv;
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE);
|
|
IF_FAILEXIT(hr = E_FAIL);
|
|
break;
|
|
}
|
|
|
|
IF_FAILEXIT(hr = pOpt->ISetProperty(hwnd, MAKEPROPSTRING(id), &var, dwFlags));
|
|
|
|
// TODO: notify option objects that option changed
|
|
|
|
exit:
|
|
return(SUCCEEDED(hr));
|
|
}
|
|
|
|
HRESULT OptionAdvise(HWND hwnd)
|
|
{
|
|
Assert(NULL != g_pOptNotify);
|
|
return(g_pOptNotify->Register(hwnd));
|
|
}
|
|
|
|
HRESULT OptionUnadvise(HWND hwnd)
|
|
{
|
|
Assert(NULL != g_pOptNotify);
|
|
return(g_pOptNotify->Unregister(hwnd));
|
|
}
|
|
|
|
COptNotify::COptNotify(void)
|
|
{
|
|
m_cRef = 1;
|
|
m_cHwnd = 0;
|
|
m_cHwndBuf = 0;
|
|
m_rgHwnd = NULL;
|
|
}
|
|
|
|
COptNotify::~COptNotify(void)
|
|
{
|
|
MemFree(m_rgHwnd);
|
|
}
|
|
|
|
STDMETHODIMP COptNotify::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
if (NULL == ppv)
|
|
return(E_INVALIDARG);
|
|
|
|
if (IID_IUnknown == riid)
|
|
{
|
|
*ppv = (IUnknown *)this;
|
|
}
|
|
else if (IID_IOptionBucketNotify == riid)
|
|
{
|
|
*ppv = (IOptionBucketNotify *)this;
|
|
}
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return(E_NOINTERFACE);
|
|
}
|
|
|
|
((IUnknown *)*ppv)->AddRef();
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COptNotify::AddRef(void)
|
|
{
|
|
return((ULONG)InterlockedIncrement(&m_cRef));
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) COptNotify::Release(void)
|
|
{
|
|
LONG cRef = InterlockedDecrement(&m_cRef);
|
|
if (0 == cRef)
|
|
delete this;
|
|
return((ULONG)cRef);
|
|
}
|
|
|
|
#define CADVISEOPT 32
|
|
|
|
HRESULT COptNotify::Register(HWND hwnd)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int cbuf;
|
|
|
|
if (m_cHwnd == m_cHwndBuf)
|
|
{
|
|
cbuf = m_cHwndBuf + CADVISEOPT;
|
|
IF_NULLEXIT(MemRealloc((void **)&m_rgHwnd, sizeof(HWND) * cbuf));
|
|
m_cHwndBuf = cbuf;
|
|
}
|
|
|
|
Assert(m_rgHwnd != NULL);
|
|
m_rgHwnd[m_cHwnd] = hwnd;
|
|
m_cHwnd++;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT COptNotify::Unregister(HWND hwnd)
|
|
{
|
|
int index = 0;
|
|
|
|
while (index < m_cHwnd)
|
|
{
|
|
if (m_rgHwnd[index] == hwnd)
|
|
break;
|
|
index++;
|
|
}
|
|
if (index >= m_cHwnd)
|
|
return (E_FAIL);
|
|
|
|
if (m_cHwnd == 1)
|
|
{
|
|
MemFree(m_rgHwnd);
|
|
m_rgHwnd = NULL;
|
|
m_cHwndBuf = 0;
|
|
}
|
|
else
|
|
{
|
|
while (index < m_cHwnd)
|
|
{
|
|
m_rgHwnd[index] = m_rgHwnd[index+1];
|
|
index++;
|
|
}
|
|
}
|
|
m_cHwnd--;
|
|
|
|
return (S_OK);
|
|
}
|
|
|
|
STDMETHODIMP COptNotify::DoNotification(IOptionBucketEx *pBckt, HWND hwnd, PROPID id)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < m_cHwnd; i++)
|
|
{
|
|
if (hwnd != m_rgHwnd[i] && IsWindow(m_rgHwnd[i]))
|
|
PostMessage(m_rgHwnd[i], CM_OPTIONADVISE, id, 0);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
void GetUserKeyPath(LPCSTR lpSubKey, LPSTR sz, int cch)
|
|
{
|
|
Assert(sz != NULL);
|
|
Assert(cch >= MAX_PATH);
|
|
|
|
LPCTSTR pszUserRoot = c_szRegRoot;
|
|
|
|
if (lpSubKey == NULL)
|
|
StrCpyN(sz, pszUserRoot, cch);
|
|
else
|
|
wnsprintf(sz, cch, c_szPathFileFmt, pszUserRoot, lpSubKey);
|
|
}
|
|
|
|
LONG AthUserCreateKey(LPCSTR lpSubKey, REGSAM samDesired, PHKEY phkResult, LPDWORD lpdwDisposition)
|
|
{
|
|
char sz[MAX_PATH];
|
|
|
|
GetUserKeyPath(lpSubKey, sz, ARRAYSIZE(sz));
|
|
|
|
return(RegCreateKeyEx(MU_GetCurrentUserHKey(), sz, 0, NULL, REG_OPTION_NON_VOLATILE,
|
|
samDesired, NULL, phkResult, lpdwDisposition));
|
|
}
|
|
|
|
LONG AthUserOpenKey(LPCSTR lpSubKey, REGSAM samDesired, PHKEY phkResult)
|
|
{
|
|
char sz[MAX_PATH];
|
|
|
|
GetUserKeyPath(lpSubKey, sz, ARRAYSIZE(sz));
|
|
|
|
return(RegOpenKeyEx(MU_GetCurrentUserHKey(), sz, 0, samDesired, phkResult));
|
|
}
|
|
|
|
LONG AthUserDeleteKey(LPCSTR lpSubKey)
|
|
{
|
|
char sz[MAX_PATH];
|
|
|
|
GetUserKeyPath(lpSubKey, sz, ARRAYSIZE(sz));
|
|
|
|
return(SHDeleteKey(MU_GetCurrentUserHKey(), sz));
|
|
}
|
|
|
|
LONG AthUserGetValue(LPCSTR lpSubKey, LPCSTR lpValueName, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
|
|
{
|
|
char sz[MAX_PATH];
|
|
|
|
GetUserKeyPath(lpSubKey, sz, ARRAYSIZE(sz));
|
|
|
|
return(SHGetValue(MU_GetCurrentUserHKey(), sz, lpValueName, lpType, lpData, lpcbData));
|
|
}
|
|
|
|
LONG AthUserSetValue(LPCSTR lpSubKey, LPCSTR lpValueName, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
|
|
{
|
|
char sz[MAX_PATH];
|
|
|
|
GetUserKeyPath(lpSubKey, sz, ARRAYSIZE(sz));
|
|
|
|
return(SHSetValue(MU_GetCurrentUserHKey(), sz, lpValueName, dwType, lpData, cbData));
|
|
}
|
|
|
|
LONG AthUserDeleteValue(LPCSTR lpSubKey, LPCSTR lpValueName)
|
|
{
|
|
char sz[MAX_PATH];
|
|
|
|
GetUserKeyPath(lpSubKey, sz, ARRAYSIZE(sz));
|
|
|
|
return(SHDeleteValue(MU_GetCurrentUserHKey(), sz, lpValueName));
|
|
}
|
|
|
|
HKEY AthUserGetKeyRoot(void)
|
|
{
|
|
return(MU_GetCurrentUserHKey());
|
|
}
|
|
|
|
void AthUserGetKeyPath(LPSTR szKey, int cch)
|
|
{
|
|
Assert(cch >= MAX_PATH);
|
|
|
|
LPCTSTR pszRegRoot = c_szRegRoot;
|
|
Assert(pszRegRoot);
|
|
|
|
StrCpyN(szKey, pszRegRoot, cch);
|
|
}
|