// cmdcmx.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include "cmdcmx.h"
#include "clsfac.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//this part is only done once
//if you need to use the GUID in another file, just include cmdcmx_guid.h
#define INITGUID
#include <initguid.h>
#include <shlguid.h>
#include "cmdcmx_guid.h"
// g_szExtTitle: Global buffer stores the title string used with DLL registration.
LPCTSTR g_szExtTitle = TEXT("CMDCMX");
// REGSTRUCT: Used to assist in DLL registration.
typedef struct{
HKEY hRootKey;
LPCTSTR lpszSubKey;
LPCTSTR lpszValueName;
LPCTSTR lpszData;
}REGSTRUCT, *LPREGSTRUCT;
// g_DllRefCount: Global reference count to this instance.
UINT g_DllRefCount = NULL;
// CcmdcmxApp
BEGIN_MESSAGE_MAP(CcmdcmxApp, CWinApp)
END_MESSAGE_MAP()
// CcmdcmxApp construction
CcmdcmxApp::CcmdcmxApp()
{
}
CcmdcmxApp::~CcmdcmxApp()
{
}
// The one and only CcmdcmxApp object
CcmdcmxApp theApp;
// CcmdcmxApp initialization
BOOL CcmdcmxApp::InitInstance()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// New instance... start the ref count at 0.
g_DllRefCount = 0;
// Standard WIN32 and MFC init stuff.
InitCommonControls();
CWinApp::InitInstance();
// Some handle magic to make AfxGetResourceHandle() handle work properly.
afxCurrentResourceHandle = afxCurrentInstanceHandle = AfxGetInstanceHandle();
return TRUE;
}
STDAPI DllCanUnloadNow(VOID)
{
return (g_DllRefCount ? S_FALSE : S_OK);
}
STDAPI DllGetClassObject( REFCLSID rclsid, REFIID riid, LPVOID *ppReturn )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
*ppReturn = NULL;
//if we don't support this classid, return the proper error code
if(!IsEqualCLSID(rclsid, CLSID_CMDCMX))
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 decrement 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;
}
STDAPI DllRegisterServer(VOID)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
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_CMDCMX, &pwsz);
if(pwsz)
{
lstrcpy(szCLSID, pwsz);
//free the string
LPMALLOC pMalloc;
CoGetMalloc(1, &pMalloc);
if(pMalloc)
{
pMalloc->Free(pwsz);
pMalloc->Release();
}
}
//get this DLL's path and file name
GetModuleFileName(AfxGetInstanceHandle(), szModule, ARRAYSIZE(szModule));
//register the CLSID entries
REGSTRUCT ClsidEntries[] = { HKEY_CLASSES_ROOT, TEXT("CLSID\\%s"), NULL, g_szExtTitle,
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("CLSID\\%s\\DefaultIcon"), NULL, TEXT("%s,0"),
NULL, NULL, NULL, NULL};
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];
//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) * sizeof(TCHAR));
RegCloseKey(hKey);
}
else
return SELFREG_E_CLASS;
}
// Add the context menu handler for all files.
lstrcpyn( szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\"), ARRAYSIZE(szSubKey));
lstrcat( szSubKey, szCLSID );
lResult = RegCreateKeyEx( HKEY_CLASSES_ROOT,szSubKey,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey,&dwDisp);
if(NOERROR == lResult)
{
TCHAR szData[MAX_PATH];
//Create the value string.
lstrcpyn(szData, g_szExtTitle, ARRAYSIZE(szData));
lResult = RegSetValueEx( hKey,NULL,0,REG_SZ,(LPBYTE)szData,(lstrlen(szData) + 1) * sizeof(TCHAR));
RegCloseKey(hKey);
}
else
return SELFREG_E_CLASS;
// Add the context menu handler for all folders
lstrcpyn( szSubKey, TEXT("Folder\\shellex\\ContextMenuHandlers\\"), ARRAYSIZE(szSubKey));
lstrcat( szSubKey, szCLSID );
lResult = RegCreateKeyEx( HKEY_CLASSES_ROOT,szSubKey,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey,&dwDisp);
if(NOERROR == lResult)
{
TCHAR szData[MAX_PATH];
//Create the value string.
lstrcpyn(szData, g_szExtTitle, ARRAYSIZE(szData));
lResult = RegSetValueEx(hKey,NULL,0,REG_SZ,(LPBYTE)szData,(lstrlen(szData) + 1) * sizeof(TCHAR));
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)
{
lstrcpyn( szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), ARRAYSIZE(szSubKey));
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.
lstrcpyn(szData, g_szExtTitle, ARRAYSIZE(szData));
lResult = RegSetValueEx(hKey,szCLSID,0,REG_SZ,(LPBYTE)szData,(lstrlen(szData) + 1) * sizeof(TCHAR));
RegCloseKey(hKey);
}
else
return SELFREG_E_CLASS;
}
//tell the shell that the folder has been added.
LPITEMIDLIST pidlDesktop, pidlMyComputer;
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidlDesktop);
SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlMyComputer);
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidlDesktop, 0);
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidlMyComputer, 0);
IMalloc *pMalloc;
if(S_OK == SHGetMalloc(&pMalloc))
{
pMalloc->Free(pidlDesktop);
pMalloc->Free(pidlMyComputer);
pMalloc->Release();
}
return S_OK;
}
STDAPI DllUnregisterServer(VOID)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
LPWSTR pwsz;
TCHAR szCLSID[MAX_PATH];
TCHAR szSubKey[MAX_PATH];
//get the CLSID in string form
StringFromIID(CLSID_CMDCMX, &pwsz);
if(pwsz)
{
lstrcpy(szCLSID, pwsz);
//free the string
LPMALLOC pMalloc;
CoGetMalloc(1, &pMalloc);
if(pMalloc)
{
pMalloc->Free(pwsz);
pMalloc->Release();
}
}
else
{
return E_FAIL;
}
//delete the object's registry entries
wsprintf(szSubKey, TEXT("CLSID\\%s"), szCLSID);
SHDeleteKey(HKEY_CLASSES_ROOT, szSubKey);
lstrcpyn( szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\"), ARRAYSIZE(szSubKey));
lstrcat( szSubKey, szCLSID );
SHDeleteKey(HKEY_CLASSES_ROOT, szSubKey);
lstrcpyn( szSubKey, TEXT("Folder\\shellex\\ContextMenuHandlers\\"), ARRAYSIZE(szSubKey));
lstrcat( szSubKey, szCLSID );
SHDeleteKey(HKEY_CLASSES_ROOT, szSubKey);
//delete the approved extensions on NT
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)
{
LRESULT lResult;
HKEY hKey;
lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"),0,KEY_SET_VALUE,&hKey);
if(NOERROR == lResult)
{
TCHAR szData[MAX_PATH];
//Create the value string.
lstrcpyn(szData, g_szExtTitle, ARRAYSIZE(szData));
lResult = RegDeleteValue( hKey, szCLSID);
RegCloseKey(hKey);
}
else
return SELFREG_E_CLASS;
}
//tell the shell that the folder has been removed.
LPITEMIDLIST pidlDesktop, pidlMyComputer;
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidlDesktop);
SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidlMyComputer);
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidlDesktop, 0);
SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidlMyComputer, 0);
IMalloc *pMalloc;
if(S_OK == SHGetMalloc(&pMalloc))
{
pMalloc->Free(pidlDesktop);
pMalloc->Free(pidlMyComputer);
pMalloc->Release();
}
return S_OK;
}
void CcmdcmxApp::ShowError( UINT id, HRESULT hRes, LPCTSTR lpctstrContext )
{
TCHAR szMsg[512] = TEXT("");
if( ::LoadString(AfxGetResourceHandle(), id, szMsg, (sizeof(szMsg)/sizeof(TCHAR))) )
{
TCHAR szErrorMsg[256] = TEXT("");
TCHAR szMsgResult[512] = TEXT("");
if( hRes != ERROR_SUCCESS )
{
ASSERT(lpctstrContext);
if( ::FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, hRes,
MAKELANGID( LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
szErrorMsg, (sizeof(szErrorMsg)/sizeof(TCHAR)), NULL ) )
{
::wsprintf( szMsgResult, szMsg, szErrorMsg, lpctstrContext );
}
else
{
::wsprintf( szMsgResult, szMsg, TEXT("Unknown"), lpctstrContext );
}
::MessageBox( ::GetDesktopWindow(), szMsgResult, g_szExtTitle, MB_OK|MB_ICONSTOP );
}
}
}