Click here to Skip to main content
15,896,453 members
Articles / Programming Languages / C++

Shell extension to make executables as services

Rate me:
Please Sign up or sign in to vote.
3.22/5 (6 votes)
8 Apr 2000 89.3K   1.9K   41  
A 'not-so-simple' shell extension allowing executable to be run as services
#include "mkexesvc.h"
#include "SvcEx.h"
#include "SvcUtils.h"
#include "resource.h"
#include <olectl.h>

typedef struct _REGSTRUCT
{
   HKEY  hRootKey;
   LPTSTR lpszSubKey;
   LPTSTR lpszValueName;
   LPTSTR lpszData;
} REGSTRUCT, *LPREGSTRUCT;

#define ARRAYSIZE(a)    (sizeof(a)/sizeof(a[0]))

extern ULONG		g_cDllRef			= 0L;
extern HINSTANCE	g_hDll				= (HINSTANCE)NULL;

extern HMENU		g_hSubMenu			= (HMENU)NULL;
extern HMENU		g_hLVDepsFloatMenu	= (HMENU)NULL;
extern HIMAGELIST	g_hDepsImageList	= (HIMAGELIST)NULL;

extern DWORD		g_dwLastError		= 0L;

// {ED7F189F-F6CA-4513-9356-8454B8017525}
#ifndef __CLSID_MkExeSvc_Defined__
#define __CLSID_MkExeSvc_Defined__
	DEFINE_GUID(CLSID_MkExeSvc, 0xed7f189f, 0xf6ca, 0x4513, 0x93, 0x56, 0x84, 0x54, 0xb8, 0x1, 0x75, 0x25);
#endif

extern "C" 
int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
	UNREFERENCED_PARAMETER(lpReserved);

    if (dwReason == DLL_PROCESS_ATTACH)
	{
		g_hDll = hInstance;
		LoadResources();
	}
	else if (dwReason == DLL_PROCESS_DETACH)
	{
		UnloadResources();
	}

    return 1;
}

STDAPI 
DllCanUnloadNow(void)
{
    return g_cDllRef == 0 ? S_OK : S_FALSE;
}

STDAPI 
DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)
{
	HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
    *ppvOut = NULL;

    if (IsEqualIID(rclsid, CLSID_MkExeSvc))
    {
        ISvcExClassFactory *pcf = new ISvcExClassFactory;
        hr = pcf->QueryInterface(riid, ppvOut);
    }
	
    return hr;
}

STDAPI 
DllRegisterServer(void)
{
	HINSTANCE hInst = g_hDll;

	int      i;
	HKEY     hKey;
	LRESULT  lResult;
	DWORD    dwDisp;
	TCHAR    szSubKey[MAX_PATH];
	TCHAR    szCLSID[MAX_PATH];
	TCHAR    szModule[MAX_PATH];
	LPWSTR   pwszShellExt;

	StringFromIID(CLSID_MkExeSvc, &pwszShellExt);

	if (pwszShellExt) 
	{
		WideCharToLocal(szCLSID, pwszShellExt, ARRAYSIZE(szCLSID));

		LPMALLOC pMalloc;
		CoGetMalloc(1, &pMalloc);
		if(pMalloc)
		{
			pMalloc->Free(pwszShellExt);
			pMalloc->Release();
		}
	}															   

	GetModuleFileName(hInst, szModule, _MAX_PATH + 1);

	REGSTRUCT ShExClsidEntries[] = 
	{
		HKEY_CLASSES_ROOT,	TEXT("CLSID\\%s"),					NULL,                   TEXT(DLLDESCNAME),
		HKEY_CLASSES_ROOT,	TEXT("CLSID\\%s\\InProcServer32"),	NULL,                   TEXT("%s"),
		HKEY_CLASSES_ROOT,	TEXT("CLSID\\%s\\InProcServer32"),	TEXT("ThreadingModel"), TEXT("Apartment"),
		NULL,                NULL,								NULL,                   NULL
	};

	for(i = 0; ShExClsidEntries[i].hRootKey; i++) 
    {
		wsprintf(szSubKey, ShExClsidEntries[i].lpszSubKey, szCLSID);
		lResult = RegCreateKeyEx(ShExClsidEntries[i].hRootKey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,
			KEY_WRITE, NULL, &hKey, &dwDisp);

		if(NOERROR == lResult) 
		{
			TCHAR szData[MAX_PATH];
			wsprintf(szData, ShExClsidEntries[i].lpszData, szModule);
			lResult = RegSetValueEx(hKey, ShExClsidEntries[i].lpszValueName, 0, REG_SZ, 
				(LPBYTE)szData, lstrlen(szData) + 1);
			RegCloseKey(hKey);
		} 
		else
			return SELFREG_E_CLASS;
   }                                

	//	Other necessary registry entries.
	REGSTRUCT OtherShExEntries[] = 
	{
			HKEY_LOCAL_MACHINE,	TEXT("software\\classes\\clsid\\"DLLDESCNAME)			  , NULL,		TEXT("%s"),
			HKEY_CLASSES_ROOT,	TEXT("exefile\\shellex\\ContextMenuHandlers\\"DLLDESCNAME), NULL,		TEXT("%s"),
			NULL,				NULL,								NULL,                   NULL
	};
	for (i = 0; OtherShExEntries[i].hRootKey; i++) 
    {
		wsprintf(szSubKey, OtherShExEntries[i].lpszSubKey, szCLSID);
		lResult = RegCreateKeyEx(OtherShExEntries[i].hRootKey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,
			KEY_WRITE, NULL, &hKey, &dwDisp);

		if(NOERROR == lResult) 
		{
			TCHAR szData[MAX_PATH];
			wsprintf(szData, OtherShExEntries[i].lpszData, szCLSID);
			lResult = RegSetValueEx(hKey, OtherShExEntries[i].lpszValueName, 0, REG_SZ,
				(LPBYTE)szData, lstrlen(szData) + 1);
			RegCloseKey(hKey);
		} 
		else
			return SELFREG_E_CLASS;
	}

	//	Register extension as 'Approved' under WindowsNT.
	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];
			lstrcpy(szData, DLLDESCNAME);
			lResult = RegSetValueEx(hKey, szCLSID, 0, REG_SZ, (LPBYTE)szData, lstrlen(szData) + 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];
	LPWSTR   pwszShellExt;

	StringFromIID(CLSID_MkExeSvc, &pwszShellExt);
	
	if (pwszShellExt) 
	{
		WideCharToLocal(szCLSID, pwszShellExt, ARRAYSIZE(szCLSID));

		LPMALLOC pMalloc;						  
		CoGetMalloc(1, &pMalloc);

		if(pMalloc)
		{
			pMalloc->Free(pwszShellExt);
			pMalloc->Release();
		}
	}															   
					    
	REGSTRUCT ShExClsidEntries[] = 
	{
		HKEY_CLASSES_ROOT, TEXT("CLSID\\%s\\InProcServer32"), NULL, NULL,
		HKEY_CLASSES_ROOT, TEXT("CLSID\\%s"), NULL, NULL,
		NULL, NULL, NULL, NULL
	};

	for(i = 0; ShExClsidEntries[i].hRootKey; i++) 
	{
		wsprintf(szSubKey, ShExClsidEntries[i].lpszSubKey, szCLSID);
		lResult = RegDeleteKey(ShExClsidEntries[i].hRootKey, szSubKey);
																			 
		if(lResult != NOERROR) 
			return SELFREG_E_CLASS;
	}

	REGSTRUCT OtherShExEntries[] = 
	{
			HKEY_CLASSES_ROOT,	TEXT("exefile\\shellex\\ContextMenuHandlers\\"DLLDESCNAME), NULL,		NULL,
			NULL,				NULL,								NULL,                   NULL
	};

	for(i = 0; OtherShExEntries[i].hRootKey; i++) 
	{
		wsprintf(szSubKey, OtherShExEntries[i].lpszSubKey, szCLSID);
		lResult = RegDeleteKey(OtherShExEntries[i].hRootKey, szSubKey);
		if(lResult != NOERROR) 
			return SELFREG_E_CLASS;
	}

	OSVERSIONINFO  osvi;
	osvi.dwOSVersionInfoSize = sizeof(osvi);
	GetVersionEx(&osvi);
	if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId)  
	{
		HKEY hkShExApproved;
		lResult = RegOpenKey(HKEY_LOCAL_MACHINE, 
			TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"), &hkShExApproved);
		if(lResult == NO_ERROR)
		{
			lResult = RegDeleteValue(hkShExApproved, szCLSID);
			RegCloseKey(hkShExApproved);
		}

		if(lResult != NOERROR)
			return SELFREG_E_CLASS;
	}

	return S_OK;
}

void 
LoadResources(void)
{
	INITCOMMONCONTROLSEX iccEx;

	iccEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
	iccEx.dwICC	 = 
		ICC_LISTVIEW_CLASSES	|	//	list view
		ICC_PROGRESS_CLASS		|	//	progress bar
		ICC_TREEVIEW_CLASSES	|	//	tree view & tooltip
		ICC_BAR_CLASSES			|	//	toolbar, status bar, trackbar & tooltip
		ICC_UPDOWN_CLASS		|	//	up-down
		ICC_USEREX_CLASSES		|	//	extended combo box 
		ICC_TAB_CLASSES 		|	//	tab & tooltip
		ICC_COOL_CLASSES		|	//	rebar
		0;
	InitCommonControlsEx(&iccEx);

	if(g_hSubMenu == (HMENU)NULL)
	{
		g_hSubMenu = CreateMenu();
	}

	if(g_hLVDepsFloatMenu == (HMENU)NULL)
	{
		g_hLVDepsFloatMenu = LoadMenu(g_hDll, MAKEINTRESOURCE(IDM_LVDEPSUPDOWN));
	}

	if(g_hDepsImageList == (HIMAGELIST)NULL)
	{
		g_hDepsImageList = 
			ImageList_LoadImage
			(
				g_hDll, 
				MAKEINTRESOURCE(IDB_DEPS), 
				16, 
				0, 
				(COLORREF)(RGB(255, 255, 255)), 
				IMAGE_BITMAP, 
				LR_LOADTRANSPARENT
			);
	}
}

void 
UnloadResources(void)
{
	if(g_hSubMenu)
	{
		DestroyMenu(g_hSubMenu);
		g_hSubMenu = (HMENU)NULL;
	}

	if(g_hLVDepsFloatMenu)
	{
		DestroyMenu(g_hLVDepsFloatMenu);
		g_hLVDepsFloatMenu = (HMENU)NULL;
	}

	if(g_hDepsImageList)
	{
		ImageList_Destroy(g_hDepsImageList);
		g_hDepsImageList = (HIMAGELIST)NULL;
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Romania Romania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions