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.

329 lines
9.2 KiB

  1. // Microsoft Corporation 1997
  2. //
  3. // This file contains methods for copying and releasing STGMEDIUMs and BINDINFOs
  4. // (which contains a STGMEDIUM).
  5. //
  6. // Created: 8-15-97 t-gpease
  7. //
  8. #include <urlmon.hxx>
  9. #undef URLMONOFFSETOF
  10. #define URLMONOFFSETOF(t,f) ((DWORD_PTR)(&((t*)0)->f))
  11. //
  12. // This function clears the BINDINFO structure.
  13. //
  14. //- The "cbSize" will not be clear and will be the same as it
  15. // was pasted in. This is by design so that you can reuse the
  16. // BINDINFO (eg copy another BINDINFO into it).
  17. //
  18. //- It does NOT release the memory that the BINDINFO oocupies
  19. // (this could be on the stack).
  20. //
  21. //- It does properly release items that the BINDINFO might be
  22. // pointing to.
  23. //
  24. STDAPI_(void)
  25. ReleaseBindInfo(BINDINFO * pbindinfo)
  26. {
  27. if ( !pbindinfo)
  28. return;
  29. DWORD cb = pbindinfo->cbSize;
  30. UrlMkAssert( cb &&
  31. "CopyBindInfo(): cbSize of the BINDINFO is ZERO. We need the cbSize to be set before calling us.");
  32. if(!cb )
  33. return; // we don't know which structure it is, so don't touch it.
  34. if (cb >= URLMONOFFSETOF(BINDINFO, dwReserved) && pbindinfo->pUnk)
  35. {
  36. pbindinfo->pUnk->Release();
  37. }
  38. // Orginal BINDINFO no need to check size
  39. if (pbindinfo->szExtraInfo)
  40. {
  41. delete [] pbindinfo->szExtraInfo;
  42. }
  43. // Orginal BINDINFO no need to check size
  44. if (pbindinfo->szCustomVerb)
  45. {
  46. delete [] pbindinfo->szCustomVerb;
  47. }
  48. // Orginal BINDINFO no need to check size
  49. ReleaseStgMedium(&pbindinfo->stgmedData);
  50. // set this to zero so other function will not try to use the BINDINFO
  51. ZeroMemory(pbindinfo, cb);
  52. pbindinfo->cbSize = cb; // but keep this intact
  53. return;
  54. }
  55. //
  56. // This function copies STGMEDIUM stuctures.
  57. //
  58. //- Users need to allocate the memory that the STGMEDIUM Dest will be copied
  59. // into.
  60. //
  61. //- If anything goes wrong, we return the proper HRESULT and STGMEDIUM.will
  62. // have been zero-ed.
  63. //
  64. STDAPI
  65. CopyStgMedium(const STGMEDIUM * pcstgmedSrc,
  66. STGMEDIUM * pstgmedDest)
  67. {
  68. HRESULT hr = S_OK;
  69. if ( !pcstgmedSrc || !pstgmedDest )
  70. return E_POINTER;
  71. ZeroMemory(pstgmedDest, sizeof(*pstgmedDest));
  72. switch (pcstgmedSrc->tymed)
  73. {
  74. case TYMED_HGLOBAL:
  75. {
  76. void * pvDest;
  77. const void * pcvSrc;
  78. DWORD_PTR dwcbLen;
  79. HGLOBAL hGlobalDest;
  80. if (!pcstgmedSrc->hGlobal)
  81. break; // nothing to do
  82. hr = E_OUTOFMEMORY;
  83. pcvSrc = GlobalLock(pcstgmedSrc->hGlobal);
  84. if (!pcvSrc)
  85. goto Cleanup;
  86. dwcbLen = GlobalSize(pcstgmedSrc->hGlobal);
  87. // We can't do the following line:
  88. // hGlobalDest = GlobalAlloc((GMEM_MOVEABLE | GMEM_SHARE), dwcbLen);
  89. // because we hand out the bindinfo.stgmedData.hglobal to callers
  90. // that do NOT lock it and use the handle instead of the pointer.
  91. hGlobalDest = GlobalAlloc(GMEM_FIXED | GMEM_SHARE, dwcbLen);
  92. if (!hGlobalDest)
  93. {
  94. GlobalUnlock(pcstgmedSrc->hGlobal);
  95. goto Cleanup;
  96. }
  97. pvDest = GlobalLock(hGlobalDest);
  98. if (!pvDest)
  99. {
  100. GlobalFree(hGlobalDest);
  101. GlobalUnlock(pcstgmedSrc->hGlobal);
  102. goto Cleanup;
  103. }
  104. UrlMkAssert(dwcbLen>>32 == 0);
  105. memcpy(pvDest, pcvSrc, (unsigned long)dwcbLen);
  106. pstgmedDest->hGlobal = hGlobalDest;
  107. GlobalUnlock(hGlobalDest);
  108. GlobalUnlock(pcstgmedSrc->hGlobal);
  109. hr = S_OK;
  110. }
  111. break;
  112. case TYMED_FILE:
  113. {
  114. if (!pcstgmedSrc->lpszFileName)
  115. break; // nothing to do
  116. hr = E_OUTOFMEMORY;
  117. LPWSTR lpwstr = OLESTRDuplicate(pcstgmedSrc->lpszFileName);
  118. if (!lpwstr)
  119. goto Cleanup;
  120. pstgmedDest->lpszFileName = lpwstr;
  121. hr = S_OK;
  122. }
  123. break;
  124. case TYMED_ISTREAM:
  125. {
  126. pstgmedDest->pstm = pcstgmedSrc->pstm;
  127. if ( pstgmedDest->pstm )
  128. pstgmedDest->pstm->AddRef();
  129. }
  130. break;
  131. case TYMED_ISTORAGE:
  132. {
  133. pstgmedDest->pstg = pcstgmedSrc->pstg;
  134. if ( pstgmedDest->pstg )
  135. pstgmedDest->pstg->AddRef();
  136. }
  137. break;
  138. default:
  139. UrlMkAssert( !"CloneStgMedium has encountered a TYMED it doesn't know how to copy." );
  140. // fall thru and copy it.
  141. case TYMED_NULL: // blindly copy
  142. case TYMED_GDI: // Just copy...
  143. memcpy(pstgmedDest, pcstgmedSrc, sizeof(*pstgmedDest));
  144. break;
  145. }
  146. // Common things that can be copied if we get to this point.
  147. pstgmedDest->tymed = pcstgmedSrc->tymed;
  148. pstgmedDest->pUnkForRelease = pcstgmedSrc->pUnkForRelease;
  149. if (pstgmedDest->pUnkForRelease)
  150. (pstgmedDest->pUnkForRelease)->AddRef();
  151. Cleanup:
  152. return hr;
  153. }
  154. //
  155. // This function copies BINDINFO structures.
  156. //
  157. // NOTE: IE4 added properties to the BINDINFO structure. This function
  158. // works with both versions. If the structure is extended in the
  159. // future, it will blindly copy the additional properties in the
  160. // structure.
  161. //
  162. //- Users need to allocate the memory that the BINDINFO Dest will be copied
  163. // into.
  164. //
  165. //- Users also need to set the "cbSize" of the BINDINFO Dest to
  166. // the sizeof(BINDINFO) before calling (see NOTE above).
  167. //
  168. //- If there is a "cbSize" conflict between the Src and the Dest, we will:
  169. // 1) Src->cbSize = Dest->cbSize, normal copy.
  170. // 2) Src->cbSize > Dest->cbSize, copy as much info about the Src into
  171. // the Dest as will fit.
  172. // 3) Src->cbSize < Dest->cbSize, copy the Src into the Dest, Zero the
  173. // remaining unfilled portion of the Dest.
  174. //
  175. //- We don't not copy the securityattribute. We clear this value of the
  176. // BINDINFO Dest.
  177. //
  178. //- If anything goes wrong, we return the proper HRESULT and clear the
  179. // the BINDINFO structure using ReleaseBindInfo() (below).
  180. // NOTE: If "cbSize" of the Dest is ZERO, we don't do anything.
  181. //
  182. STDAPI
  183. CopyBindInfo( const BINDINFO * pcbiSrc,
  184. BINDINFO *pbiDest )
  185. {
  186. /****** 8-15-97 t-gpease
  187. Current structure at the time of writing... from URLMON.H
  188. typedef struct tagBINDINFO {
  189. ULONG cbSize;
  190. LPWSTR szExtraInfo;
  191. STGMEDIUM stgmedData;
  192. DWORD grfBindInfoF;
  193. DWORD dwBindVerb;
  194. LPWSTR szCustomVerb;
  195. DWORD cbstgmedData;
  196. // new part below this line //
  197. DWORD dwOptions;
  198. DWORD dwOptionsFlags;
  199. DWORD dwCodePage;
  200. SECURITY_ATTRIBUTES securityAttributes;
  201. IID iid;
  202. IUnknown __RPC_FAR *pUnk;
  203. DWORD dwReserved;
  204. } BINDINFO;
  205. Anything bigger than this we will blindly copy.the size of cbSize
  206. *******/
  207. // NOTE: hr will an error until just before the Cleanup label.
  208. HRESULT hr = E_INVALIDARG;
  209. DWORD cbSrc;
  210. DWORD cbDst;
  211. if (!pcbiSrc || !pbiDest)
  212. return E_POINTER;
  213. cbSrc = pcbiSrc->cbSize;
  214. cbDst = pbiDest->cbSize;
  215. UrlMkAssert( cbSrc &&
  216. "CopyBindInfo(): cbSize of the source is ZERO. You must set the cbSize.");
  217. UrlMkAssert( cbDst &&
  218. "CopyBindInfo(): cbSize of the destination is ZERO. It needs to be set to the size of the BINDINFO before calling us.");
  219. if (!cbSrc || !cbDst)
  220. goto Abort; // nothing to do or can do.
  221. // Copy those bytes in common, zero the rest if any
  222. memcpy(pbiDest, pcbiSrc, min(cbSrc, cbDst));
  223. pbiDest->cbSize = cbDst; // always keep this intact
  224. if (cbDst > cbSrc)
  225. {
  226. ZeroMemory((BYTE *)pbiDest + cbSrc, cbDst - cbSrc);
  227. }
  228. if (cbDst >= URLMONOFFSETOF(BINDINFO, dwReserved))
  229. {
  230. ZeroMemory(&pbiDest->securityAttributes, sizeof(SECURITY_ATTRIBUTES));
  231. }
  232. if (pcbiSrc->pUnk && cbDst >= URLMONOFFSETOF(BINDINFO, dwReserved))
  233. {
  234. pbiDest->pUnk->AddRef();
  235. }
  236. // NULL these anything fails we don't want to free the Sources resources.
  237. pbiDest->szExtraInfo = NULL;
  238. pbiDest->szCustomVerb = NULL;
  239. // Original BINDINFO no need to check size
  240. hr = CopyStgMedium( &pcbiSrc->stgmedData, &pbiDest->stgmedData );
  241. if (hr)
  242. goto Cleanup;
  243. // Original BINDINFO no need to check size
  244. if (pcbiSrc->szExtraInfo)
  245. {
  246. LPWSTR lpwstr = OLESTRDuplicate(pcbiSrc->szExtraInfo);
  247. if (!lpwstr)
  248. {
  249. hr = E_OUTOFMEMORY;
  250. goto Cleanup;
  251. }
  252. pbiDest->szExtraInfo= lpwstr;
  253. }
  254. // Original BINDINFO no need to check size
  255. if (pcbiSrc->szCustomVerb)
  256. {
  257. LPWSTR lpwstr = OLESTRDuplicate(pcbiSrc->szCustomVerb);
  258. if (!lpwstr)
  259. {
  260. hr = E_OUTOFMEMORY;
  261. goto Cleanup;
  262. }
  263. pbiDest->szCustomVerb= lpwstr;
  264. }
  265. Cleanup:
  266. if (hr)
  267. {
  268. // This will set pbiDest members to zero so other function will not
  269. // try to use the new BINDINFO.
  270. ReleaseBindInfo( pbiDest );
  271. }
  272. Abort:
  273. return(hr);
  274. }