mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
399 lines
9.6 KiB
D
399 lines
9.6 KiB
D
|
|
/*
|
|
* Hello Object DLL Self-Registering Server
|
|
* Heavily modified from:
|
|
*/
|
|
/*
|
|
* SELFREG.CPP
|
|
* Server Self-Registrtation Utility, Chapter 5
|
|
*
|
|
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
|
|
*
|
|
* Kraig Brockschmidt, Microsoft
|
|
* Internet : kraigb@microsoft.com
|
|
* Compuserve: >INTERNET:kraigb@microsoft.com
|
|
*/
|
|
|
|
import core.stdc.stdio;
|
|
import core.stdc.stdlib;
|
|
import core.stdc.string;
|
|
import std.string;
|
|
import core.sys.windows.com;
|
|
import core.sys.windows.winbase;
|
|
import core.sys.windows.windef;
|
|
import core.sys.windows.winreg;
|
|
|
|
import chello;
|
|
|
|
// This class factory object creates Hello objects.
|
|
|
|
class CHelloClassFactory : ComObject, IClassFactory
|
|
{
|
|
public:
|
|
this()
|
|
{
|
|
printf("CHelloClassFactory()\n");
|
|
}
|
|
|
|
~this()
|
|
{
|
|
printf("~CHelloClassFactory()");
|
|
}
|
|
|
|
extern (Windows) :
|
|
|
|
// IUnknown members
|
|
override HRESULT QueryInterface(const (IID)*riid, LPVOID *ppv)
|
|
{
|
|
printf("CHelloClassFactory.QueryInterface()\n");
|
|
|
|
if (IID_IUnknown == *riid)
|
|
{
|
|
printf("IUnknown\n");
|
|
*ppv = cast(void*) cast(IUnknown) this;
|
|
}
|
|
else if (IID_IClassFactory == *riid)
|
|
{
|
|
printf("IClassFactory\n");
|
|
*ppv = cast(void*) cast(IClassFactory) this;
|
|
}
|
|
else
|
|
{
|
|
*ppv = null;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
// IClassFactory members
|
|
override HRESULT CreateInstance(IUnknown pUnkOuter, IID*riid, LPVOID *ppvObj)
|
|
{
|
|
CHello pObj;
|
|
HRESULT hr;
|
|
|
|
printf("CHelloClassFactory.CreateInstance()\n");
|
|
*ppvObj = null;
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
// Verify that a controlling unknown asks for IUnknown
|
|
if (null !is pUnkOuter && memcmp(&IID_IUnknown, riid, IID.sizeof))
|
|
return CLASS_E_NOAGGREGATION;
|
|
|
|
// Create the object passing function to notify on destruction.
|
|
pObj = new CHello(pUnkOuter, &ObjectDestroyed);
|
|
|
|
if (!pObj)
|
|
return hr;
|
|
|
|
if (pObj.Init())
|
|
{
|
|
hr = pObj.QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
// Kill the object if initial creation or Init failed.
|
|
if (FAILED(hr))
|
|
delete pObj;
|
|
else
|
|
g_cObj++;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT LockServer(BOOL fLock)
|
|
{
|
|
printf("CHelloClassFactory.LockServer(%d)\n", fLock);
|
|
|
|
if (fLock)
|
|
g_cLock++;
|
|
else
|
|
g_cLock--;
|
|
|
|
return NOERROR;
|
|
}
|
|
};
|
|
|
|
// Count number of objects and number of locks.
|
|
ULONG g_cObj =0;
|
|
ULONG g_cLock=0;
|
|
|
|
import core.sys.windows.dll;
|
|
HINSTANCE g_hInst;
|
|
|
|
extern (Windows):
|
|
|
|
BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
|
|
{
|
|
switch (ulReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
g_hInst = hInstance;
|
|
dll_process_attach( hInstance, true );
|
|
printf("ATTACH\n");
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
printf("DETACH\n");
|
|
dll_process_detach( hInstance, true );
|
|
break;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
dll_thread_attach( true, true );
|
|
printf("THREAD_ATTACH\n");
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
dll_thread_detach( true, true );
|
|
printf("THREAD_DETACH\n");
|
|
break;
|
|
|
|
default:
|
|
assert(0);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* DllGetClassObject
|
|
*
|
|
* Purpose:
|
|
* Provides an IClassFactory for a given CLSID that this DLL is
|
|
* registered to support. This DLL is placed under the CLSID
|
|
* in the registration database as the InProcServer.
|
|
*
|
|
* Parameters:
|
|
* clsID REFCLSID that identifies the class factory
|
|
* desired. Since this parameter is passed this
|
|
* DLL can handle any number of objects simply
|
|
* by returning different class factories here
|
|
* for different CLSIDs.
|
|
*
|
|
* riid REFIID specifying the interface the caller wants
|
|
* on the class object, usually IID_ClassFactory.
|
|
*
|
|
* ppv LPVOID * in which to return the interface
|
|
* pointer.
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR on success, otherwise an error code.
|
|
*/
|
|
HRESULT DllGetClassObject(CLSID*rclsid, IID*riid, LPVOID *ppv)
|
|
{
|
|
HRESULT hr;
|
|
CHelloClassFactory pObj;
|
|
|
|
printf("DllGetClassObject()\n");
|
|
|
|
if (CLSID_Hello != *rclsid)
|
|
return E_FAIL;
|
|
|
|
pObj = new CHelloClassFactory();
|
|
|
|
if (!pObj)
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = pObj.QueryInterface(riid, ppv);
|
|
|
|
if (FAILED(hr))
|
|
delete pObj;
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
* Answers if the DLL can be freed, that is, if there are no
|
|
* references to anything this DLL provides.
|
|
*
|
|
* Return Value:
|
|
* BOOL true if nothing is using us, false otherwise.
|
|
*/
|
|
HRESULT DllCanUnloadNow()
|
|
{
|
|
SCODE sc;
|
|
|
|
printf("DllCanUnloadNow()\n");
|
|
|
|
// Any locks or objects?
|
|
sc = (0 == g_cObj && 0 == g_cLock) ? S_OK : S_FALSE;
|
|
return sc;
|
|
}
|
|
|
|
/*
|
|
* Instructs the server to create its own registry entries
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR if registration successful, error
|
|
* otherwise.
|
|
*/
|
|
HRESULT DllRegisterServer()
|
|
{
|
|
char[128] szID;
|
|
char[128] szCLSID;
|
|
char[512] szModule;
|
|
|
|
printf("DllRegisterServer()\n");
|
|
|
|
// Create some base key strings.
|
|
StringFromGUID2(&CLSID_Hello, cast(LPOLESTR) szID, 128);
|
|
unicode2ansi(szID.ptr);
|
|
strcpy(szCLSID.ptr, "CLSID\\");
|
|
strcat(szCLSID.ptr, szID.ptr);
|
|
|
|
// Create ProgID keys
|
|
SetKeyAndValue("Hello1.0", null, "Hello Object");
|
|
SetKeyAndValue("Hello1.0", "CLSID", szID.ptr);
|
|
|
|
// Create VersionIndependentProgID keys
|
|
SetKeyAndValue("Hello", null, "Hello Object");
|
|
SetKeyAndValue("Hello", "CurVer", "Hello1.0");
|
|
SetKeyAndValue("Hello", "CLSID", szID.ptr);
|
|
|
|
// Create entries under CLSID
|
|
SetKeyAndValue(szCLSID.ptr, null, "Hello Object");
|
|
SetKeyAndValue(szCLSID.ptr, "ProgID", "Hello1.0");
|
|
SetKeyAndValue(szCLSID.ptr, "VersionIndependentProgID", "Hello");
|
|
SetKeyAndValue(szCLSID.ptr, "NotInsertable", null);
|
|
|
|
GetModuleFileNameA(g_hInst, szModule.ptr, szModule.length);
|
|
|
|
SetKeyAndValue(szCLSID.ptr, "InprocServer32", szModule.ptr);
|
|
return NOERROR;
|
|
}
|
|
|
|
/*
|
|
* Purpose:
|
|
* Instructs the server to remove its own registry entries
|
|
*
|
|
* Return Value:
|
|
* HRESULT NOERROR if registration successful, error
|
|
* otherwise.
|
|
*/
|
|
HRESULT DllUnregisterServer()
|
|
{
|
|
char[128] szID;
|
|
char[128] szCLSID;
|
|
char[256] szTemp;
|
|
|
|
printf("DllUnregisterServer()\n");
|
|
|
|
// Create some base key strings.
|
|
StringFromGUID2(&CLSID_Hello, cast(LPOLESTR) szID, 128);
|
|
unicode2ansi(szID.ptr);
|
|
strcpy(szCLSID.ptr, "CLSID\\");
|
|
strcat(szCLSID.ptr, szID.ptr);
|
|
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello\\CurVer");
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello\\CLSID");
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello");
|
|
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello1.0\\CLSID");
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, "Hello1.0");
|
|
|
|
strcpy(szTemp.ptr, szCLSID.ptr);
|
|
strcat(szTemp.ptr, "\\");
|
|
strcat(szTemp.ptr, "ProgID");
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, szTemp.ptr);
|
|
|
|
strcpy(szTemp.ptr, szCLSID.ptr);
|
|
strcat(szTemp.ptr, "\\");
|
|
strcat(szTemp.ptr, "VersionIndependentProgID");
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, szTemp.ptr);
|
|
|
|
strcpy(szTemp.ptr, szCLSID.ptr);
|
|
strcat(szTemp.ptr, "\\");
|
|
strcat(szTemp.ptr, "NotInsertable");
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, szTemp.ptr);
|
|
|
|
strcpy(szTemp.ptr, szCLSID.ptr);
|
|
strcat(szTemp.ptr, "\\");
|
|
strcat(szTemp.ptr, "InprocServer32");
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, szTemp.ptr);
|
|
|
|
RegDeleteKeyA(HKEY_CLASSES_ROOT, szCLSID.ptr);
|
|
return NOERROR;
|
|
}
|
|
|
|
/*
|
|
* SetKeyAndValue
|
|
*
|
|
* Purpose:
|
|
* Private helper function for DllRegisterServer that creates
|
|
* a key, sets a value, and closes that key.
|
|
*
|
|
* Parameters:
|
|
* pszKey LPTSTR to the name of the key
|
|
* pszSubkey LPTSTR ro the name of a subkey
|
|
* pszValue LPTSTR to the value to store
|
|
*
|
|
* Return Value:
|
|
* BOOL true if successful, false otherwise.
|
|
*/
|
|
BOOL SetKeyAndValue(LPCSTR pszKey, LPCSTR pszSubkey, LPCSTR pszValue)
|
|
{
|
|
HKEY hKey;
|
|
char[256] szKey;
|
|
BOOL result;
|
|
|
|
strcpy(szKey.ptr, pszKey);
|
|
|
|
if (pszSubkey)
|
|
{
|
|
strcat(szKey.ptr, "\\");
|
|
strcat(szKey.ptr, pszSubkey);
|
|
}
|
|
|
|
result = true;
|
|
|
|
int regresult = RegCreateKeyExA(HKEY_CLASSES_ROOT,
|
|
szKey.ptr, 0, null, REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS, null, &hKey, null);
|
|
if (ERROR_SUCCESS != regresult)
|
|
{
|
|
result = false;
|
|
// If the value is 5, you'll need to run the program with Administrator privileges
|
|
printf("RegCreateKeyExA() failed with 0x%x\n", regresult);
|
|
}
|
|
else
|
|
{
|
|
if (null != pszValue)
|
|
{
|
|
if (RegSetValueExA(hKey, null, 0, REG_SZ, cast(BYTE *) pszValue,
|
|
cast(int)((strlen(pszValue) + 1) * char.sizeof)) != ERROR_SUCCESS)
|
|
result = false;
|
|
}
|
|
|
|
if (RegCloseKey(hKey) != ERROR_SUCCESS)
|
|
result = false;
|
|
}
|
|
|
|
if (!result)
|
|
printf("SetKeyAndValue() failed\n");
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* ObjectDestroyed
|
|
*
|
|
* Purpose:
|
|
* Function for the Hello object to call when it gets destroyed.
|
|
* Since we're in a DLL we only track the number of objects here,
|
|
* letting DllCanUnloadNow take care of the rest.
|
|
*/
|
|
|
|
extern (D) void ObjectDestroyed()
|
|
{
|
|
printf("ObjectDestroyed()\n");
|
|
g_cObj--;
|
|
}
|
|
|
|
void unicode2ansi(char *s)
|
|
{
|
|
wchar *w;
|
|
|
|
for (w = cast(wchar *) s; *w; w++)
|
|
*s++ = cast(char)*w;
|
|
|
|
*s = 0;
|
|
}
|