Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. seo.cpp
  5. Abstract:
  6. This module contains the implementation for the Server
  7. Extension Object service.
  8. Author:
  9. Don Dumitru (dondu@microsoft.com)
  10. Revision History:
  11. dondu 10/11/96 created
  12. dondu 11/26/96 major rewrite
  13. andyj 02/03/97 Added CSEOMimeDictionary support
  14. andyj 02/12/97 Converted PropertyBag's to Dictonary's
  15. andyj 04/11/97 Added CSEOGenericMoniker
  16. --*/
  17. // SEO.cpp : Implementation of DLL Exports.
  18. // Note: Proxy/Stub Information
  19. // To build a separate proxy/stub DLL,
  20. // <<TBD>>.
  21. #include "stdafx.h"
  22. //#define IID_DEFINED
  23. #include "initguid.h"
  24. #define SEODLLDEF // identifiers get exported through the .DEF file
  25. #include "seodefs.h"
  26. #include "mimeole.h"
  27. #include "String"
  28. #include "MEMBAG.h"
  29. #include "IADMW.H" // Needed by METABAG.H
  30. #include "METABAG.H"
  31. #include "SEO_i.c"
  32. #include "regprop.h"
  33. //#include "mimebag.h"
  34. #include "item.h"
  35. #include "fhash.h"
  36. #include "router.h"
  37. #include "rwnew.h"
  38. #include "seolock.h"
  39. #include "subdict.h"
  40. #include "stream.h"
  41. #include "events.h"
  42. #include "gmoniker.h"
  43. #include "seolib.h"
  44. CSEOComModule _Module;
  45. BEGIN_OBJECT_MAP(ObjectMap)
  46. OBJECT_ENTRY(CLSID_CSEORegDictionary, CSEORegDictionary)
  47. // OBJECT_ENTRY(CLSID_CSEOMimeDictionary, CSEOMimeDictionary)
  48. OBJECT_ENTRY(CLSID_CSEOMemDictionary, CSEOMemDictionary)
  49. OBJECT_ENTRY(CLSID_CSEOMetaDictionary, CSEOMetaDictionary)
  50. OBJECT_ENTRY(CLSID_CSEODictionaryItem, CSEODictionaryItem)
  51. OBJECT_ENTRY(CLSID_CSEORouter, CSEORouter)
  52. OBJECT_ENTRY(CLSID_CEventLock, CEventLock)
  53. OBJECT_ENTRY(CLSID_CSEOStream, CSEOStream)
  54. OBJECT_ENTRY(CLSID_CEventManager, CEventManager)
  55. OBJECT_ENTRY(CLSID_CSEOGenericMoniker, CSEOGenericMoniker)
  56. OBJECT_ENTRY(CLSID_CEventMetabaseDatabaseManager, CEventMetabaseDatabaseManager)
  57. OBJECT_ENTRY(CLSID_CEventBindingManager, CEventBindingManager)
  58. OBJECT_ENTRY(CLSID_CEventUtil, CEventUtil)
  59. OBJECT_ENTRY(CLSID_CEventComCat, CEventComCat)
  60. OBJECT_ENTRY(CLSID_CEventRouter, CEventRouter)
  61. OBJECT_ENTRY(CLSID_CEventServiceObject, CEventServiceObject)
  62. END_OBJECT_MAP()
  63. ALLOC_DEBUG_MODULE
  64. /////////////////////////////////////////////////////////////////////////////
  65. // CSEOComModule
  66. static GUID g_appidSEO = { /* 064b2506-630b-11d2-a028-00c04fa37348 */
  67. 0x064b2506,
  68. 0x630b,
  69. 0x11d2,
  70. {0xa0, 0x28, 0x00, 0xc0, 0x4f, 0xa3, 0x73, 0x48}
  71. };
  72. const GUID *CSEOComModule::GetAPPID() {
  73. return (&g_appidSEO);
  74. }
  75. HRESULT CSEOComModule::WriteAPPID() {
  76. CStringGUID guid;
  77. LPSTR pszKey;
  78. CRegKey rk;
  79. LONG lRes;
  80. HRESULT hrRes = S_OK;
  81. guid = *GetAPPID();
  82. if (!guid) {
  83. return (CO_E_CLASSSTRING);
  84. }
  85. pszKey = (LPSTR) alloca(strlen("AppID\\")+strlen(guid)+1);
  86. if (!pszKey) {
  87. return (E_OUTOFMEMORY);
  88. }
  89. strcpy(pszKey,"AppID\\");
  90. strcat(pszKey,guid);
  91. lRes = rk.Create(HKEY_CLASSES_ROOT,pszKey);
  92. if (lRes != ERROR_SUCCESS) {
  93. return (HRESULT_FROM_WIN32(lRes));
  94. }
  95. lRes = rk.SetValue("Server Extension Objects");
  96. if (lRes != ERROR_SUCCESS) {
  97. hrRes = HRESULT_FROM_WIN32(lRes);
  98. goto exit;
  99. }
  100. lRes = rk.SetValue("","DllSurrogate");
  101. if (lRes != ERROR_SUCCESS) {
  102. hrRes = HRESULT_FROM_WIN32(lRes);
  103. goto exit;
  104. }
  105. exit:
  106. rk.Close();
  107. if (!SUCCEEDED(hrRes)) {
  108. EraseAPPID();
  109. }
  110. return (hrRes);
  111. }
  112. HRESULT CSEOComModule::EraseAPPID() {
  113. CStringGUID guid;
  114. LPSTR pszKey;
  115. CRegKey rk;
  116. LONG lRes;
  117. HRESULT hrRes = S_OK;
  118. guid = *GetAPPID();
  119. if (!guid) {
  120. return (CO_E_CLASSSTRING);
  121. }
  122. pszKey = (LPSTR) alloca(strlen(guid)+strlen("AppID\\")+1);
  123. if (!pszKey) {
  124. return (E_OUTOFMEMORY);
  125. }
  126. strcpy(pszKey,"AppID\\");
  127. strcat(pszKey,guid);
  128. lRes = rk.Open(HKEY_CLASSES_ROOT,"");
  129. if (lRes != ERROR_SUCCESS) {
  130. return (HRESULT_FROM_WIN32(lRes));
  131. }
  132. lRes = rk.RecurseDeleteKey(pszKey);
  133. if (lRes != ERROR_SUCCESS) {
  134. hrRes = HRESULT_FROM_WIN32(lRes);
  135. goto exit;
  136. }
  137. exit:
  138. rk.Close();
  139. return (hrRes);
  140. }
  141. /////////////////////////////////////////////////////////////////////////////
  142. // DLL Entry Point
  143. extern "C"
  144. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved) {
  145. if (dwReason == DLL_PROCESS_ATTACH) {
  146. _Module.Init(ObjectMap,hInstance);
  147. INIT_DEBUG_MODULE
  148. DisableThreadLibraryCalls(hInstance);
  149. }
  150. else if (dwReason == DLL_PROCESS_DETACH) {
  151. TERM_DEBUG_MODULE
  152. _Module.Term();
  153. if (!lpvReserved) {
  154. // lpvReserved is NULL when called because of FreeLibrary, and
  155. // non-NULL when called during normal process termination. We
  156. // only want to perform this operation during FreeLibrary,
  157. // because we are calling into another .DLL and we only want to
  158. // do that if we are sure that the other .DLL hasn't already
  159. // terminated.
  160. MyMallocTerm();
  161. }
  162. }
  163. return (TRUE); // ok
  164. }
  165. /////////////////////////////////////////////////////////////////////////////
  166. // Used to determine whether the DLL can be unloaded by OLE
  167. STDAPI DllCanUnloadNow(void) {
  168. TraceFunctEnter("DllCanUnloadNow");
  169. HRESULT hRes = (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
  170. DebugTrace(0,"Returns %s.",(hRes==S_OK)?"S_OK":"S_FALSE");
  171. TraceFunctLeave();
  172. return (hRes);
  173. }
  174. /////////////////////////////////////////////////////////////////////////////
  175. // Returns a class factory to create an object of the requested type
  176. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
  177. TraceFunctEnter("DllGetClassObject");
  178. HRESULT hRes = _Module.GetClassObject(rclsid,riid,ppv);
  179. DebugTrace(0,"Returns 0x%08x.",hRes);
  180. TraceFunctLeave();
  181. return (hRes);
  182. }
  183. /////////////////////////////////////////////////////////////////////////////
  184. // DllRegisterServer - Adds entries to the system registry
  185. STDAPI DllRegisterServer(void) {
  186. TraceFunctEnter("DllRegisterServer");
  187. // registers object, typelib and all interfaces in typelib
  188. HRESULT hRes = _Module.WriteAPPID();
  189. if (SUCCEEDED(hRes)) {
  190. hRes = _Module.RegisterServer(TRUE);
  191. if (!SUCCEEDED(hRes)) {
  192. _Module.UnregisterServer();
  193. _Module.EraseAPPID();
  194. }
  195. }
  196. DebugTrace(0,"Returns 0x%08x.",hRes);
  197. TraceFunctLeave();
  198. return (hRes);
  199. }
  200. /////////////////////////////////////////////////////////////////////////////
  201. // DllUnregisterServer - Removes entries from the system registry
  202. STDAPI DllUnregisterServer(void) {
  203. TraceFunctEnter("DllUnregisterServer");
  204. _Module.UnregisterServer();
  205. _Module.EraseAPPID();
  206. DebugTrace(0,"Returns S_OK");
  207. TraceFunctLeave();
  208. return (S_OK);
  209. }
  210. SEODLLDEF HRESULT STDAPICALLTYPE MCISInitSEOA(LPCSTR pszService, DWORD dwVirtualServer, ISEORouter **ppshHandle) {
  211. TraceFunctEnter("MCISInitSEOA");
  212. HRESULT hrRes;
  213. CComPtr<ISEODictionary> pdictTmp;
  214. CComPtr<ISEORouter> prouterResult;
  215. if (!ppshHandle) {
  216. return (E_POINTER);
  217. }
  218. *ppshHandle = NULL;
  219. hrRes = MCISGetBindingInMetabaseA(pszService,dwVirtualServer,GUID_NULL,NULL,TRUE,FALSE,&pdictTmp);
  220. if (!SUCCEEDED(hrRes)) {
  221. TraceFunctLeave();
  222. return (hrRes);
  223. }
  224. hrRes = CComObject<CSEORouter>::_CreatorClass::CreateInstance(NULL,
  225. IID_ISEORouter,
  226. (LPVOID *) &prouterResult);
  227. if (!SUCCEEDED(hrRes)) {
  228. TraceFunctLeave();
  229. return (hrRes);
  230. }
  231. hrRes = prouterResult->put_Database(pdictTmp);
  232. if (!SUCCEEDED(hrRes)) {
  233. TraceFunctLeave();
  234. return (hrRes);
  235. }
  236. *ppshHandle = prouterResult;
  237. (*ppshHandle)->AddRef();
  238. TraceFunctLeave();
  239. return (S_OK);
  240. }
  241. SEODLLDEF HRESULT STDAPICALLTYPE MCISInitSEOW(LPCWSTR pszService, DWORD dwVirtualServer, ISEORouter **ppshHandle) {
  242. TraceFunctEnter("MCISInitSEOW");
  243. HRESULT hrRes;
  244. CComPtr<ISEODictionary> pdictTmp;
  245. CComPtr<ISEORouter> prouterResult;
  246. if (!ppshHandle) {
  247. return (E_POINTER);
  248. }
  249. *ppshHandle = NULL;
  250. hrRes = MCISGetBindingInMetabaseW(pszService,dwVirtualServer,GUID_NULL,NULL,TRUE,FALSE,&pdictTmp);
  251. if (!SUCCEEDED(hrRes)) {
  252. TraceFunctLeave();
  253. return (hrRes);
  254. }
  255. hrRes = CComObject<CSEORouter>::_CreatorClass::CreateInstance(NULL,
  256. IID_ISEORouter,
  257. (LPVOID *) &prouterResult);
  258. if (!SUCCEEDED(hrRes)) {
  259. TraceFunctLeave();
  260. return (hrRes);
  261. }
  262. hrRes = prouterResult->put_Database(pdictTmp);
  263. if (!SUCCEEDED(hrRes)) {
  264. TraceFunctLeave();
  265. return (hrRes);
  266. }
  267. *ppshHandle = prouterResult;
  268. (*ppshHandle)->AddRef();
  269. TraceFunctLeave();
  270. return (S_OK);
  271. }
  272. static HRESULT GetSubDictA(ISEODictionary *pdictBase,
  273. LPCSTR pszName,
  274. LPCSTR *ppszSubName,
  275. ISEODictionary **ppdictResult) {
  276. HRESULT hrRes;
  277. LPSTR pszNameCopy = (LPSTR) _alloca((strlen(pszName)+1)*sizeof(CHAR));
  278. LPSTR pszNameCurr;
  279. CComPtr<ISEODictionary> pdictCurr = pdictBase;
  280. LPSTR pszSlash;
  281. if (!ppdictResult) {
  282. return (E_POINTER);
  283. }
  284. *ppdictResult = NULL;
  285. if (!pdictBase || !pszName || !ppszSubName) {
  286. return (E_POINTER);
  287. }
  288. strcpy(pszNameCopy,pszName);
  289. pszNameCurr = pszNameCopy;
  290. while ((pszSlash=strchr(pszNameCurr,'\\'))!=NULL) {
  291. CComPtr<ISEODictionary> pdictSub;
  292. *pszSlash = 0;
  293. pdictSub.Release();
  294. hrRes = pdictCurr->GetInterfaceA(pszNameCurr,IID_ISEODictionary,(IUnknown **) &pdictSub);
  295. if (!SUCCEEDED(hrRes) && (hrRes != SEO_E_NOTPRESENT)) {
  296. return (hrRes);
  297. }
  298. if (!SUCCEEDED(hrRes)) {
  299. hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
  300. IID_ISEODictionary,
  301. (LPVOID *) &pdictSub);
  302. if (!SUCCEEDED(hrRes)) {
  303. return (hrRes);
  304. }
  305. hrRes = pdictCurr->SetInterfaceA(pszNameCurr,pdictSub);
  306. if (!SUCCEEDED(hrRes)) {
  307. return (hrRes);
  308. }
  309. }
  310. pdictCurr = pdictSub;
  311. pszNameCurr = pszSlash + 1;
  312. }
  313. *ppszSubName = pszName + (pszNameCurr - pszNameCopy);
  314. *ppdictResult = pdictCurr;
  315. (*ppdictResult)->AddRef();
  316. return (S_OK);
  317. }
  318. static HRESULT GetSubDictW(ISEODictionary *pdictBase,
  319. LPCWSTR pszName,
  320. LPCWSTR *ppszSubName,
  321. ISEODictionary **ppdictResult) {
  322. HRESULT hrRes;
  323. LPWSTR pszNameCopy = (LPWSTR) _alloca((wcslen(pszName)+1)*sizeof(WCHAR));
  324. LPWSTR pszNameCurr;
  325. CComPtr<ISEODictionary> pdictCurr = pdictBase;
  326. LPWSTR pszSlash;
  327. if (!ppdictResult) {
  328. return (E_POINTER);
  329. }
  330. *ppdictResult = NULL;
  331. if (!pdictBase || !pszName || !ppszSubName) {
  332. return (E_POINTER);
  333. }
  334. wcscpy(pszNameCopy,pszName);
  335. pszNameCurr = pszNameCopy;
  336. while ((pszSlash=wcschr(pszNameCurr,'\\'))!=NULL) {
  337. CComPtr<ISEODictionary> pdictSub;
  338. *pszSlash = 0;
  339. pdictSub.Release();
  340. hrRes = pdictCurr->GetInterfaceW(pszNameCurr,IID_ISEODictionary,(IUnknown **) &pdictSub);
  341. if (!SUCCEEDED(hrRes) && (hrRes != SEO_E_NOTPRESENT)) {
  342. return (hrRes);
  343. }
  344. if (!SUCCEEDED(hrRes)) {
  345. hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
  346. IID_ISEODictionary,
  347. (LPVOID *) &pdictSub);
  348. if (!SUCCEEDED(hrRes)) {
  349. return (hrRes);
  350. }
  351. hrRes = pdictCurr->SetInterfaceW(pszNameCurr,pdictSub);
  352. if (!SUCCEEDED(hrRes)) {
  353. return (hrRes);
  354. }
  355. }
  356. pdictCurr = pdictSub;
  357. pszNameCurr = pszSlash + 1;
  358. }
  359. *ppszSubName = pszName + (pszNameCurr - pszNameCopy);
  360. *ppdictResult = pdictCurr;
  361. (*ppdictResult)->AddRef();
  362. return (S_OK);
  363. }
  364. SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateDictionaryFromMultiSzA( DWORD dwCount,
  365. LPCSTR *ppszNames,
  366. LPCSTR *ppszValues,
  367. BOOL bCopy,
  368. BOOL bReadOnly,
  369. ISEODictionary **ppdictResult) {
  370. HRESULT hrRes;
  371. DWORD dwIdx;
  372. CComPtr<ISEODictionary> pdictTmp;
  373. if (!ppdictResult) {
  374. return (E_POINTER);
  375. }
  376. *ppdictResult = NULL;
  377. if (!ppszNames || !ppszValues) {
  378. return (E_POINTER);
  379. }
  380. hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
  381. IID_ISEODictionary,
  382. (LPVOID *) &pdictTmp);
  383. if (!SUCCEEDED(hrRes)) {
  384. return (hrRes);
  385. }
  386. for (dwIdx=0;dwIdx<dwCount;dwIdx++) {
  387. if (!ppszNames[dwIdx] || !ppszNames[dwIdx][0]) {
  388. return (E_POINTER);
  389. }
  390. LPCSTR pszSubString;
  391. CComPtr<ISEODictionary> pdictSub;
  392. LPCSTR pszSubName;
  393. pdictSub.Release();
  394. hrRes = GetSubDictA(pdictTmp,ppszNames[dwIdx],&pszSubName,&pdictSub);
  395. pszSubString = ppszValues[dwIdx];
  396. if (pszSubString[strlen(pszSubString)+1]) {
  397. CComPtr<ISEODictionaryItem> pitemValue;
  398. hrRes = CComObject<CSEODictionaryItem>::_CreatorClass::CreateInstance(NULL,
  399. IID_ISEODictionaryItem,
  400. (LPVOID *) &pitemValue);
  401. if (!SUCCEEDED(hrRes)) {
  402. return (hrRes);
  403. }
  404. while (*pszSubString) {
  405. hrRes = pitemValue->AddStringA((DWORD) -1,pszSubString);
  406. if (!SUCCEEDED(hrRes)) {
  407. return (hrRes);
  408. }
  409. pszSubString += strlen(pszSubString) + 1;
  410. }
  411. hrRes = pdictSub->SetInterfaceA(pszSubName,pitemValue);
  412. if (!SUCCEEDED(hrRes)) {
  413. return (hrRes);
  414. }
  415. } else {
  416. hrRes = pdictSub->SetStringA(pszSubName,(strlen(pszSubString)+1)*sizeof(CHAR),pszSubString);
  417. if (!SUCCEEDED(hrRes)) {
  418. return (hrRes);
  419. }
  420. }
  421. }
  422. *ppdictResult = pdictTmp;
  423. (*ppdictResult)->AddRef();
  424. return (S_OK);
  425. }
  426. SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateDictionaryFromMultiSzW( DWORD dwCount,
  427. LPCWSTR *ppszNames,
  428. LPCWSTR *ppszValues,
  429. BOOL bCopy,
  430. BOOL bReadOnly,
  431. ISEODictionary **ppdictResult) {
  432. HRESULT hrRes;
  433. DWORD dwIdx;
  434. CComPtr<ISEODictionary> pdictTmp;
  435. if (!ppdictResult) {
  436. return (E_POINTER);
  437. }
  438. *ppdictResult = NULL;
  439. if (!ppszNames || !ppszValues) {
  440. return (E_POINTER);
  441. }
  442. hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
  443. IID_ISEODictionary,
  444. (LPVOID *) &pdictTmp);
  445. if (!SUCCEEDED(hrRes)) {
  446. return (hrRes);
  447. }
  448. for (dwIdx=0;dwIdx<dwCount;dwIdx++) {
  449. if (!ppszNames[dwIdx] || !ppszNames[dwIdx][0]) {
  450. return (E_POINTER);
  451. }
  452. LPCWSTR pszSubString;
  453. CComPtr<ISEODictionary> pdictSub;
  454. LPCWSTR pszSubName;
  455. pdictSub.Release();
  456. hrRes = GetSubDictW(pdictTmp,ppszNames[dwIdx],&pszSubName,&pdictSub);
  457. pszSubString = ppszValues[dwIdx];
  458. if (pszSubString[wcslen(pszSubString)+1]) {
  459. CComPtr<ISEODictionaryItem> pitemValue;
  460. hrRes = CComObject<CSEODictionaryItem>::_CreatorClass::CreateInstance(NULL,
  461. IID_ISEODictionaryItem,
  462. (LPVOID *) &pitemValue);
  463. if (!SUCCEEDED(hrRes)) {
  464. return (hrRes);
  465. }
  466. while (*pszSubString) {
  467. hrRes = pitemValue->AddStringW((DWORD) -1,pszSubString);
  468. if (!SUCCEEDED(hrRes)) {
  469. return (hrRes);
  470. }
  471. pszSubString += wcslen(pszSubString) + 1;
  472. }
  473. hrRes = pdictSub->SetInterfaceW(pszSubName,pitemValue);
  474. if (!SUCCEEDED(hrRes)) {
  475. return (hrRes);
  476. }
  477. } else {
  478. hrRes = pdictSub->SetStringW(pszSubName,(wcslen(pszSubString)+1)*sizeof(CHAR),pszSubString);
  479. if (!SUCCEEDED(hrRes)) {
  480. return (hrRes);
  481. }
  482. }
  483. }
  484. *ppdictResult = pdictTmp;
  485. (*ppdictResult)->AddRef();
  486. return (S_OK);
  487. }
  488. SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateMultiSzFromDictionaryA( ISEODictionary *pdictDictionary,
  489. DWORD *pdwCount,
  490. LPSTR **pppszNames,
  491. LPSTR **pppszValues) {
  492. return (E_NOTIMPL);
  493. }
  494. SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateMultiSzFromDictionaryW( ISEODictionary *pdictDictionary,
  495. DWORD *pdwCount,
  496. LPWSTR **pppszNames,
  497. LPWSTR **pppszValues) {
  498. return (E_NOTIMPL);
  499. }
  500. #define DW2W(x) _itow(x,(LPWSTR) _alloca(11*sizeof(WCHAR)),10)
  501. SEODLLDEF HRESULT STDAPICALLTYPE MCISGetBindingInMetabaseA( LPCSTR pszService,
  502. DWORD dwVirtualServer,
  503. REFGUID guidEventSource,
  504. LPCSTR pszBinding,
  505. BOOL bCreate,
  506. BOOL fLock,
  507. ISEODictionary **ppdictResult) {
  508. USES_CONVERSION;
  509. return (MCISGetBindingInMetabaseW(pszService?A2W(pszService):NULL,
  510. dwVirtualServer,
  511. guidEventSource,
  512. pszBinding?A2W(pszBinding):NULL,
  513. bCreate,
  514. fLock,
  515. ppdictResult));
  516. }
  517. SEODLLDEF HRESULT STDAPICALLTYPE MCISGetBindingInMetabaseW( LPCWSTR pszService,
  518. DWORD dwVirtualServer,
  519. REFGUID guidEventSource,
  520. LPCWSTR pszBinding,
  521. BOOL bCreate,
  522. BOOL fLock,
  523. ISEODictionary **ppdictResult) {
  524. HRESULT hrRes;
  525. CComPtr<ISEOInitObject> pinitRoot;
  526. CComPtr<ISEODictionary> pdictTmp;
  527. CComQIPtr<IPropertyBag,&IID_IPropertyBag> ppropTmp;
  528. CComQIPtr<ISEODictionary,&IID_ISEODictionary> pdictRoot;
  529. CComBSTR bstrPath;
  530. if (!ppdictResult) {
  531. return (E_POINTER);
  532. }
  533. *ppdictResult = NULL;
  534. if (!pszService) {
  535. return (E_POINTER);
  536. }
  537. if ((guidEventSource != GUID_NULL) && !pszBinding && !bCreate) {
  538. return (E_INVALIDARG);
  539. }
  540. hrRes = CComObject<CSEOMetaDictionary>::_CreatorClass::CreateInstance(NULL,
  541. IID_ISEOInitObject,
  542. (LPVOID *) &pinitRoot);
  543. if (!SUCCEEDED(hrRes)) {
  544. return (hrRes);
  545. }
  546. hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
  547. IID_ISEODictionary,
  548. (LPVOID *) &pdictTmp);
  549. if (!SUCCEEDED(hrRes)) {
  550. return (hrRes);
  551. }
  552. hrRes = pdictTmp->SetStringW(L"MetabasePath",1,L"");
  553. if (!SUCCEEDED(hrRes)) {
  554. return (hrRes);
  555. }
  556. ppropTmp = pdictTmp;
  557. if (!ppropTmp) {
  558. return (E_NOINTERFACE);
  559. }
  560. hrRes = pinitRoot->Load(ppropTmp,NULL);
  561. if (!SUCCEEDED(hrRes)) {
  562. return (hrRes);
  563. }
  564. pdictRoot = pinitRoot;
  565. if (!pdictRoot) {
  566. return (E_NOINTERFACE);
  567. }
  568. bstrPath = "LM/";
  569. bstrPath.Append(pszService);
  570. bstrPath.Append("/");
  571. bstrPath.Append(DW2W(dwVirtualServer));
  572. bstrPath.Append("/SEO");
  573. if (guidEventSource != GUID_NULL) {
  574. CStringGUID objGuid;
  575. bstrPath.Append("/BindingPoints/");
  576. objGuid = guidEventSource;
  577. if (!objGuid) {
  578. return (E_INVALIDARG);
  579. }
  580. bstrPath.Append((LPCOLESTR) objGuid);
  581. bstrPath.Append("/Bindings/");
  582. if (pszBinding) {
  583. bstrPath.Append(pszBinding);
  584. } else {
  585. if (!objGuid.CalcNew()) {
  586. return (E_FAIL);
  587. }
  588. bstrPath.Append((LPCOLESTR) objGuid);
  589. }
  590. }
  591. again:
  592. hrRes = pdictRoot->GetInterfaceW(bstrPath,IID_ISEODictionary,(IUnknown **) ppdictResult);
  593. if (SUCCEEDED(hrRes) || (hrRes != SEO_E_NOTPRESENT) || !bCreate) {
  594. return (hrRes);
  595. }
  596. // We got an SEO_E_NOTPRESENT error, and the caller specified bCreate==TRUE, so we need
  597. // to create the sub-key. We do this by writing an empty dictionary to the sub-key - we'll
  598. // empty the dictionary we used to initialize the root, and write that to the sub-key.
  599. CComVariant varEmpty;
  600. hrRes = pdictTmp->SetVariantW(L"MetabasePath",&varEmpty);
  601. if (!SUCCEEDED(hrRes)) {
  602. return (hrRes);
  603. }
  604. hrRes = pdictRoot->SetInterfaceW(bstrPath,pdictTmp);
  605. if (!SUCCEEDED(hrRes)) {
  606. return (hrRes);
  607. }
  608. bCreate = FALSE;
  609. goto again;
  610. }
  611. SEODLLDEF HRESULT STDAPICALLTYPE SEOListenForEvent( ISEORouter *piRouter,
  612. HANDLE hEvent,
  613. ISEOEventSink *psinkEventSink,
  614. BOOL bOnce,
  615. DWORD *pdwListenHandle) {
  616. return (E_NOTIMPL);
  617. }
  618. SEODLLDEF HRESULT STDAPICALLTYPE SEOCancelListenForEvent( DWORD dwHandle) {
  619. return (E_NOTIMPL);
  620. }
  621. SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateIStreamFromFileA( HANDLE hFile,
  622. LPCSTR pszFile,
  623. IStream **ppstreamResult) {
  624. HRESULT hrRes;
  625. CComObject<CSEOStream> *pStream;
  626. ULARGE_INTEGER libOffset;
  627. if (!ppstreamResult) {
  628. return (E_POINTER);
  629. }
  630. *ppstreamResult = NULL;
  631. hrRes = CComObject<CSEOStream>::CreateInstance(&pStream);
  632. if (!SUCCEEDED(hrRes)) {
  633. return (hrRes);
  634. }
  635. pStream->AddRef();
  636. libOffset.QuadPart = 0;
  637. hrRes = pStream->Init(hFile,pszFile,libOffset,NULL);
  638. if (SUCCEEDED(hrRes)) {
  639. hrRes = pStream->QueryInterface(IID_IStream,(LPVOID *) ppstreamResult);
  640. }
  641. pStream->Release();
  642. return (hrRes);
  643. }
  644. SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateIStreamFromFileW( HANDLE hFile,
  645. LPCWSTR pszFile,
  646. IStream **ppstreamResult) {
  647. HRESULT hrRes;
  648. CComObject<CSEOStream> *pStream;
  649. ULARGE_INTEGER libOffset;
  650. if (!ppstreamResult) {
  651. return (E_POINTER);
  652. }
  653. *ppstreamResult = NULL;
  654. hrRes = CComObject<CSEOStream>::CreateInstance(&pStream);
  655. if (!SUCCEEDED(hrRes)) {
  656. return (hrRes);
  657. }
  658. pStream->AddRef();
  659. libOffset.QuadPart = 0;
  660. hrRes = pStream->Init(hFile,pszFile,libOffset,NULL);
  661. if (SUCCEEDED(hrRes)) {
  662. hrRes = pStream->QueryInterface(IID_IStream,(LPVOID *) ppstreamResult);
  663. }
  664. pStream->Release();
  665. return (hrRes);
  666. }
  667. SEODLLDEF HRESULT STDAPICALLTYPE SEOCopyDictionary(ISEODictionary *pdictIn, ISEODictionary **ppdictResult) {
  668. HRESULT hrRes;
  669. CComPtr<ISEODictionary> pdictTmp;
  670. if (!ppdictResult) {
  671. return (E_POINTER);
  672. }
  673. *ppdictResult = NULL;
  674. hrRes = CComObject<CSEOMemDictionary>::_CreatorClass::CreateInstance(NULL,
  675. IID_ISEODictionary,
  676. (LPVOID *) &pdictTmp);
  677. if (!SUCCEEDED(hrRes)) {
  678. return (hrRes);
  679. }
  680. if (pdictIn) {
  681. CComPtr<IUnknown> punkEnum;
  682. hrRes = pdictIn->get__NewEnum(&punkEnum);
  683. if (!SUCCEEDED(hrRes)) {
  684. return (hrRes);
  685. }
  686. CComQIPtr<IEnumVARIANT,&IID_IEnumVARIANT> pevEnum(punkEnum);
  687. if (!pevEnum) {
  688. return (E_NOINTERFACE);
  689. }
  690. VARIANT varName;
  691. VariantInit(&varName);
  692. while ((hrRes=pevEnum->Next(1,&varName,NULL))==S_OK) {
  693. VARIANT varValue;
  694. VariantInit(&varValue);
  695. hrRes = pdictIn->get_Item(&varName,&varValue);
  696. if (!SUCCEEDED(hrRes) || (varValue.vt == VT_EMPTY)) {
  697. VariantClear(&varName);
  698. return (hrRes);
  699. }
  700. hrRes = VariantChangeType(&varValue,&varValue,0,VT_UNKNOWN);
  701. if (SUCCEEDED(hrRes)) {
  702. CComQIPtr<ISEODictionary,&IID_ISEODictionary> pdictSub(varValue.punkVal);
  703. if (pdictSub) {
  704. CComPtr<ISEODictionary> pdictSubCopy;
  705. hrRes = SEOCopyDictionary(pdictSub,&pdictSubCopy);
  706. if (!SUCCEEDED(hrRes)) {
  707. VariantClear(&varName);
  708. return (hrRes);
  709. }
  710. varValue.punkVal->Release();
  711. varValue.punkVal = pdictSubCopy;
  712. varValue.punkVal->AddRef();
  713. }
  714. }
  715. hrRes = pdictTmp->put_Item(&varName,&varValue);
  716. VariantClear(&varName);
  717. VariantClear(&varValue);
  718. if (!SUCCEEDED(hrRes)) {
  719. return (hrRes);
  720. }
  721. }
  722. if (hrRes == S_FALSE) {
  723. hrRes = S_OK;
  724. }
  725. }
  726. *ppdictResult = pdictTmp;
  727. (*ppdictResult)->AddRef();
  728. return (hrRes);
  729. }
  730. static HRESULT ReadLineFromStream(IStream *pstreamIn, LPSTR *ppszLine) {
  731. HRESULT hrRes;
  732. const int c_iAllocSize = 512;
  733. LPSTR pszTmp = NULL;
  734. LPSTR pszCurr = NULL;
  735. LPSTR pszEnd = NULL;
  736. BOOL bInEscape = FALSE;
  737. BOOL bEOF = FALSE;
  738. if (!pstreamIn || !ppszLine) {
  739. return (E_POINTER);
  740. }
  741. CoTaskMemFree(*ppszLine);
  742. *ppszLine = NULL;
  743. while (1) {
  744. if (pszCurr == pszEnd) {
  745. LPSTR pszNew = (LPSTR) CoTaskMemRealloc(pszTmp,((pszCurr-pszTmp)+c_iAllocSize)*sizeof(*pszTmp));
  746. if (!pszNew) {
  747. CoTaskMemFree(pszTmp);
  748. return (E_OUTOFMEMORY);
  749. }
  750. pszCurr = pszNew + (pszCurr-pszTmp);
  751. pszEnd = pszCurr + c_iAllocSize;
  752. pszTmp = pszNew;
  753. }
  754. hrRes = pstreamIn->Read(pszCurr,sizeof(*pszCurr),NULL);
  755. if (!SUCCEEDED(hrRes)) {
  756. CoTaskMemFree(pszTmp);
  757. return (hrRes);
  758. }
  759. if (hrRes == S_FALSE) {
  760. // end-of-file - pretend like non-escaped '\n'
  761. bInEscape = FALSE;
  762. *pszCurr = '\n';
  763. bEOF = TRUE;
  764. }
  765. if (*pszCurr == '\r') {
  766. // always eat carriage returns - even escaped ones
  767. continue;
  768. }
  769. if (bInEscape) {
  770. switch (*pszCurr) {
  771. case 'n':
  772. // escape-n becomes linefeed
  773. *pszCurr = '\n';
  774. break;
  775. case 'r':
  776. // escape-r becomes carriage return
  777. *pszCurr = '\r';
  778. break;
  779. case '\n':
  780. // escaped-linefeed means line continuation
  781. pszCurr--;
  782. break;
  783. // for now, don't allow embedded NULLs - this is because we return a NULL-terminated string
  784. // case '0':
  785. // // escape-0 means embedded NULL
  786. // *pszCurr = 0;
  787. // break;
  788. case 0:
  789. // escape-NULL - just eat
  790. pszCurr--;
  791. break;
  792. default:
  793. // escape-(anything else) is just passed through
  794. break;
  795. }
  796. bInEscape = FALSE;
  797. } else {
  798. BOOL bFinished = FALSE;
  799. switch (*pszCurr) {
  800. case '\\':
  801. // first character of escape sequence
  802. pszCurr--;
  803. bInEscape = TRUE;
  804. break;
  805. case '\n':
  806. // end-of-line
  807. bFinished = TRUE;
  808. break;
  809. case 0:
  810. // non-escaped NULL - just eat
  811. pszCurr--;
  812. break;
  813. }
  814. if (bFinished) {
  815. break;
  816. }
  817. }
  818. pszCurr++;
  819. }
  820. *pszCurr = 0;
  821. *ppszLine = pszTmp;
  822. return (bEOF?S_FALSE:S_OK);
  823. }
  824. static HRESULT SEOCreateMultiSzFromIStreamA(IStream *pstreamIn,
  825. DWORD *pdwCount,
  826. LPSTR **pppszNames,
  827. LPSTR **pppszValues) {
  828. HRESULT hrRes;
  829. LPSTR *ppszLines = NULL;
  830. DWORD dwLines = NULL;
  831. if (!pstreamIn || !pdwCount || !pppszNames || !pppszValues) {
  832. return (E_POINTER);
  833. }
  834. *pdwCount = 0;
  835. *pppszNames = NULL;
  836. *pppszValues = NULL;
  837. while (1) {
  838. LPSTR *ppszNew = (LPSTR *) CoTaskMemRealloc(ppszLines,sizeof(*ppszLines)*(dwLines+1));
  839. if (!ppszNew) {
  840. hrRes = E_OUTOFMEMORY;
  841. break;
  842. }
  843. ppszLines = ppszNew;
  844. ppszLines[dwLines] = NULL;
  845. hrRes = ReadLineFromStream(pstreamIn,&ppszLines[dwLines]);
  846. if (!SUCCEEDED(hrRes)) {
  847. break;
  848. }
  849. if (!ppszLines[dwLines][0] ||
  850. (ppszLines[dwLines][0] == '#') ||
  851. !strchr(ppszLines[dwLines],'=')) {
  852. if (hrRes == S_FALSE) {
  853. break;
  854. }
  855. CoTaskMemFree(ppszLines[dwLines]);
  856. continue;
  857. }
  858. dwLines++;
  859. }
  860. if (SUCCEEDED(hrRes)) {
  861. DWORD dwIdx;
  862. LPSTR pszNameCurr = NULL;
  863. LPSTR pszValueCurr = NULL;
  864. hrRes = S_OK;
  865. while (1) {
  866. for (dwIdx=0;dwIdx<dwLines;dwIdx++) {
  867. LPSTR pszEquals = strchr(ppszLines[dwIdx],'=');
  868. if (*pppszNames) {
  869. (*pppszNames)[dwIdx] = pszNameCurr;
  870. memcpy(pszNameCurr,
  871. ppszLines[dwIdx],
  872. (pszEquals-ppszLines[dwIdx])*sizeof(*pszNameCurr));
  873. (*pppszValues)[dwIdx] = pszValueCurr;
  874. strcpy(pszValueCurr,pszEquals+1);
  875. }
  876. pszNameCurr += pszEquals - ppszLines[dwIdx] + 1;
  877. pszValueCurr += strlen(pszEquals+1) + 1 + 1; // multi-sz, so is double-NULL terminated
  878. }
  879. if (*pppszNames) {
  880. *pdwCount = dwLines;
  881. break;
  882. }
  883. if (!*pppszNames) {
  884. DWORD dwNameBytes = dwLines * sizeof(*pppszNames) + ((LPBYTE) pszNameCurr - (LPBYTE) NULL);
  885. DWORD dwValueBytes = dwLines * sizeof(*pppszValues) + ((LPBYTE) pszValueCurr - (LPBYTE) NULL);
  886. *pppszNames = (LPSTR *) CoTaskMemAlloc(dwNameBytes);
  887. *pppszValues = (LPSTR *) CoTaskMemAlloc(dwValueBytes);
  888. if (!*pppszNames || !*pppszValues) {
  889. hrRes = E_OUTOFMEMORY;
  890. break;
  891. }
  892. memset(*pppszNames,0,dwNameBytes);
  893. memset(*pppszValues,0,dwValueBytes);
  894. pszNameCurr = (LPSTR) ((LPBYTE) *pppszNames + dwLines * sizeof(*pppszNames));
  895. pszValueCurr = (LPSTR) ((LPBYTE) *pppszValues + dwLines * sizeof(*pppszValues));
  896. }
  897. }
  898. }
  899. if (!SUCCEEDED(hrRes)) {
  900. *pdwCount = 0;
  901. CoTaskMemFree(*pppszNames);
  902. CoTaskMemFree(*pppszValues);
  903. }
  904. for (DWORD dwIdx=0;dwIdx<dwLines;dwIdx++) {
  905. CoTaskMemFree(ppszLines[dwIdx]);
  906. }
  907. CoTaskMemFree(ppszLines);
  908. return (hrRes);
  909. }
  910. SEODLLDEF HRESULT STDAPICALLTYPE SEOCreateDictionaryFromIStream(IStream *pstreamIn, ISEODictionary **ppdictResult) {
  911. HRESULT hrRes;
  912. DWORD dwCount;
  913. LPSTR *ppszNames;
  914. LPSTR *ppszValues;
  915. if (!ppdictResult) {
  916. return (E_POINTER);
  917. }
  918. hrRes = SEOCreateMultiSzFromIStreamA(pstreamIn,&dwCount,&ppszNames,&ppszValues);
  919. if (!SUCCEEDED(hrRes)) {
  920. return (hrRes);
  921. }
  922. hrRes = SEOCreateDictionaryFromMultiSzA(dwCount,
  923. (LPCSTR *) ppszNames,
  924. (LPCSTR *) ppszValues,
  925. TRUE,
  926. FALSE,
  927. ppdictResult);
  928. CoTaskMemFree(ppszNames);
  929. CoTaskMemFree(ppszValues);
  930. return (hrRes);
  931. }
  932. static HRESULT SEOWriteMultiSzToIStreamA(DWORD dwCount, LPCSTR *ppszNames, LPCSTR *ppszValues, IStream *pstreamOut) {
  933. return (E_NOTIMPL);
  934. }
  935. SEODLLDEF HRESULT STDAPICALLTYPE SEOWriteDictionaryToIStream(ISEODictionary *pdictIn, IStream *pstreamOut) {
  936. HRESULT hrRes;
  937. DWORD dwCount;
  938. LPSTR *ppszNames;
  939. LPSTR *ppszValues;
  940. if (!pstreamOut) {
  941. return (E_POINTER);
  942. }
  943. hrRes = SEOCreateMultiSzFromDictionaryA(pdictIn,&dwCount,&ppszNames,&ppszValues);
  944. if (!SUCCEEDED(hrRes)) {
  945. return (hrRes);
  946. }
  947. hrRes = SEOWriteMultiSzToIStreamA(dwCount,(LPCSTR *) ppszNames,(LPCSTR *) ppszValues,pstreamOut);
  948. CoTaskMemFree(ppszNames);
  949. CoTaskMemFree(ppszValues);
  950. return (hrRes);
  951. }