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.

437 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. gmoniker.cpp
  5. Abstract:
  6. This module contains the implementation of the
  7. CSEOGenericMoniker object.
  8. Author:
  9. Andy Jacobs (andyj@microsoft.com)
  10. Revision History:
  11. andyj 04/11/97 created
  12. --*/
  13. // GMONIKER.cpp : Implementation of CSEOGenericMoniker
  14. #include "stdafx.h"
  15. #include "seodefs.h"
  16. #include "GMONIKER.h"
  17. #ifndef CSTR_EQUAL
  18. #define CSTR_EQUAL (2)
  19. #endif
  20. LPCOLESTR szObjectType = OLESTR("MonikerType");
  21. const WCHAR QUOTE_CHAR = L'\\';
  22. const WCHAR NAME_SEP = L'=';
  23. const WCHAR ENTRY_SEP = L' ';
  24. const WCHAR PROGID_PREFIX = L'@';
  25. const WCHAR PROGID_POSTFIX = L':';
  26. IsPrefix(LPCOLESTR psPrefix, LPCOLESTR psString, int iLen) {
  27. return (CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
  28. psPrefix, iLen, psString, iLen));
  29. }
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CSEOGenericMoniker
  32. // IPersist Members
  33. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::GetClassID(/* [out] */ CLSID __RPC_FAR *pClassID) {
  34. if(!pClassID) return E_POINTER;
  35. memcpy(pClassID, &CLSID_CSEOGenericMoniker, sizeof(CLSID));
  36. _ASSERT(IsEqualCLSID(*pClassID, CLSID_CSEOGenericMoniker));
  37. return S_OK;
  38. }
  39. // IPersistStream Members
  40. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::IsDirty(void) {
  41. return S_FALSE; // Shallow binding representation hasn't changed
  42. }
  43. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Load(
  44. /* [unique][in] */ IStream __RPC_FAR *pStm) {
  45. return m_bstrMoniker.ReadFromStream(pStm);
  46. }
  47. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Save(
  48. /* [unique][in] */ IStream __RPC_FAR *pStm,
  49. /* [in] */ BOOL fClearDirty) {
  50. return m_bstrMoniker.WriteToStream(pStm);
  51. }
  52. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::GetSizeMax(
  53. /* [out] */ ULARGE_INTEGER __RPC_FAR *pcbSize) {
  54. if(!pcbSize) return E_POINTER;
  55. // Conservitive size estimate of bytes needed to save object
  56. pcbSize->QuadPart = m_bstrMoniker.Length() * sizeof(WCHAR) * 2;
  57. return S_OK;
  58. }
  59. // IMoniker Members
  60. /* [local] */ HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::BindToObject(
  61. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  62. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  63. /* [in] */ REFIID riidResult,
  64. /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvResult) {
  65. if(!pbc || !ppvResult) return E_POINTER;
  66. *ppvResult = NULL;
  67. // First, get the Running Object Table
  68. BOOL bFoundInTable = TRUE;
  69. CComPtr<IRunningObjectTable> pROT;
  70. CComPtr<IUnknown> punkObject;
  71. HRESULT hRes = pbc->GetRunningObjectTable(&pROT);
  72. if(FAILED(hRes)) return hRes;
  73. _ASSERT(!!pROT); // operator!() is defined, so use !! to test for existance.
  74. if(!pROT) return E_UNEXPECTED; // GetRunningObjectTable() didn't work
  75. // Try to find in Running Object Table
  76. hRes = pROT->GetObject((IMoniker *) this, &punkObject);
  77. // If not currently running then create it
  78. if(FAILED(hRes) || !punkObject) {
  79. bFoundInTable = FALSE;
  80. CComPtr<IPropertyBag> pBag;
  81. hRes = CoCreateInstance(CLSID_CSEOMemDictionary, NULL, CLSCTX_ALL,
  82. IID_IPropertyBag, (LPVOID *) &pBag);
  83. if(FAILED(hRes)) return hRes;
  84. _ASSERT(!!pBag); // operator!() is defined, so use !! to test for existance.
  85. SetPropertyBag(pBag);
  86. CComPtr<ISEOInitObject> pInitObject;
  87. hRes = CreateBoundObject(pBag, &pInitObject);
  88. if(FAILED(hRes)) return hRes;
  89. _ASSERT(!!pInitObject); // operator!() is defined, so use !! to test for existance.
  90. if(!pInitObject) return E_UNEXPECTED; // CreateBoundObject returned S_OK, but didn't Create an object
  91. hRes = pInitObject->Load(pBag, NULL);
  92. punkObject = pInitObject; // Save copy of pointer
  93. /* TBD: Register with the Running Object Table
  94. DWORD dwRegister;
  95. if(SUCCEEDED(hRes)) pROT->Register(0, pInitObject, (IMoniker *) this, &dwRegister);
  96. */
  97. }
  98. // punkObject should have been set by one of the code paths before this
  99. _ASSERT(!!punkObject); // operator!() is defined, so use !! to test for existance.
  100. if(!punkObject) return E_UNEXPECTED;
  101. return punkObject->QueryInterface(riidResult, ppvResult);
  102. }
  103. /* [local] */ HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::BindToStorage(
  104. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  105. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  106. /* [in] */ REFIID riid,
  107. /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObj) {
  108. return MK_E_NOSTORAGE; // The object identified by this moniker does not have its own storage.
  109. }
  110. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Reduce(
  111. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  112. /* [in] */ DWORD dwReduceHowFar,
  113. /* [unique][out][in] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkToLeft,
  114. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkReduced) {
  115. if(!ppmkReduced) return E_POINTER;
  116. *ppmkReduced = (IMoniker *) this;
  117. _ASSERT(!!*ppmkReduced); // operator!() is defined, so use !! to test for existance.
  118. if(!*ppmkReduced) return E_UNEXPECTED; // "this" not set...
  119. HRESULT hRes = (*ppmkReduced)->AddRef(); // Do this for self (the object being returned)
  120. if(SUCCEEDED(hRes)) hRes = MK_S_REDUCED_TO_SELF; // This moniker could not be reduced any further, so ppmkReduced indicates this moniker.
  121. return hRes;
  122. }
  123. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::ComposeWith(
  124. /* [unique][in] */ IMoniker __RPC_FAR *pmkRight,
  125. /* [in] */ BOOL fOnlyIfNotGeneric,
  126. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkComposite) {
  127. ATLTRACENOTIMPL(_T("CSEOGenericMoniker::ComposeWith"));
  128. }
  129. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Enum(
  130. /* [in] */ BOOL fForward,
  131. /* [out] */ IEnumMoniker __RPC_FAR *__RPC_FAR *ppenumMoniker) {
  132. if(!ppenumMoniker) return E_POINTER;
  133. *ppenumMoniker = NULL;
  134. return S_OK;
  135. }
  136. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::IsEqual(
  137. /* [unique][in] */ IMoniker __RPC_FAR *pmkOtherMoniker) {
  138. ATLTRACENOTIMPL(_T("CSEOGenericMoniker::IsEqual"));
  139. // Return S_OK vs. S_FALSE
  140. }
  141. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Hash(
  142. /* [out] */ DWORD __RPC_FAR *pdwHash) {
  143. if(!pdwHash) return E_POINTER;
  144. *pdwHash = 0; // ATLTRACENOTIMPL(_T("CSEOGenericMoniker::Hash"));
  145. return S_OK;
  146. }
  147. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::IsRunning(
  148. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  149. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  150. /* [unique][in] */ IMoniker __RPC_FAR *pmkNewlyRunning) {
  151. HRESULT hRes = E_UNEXPECTED; // hRes not set to something else
  152. if(pmkToLeft) { // If something on the left, pass it to them
  153. hRes = pmkToLeft->IsRunning(pbc, NULL, pmkNewlyRunning);
  154. } else if(pbc) { // No Moniker to left, but have a BindCtx
  155. CComPtr<IRunningObjectTable> pROT;
  156. hRes = pbc->GetRunningObjectTable(&pROT);
  157. if(FAILED(hRes)) return hRes;
  158. if(pROT) { // Try to find in Running Object Table
  159. hRes = pROT->IsRunning((IMoniker *) this);
  160. }
  161. } else {
  162. hRes = E_POINTER; // No BindCtx
  163. }
  164. return hRes;
  165. }
  166. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::GetTimeOfLastChange(
  167. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  168. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  169. /* [out] */ FILETIME __RPC_FAR *pFileTime) {
  170. return MK_E_UNAVAILABLE;
  171. }
  172. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::Inverse(
  173. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmk) {
  174. return MK_E_NOINVERSE;
  175. }
  176. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::CommonPrefixWith(
  177. /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
  178. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkPrefix) {
  179. return MK_E_NOPREFIX;
  180. }
  181. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::RelativePathTo(
  182. /* [unique][in] */ IMoniker __RPC_FAR *pmkOther,
  183. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkRelPath) {
  184. ATLTRACENOTIMPL(_T("CSEOGenericMoniker::RelativePathTo"));
  185. }
  186. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::GetDisplayName(
  187. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  188. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  189. /* [out] */ LPOLESTR __RPC_FAR *ppszDisplayName) {
  190. if(!ppszDisplayName) return E_POINTER;
  191. *ppszDisplayName = NULL;
  192. CComPtr<IMalloc> pMalloc;
  193. HRESULT hRes = CoGetMalloc(1, &pMalloc);
  194. if(SUCCEEDED(hRes)) {
  195. _ASSERT(!!pMalloc); // operator!() is defined, so use !! to test for existance.
  196. hRes = E_OUTOFMEMORY;
  197. int iSize = 5 + m_bstrMoniker.Length() + lstrlenW(GENERIC_MONIKER_VERPROGID);
  198. *ppszDisplayName = (LPOLESTR) pMalloc->Alloc(iSize * sizeof(WCHAR));
  199. if(*ppszDisplayName) {
  200. **ppszDisplayName = 0; // Terminate string
  201. lstrcatW(*ppszDisplayName, L"@");
  202. lstrcatW(*ppszDisplayName, GENERIC_MONIKER_VERPROGID); // Build the display name
  203. lstrcatW(*ppszDisplayName, L": ");
  204. lstrcatW(*ppszDisplayName, m_bstrMoniker);
  205. hRes = S_OK;
  206. }
  207. }
  208. return hRes;
  209. }
  210. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::ParseDisplayName(
  211. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  212. /* [unique][in] */ IMoniker __RPC_FAR *pmkToLeft,
  213. /* [in] */ LPOLESTR pszDisplayName,
  214. /* [out] */ ULONG __RPC_FAR *pchEaten,
  215. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut) {
  216. // Deligate!!!
  217. return ParseDisplayName(pbc, pszDisplayName, pchEaten, ppmkOut);
  218. }
  219. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::IsSystemMoniker(
  220. /* [out] */ DWORD __RPC_FAR *pdwMksys) {
  221. if(!pdwMksys) return E_POINTER;
  222. *pdwMksys = MKSYS_NONE;
  223. return S_FALSE; // Not a system moniker
  224. }
  225. // IParseDisplayName Members
  226. HRESULT STDMETHODCALLTYPE CSEOGenericMoniker::ParseDisplayName(
  227. /* [unique][in] */ IBindCtx __RPC_FAR *pbc,
  228. /* [in] */ LPOLESTR pszDisplayName,
  229. /* [out] */ ULONG __RPC_FAR *pchEaten,
  230. /* [out] */ IMoniker __RPC_FAR *__RPC_FAR *ppmkOut) {
  231. if(!pszDisplayName || !pchEaten || !ppmkOut) return E_POINTER;
  232. *pchEaten = 0; // Nothing parsed so far
  233. CComBSTR bstrMoniker;
  234. CComBSTR bstrProgID(GENERIC_MONIKER_PROGID);
  235. CComBSTR bstrVerProgID(GENERIC_MONIKER_VERPROGID);
  236. // The Ver string should completely contain the non-Ver string
  237. _ASSERT(bstrProgID.Length() > 0); // Something should be there
  238. _ASSERT(bstrProgID.Length() <= bstrVerProgID.Length());
  239. _ASSERT(IsPrefix(bstrProgID, bstrVerProgID, bstrProgID.Length()));
  240. if(PROGID_PREFIX == pszDisplayName[*pchEaten]) {
  241. ++(*pchEaten);
  242. }
  243. if(IsPrefix(bstrProgID, pszDisplayName + *pchEaten, bstrProgID.Length())) {
  244. if(IsPrefix(bstrVerProgID, pszDisplayName + *pchEaten, bstrVerProgID.Length())) {
  245. *pchEaten += bstrVerProgID.Length();
  246. } else { // Non-version string matched
  247. *pchEaten += bstrProgID.Length();
  248. }
  249. if(pszDisplayName[*pchEaten] &&
  250. (PROGID_POSTFIX == pszDisplayName[*pchEaten])) {
  251. ++(*pchEaten);
  252. }
  253. while(pszDisplayName[*pchEaten] &&
  254. (pszDisplayName[*pchEaten] == ENTRY_SEP)) {
  255. ++(*pchEaten);
  256. }
  257. if(pszDisplayName[*pchEaten]) { // If still something left
  258. bstrMoniker = &pszDisplayName[*pchEaten];
  259. *pchEaten += bstrMoniker.Length();
  260. }
  261. }
  262. CComObject<CSEOGenericMoniker> *pMoniker;
  263. HRESULT hRes = CComObject<CSEOGenericMoniker>::CreateInstance(&pMoniker);
  264. if(FAILED(hRes)) return hRes;
  265. _ASSERT(!!pMoniker); // operator!() is defined, so use !! to test for existance.
  266. if(!pMoniker) return E_UNEXPECTED; // CreateInstance failed (but returned S_OK)
  267. pMoniker->SetMonikerString(bstrMoniker);
  268. *ppmkOut = (IMoniker *) pMoniker;
  269. return pMoniker->AddRef();
  270. }
  271. HRESULT CSEOGenericMoniker::FinalConstruct() {
  272. HRESULT hrRes;
  273. hrRes = CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&m_pUnkMarshaler.p);
  274. _ASSERTE(!SUCCEEDED(hrRes)||m_pUnkMarshaler);
  275. return (SUCCEEDED(hrRes)?S_OK:hrRes);
  276. }
  277. void CSEOGenericMoniker::FinalRelease() {
  278. m_pUnkMarshaler.Release();
  279. }
  280. void CSEOGenericMoniker::SetPropertyBag(IPropertyBag *pBag) {
  281. if(!pBag) return;
  282. int iStringLength = m_bstrMoniker.Length();
  283. int iCurrentPos = 0;
  284. while(iCurrentPos < iStringLength) {
  285. CComBSTR bstrName;
  286. CComBSTR bstrValue;
  287. // Eat up multiple spaces for entry separators
  288. while((iCurrentPos < iStringLength) &&
  289. (m_bstrMoniker.m_str[iCurrentPos] == ENTRY_SEP)) {
  290. ++iCurrentPos;
  291. }
  292. // Read in the Name
  293. while((iCurrentPos < iStringLength) &&
  294. (m_bstrMoniker.m_str[iCurrentPos] != NAME_SEP)) {
  295. if((iCurrentPos < iStringLength - 1) &&
  296. (m_bstrMoniker.m_str[iCurrentPos] == QUOTE_CHAR)) {
  297. ++iCurrentPos;
  298. }
  299. bstrName.Append(&m_bstrMoniker.m_str[iCurrentPos], 1);
  300. ++iCurrentPos;
  301. }
  302. BOOL bFoundSep = FALSE;
  303. if((iCurrentPos < iStringLength) &&
  304. (m_bstrMoniker.m_str[iCurrentPos] == NAME_SEP)) {
  305. bFoundSep = TRUE;
  306. ++iCurrentPos;
  307. }
  308. // Read in the value
  309. while((iCurrentPos < iStringLength) &&
  310. (m_bstrMoniker.m_str[iCurrentPos] != ENTRY_SEP)) {
  311. if((iCurrentPos < iStringLength - 1) &&
  312. (m_bstrMoniker.m_str[iCurrentPos] == QUOTE_CHAR)) {
  313. ++iCurrentPos;
  314. }
  315. bstrValue.Append(&m_bstrMoniker.m_str[iCurrentPos], 1);
  316. ++iCurrentPos;
  317. }
  318. if(bFoundSep) { // If it's a real entry
  319. CComVariant varValue = bstrValue; // Convert BSTR to Variant
  320. pBag->Write(bstrName, &varValue);
  321. // Even if error occurs in Write(), continue processing
  322. }
  323. // Eat up multiple spaces for entry separators
  324. while((iCurrentPos < iStringLength) &&
  325. (m_bstrMoniker.m_str[iCurrentPos] == ENTRY_SEP)) {
  326. ++iCurrentPos;
  327. }
  328. }
  329. }
  330. HRESULT CSEOGenericMoniker::CreateBoundObject(IPropertyBag *pBag, ISEOInitObject **ppResult) {
  331. _ASSERT(ppResult);
  332. *ppResult = NULL;
  333. if(!pBag) return E_POINTER;
  334. CComVariant varPROGID;
  335. CLSID clsid;
  336. varPROGID.vt = VT_BSTR; // Request type from Read()
  337. varPROGID.bstrVal = NULL;
  338. HRESULT hRes = pBag->Read(szObjectType, &varPROGID, NULL);
  339. if(SUCCEEDED(hRes)) {
  340. _ASSERT(varPROGID.vt == VT_BSTR);
  341. hRes = CLSIDFromProgID(varPROGID.bstrVal, &clsid);
  342. }
  343. if(SUCCEEDED(hRes)) {
  344. hRes = CoCreateInstance(clsid, NULL, CLSCTX_ALL,
  345. IID_ISEOInitObject, (LPVOID *) ppResult);
  346. }
  347. return hRes;
  348. }