Helpers
Actually these are more suitable for interfaces, but hopefully good for other objects too needing auto-deletion on getting out-of-scope.
template<typename T>
class AutoDeleteHlp
{
typedef T _Item;
public:
AutoDeleteHlp(T t)
{
m_T = t;
}
~AutoDeleteHlp()
{}
operator T ()
{
return m_T;
}
operator T *()
{
return (T *)&m_T;
}
virtual operator bool()
{
return (m_T != NULL) ? true : false;
}
T **operator &()
{
return &m_T;
}
T *Get()
{
return m_T;
}
void Set(T t)
{
m_T = t;
}
private:
virtual void Delete() = 0;
protected:
T m_T;
};
The (incomplete) registry key helper
class RegKey_ : public AutoDeleteHlp<HKEY>
{
public:
RegKey_(HKEY hk = 0)
: AutoDeleteHlp<HKEY>(hk)
{}
~RegKey_()
{
Delete();
}
LONG Open(HKEY hKey, LPCTSTR lpSubkeyName, REGSAM regSam = KEY_READ)
{
return ::RegOpenKeyEx(hKey, lpSubkeyName, 0, regSam, &m_T);
}
LONG ReadString(LPTSTR lpString, DWORD cbData,
LPCTSTR lpValName = _T(""))
{
DWORD dwType;
return ::RegQueryValueEx(m_T, lpValName, NULL,
&dwType, (LPBYTE)lpString, &cbData);
}
LONG Read(LPBYTE lpData, DWORD cbData, LPCTSTR lpValName = _T(""))
{
DWORD dwType;
return ::RegQueryValueEx(m_T, lpValName, NULL,
&dwType, (LPBYTE)lpData, &cbData);
}
private:
virtual void Delete()
{
if(m_T)
{
_Item hk = m_T;
m_T = 0;
if(::RegCloseKey(hk))
{
hk = NULL;
}
}
}
};
...the CreateProcess
wrapper (for executing a command line):
class CmdLineExec_
{
private:
STARTUPINFO m_si;
PROCESS_INFORMATION m_pi;
TCHAR m_lpCmdLine[_MAX_PATH + 1];
public:
CmdLineExec_(LPCTSTR lpCmdLine)
{
ZeroMemory(&m_si, sizeof(STARTUPINFO));
ZeroMemory(&m_pi, sizeof(PROCESS_INFORMATION));
if(lpCmdLine != NULL)
{
lstrcpyn(m_lpCmdLine, lpCmdLine, _MAX_PATH + 1);
}
else
{
lstrcpyn(m_lpCmdLine, _T(""), _MAX_PATH + 1);
}
}
~CmdLineExec_()
{
if(m_pi.hProcess)
{
CloseHandle(m_pi.hProcess);
}
if(m_pi.hThread)
{
CloseHandle(m_pi.hThread);
}
}
public:
BOOL Execute(DWORD *pdwLastError = NULL)
{
BOOL fRet = CreateProcess(NULL, (LPTSTR)m_lpCmdLine, NULL,
NULL, FALSE, 0, NULL, NULL, &m_si, &m_pi);
if(pdwLastError != NULL)
{
*pdwLastError = GetLastError();
}
return fRet;
}
};
... and finally the default mail client wrapper:
class DefaultMailClient_ : public RegKey_
{
private:
TCHAR m_szDefMailClient[_MAX_PATH + 1];
BOOL m_fValid;
public:
TCHAR m_szDefMailCmd[_MAX_PATH + 1];
public:
DefaultMailClient_(HKEY hk = 0)
: RegKey_(hk)
{
lstrcpyn(m_szDefMailClient, _T("SOFTWARE\\Clients\\Mail"),
_MAX_PATH);
lstrcpyn(m_szDefMailCmd, _T(""), _MAX_PATH);
m_fValid = GetCmdLine();
}
~DefaultMailClient_()
{
Delete();
}
public:
BOOL IsValid()
{
return m_fValid;
}
BOOL Execute()
{
CmdLineExec_ cmdl(m_szDefMailCmd);
return cmdl.Execute();
}
protected:
BOOL GetCmdLine()
{
LONG retval;
retval = Open(HKEY_LOCAL_MACHINE, m_szDefMailClient);
if(retval == NO_ERROR)
{
DWORD cbData = _MAX_PATH;
retval = ReadString(m_szDefMailClient, cbData);
if(retval == NO_ERROR)
{
TCHAR szCmdLine[_MAX_PATH + 1];
lstrcpyn(szCmdLine, _T("SOFTWARE\\Clients\\Mail\\"),
_MAX_PATH + 1);
_tcsncat(szCmdLine, m_szDefMailClient, _MAX_PATH + 1);
_tcsncat(szCmdLine, _T(\\shell\\open\\command),
_MAX_PATH + 1);
RegKey_ rk;
if(rk.Open(HKEY_LOCAL_MACHINE, szCmdLine) == NO_ERROR)
{
retval = rk.ReadString(m_szDefMailCmd, _MAX_PATH);
if(retval == NO_ERROR)
{
return TRUE;
}
}
}
}
return FALSE;
}
private:
virtual void Delete()
{
if(m_T)
{
_Item hk = m_T;
m_T = 0;
if(::RegCloseKey(hk))
{
hk = NULL;
}
}
}
};
Calling routine
void OpenDefaultMailClient()
{
DefaultMailClient_ dmcl;
if(dmcl.IsValid())
{
if(!dmcl.Execute())
{
MessageBox(NULL,
_T("Could not launch the default mail client."),
NULL, MB_OK);
}
}
}
main
simply calls this function:
void main()
{
OpenDefaultMailClient();
}
For convenience, the dsw and dsp files are included, and also the makefile. For a single-file project, open a console and execute :-
...> nmake /f dmcl.mak
Conclusion
That's it. Keep it simple. Use the function instead of digging registry yourself (like I did). Tested on Windows 2000 SP3. Let me know if you have problems on other platforms.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.