You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1094 lines
28 KiB
1094 lines
28 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
seo.cpp
|
|
|
|
Abstract:
|
|
|
|
This module contains the implementation for the Server
|
|
Extension Object service.
|
|
|
|
Author:
|
|
|
|
Don Dumitru ([email protected])
|
|
|
|
Revision History:
|
|
|
|
dondu 10/11/96 created
|
|
dondu 11/26/96 major rewrite
|
|
andyj 02/03/97 Added CSEOMimeDictionary support
|
|
andyj 02/12/97 Converted PropertyBag's to Dictonary's
|
|
andyj 04/11/97 Added CSEOGenericMoniker
|
|
|
|
--*/
|
|
|
|
|
|
// SEO.cpp : Implementation of DLL Exports.
|
|
|
|
// Note: Proxy/Stub Information
|
|
// To build a separate proxy/stub DLL,
|
|
// <<TBD>>.
|
|
|
|
#include "stdafx.h"
|
|
|
|
//#define IID_DEFINED
|
|
#include "initguid.h"
|
|
|
|
#define SEODLLDEF // identifiers get exported through the .DEF file
|
|
#include "seodefs.h"
|
|
|
|
#include "mimeole.h"
|
|
|
|
#include "String"
|
|
#include "MEMBAG.h"
|
|
|
|
#include "IADMW.H" // Needed by METABAG.H
|
|
#include "METABAG.H"
|
|
|
|
#include "SEO_i.c"
|
|
#include "regprop.h"
|
|
//#include "mimebag.h"
|
|
#include "item.h"
|
|
#include "fhash.h"
|
|
#include "router.h"
|
|
#include "rwnew.h"
|
|
#include "seolock.h"
|
|
#include "subdict.h"
|
|
#include "stream.h"
|
|
#include "events.h"
|
|
#include "gmoniker.h"
|
|
#include "seolib.h"
|
|
|
|
|
|
CSEOComModule _Module;
|
|
|
|
BEGIN_OBJECT_MAP(ObjectMap)
|
|
OBJECT_ENTRY(CLSID_CSEORegDictionary, CSEORegDictionary)
|
|
// OBJECT_ENTRY(CLSID_CSEOMimeDictionary, CSEOMimeDictionary)
|
|
OBJECT_ENTRY(CLSID_CSEOMemDictionary, CSEOMemDictionary)
|
|
OBJECT_ENTRY(CLSID_CSEOMetaDictionary, CSEOMetaDictionary)
|
|
OBJECT_ENTRY(CLSID_CSEODictionaryItem, CSEODictionaryItem)
|
|
OBJECT_ENTRY(CLSID_CSEORouter, CSEORouter)
|
|
OBJECT_ENTRY(CLSID_CEventLock, CEventLock)
|
|
OBJECT_ENTRY(CLSID_CSEOStream, CSEOStream)
|
|
OBJECT_ENTRY(CLSID_CEventManager, CEventManager)
|
|
OBJECT_ENTRY(CLSID_CSEOGenericMoniker, CSEOGenericMoniker)
|
|
OBJECT_ENTRY(CLSID_CEventMetabaseDatabaseManager, CEventMetabaseDatabaseManager)
|
|
OBJECT_ENTRY(CLSID_CEventBindingManager, CEventBindingManager)
|
|
OBJECT_ENTRY(CLSID_CEventUtil, CEventUtil)
|
|
OBJECT_ENTRY(CLSID_CEventComCat, CEventComCat)
|
|
OBJECT_ENTRY(CLSID_CEventRouter, CEventRouter)
|
|
OBJECT_ENTRY(CLSID_CEventServiceObject, CEventServiceObject)
|
|
END_OBJECT_MAP()
|
|
|
|
ALLOC_DEBUG_MODULE
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CSEOComModule
|
|
|
|
static GUID g_appidSEO = { /* 064b2506-630b-11d2-a028-00c04fa37348 */
|
|
0x064b2506,
|
|
0x630b,
|
|
0x11d2,
|
|
{0xa0, 0x28, 0x00, 0xc0, 0x4f, 0xa3, 0x73, 0x48}
|
|
};
|
|
|
|
const GUID *CSEOComModule::GetAPPID() {
|
|
|
|
return (&g_appidSEO);
|
|
}
|
|
|
|
|
|
HRESULT CSEOComModule::WriteAPPID() {
|
|
CStringGUID guid;
|
|
LPSTR pszKey;
|
|
CRegKey rk;
|
|
LONG lRes;
|
|
HRESULT hrRes = S_OK;
|
|
|
|
guid = *GetAPPID();
|
|
if (!guid) {
|
|
return (CO_E_CLASSSTRING);
|
|
}
|
|
pszKey = (LPSTR) alloca(strlen("AppID\\")+strlen(guid)+1);
|
|
if (!pszKey) {
|
|
return (E_OUTOFMEMORY);
|
|
}
|
|
strcpy(pszKey,"AppID\\");
|
|
strcat(pszKey,guid);
|
|
lRes = rk.Create(HKEY_CLASSES_ROOT,pszKey);
|
|
if (lRes != ERROR_SUCCESS) {
|
|
return (HRESULT_FROM_WIN32(lRes));
|
|
}
|
|
lRes = rk.SetValue("Server Extension Objects");
|
|
if (lRes != ERROR_SUCCESS) {
|
|
hrRes = HRESULT_FROM_WIN32(lRes);
|
|
goto exit;
|
|
}
|
|
lRes = rk.SetValue("","DllSurrogate");
|
|
if (lRes != ERROR_SUCCESS) {
|
|
hrRes = HRESULT_FROM_WIN32(lRes);
|
|
goto exit;
|
|
}
|
|
exit:
|
|
rk.Close();
|
|
if (!SUCCEEDED(hrRes)) {
|
|
EraseAPPID();
|
|
}
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
HRESULT CSEOComModule::EraseAPPID() {
|
|
CStringGUID guid;
|
|
LPSTR pszKey;
|
|
CRegKey rk;
|
|
LONG lRes;
|
|
HRESULT hrRes = S_OK;
|
|
|
|
guid = *GetAPPID();
|
|
if (!guid) {
|
|
return (CO_E_CLASSSTRING);
|
|
}
|
|
pszKey = (LPSTR) alloca(strlen(guid)+strlen("AppID\\")+1);
|
|
if (!pszKey) {
|
|
return (E_OUTOFMEMORY);
|
|
}
|
|
strcpy(pszKey,"AppID\\");
|
|
strcat(pszKey,guid);
|
|
lRes = rk.Open(HKEY_CLASSES_ROOT,"");
|
|
if (lRes != ERROR_SUCCESS) {
|
|
return (HRESULT_FROM_WIN32(lRes));
|
|
}
|
|
lRes = rk.RecurseDeleteKey(pszKey);
|
|
if (lRes != ERROR_SUCCESS) {
|
|
hrRes = HRESULT_FROM_WIN32(lRes);
|
|
goto exit;
|
|
}
|
|
exit:
|
|
rk.Close();
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DLL Entry Point
|
|
|
|
extern "C"
|
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved) {
|
|
|
|
if (dwReason == DLL_PROCESS_ATTACH) {
|
|
_Module.Init(ObjectMap,hInstance);
|
|
INIT_DEBUG_MODULE
|
|
DisableThreadLibraryCalls(hInstance);
|
|
}
|
|
else if (dwReason == DLL_PROCESS_DETACH) {
|
|
TERM_DEBUG_MODULE
|
|
_Module.Term();
|
|
if (!lpvReserved) {
|
|
// lpvReserved is NULL when called because of FreeLibrary, and
|
|
// non-NULL when called during normal process termination. We
|
|
// only want to perform this operation during FreeLibrary,
|
|
// because we are calling into another .DLL and we only want to
|
|
// do that if we are sure that the other .DLL hasn't already
|
|
// terminated.
|
|
MyMallocTerm();
|
|
}
|
|
}
|
|
return (TRUE); // ok
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Used to determine whether the DLL can be unloaded by OLE
|
|
|
|
STDAPI DllCanUnloadNow(void) {
|
|
|
|
TraceFunctEnter("DllCanUnloadNow");
|
|
HRESULT hRes = (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
|
|
DebugTrace(0,"Returns %s.",(hRes==S_OK)?"S_OK":"S_FALSE");
|
|
TraceFunctLeave();
|
|
return (hRes);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Returns a class factory to create an object of the requested type
|
|
|
|
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
|
|
|
|
TraceFunctEnter("DllGetClassObject");
|
|
HRESULT hRes = _Module.GetClassObject(rclsid,riid,ppv);
|
|
DebugTrace(0,"Returns 0x%08x.",hRes);
|
|
TraceFunctLeave();
|
|
return (hRes);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DllRegisterServer - Adds entries to the system registry
|
|
|
|
STDAPI DllRegisterServer(void) {
|
|
|
|
TraceFunctEnter("DllRegisterServer");
|
|
// registers object, typelib and all interfaces in typelib
|
|
HRESULT hRes = _Module.WriteAPPID();
|
|
if (SUCCEEDED(hRes)) {
|
|
hRes = _Module.RegisterServer(TRUE);
|
|
if (!SUCCEEDED(hRes)) {
|
|
_Module.UnregisterServer();
|
|
_Module.EraseAPPID();
|
|
}
|
|
}
|
|
DebugTrace(0,"Returns 0x%08x.",hRes);
|
|
TraceFunctLeave();
|
|
return (hRes);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DllUnregisterServer - Removes entries from the system registry
|
|
|
|
STDAPI DllUnregisterServer(void) {
|
|
|
|
TraceFunctEnter("DllUnregisterServer");
|
|
_Module.UnregisterServer();
|
|
_Module.EraseAPPID();
|
|
DebugTrace(0,"Returns S_OK");
|
|
TraceFunctLeave();
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE MCISInitSEOA(LPCSTR pszService, DWORD dwVirtualServer, ISEORouter **ppshHandle) {
|
|
TraceFunctEnter("MCISInitSEOA");
|
|
HRESULT hrRes;
|
|
CComPtr<ISEODictionary> pdictTmp;
|
|
CComPtr<ISEORouter> prouterResult;
|
|
|
|
if (!ppshHandle) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppshHandle = NULL;
|
|
hrRes = MCISGetBindingInMetabaseA(pszService,dwVirtualServer,GUID_NULL,NULL,TRUE,FALSE,&pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
TraceFunctLeave();
|
|
return (hrRes);
|
|
}
|
|
hrRes = CComObject<CSEORouter>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEORouter,
|
|
(LPVOID *) &prouterResult);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
TraceFunctLeave();
|
|
return (hrRes);
|
|
}
|
|
hrRes = prouterResult->put_Database(pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
TraceFunctLeave();
|
|
return (hrRes);
|
|
}
|
|
*ppshHandle = prouterResult;
|
|
(*ppshHandle)->AddRef();
|
|
TraceFunctLeave();
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE MCISInitSEOW(LPCWSTR pszService, DWORD dwVirtualServer, ISEORouter **ppshHandle) {
|
|
TraceFunctEnter("MCISInitSEOW");
|
|
HRESULT hrRes;
|
|
CComPtr<ISEODictionary> pdictTmp;
|
|
CComPtr<ISEORouter> prouterResult;
|
|
|
|
if (!ppshHandle) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppshHandle = NULL;
|
|
hrRes = MCISGetBindingInMetabaseW(pszService,dwVirtualServer,GUID_NULL,NULL,TRUE,FALSE,&pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
TraceFunctLeave();
|
|
return (hrRes);
|
|
}
|
|
hrRes = CComObject<CSEORouter>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEORouter,
|
|
(LPVOID *) &prouterResult);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
TraceFunctLeave();
|
|
return (hrRes);
|
|
}
|
|
hrRes = prouterResult->put_Database(pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
TraceFunctLeave();
|
|
return (hrRes);
|
|
}
|
|
*ppshHandle = prouterResult;
|
|
(*ppshHandle)->AddRef();
|
|
TraceFunctLeave();
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
static HRESULT GetSubDictA(ISEODictionary *pdictBase,
|
|
LPCSTR pszName,
|
|
LPCSTR *ppszSubName,
|
|
ISEODictionary **ppdictResult) {
|
|
HRESULT hrRes;
|
|
LPSTR pszNameCopy = (LPSTR) _alloca((strlen(pszName)+1)*sizeof(CHAR));
|
|
LPSTR pszNameCurr;
|
|
CComPtr<ISEODictionary> pdictCurr = pdictBase;
|
|
LPSTR pszSlash;
|
|
|
|
if (!ppdictResult) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppdictResult = NULL;
|
|
if (!pdictBase || !pszName || !ppszSubName) {
|
|
return (E_POINTER);
|
|
}
|
|
strcpy(pszNameCopy,pszName);
|
|
pszNameCurr = pszNameCopy;
|
|
while ((pszSlash=strchr(pszNameCurr,'\\'))!=NULL) {
|
|
CComPtr<ISEODictionary> pdictSub;
|
|
|
|
*pszSlash = 0;
|
|
pdictSub.Release();
|
|
hrRes = pdictCurr->GetInterfaceA(pszNameCurr,IID_ISEODictionary,(IUnknown **) &pdictSub);
|
|
if (!SUCCEEDED(hrRes) && (hrRes != SEO_E_NOTPRESENT)) {
|
|
return (hrRes);
|
|
}
|
|
if (!SUCCEEDED(hrRes)) {
|
|
hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEODictionary,
|
|
(LPVOID *) &pdictSub);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
hrRes = pdictCurr->SetInterfaceA(pszNameCurr,pdictSub);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
}
|
|
pdictCurr = pdictSub;
|
|
pszNameCurr = pszSlash + 1;
|
|
}
|
|
*ppszSubName = pszName + (pszNameCurr - pszNameCopy);
|
|
*ppdictResult = pdictCurr;
|
|
(*ppdictResult)->AddRef();
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
static HRESULT GetSubDictW(ISEODictionary *pdictBase,
|
|
LPCWSTR pszName,
|
|
LPCWSTR *ppszSubName,
|
|
ISEODictionary **ppdictResult) {
|
|
HRESULT hrRes;
|
|
LPWSTR pszNameCopy = (LPWSTR) _alloca((wcslen(pszName)+1)*sizeof(WCHAR));
|
|
LPWSTR pszNameCurr;
|
|
CComPtr<ISEODictionary> pdictCurr = pdictBase;
|
|
LPWSTR pszSlash;
|
|
|
|
if (!ppdictResult) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppdictResult = NULL;
|
|
if (!pdictBase || !pszName || !ppszSubName) {
|
|
return (E_POINTER);
|
|
}
|
|
wcscpy(pszNameCopy,pszName);
|
|
pszNameCurr = pszNameCopy;
|
|
while ((pszSlash=wcschr(pszNameCurr,'\\'))!=NULL) {
|
|
CComPtr<ISEODictionary> pdictSub;
|
|
|
|
*pszSlash = 0;
|
|
pdictSub.Release();
|
|
hrRes = pdictCurr->GetInterfaceW(pszNameCurr,IID_ISEODictionary,(IUnknown **) &pdictSub);
|
|
if (!SUCCEEDED(hrRes) && (hrRes != SEO_E_NOTPRESENT)) {
|
|
return (hrRes);
|
|
}
|
|
if (!SUCCEEDED(hrRes)) {
|
|
hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEODictionary,
|
|
(LPVOID *) &pdictSub);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
hrRes = pdictCurr->SetInterfaceW(pszNameCurr,pdictSub);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
}
|
|
pdictCurr = pdictSub;
|
|
pszNameCurr = pszSlash + 1;
|
|
}
|
|
*ppszSubName = pszName + (pszNameCurr - pszNameCopy);
|
|
*ppdictResult = pdictCurr;
|
|
(*ppdictResult)->AddRef();
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateDictionaryFromMultiSzA( DWORD dwCount,
|
|
LPCSTR *ppszNames,
|
|
LPCSTR *ppszValues,
|
|
BOOL bCopy,
|
|
BOOL bReadOnly,
|
|
ISEODictionary **ppdictResult) {
|
|
HRESULT hrRes;
|
|
DWORD dwIdx;
|
|
CComPtr<ISEODictionary> pdictTmp;
|
|
|
|
if (!ppdictResult) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppdictResult = NULL;
|
|
if (!ppszNames || !ppszValues) {
|
|
return (E_POINTER);
|
|
}
|
|
hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEODictionary,
|
|
(LPVOID *) &pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
for (dwIdx=0;dwIdx<dwCount;dwIdx++) {
|
|
if (!ppszNames[dwIdx] || !ppszNames[dwIdx][0]) {
|
|
return (E_POINTER);
|
|
}
|
|
LPCSTR pszSubString;
|
|
CComPtr<ISEODictionary> pdictSub;
|
|
LPCSTR pszSubName;
|
|
|
|
pdictSub.Release();
|
|
hrRes = GetSubDictA(pdictTmp,ppszNames[dwIdx],&pszSubName,&pdictSub);
|
|
pszSubString = ppszValues[dwIdx];
|
|
if (pszSubString[strlen(pszSubString)+1]) {
|
|
CComPtr<ISEODictionaryItem> pitemValue;
|
|
|
|
hrRes = CComObject<CSEODictionaryItem>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEODictionaryItem,
|
|
(LPVOID *) &pitemValue);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
while (*pszSubString) {
|
|
hrRes = pitemValue->AddStringA((DWORD) -1,pszSubString);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
pszSubString += strlen(pszSubString) + 1;
|
|
}
|
|
hrRes = pdictSub->SetInterfaceA(pszSubName,pitemValue);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
} else {
|
|
hrRes = pdictSub->SetStringA(pszSubName,(strlen(pszSubString)+1)*sizeof(CHAR),pszSubString);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
}
|
|
}
|
|
*ppdictResult = pdictTmp;
|
|
(*ppdictResult)->AddRef();
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateDictionaryFromMultiSzW( DWORD dwCount,
|
|
LPCWSTR *ppszNames,
|
|
LPCWSTR *ppszValues,
|
|
BOOL bCopy,
|
|
BOOL bReadOnly,
|
|
ISEODictionary **ppdictResult) {
|
|
|
|
HRESULT hrRes;
|
|
DWORD dwIdx;
|
|
CComPtr<ISEODictionary> pdictTmp;
|
|
|
|
if (!ppdictResult) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppdictResult = NULL;
|
|
if (!ppszNames || !ppszValues) {
|
|
return (E_POINTER);
|
|
}
|
|
hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEODictionary,
|
|
(LPVOID *) &pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
for (dwIdx=0;dwIdx<dwCount;dwIdx++) {
|
|
if (!ppszNames[dwIdx] || !ppszNames[dwIdx][0]) {
|
|
return (E_POINTER);
|
|
}
|
|
LPCWSTR pszSubString;
|
|
CComPtr<ISEODictionary> pdictSub;
|
|
LPCWSTR pszSubName;
|
|
|
|
pdictSub.Release();
|
|
hrRes = GetSubDictW(pdictTmp,ppszNames[dwIdx],&pszSubName,&pdictSub);
|
|
pszSubString = ppszValues[dwIdx];
|
|
if (pszSubString[wcslen(pszSubString)+1]) {
|
|
CComPtr<ISEODictionaryItem> pitemValue;
|
|
|
|
hrRes = CComObject<CSEODictionaryItem>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEODictionaryItem,
|
|
(LPVOID *) &pitemValue);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
while (*pszSubString) {
|
|
hrRes = pitemValue->AddStringW((DWORD) -1,pszSubString);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
pszSubString += wcslen(pszSubString) + 1;
|
|
}
|
|
hrRes = pdictSub->SetInterfaceW(pszSubName,pitemValue);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
} else {
|
|
hrRes = pdictSub->SetStringW(pszSubName,(wcslen(pszSubString)+1)*sizeof(CHAR),pszSubString);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
}
|
|
}
|
|
*ppdictResult = pdictTmp;
|
|
(*ppdictResult)->AddRef();
|
|
return (S_OK);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateMultiSzFromDictionaryA( ISEODictionary *pdictDictionary,
|
|
DWORD *pdwCount,
|
|
LPSTR **pppszNames,
|
|
LPSTR **pppszValues) {
|
|
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateMultiSzFromDictionaryW( ISEODictionary *pdictDictionary,
|
|
DWORD *pdwCount,
|
|
LPWSTR **pppszNames,
|
|
LPWSTR **pppszValues) {
|
|
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
#define DW2W(x) _itow(x,(LPWSTR) _alloca(11*sizeof(WCHAR)),10)
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE MCISGetBindingInMetabaseA( LPCSTR pszService,
|
|
DWORD dwVirtualServer,
|
|
REFGUID guidEventSource,
|
|
LPCSTR pszBinding,
|
|
BOOL bCreate,
|
|
BOOL fLock,
|
|
ISEODictionary **ppdictResult) {
|
|
USES_CONVERSION;
|
|
|
|
return (MCISGetBindingInMetabaseW(pszService?A2W(pszService):NULL,
|
|
dwVirtualServer,
|
|
guidEventSource,
|
|
pszBinding?A2W(pszBinding):NULL,
|
|
bCreate,
|
|
fLock,
|
|
ppdictResult));
|
|
}
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE MCISGetBindingInMetabaseW( LPCWSTR pszService,
|
|
DWORD dwVirtualServer,
|
|
REFGUID guidEventSource,
|
|
LPCWSTR pszBinding,
|
|
BOOL bCreate,
|
|
BOOL fLock,
|
|
ISEODictionary **ppdictResult) {
|
|
HRESULT hrRes;
|
|
CComPtr<ISEOInitObject> pinitRoot;
|
|
CComPtr<ISEODictionary> pdictTmp;
|
|
CComQIPtr<IPropertyBag,&IID_IPropertyBag> ppropTmp;
|
|
CComQIPtr<ISEODictionary,&IID_ISEODictionary> pdictRoot;
|
|
CComBSTR bstrPath;
|
|
|
|
if (!ppdictResult) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppdictResult = NULL;
|
|
if (!pszService) {
|
|
return (E_POINTER);
|
|
}
|
|
if ((guidEventSource != GUID_NULL) && !pszBinding && !bCreate) {
|
|
return (E_INVALIDARG);
|
|
}
|
|
hrRes = CComObject<CSEOMetaDictionary>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEOInitObject,
|
|
(LPVOID *) &pinitRoot);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEODictionary,
|
|
(LPVOID *) &pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
hrRes = pdictTmp->SetStringW(L"MetabasePath",1,L"");
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
ppropTmp = pdictTmp;
|
|
if (!ppropTmp) {
|
|
return (E_NOINTERFACE);
|
|
}
|
|
hrRes = pinitRoot->Load(ppropTmp,NULL);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
pdictRoot = pinitRoot;
|
|
if (!pdictRoot) {
|
|
return (E_NOINTERFACE);
|
|
}
|
|
bstrPath = "LM/";
|
|
bstrPath.Append(pszService);
|
|
bstrPath.Append("/");
|
|
bstrPath.Append(DW2W(dwVirtualServer));
|
|
bstrPath.Append("/SEO");
|
|
if (guidEventSource != GUID_NULL) {
|
|
CStringGUID objGuid;
|
|
|
|
bstrPath.Append("/BindingPoints/");
|
|
objGuid = guidEventSource;
|
|
if (!objGuid) {
|
|
return (E_INVALIDARG);
|
|
}
|
|
bstrPath.Append((LPCOLESTR) objGuid);
|
|
bstrPath.Append("/Bindings/");
|
|
if (pszBinding) {
|
|
bstrPath.Append(pszBinding);
|
|
} else {
|
|
if (!objGuid.CalcNew()) {
|
|
return (E_FAIL);
|
|
}
|
|
bstrPath.Append((LPCOLESTR) objGuid);
|
|
}
|
|
}
|
|
again:
|
|
hrRes = pdictRoot->GetInterfaceW(bstrPath,IID_ISEODictionary,(IUnknown **) ppdictResult);
|
|
if (SUCCEEDED(hrRes) || (hrRes != SEO_E_NOTPRESENT) || !bCreate) {
|
|
return (hrRes);
|
|
}
|
|
// We got an SEO_E_NOTPRESENT error, and the caller specified bCreate==TRUE, so we need
|
|
// to create the sub-key. We do this by writing an empty dictionary to the sub-key - we'll
|
|
// empty the dictionary we used to initialize the root, and write that to the sub-key.
|
|
CComVariant varEmpty;
|
|
hrRes = pdictTmp->SetVariantW(L"MetabasePath",&varEmpty);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
hrRes = pdictRoot->SetInterfaceW(bstrPath,pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
bCreate = FALSE;
|
|
goto again;
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOListenForEvent( ISEORouter *piRouter,
|
|
HANDLE hEvent,
|
|
ISEOEventSink *psinkEventSink,
|
|
BOOL bOnce,
|
|
DWORD *pdwListenHandle) {
|
|
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCancelListenForEvent( DWORD dwHandle) {
|
|
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateIStreamFromFileA( HANDLE hFile,
|
|
LPCSTR pszFile,
|
|
IStream **ppstreamResult) {
|
|
HRESULT hrRes;
|
|
CComObject<CSEOStream> *pStream;
|
|
ULARGE_INTEGER libOffset;
|
|
|
|
if (!ppstreamResult) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppstreamResult = NULL;
|
|
hrRes = CComObject<CSEOStream>::CreateInstance(&pStream);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
pStream->AddRef();
|
|
libOffset.QuadPart = 0;
|
|
hrRes = pStream->Init(hFile,pszFile,libOffset,NULL);
|
|
if (SUCCEEDED(hrRes)) {
|
|
hrRes = pStream->QueryInterface(IID_IStream,(LPVOID *) ppstreamResult);
|
|
}
|
|
pStream->Release();
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateIStreamFromFileW( HANDLE hFile,
|
|
LPCWSTR pszFile,
|
|
IStream **ppstreamResult) {
|
|
HRESULT hrRes;
|
|
CComObject<CSEOStream> *pStream;
|
|
ULARGE_INTEGER libOffset;
|
|
|
|
if (!ppstreamResult) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppstreamResult = NULL;
|
|
hrRes = CComObject<CSEOStream>::CreateInstance(&pStream);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
pStream->AddRef();
|
|
libOffset.QuadPart = 0;
|
|
hrRes = pStream->Init(hFile,pszFile,libOffset,NULL);
|
|
if (SUCCEEDED(hrRes)) {
|
|
hrRes = pStream->QueryInterface(IID_IStream,(LPVOID *) ppstreamResult);
|
|
}
|
|
pStream->Release();
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCopyDictionary(ISEODictionary *pdictIn, ISEODictionary **ppdictResult) {
|
|
HRESULT hrRes;
|
|
CComPtr<ISEODictionary> pdictTmp;
|
|
|
|
if (!ppdictResult) {
|
|
return (E_POINTER);
|
|
}
|
|
*ppdictResult = NULL;
|
|
hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
|
|
IID_ISEODictionary,
|
|
(LPVOID *) &pdictTmp);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
if (pdictIn) {
|
|
CComPtr<IUnknown> punkEnum;
|
|
|
|
hrRes = pdictIn->get__NewEnum(&punkEnum);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
CComQIPtr<IEnumVARIANT,&IID_IEnumVARIANT> pevEnum(punkEnum);
|
|
if (!pevEnum) {
|
|
return (E_NOINTERFACE);
|
|
}
|
|
VARIANT varName;
|
|
VariantInit(&varName);
|
|
while ((hrRes=pevEnum->Next(1,&varName,NULL))==S_OK) {
|
|
VARIANT varValue;
|
|
|
|
VariantInit(&varValue);
|
|
hrRes = pdictIn->get_Item(&varName,&varValue);
|
|
if (!SUCCEEDED(hrRes) || (varValue.vt == VT_EMPTY)) {
|
|
VariantClear(&varName);
|
|
return (hrRes);
|
|
}
|
|
hrRes = VariantChangeType(&varValue,&varValue,0,VT_UNKNOWN);
|
|
if (SUCCEEDED(hrRes)) {
|
|
CComQIPtr<ISEODictionary,&IID_ISEODictionary> pdictSub(varValue.punkVal);
|
|
|
|
if (pdictSub) {
|
|
CComPtr<ISEODictionary> pdictSubCopy;
|
|
|
|
hrRes = SEOCopyDictionary(pdictSub,&pdictSubCopy);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
VariantClear(&varName);
|
|
return (hrRes);
|
|
}
|
|
varValue.punkVal->Release();
|
|
varValue.punkVal = pdictSubCopy;
|
|
varValue.punkVal->AddRef();
|
|
}
|
|
}
|
|
hrRes = pdictTmp->put_Item(&varName,&varValue);
|
|
VariantClear(&varName);
|
|
VariantClear(&varValue);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
}
|
|
if (hrRes == S_FALSE) {
|
|
hrRes = S_OK;
|
|
}
|
|
}
|
|
*ppdictResult = pdictTmp;
|
|
(*ppdictResult)->AddRef();
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
static HRESULT ReadLineFromStream(IStream *pstreamIn, LPSTR *ppszLine) {
|
|
HRESULT hrRes;
|
|
const int c_iAllocSize = 512;
|
|
LPSTR pszTmp = NULL;
|
|
LPSTR pszCurr = NULL;
|
|
LPSTR pszEnd = NULL;
|
|
BOOL bInEscape = FALSE;
|
|
BOOL bEOF = FALSE;
|
|
|
|
if (!pstreamIn || !ppszLine) {
|
|
return (E_POINTER);
|
|
}
|
|
CoTaskMemFree(*ppszLine);
|
|
*ppszLine = NULL;
|
|
while (1) {
|
|
if (pszCurr == pszEnd) {
|
|
LPSTR pszNew = (LPSTR) CoTaskMemRealloc(pszTmp,((pszCurr-pszTmp)+c_iAllocSize)*sizeof(*pszTmp));
|
|
|
|
if (!pszNew) {
|
|
CoTaskMemFree(pszTmp);
|
|
return (E_OUTOFMEMORY);
|
|
}
|
|
pszCurr = pszNew + (pszCurr-pszTmp);
|
|
pszEnd = pszCurr + c_iAllocSize;
|
|
pszTmp = pszNew;
|
|
}
|
|
hrRes = pstreamIn->Read(pszCurr,sizeof(*pszCurr),NULL);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
CoTaskMemFree(pszTmp);
|
|
return (hrRes);
|
|
}
|
|
if (hrRes == S_FALSE) {
|
|
// end-of-file - pretend like non-escaped '\n'
|
|
bInEscape = FALSE;
|
|
*pszCurr = '\n';
|
|
bEOF = TRUE;
|
|
}
|
|
if (*pszCurr == '\r') {
|
|
// always eat carriage returns - even escaped ones
|
|
continue;
|
|
}
|
|
if (bInEscape) {
|
|
switch (*pszCurr) {
|
|
|
|
case 'n':
|
|
// escape-n becomes linefeed
|
|
*pszCurr = '\n';
|
|
break;
|
|
|
|
case 'r':
|
|
// escape-r becomes carriage return
|
|
*pszCurr = '\r';
|
|
break;
|
|
|
|
case '\n':
|
|
// escaped-linefeed means line continuation
|
|
pszCurr--;
|
|
break;
|
|
|
|
// for now, don't allow embedded NULLs - this is because we return a NULL-terminated string
|
|
// case '0':
|
|
// // escape-0 means embedded NULL
|
|
// *pszCurr = 0;
|
|
// break;
|
|
|
|
case 0:
|
|
// escape-NULL - just eat
|
|
pszCurr--;
|
|
break;
|
|
|
|
default:
|
|
// escape-(anything else) is just passed through
|
|
break;
|
|
}
|
|
bInEscape = FALSE;
|
|
} else {
|
|
BOOL bFinished = FALSE;
|
|
|
|
switch (*pszCurr) {
|
|
|
|
case '\\':
|
|
// first character of escape sequence
|
|
pszCurr--;
|
|
bInEscape = TRUE;
|
|
break;
|
|
|
|
case '\n':
|
|
// end-of-line
|
|
bFinished = TRUE;
|
|
break;
|
|
|
|
case 0:
|
|
// non-escaped NULL - just eat
|
|
pszCurr--;
|
|
break;
|
|
}
|
|
if (bFinished) {
|
|
break;
|
|
}
|
|
}
|
|
pszCurr++;
|
|
}
|
|
*pszCurr = 0;
|
|
*ppszLine = pszTmp;
|
|
return (bEOF?S_FALSE:S_OK);
|
|
}
|
|
|
|
|
|
static HRESULT SEOCreateMultiSzFromIStreamA(IStream *pstreamIn,
|
|
DWORD *pdwCount,
|
|
LPSTR **pppszNames,
|
|
LPSTR **pppszValues) {
|
|
HRESULT hrRes;
|
|
LPSTR *ppszLines = NULL;
|
|
DWORD dwLines = NULL;
|
|
|
|
if (!pstreamIn || !pdwCount || !pppszNames || !pppszValues) {
|
|
return (E_POINTER);
|
|
}
|
|
*pdwCount = 0;
|
|
*pppszNames = NULL;
|
|
*pppszValues = NULL;
|
|
while (1) {
|
|
LPSTR *ppszNew = (LPSTR *) CoTaskMemRealloc(ppszLines,sizeof(*ppszLines)*(dwLines+1));
|
|
|
|
if (!ppszNew) {
|
|
hrRes = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
ppszLines = ppszNew;
|
|
ppszLines[dwLines] = NULL;
|
|
hrRes = ReadLineFromStream(pstreamIn,&ppszLines[dwLines]);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
break;
|
|
}
|
|
if (!ppszLines[dwLines][0] ||
|
|
(ppszLines[dwLines][0] == '#') ||
|
|
!strchr(ppszLines[dwLines],'=')) {
|
|
if (hrRes == S_FALSE) {
|
|
break;
|
|
}
|
|
CoTaskMemFree(ppszLines[dwLines]);
|
|
continue;
|
|
}
|
|
dwLines++;
|
|
}
|
|
if (SUCCEEDED(hrRes)) {
|
|
DWORD dwIdx;
|
|
LPSTR pszNameCurr = NULL;
|
|
LPSTR pszValueCurr = NULL;
|
|
|
|
hrRes = S_OK;
|
|
while (1) {
|
|
for (dwIdx=0;dwIdx<dwLines;dwIdx++) {
|
|
LPSTR pszEquals = strchr(ppszLines[dwIdx],'=');
|
|
|
|
if (*pppszNames) {
|
|
(*pppszNames)[dwIdx] = pszNameCurr;
|
|
memcpy(pszNameCurr,
|
|
ppszLines[dwIdx],
|
|
(pszEquals-ppszLines[dwIdx])*sizeof(*pszNameCurr));
|
|
(*pppszValues)[dwIdx] = pszValueCurr;
|
|
strcpy(pszValueCurr,pszEquals+1);
|
|
}
|
|
pszNameCurr += pszEquals - ppszLines[dwIdx] + 1;
|
|
pszValueCurr += strlen(pszEquals+1) + 1 + 1; // multi-sz, so is double-NULL terminated
|
|
}
|
|
if (*pppszNames) {
|
|
*pdwCount = dwLines;
|
|
break;
|
|
}
|
|
if (!*pppszNames) {
|
|
DWORD dwNameBytes = dwLines * sizeof(*pppszNames) + ((LPBYTE) pszNameCurr - (LPBYTE) NULL);
|
|
DWORD dwValueBytes = dwLines * sizeof(*pppszValues) + ((LPBYTE) pszValueCurr - (LPBYTE) NULL);
|
|
|
|
*pppszNames = (LPSTR *) CoTaskMemAlloc(dwNameBytes);
|
|
*pppszValues = (LPSTR *) CoTaskMemAlloc(dwValueBytes);
|
|
if (!*pppszNames || !*pppszValues) {
|
|
hrRes = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
memset(*pppszNames,0,dwNameBytes);
|
|
memset(*pppszValues,0,dwValueBytes);
|
|
pszNameCurr = (LPSTR) ((LPBYTE) *pppszNames + dwLines * sizeof(*pppszNames));
|
|
pszValueCurr = (LPSTR) ((LPBYTE) *pppszValues + dwLines * sizeof(*pppszValues));
|
|
}
|
|
}
|
|
}
|
|
if (!SUCCEEDED(hrRes)) {
|
|
*pdwCount = 0;
|
|
CoTaskMemFree(*pppszNames);
|
|
CoTaskMemFree(*pppszValues);
|
|
}
|
|
for (DWORD dwIdx=0;dwIdx<dwLines;dwIdx++) {
|
|
CoTaskMemFree(ppszLines[dwIdx]);
|
|
}
|
|
CoTaskMemFree(ppszLines);
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateDictionaryFromIStream(IStream *pstreamIn, ISEODictionary **ppdictResult) {
|
|
HRESULT hrRes;
|
|
DWORD dwCount;
|
|
LPSTR *ppszNames;
|
|
LPSTR *ppszValues;
|
|
|
|
if (!ppdictResult) {
|
|
return (E_POINTER);
|
|
}
|
|
hrRes = SEOCreateMultiSzFromIStreamA(pstreamIn,&dwCount,&ppszNames,&ppszValues);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
hrRes = SEOCreateDictionaryFromMultiSzA(dwCount,
|
|
(LPCSTR *) ppszNames,
|
|
(LPCSTR *) ppszValues,
|
|
TRUE,
|
|
FALSE,
|
|
ppdictResult);
|
|
CoTaskMemFree(ppszNames);
|
|
CoTaskMemFree(ppszValues);
|
|
return (hrRes);
|
|
}
|
|
|
|
|
|
static HRESULT SEOWriteMultiSzToIStreamA(DWORD dwCount, LPCSTR *ppszNames, LPCSTR *ppszValues, IStream *pstreamOut) {
|
|
|
|
return (E_NOTIMPL);
|
|
}
|
|
|
|
|
|
SEODLLDEF HRESULT STDAPICALLTYPE SEOWriteDictionaryToIStream(ISEODictionary *pdictIn, IStream *pstreamOut) {
|
|
HRESULT hrRes;
|
|
DWORD dwCount;
|
|
LPSTR *ppszNames;
|
|
LPSTR *ppszValues;
|
|
|
|
if (!pstreamOut) {
|
|
return (E_POINTER);
|
|
}
|
|
hrRes = SEOCreateMultiSzFromDictionaryA(pdictIn,&dwCount,&ppszNames,&ppszValues);
|
|
if (!SUCCEEDED(hrRes)) {
|
|
return (hrRes);
|
|
}
|
|
hrRes = SEOWriteMultiSzToIStreamA(dwCount,(LPCSTR *) ppszNames,(LPCSTR *) ppszValues,pstreamOut);
|
|
CoTaskMemFree(ppszNames);
|
|
CoTaskMemFree(ppszValues);
|
|
return (hrRes);
|
|
}
|