Source code of Windows XP (NT5)
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.

315 lines
8.7 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: defutil.cpp
  7. //
  8. // Contents: Implementations of utility functions for the default
  9. // handler and default link objects
  10. //
  11. // Classes: none
  12. //
  13. // Functions: DuLockContainer
  14. // DuSetClientSite
  15. // DuGetClientSite
  16. // DuCacheDelegate
  17. //
  18. // History: dd-mmm-yy Author Comment
  19. // 11-Jan-94 alexgo added VDATEHEAP macros to every function
  20. // 20-Nov-93 alexgo 32bit port
  21. //
  22. //--------------------------------------------------------------------------
  23. #include <le2int.h>
  24. #pragma SEG(defutil)
  25. #include <olerem.h>
  26. #include <ole2dbg.h>
  27. ASSERTDATA
  28. NAME_SEG(defutil)
  29. //+-------------------------------------------------------------------------
  30. //
  31. // Function: DuLockContainer
  32. //
  33. // Synopsis: Calls IOleContainer->LockContainer from the given client site
  34. //
  35. // Effects: Unlocking the container may release the calling object.
  36. //
  37. // Arguments: [pCS] -- the client site from which to get
  38. // the IOleContainer pointer
  39. // [fLockNew] -- TRUE == lock, FALSE == unlock
  40. // [pfLockCur] -- pointer to a flag with the current lock
  41. // state
  42. //
  43. // Requires:
  44. //
  45. // Returns: void
  46. //
  47. // Signals:
  48. //
  49. // Modifies:
  50. //
  51. // Algorithm:
  52. //
  53. // History: dd-mmm-yy Author Comment
  54. // 20-Nov-93 alexgo 32bit port
  55. //
  56. // Notes:
  57. //
  58. //--------------------------------------------------------------------------
  59. #pragma SEG(DuLockContainer)
  60. INTERNAL_(void) DuLockContainer(IOleClientSite FAR* pCS, BOOL fLockNew,
  61. BOOL FAR*pfLockCur)
  62. {
  63. VDATEHEAP();
  64. #ifdef _DEBUG
  65. BOOL fLocked = FALSE; // used only for debugging so don't waste
  66. // the code space in the retail version
  67. #endif // _DEBUG
  68. IOleContainer FAR* pContainer;
  69. //the double bang turns each into a true boolean
  70. if (!!fLockNew == !!*pfLockCur)
  71. {
  72. // already locked as needed
  73. return;
  74. }
  75. // set flag to false first since unlocking container may release obj;
  76. // we can just set to false since it is either already false or going
  77. // to become false (don't set to true until we know the lock completed).
  78. *pfLockCur = FALSE;
  79. if (pCS == NULL)
  80. {
  81. pContainer = NULL;
  82. }
  83. else
  84. {
  85. HRESULT hresult = pCS->GetContainer(&pContainer);
  86. // Excel 5 can return S_FALSE, pContainer == NULL
  87. // so we can't use AssertOutPtrIface here since it
  88. // expects all successful returns to provide a
  89. // valid interface
  90. if (hresult != NOERROR)
  91. {
  92. pContainer = NULL; // just in case
  93. }
  94. }
  95. if (pContainer != NULL)
  96. {
  97. // we assume that LockContainer will succeed first and
  98. // and set the locked flag that was passed into us. This
  99. // way, if LockContainer succeeeds, we won't access memory
  100. // that could have potentially been blown away.
  101. // If it *fails*, then we handle reset the flag (as our
  102. // memory would not have been free'd)
  103. BOOL fLockOld = *pfLockCur;
  104. *pfLockCur = fLockNew;
  105. if( pContainer->LockContainer(fLockNew) != NOERROR )
  106. {
  107. //failure case, we were not deleted
  108. *pfLockCur = fLockOld;
  109. //fLocked is FALSE
  110. }
  111. #ifdef _DEBUG
  112. else
  113. {
  114. fLocked = TRUE;
  115. }
  116. #endif // _DEBUG
  117. pContainer->Release();
  118. }
  119. }
  120. //+-------------------------------------------------------------------------
  121. //
  122. // Function: DuSetClientSite
  123. //
  124. // Synopsis: Called by the default handler and deflink SetClientSite
  125. // implemenations; Releases the old client site (and unlocks
  126. // its container), stores the client site (locking its
  127. // container).
  128. //
  129. // Effects:
  130. //
  131. // Arguments: [fRunning] -- whether or not the delegate is running
  132. // [pCSNew] -- the new client site
  133. // [ppCSCur] -- a pointer to the original client site
  134. // pointer. [*ppCSCur] will be reset
  135. // to the new client site pointer.
  136. // [pfLockCur] -- pointer to the fLocked flag, used by
  137. // DuLockContainer.
  138. //
  139. // Requires:
  140. //
  141. // Returns: HRESULT
  142. //
  143. // Signals:
  144. //
  145. // Modifies:
  146. //
  147. // Algorithm:
  148. //
  149. // History: dd-mmm-yy Author Comment
  150. // 22-Nov-93 alexgo 32bit port
  151. //
  152. // Notes:
  153. //
  154. //--------------------------------------------------------------------------
  155. #pragma SEG(DuSetClientSite)
  156. INTERNAL DuSetClientSite(BOOL fRunning, IOleClientSite FAR* pCSNew,
  157. IOleClientSite FAR* FAR* ppCSCur, BOOL FAR*pfLockCur)
  158. {
  159. VDATEHEAP();
  160. if (pCSNew)
  161. {
  162. VDATEIFACE( pCSNew );
  163. }
  164. IOleClientSite FAR* pCSOldClientSite = *ppCSCur;
  165. BOOL fLockOldClientSite = *pfLockCur;
  166. *pfLockCur = FALSE; // New ClientSite is not Locked.
  167. if ((*ppCSCur = pCSNew) != NULL)
  168. {
  169. // we've decided to keep the pointer that's been passed to us. So we
  170. // must AddRef() and Lock if in Running state.
  171. pCSNew->AddRef();
  172. // Lock the newcontainer
  173. if (fRunning)
  174. {
  175. DuLockContainer(pCSNew, TRUE, pfLockCur);
  176. }
  177. }
  178. // If Already Had a ClientSite, Unlock and Free
  179. if (pCSOldClientSite != NULL)
  180. {
  181. // Unlock the old container
  182. if (fRunning)
  183. {
  184. DuLockContainer(pCSOldClientSite, FALSE, &fLockOldClientSite);
  185. }
  186. pCSOldClientSite->Release();
  187. }
  188. return NOERROR;
  189. }
  190. //+-------------------------------------------------------------------------
  191. //
  192. // Function: DuCacheDelegate
  193. //
  194. // Synopsis: Retrieves the requested interface from [pUnk]. If [fAgg] is
  195. // true, we release the pointer (so ref counts to not get
  196. // obfuscated ;-)
  197. //
  198. // Effects:
  199. //
  200. // Arguments: [ppUnk] -- the object to QueryInterface on
  201. // [iid] -- the requested interface
  202. // [ppv] -- where to put the pointer to the interface
  203. // [pUnkOuter] -- controlling unknown, if non-NULL indicates
  204. // aggregation and release is called on it
  205. //
  206. //
  207. //
  208. // Requires:
  209. //
  210. // Returns: void *, the requested interface pointer
  211. //
  212. // Signals:
  213. //
  214. // Modifies:
  215. //
  216. // Algorithm:
  217. //
  218. // History: dd-mmm-yy Author Comment
  219. // 29-Jun-94 alexgo better handle re-entrancy
  220. // 20-Jun-94 alexgo updated to May '94 aggregation rules
  221. // 22-Nov-93 alexgo 32bit port
  222. //
  223. // Notes:
  224. //
  225. //--------------------------------------------------------------------------
  226. #pragma SEG(DuCacheDelegate)
  227. INTERNAL_(void FAR*) DuCacheDelegate(IUnknown FAR** ppUnk,
  228. REFIID iid, LPVOID FAR* ppv, IUnknown *pUnkOuter)
  229. {
  230. VDATEHEAP();
  231. if (*ppUnk != NULL && *ppv == NULL)
  232. {
  233. if ((*ppUnk)->QueryInterface (iid, ppv) == NOERROR)
  234. {
  235. // the QI may actually be an outgoing call so it
  236. // is possible that ppUnk was released and set to
  237. // NULL during our call. To make the default link
  238. // and handler simpler, we check for that case and
  239. // release any pointer we may have obtained
  240. // from the QI
  241. if( *ppUnk == NULL )
  242. {
  243. LEDebugOut((DEB_WARN, "WARNING: Delegate "
  244. "released during QI, should be OK\n"));
  245. if( *ppv )
  246. {
  247. // this should never be a final
  248. // release on the default handler
  249. // since we are calling it from
  250. // within a method in the default
  251. // link object. Therefore,
  252. // we do not need to guard this
  253. // release
  254. //
  255. // in the case of the link object,
  256. // this may be the final release
  257. // on the proxies, but since they are
  258. // not aggregated into the link
  259. // object, that's OK.
  260. (*(IUnknown **)ppv)->Release();
  261. *ppv = NULL;
  262. }
  263. }
  264. if( pUnkOuter && *ppv)
  265. {
  266. // we will keep the pointer but we don't want
  267. // to bump the ref count of the aggregate,
  268. // so we gotta do Release() on the controlling
  269. // unknown.
  270. pUnkOuter->Release();
  271. }
  272. }
  273. }
  274. return *ppv;
  275. }
  276.