dpnphupnp: Implement Class Factory
Maarten Lankhorst
m.b.lankhorst at gmail.com
Sat May 26 07:02:03 CDT 2007
Based on the existing one from qcap, only trimmed down a little.
-------------- next part --------------
>From c0fc1847202a784d73df4c030571470f6e54e935 Mon Sep 17 00:00:00 2001
From: Maarten Lankhorst <m.b.lankhorst at gmail.com>
Date: Sat, 26 May 2007 12:49:37 +0200
Subject: [PATCH 3/4] dpnhupnp: Implement ClassFactory and Dll(Un)RegisterServer
---
dlls/dpnhupnp/dpnhupnp_main.c | 304 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 296 insertions(+), 8 deletions(-)
diff --git a/dlls/dpnhupnp/dpnhupnp_main.c b/dlls/dpnhupnp/dpnhupnp_main.c
index 51e97fc..d056952 100644
--- a/dlls/dpnhupnp/dpnhupnp_main.c
+++ b/dlls/dpnhupnp/dpnhupnp_main.c
@@ -46,11 +46,27 @@
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(upnp);
+
+/*
+ * defines and constants
+ */
+#define MAX_KEY_LEN 260
+
+static WCHAR const clsid_keyname[6] = {'C','L','S','I','D',0 };
+static WCHAR const ips32_keyname[15] = {'I','n','P','r','o','c','S','e','r','v','e','r','3','2',0};
+static WCHAR const tmodel_keyname[15] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
+static WCHAR const tmodel_both[] = {'B','o','t','h',0};
+static LONG objects_ref;
+static LONG server_locks;
+/*
+static WCHAR const nathelperupnp[] = { 'D','i','r','e','c','t','P','l','a','y',' ','N','A','T',' ',
+ 'H','e','l','p','e','r',' ','U','P','n','P',' ','O','b','j','e','c','t',0};
+ */
+
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
{
TRACE("(%p, %08x, %p)\n", hInstDLL, fdwReason, lpv);
-
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
@@ -64,28 +80,300 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
HRESULT WINAPI DllCanUnloadNow(void)
{
- FIXME("stub\n");
+ TRACE("\n");
+
+ if (!objects_ref && !server_locks)
+ return S_OK;
return S_FALSE;
}
+typedef IUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWN pUnkOuter, HRESULT *phr);
+
+typedef struct tagCFactoryTemplate {
+ const WCHAR *m_Name;
+ const CLSID *m_ClsID;
+ LPFNNewCOMObject m_lpfnNew;
+} CFactoryTemplate;
+
+static CFactoryTemplate const g_cTemplates[] = {
+#if 0
+ {
+ nathelperupnp,
+ &CLSID_DirectPlayNATHelpUPnP,
+ Create_UPNP
+ },
+#endif
+};
+
+static const int g_numTemplates = sizeof(g_cTemplates) / sizeof(g_cTemplates[0]);
+
+typedef struct {
+ IClassFactory ITF_IClassFactory;
+
+ LONG ref;
+ LPFNNewCOMObject pfnCreateInstance;
+} IClassFactoryImpl;
+
+static HRESULT WINAPI
+DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
+{
+ IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IClassFactory))
+ {
+ IClassFactory_AddRef(iface);
+ *ppobj = This;
+ return S_OK;
+ }
+
+ WARN("(%p)->(%s,%p), not found\n", This, debugstr_guid(riid), ppobj);
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
+{
+ IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+ return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
+{
+ IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ if (ref == 0)
+ HeapFree(GetProcessHeap(), 0, This);
+
+ return ref;
+}
+
+static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
+ REFIID riid, LPVOID *ppobj)
+{
+ IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+ HRESULT hres = ERROR_SUCCESS;
+ LPUNKNOWN punk;
+
+ TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
+
+ if (!ppobj)
+ return E_POINTER;
+
+ /* Enforce the normal OLE rules regarding interfaces and delegation */
+ if (pOuter && !IsEqualGUID(riid, &IID_IUnknown))
+ return E_NOINTERFACE;
+
+ *ppobj = NULL;
+ punk = This->pfnCreateInstance(pOuter, &hres);
+ if (!punk)
+ {
+ /* No object created, update error if it isn't done already and return */
+ if (!FAILED(hres))
+ hres = E_OUTOFMEMORY;
+ return hres;
+ }
+
+ if (SUCCEEDED(hres))
+ hres = IUnknown_QueryInterface(punk, riid, ppobj);
+
+ /* Releasing the object. If everything was successful, QueryInterface
+ should have incremented the refcount once more, otherwise this will
+ purge the object. */
+ IUnknown_Release(punk);
+ return hres;
+}
+
+static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
+{
+ IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
+ TRACE("(%p)->(%d)\n",This, dolock);
+
+ if (dolock)
+ InterlockedIncrement(&server_locks);
+ else
+ InterlockedDecrement(&server_locks);
+ return S_OK;
+}
+
+static const IClassFactoryVtbl DSCF_Vtbl =
+{
+ DSCF_QueryInterface,
+ DSCF_AddRef,
+ DSCF_Release,
+ DSCF_CreateInstance,
+ DSCF_LockServer
+};
+
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
- FIXME("stub\n");
- return E_FAIL;
+ const CFactoryTemplate *pList = g_cTemplates;
+ IClassFactoryImpl *factory;
+ int i;
+
+ TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
+
+ if (!ppv)
+ return E_POINTER;
+
+ *ppv = NULL;
+
+ if (!IsEqualGUID(&IID_IClassFactory, riid) &&
+ !IsEqualGUID(&IID_IUnknown, riid))
+ return E_NOINTERFACE;
+
+ for (i = 0; i < g_numTemplates; i++, pList++)
+ {
+ if (IsEqualGUID(pList->m_ClsID, rclsid))
+ break;
+ }
+
+ if (i == g_numTemplates)
+ {
+ FIXME("%s: no class found.\n", debugstr_guid(rclsid));
+ return CLASS_E_CLASSNOTAVAILABLE;
+ }
+
+ factory = HeapAlloc(GetProcessHeap(), 0, sizeof(IClassFactoryImpl));
+ if (!factory)
+ return E_OUTOFMEMORY;
+
+ factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl;
+ factory->ref = 1;
+
+ factory->pfnCreateInstance = pList->m_lpfnNew;
+
+ *ppv = &(factory->ITF_IClassFactory);
+ return S_OK;
+}
+
+/*
+ * Delete a key and all its subkeys
+ */
+static HRESULT DeleteEntireSubKey(HKEY hkey, LPWSTR strSubKey)
+{
+ WCHAR buffer[MAX_KEY_LEN];
+ DWORD dw = MAX_KEY_LEN;
+ FILETIME ft;
+ HKEY hk;
+ LONG ret = RegOpenKeyExW(hkey, strSubKey, 0, MAXIMUM_ALLOWED, &hk);
+
+ if (ERROR_SUCCESS == ret)
+ {
+ /* Keep on enumerating the first key and deleting that */
+ for( ; ; )
+ {
+ dw = MAX_KEY_LEN;
+
+ ret = RegEnumKeyExW(hk, 0, buffer, &dw, NULL, NULL, NULL, &ft);
+
+ if (ERROR_SUCCESS == ret)
+ DeleteEntireSubKey(hk, buffer);
+ else
+ break;
+ }
+ RegCloseKey(hk);
+ RegDeleteKeyW(hkey, strSubKey);
+ }
+ return NOERROR;
+}
+
+/*
+ * SetupRegisterClass()
+ */
+static HRESULT SetupRegisterClass(HKEY clsid, LPCWSTR szCLSID,
+ LPCWSTR szDescription,
+ LPCWSTR szFileName,
+ LPCWSTR szServerType,
+ LPCWSTR szThreadingModel)
+{
+ HKEY hkey, hsubkey = NULL;
+ LONG ret = RegCreateKeyW(clsid, szCLSID, &hkey);
+ if (ERROR_SUCCESS != ret)
+ return HRESULT_FROM_WIN32(ret);
+
+ /* set description string */
+ ret = RegSetValueW(hkey, NULL, REG_SZ, szDescription,
+ sizeof(WCHAR) * (lstrlenW(szDescription) + 1));
+ if (ERROR_SUCCESS != ret)
+ goto err_out;
+
+ /* create CLSID\\{"CLSID"}\\"ServerType" key, using key to CLSID\\{"CLSID"}
+ passed back by last call to RegCreateKeyW(). */
+ ret = RegCreateKeyW(hkey, szServerType, &hsubkey);
+ if (ERROR_SUCCESS != ret)
+ goto err_out;
+
+ /* set server path */
+ ret = RegSetValueW(hsubkey, NULL, REG_SZ, szFileName,
+ sizeof(WCHAR) * (lstrlenW(szFileName) + 1));
+ if (ERROR_SUCCESS != ret)
+ goto err_out;
+
+ /* set threading model */
+ ret = RegSetValueExW(hsubkey, tmodel_keyname, 0L, REG_SZ,
+ (const BYTE*)szThreadingModel,
+ sizeof(WCHAR) * (lstrlenW(szThreadingModel) + 1));
+err_out:
+ if (hsubkey)
+ RegCloseKey(hsubkey);
+ RegCloseKey(hkey);
+ return HRESULT_FROM_WIN32(ret);
+}
+
+/****************************************************************************
+ * SetupRegisterServers
+ *
+ * This function is table driven using the static members of the
+ * CFactoryTemplate class defined in the Dll.
+ *
+ * It registers the Dll as the InprocServer32 for all the classes in
+ * CFactoryTemplate
+ *
+ ****************************************************************************/
+static HRESULT SetupRegisterServers(const CFactoryTemplate * pList, int num,
+ BOOL bRegister)
+{
+ static const WCHAR szFileName[] = {'d','p','n','h','u','p','n','p','.','d','l','l', 0};
+ HRESULT hr = NOERROR;
+ HKEY hkey;
+ OLECHAR szCLSID[CHARS_IN_GUID];
+ LONG i, ret;
+ ret = RegCreateKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkey);
+ if (ret != ERROR_SUCCESS)
+ return HRESULT_FROM_WIN32(ret);
+
+ for (i = 0; i < num; i++, pList++)
+ {
+ /* (un)register CLSID and InprocServer32 */
+ hr = StringFromGUID2(pList->m_ClsID, szCLSID, CHARS_IN_GUID);
+ if (SUCCEEDED(hr))
+ {
+ if (bRegister )
+ hr = SetupRegisterClass(hkey, szCLSID,
+ pList->m_Name, szFileName,
+ ips32_keyname, tmodel_both);
+ else
+ hr = DeleteEntireSubKey(hkey, szCLSID);
+ }
+ }
+ RegCloseKey(hkey);
+ return hr;
}
HRESULT WINAPI DllRegisterServer(void)
{
- FIXME("stub\n");
+ TRACE("()\n");
- return S_FALSE;
+ return SetupRegisterServers(g_cTemplates, g_numTemplates, TRUE);
}
HRESULT WINAPI DllUnregisterServer(void)
{
- FIXME("stub\n");
+ TRACE("\n");
- return S_FALSE;
+ return SetupRegisterServers(g_cTemplates, g_numTemplates, FALSE);
}
HRESULT WINAPI DirectPlayNATHelpCreate(const LPGUID pIID, void ** ppvInterface)
--
1.4.4.2
More information about the wine-patches
mailing list