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.

336 lines
10 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. sxsasmitem.cpp
  5. Abstract:
  6. CAssemblyCacheItem implementation for installation
  7. Author:
  8. Xiaoyu Wu (xiaoyuw) April 2000
  9. Revision History:
  10. xiaoyuw 10/26/2000 revise during beta2 code review period
  11. --*/
  12. #include "stdinc.h"
  13. #include "sxsp.h"
  14. #include "fusionbuffer.h"
  15. #include "fusion.h"
  16. #include "sxsasmitem.h"
  17. #include "cassemblycacheitemstream.h"
  18. #include "util.h"
  19. #include "fusiontrace.h"
  20. #include "sxsapi.h"
  21. CAssemblyCacheItem::CAssemblyCacheItem() : m_cRef(0),
  22. m_pRunOnceCookie(NULL), m_pInstallCookie(NULL),
  23. m_fCommit(FALSE), m_fManifest(FALSE)
  24. {
  25. }
  26. CAssemblyCacheItem::~CAssemblyCacheItem()
  27. {
  28. CSxsPreserveLastError ple;
  29. ASSERT_NTC(m_cRef == 0);
  30. if (m_pRunOnceCookie)
  31. {
  32. if (!::SxspCancelRunOnceDeleteDirectory(m_pRunOnceCookie))
  33. {
  34. ::FusionpDbgPrintEx(
  35. FUSION_DBG_LEVEL_ERROR,
  36. "SXS.DLL: SxspCancelRunOnceDeleteDirectory returns FALSE, file a BUG\n");
  37. }
  38. }
  39. if (!m_strTempDir.IsEmpty())
  40. {
  41. if (!::SxspDeleteDirectory(m_strTempDir))
  42. {
  43. ::FusionpDbgPrintEx(
  44. FUSION_DBG_LEVEL_ERROR,
  45. "SXS.DLL: SxspDeleteDirectory returns FALSE, file a BUG\n");
  46. }
  47. }
  48. ple.Restore();
  49. }
  50. HRESULT
  51. CAssemblyCacheItem::Initialize()
  52. {
  53. HRESULT hr = NOERROR;
  54. FN_TRACE_HR(hr);
  55. //create temporary directory for this assembly
  56. IFW32FALSE_EXIT(::SxspCreateWinSxsTempDirectory(m_strTempDir, NULL, &m_strUidBuf, NULL));
  57. IFW32FALSE_EXIT(::SxspCreateRunOnceDeleteDirectory(m_strTempDir, &m_strUidBuf, (PVOID *)&m_pRunOnceCookie));
  58. hr = NOERROR;
  59. Exit:
  60. return hr ;
  61. }
  62. // ---------------------------------------------------------------------------
  63. // CAssemblyCacheItem::CreateStream
  64. // ---------------------------------------------------------------------------
  65. STDMETHODIMP CAssemblyCacheItem::CreateStream(
  66. /* [in] */ DWORD dwFlags,
  67. /* [in] */ LPCWSTR pszName,
  68. /* [in] */ DWORD dwFormat,
  69. /* [in] */ DWORD dwFormatFlags,
  70. /* [out] */ IStream** ppStream,
  71. /* [in, optional] */ ULARGE_INTEGER *puliMaxSize) // ????? in or OUT ?????
  72. {
  73. HRESULT hr = NOERROR;
  74. FN_TRACE_HR(hr);
  75. CStringBuffer FullPathFileNameBuf;
  76. CStringBuffer FullPathSubDirBuf;
  77. CSmartPtr<CAssemblyCacheItemStream> pStream;
  78. const static WCHAR szTemp[] = L"..";
  79. // The puliMaxSize is intended to be a hint for preallocation of the temporary storage for the stream. We just don't
  80. // use it.
  81. UNUSED(puliMaxSize);
  82. if (ppStream != NULL)
  83. *ppStream = NULL;
  84. ::FusionpDbgPrintEx(
  85. FUSION_DBG_LEVEL_INSTALLATION,
  86. "SXS: %s called with:\n"
  87. " dwFlags = 0x%08lx\n"
  88. " pszName = \"%ls\"\n"
  89. " dwFormat = %lu\n"
  90. " dwFormatFlags = %lu\n"
  91. " ppStream = %p\n"
  92. " puliMaxSize = %p\n",
  93. __FUNCTION__,
  94. dwFlags,
  95. pszName,
  96. dwFormat,
  97. dwFormatFlags,
  98. ppStream,
  99. puliMaxSize);
  100. PARAMETER_CHECK(dwFlags == 0);
  101. PARAMETER_CHECK(pszName != NULL);
  102. PARAMETER_CHECK(ppStream != NULL);
  103. //Darwin should clean their code about this : use _WIN32_ flags only
  104. PARAMETER_CHECK(
  105. (dwFormat == STREAM_FORMAT_COMPLIB_MANIFEST) ||
  106. (dwFormat == STREAM_FORMAT_WIN32_MANIFEST) ||
  107. (dwFormat == STREAM_FORMAT_COMPLIB_MODULE) ||
  108. (dwFormat == STREAM_FORMAT_WIN32_MODULE));
  109. PARAMETER_CHECK(dwFormatFlags == 0);
  110. // It's illegal to have more than one manifest in the assembly...
  111. PARAMETER_CHECK((!m_fManifest) || ((dwFormat != STREAM_FORMAT_COMPLIB_MANIFEST) && (dwFormat != STREAM_FORMAT_WIN32_MANIFEST)));
  112. *ppStream = NULL;
  113. // one and only one manifest stream for each assembly item.....
  114. if ((dwFormat == STREAM_FORMAT_COMPLIB_MANIFEST) || (dwFormat == STREAM_FORMAT_WIN32_MANIFEST))
  115. {
  116. PARAMETER_CHECK(m_fManifest == FALSE);
  117. m_fManifest = TRUE;
  118. }
  119. INTERNAL_ERROR_CHECK(!m_strTempDir.IsEmpty()); // temporary directory must be there !
  120. IFW32FALSE_EXIT(FullPathFileNameBuf.Win32Assign(m_strTempDir));
  121. IFW32FALSE_EXIT(FullPathFileNameBuf.Win32EnsureTrailingPathSeparator());
  122. IFW32FALSE_EXIT(FullPathFileNameBuf.Win32Append(pszName, ::wcslen(pszName)));
  123. // xiaoyuw@ : below wcsstr() is from old code : not sure whether we need do it
  124. // Do not allow path hackery.
  125. // need to validate this will result in a relative path within asmcache dir.
  126. // For now don't allow ".." in path; collapse the path before doing this.
  127. PARAMETER_CHECK(wcsstr(pszName, szTemp) == NULL);
  128. if (wcscspn(pszName, CUnicodeCharTraits::PathSeparators()) != wcslen(pszName))
  129. {
  130. // before file-copying, create subdirectory if needed
  131. // check backslash and forword-slash
  132. // the filename contains path info inside, such as "abc\a.dll", so we have to create "abc" subdirectory
  133. // under the temporary directory
  134. CStringBuffer sbRelativeFilePath;
  135. IFW32FALSE_EXIT(sbRelativeFilePath.Win32Assign(pszName, wcslen(pszName)));
  136. IFW32FALSE_EXIT(sbRelativeFilePath.Win32RemoveLastPathElement());
  137. IFW32FALSE_EXIT(::SxspCreateMultiLevelDirectory(m_strTempDir, sbRelativeFilePath));
  138. }
  139. IFW32FALSE_EXIT(pStream.Win32Allocate(__FILE__, __LINE__));
  140. IFW32FALSE_EXIT(
  141. pStream->OpenForWrite(
  142. FullPathFileNameBuf,
  143. 0,
  144. CREATE_NEW,
  145. FILE_FLAG_SEQUENTIAL_SCAN));
  146. if ((dwFormat == STREAM_FORMAT_COMPLIB_MANIFEST) || (dwFormat == STREAM_FORMAT_WIN32_MANIFEST)) // but should not be set both bits
  147. IFW32FALSE_EXIT(m_strManifestFileName.Win32Assign(FullPathFileNameBuf)); // record manifest filename
  148. //
  149. // By COM rules, this does the addref. Then we have to detach from this
  150. // instance so that we don't delete it
  151. //
  152. IFCOMFAILED_EXIT(pStream->QueryInterface(IID_IStream, (PVOID*)ppStream));
  153. pStream.Detach();
  154. hr = NOERROR;
  155. Exit:
  156. return hr;
  157. }
  158. // ---------------------------------------------------------------------------
  159. // CAssemblyCacheItem::Commit
  160. // ---------------------------------------------------------------------------
  161. STDMETHODIMP CAssemblyCacheItem::Commit(
  162. DWORD dwFlags,
  163. ULONG *pulDisposition
  164. )
  165. {
  166. HRESULT hr = NOERROR;
  167. FN_TRACE_HR(hr);
  168. ULONG ulDisposition;
  169. SXS_INSTALLW Install = { sizeof(Install) };
  170. ::FusionpDbgPrintEx(
  171. FUSION_DBG_LEVEL_INSTALLATION,
  172. "SXS: %s called:\n"
  173. " dwFlags = 0x%08lx\n"
  174. " pulDisposition = %p\n",
  175. __FUNCTION__,
  176. dwFlags,
  177. pulDisposition);
  178. if (pulDisposition)
  179. *pulDisposition = 0;
  180. PARAMETER_CHECK((dwFlags & ~(IASSEMBLYCACHEITEM_COMMIT_FLAG_REFRESH)) == 0);
  181. // check internal error whether it is ready to commit
  182. PARAMETER_CHECK(m_fManifest);
  183. INTERNAL_ERROR_CHECK(!m_strManifestFileName.IsEmpty()); //m_pRunOnceCookie here should be NULL...
  184. // commit here
  185. if ((!m_fCommit) || (dwFlags & IASSEMBLYCACHEITEM_COMMIT_FLAG_REFRESH))
  186. {
  187. Install.dwFlags = SXS_INSTALL_FLAG_INSTALLED_BY_DARWIN |
  188. ((dwFlags & IASSEMBLYCACHEITEM_COMMIT_FLAG_REFRESH) ? SXS_INSTALL_FLAG_REPLACE_EXISTING : 0);
  189. if (m_pInstallCookie != NULL)
  190. {
  191. Install.dwFlags |= SXS_INSTALL_FLAG_INSTALL_COOKIE_VALID;
  192. Install.pvInstallCookie = m_pInstallCookie;
  193. }
  194. Install.lpManifestPath = m_strManifestFileName;
  195. IFW32FALSE_EXIT(::SxsInstallW(&Install));
  196. if ((dwFlags & IASSEMBLYCACHEITEM_COMMIT_FLAG_REFRESH) && (m_fCommit))
  197. {
  198. ::FusionpDbgPrintEx(
  199. FUSION_DBG_LEVEL_INSTALLATION,
  200. "SXS: %s - setting disposition to IASSEMBLYCACHEITEM_COMMIT_DISPOSITION_REFRESHED\n",
  201. __FUNCTION__);
  202. ulDisposition = IASSEMBLYCACHEITEM_COMMIT_DISPOSITION_REFRESHED;
  203. }
  204. else
  205. {
  206. ::FusionpDbgPrintEx(
  207. FUSION_DBG_LEVEL_INSTALLATION,
  208. "SXS: %s - setting disposition to IASSEMBLYCACHEITEM_COMMIT_DISPOSITION_INSTALLED\n",
  209. __FUNCTION__);
  210. ulDisposition = IASSEMBLYCACHEITEM_COMMIT_DISPOSITION_INSTALLED;
  211. }
  212. m_fCommit = TRUE; // committed successfully
  213. }
  214. else
  215. {
  216. ::FusionpDbgPrintEx(
  217. FUSION_DBG_LEVEL_INSTALLATION,
  218. "SXS: %s - setting disposition to IASSEMBLYCACHEITEM_COMMIT_DISPOSITION_ALREADY_INSTALLED\n",
  219. __FUNCTION__);
  220. ulDisposition = IASSEMBLYCACHEITEM_COMMIT_DISPOSITION_ALREADY_INSTALLED;
  221. }
  222. if (pulDisposition)
  223. *pulDisposition = ulDisposition;
  224. hr = NOERROR;
  225. Exit :
  226. return hr;
  227. }
  228. // ---------------------------------------------------------------------------
  229. // CAssemblyCacheItem::AbortItem
  230. // ---------------------------------------------------------------------------
  231. STDMETHODIMP CAssemblyCacheItem::AbortItem()
  232. {
  233. ::FusionpDbgPrintEx(
  234. FUSION_DBG_LEVEL_ERROR,
  235. "SXS: %s called; returning E_NOTIMPL\n",
  236. __FUNCTION__);
  237. return E_NOTIMPL;
  238. }
  239. // ---------------------------------------------------------------------------
  240. // CAssemblyCacheItem::QI
  241. // ---------------------------------------------------------------------------
  242. STDMETHODIMP
  243. CAssemblyCacheItem::QueryInterface(REFIID riid, void** ppvObj)
  244. {
  245. if ((riid == IID_IUnknown) ||
  246. (riid == IID_IAssemblyCacheItem))
  247. {
  248. *ppvObj = static_cast<IAssemblyCacheItem*> (this);
  249. AddRef();
  250. return S_OK;
  251. }
  252. else
  253. {
  254. *ppvObj = NULL;
  255. return E_NOINTERFACE;
  256. }
  257. }
  258. // ---------------------------------------------------------------------------
  259. // CAssemblyCacheItem::AddRef
  260. // ---------------------------------------------------------------------------
  261. STDMETHODIMP_(ULONG)
  262. CAssemblyCacheItem::AddRef()
  263. {
  264. return ::SxspInterlockedIncrement (&m_cRef);
  265. }
  266. // ---------------------------------------------------------------------------
  267. // CAssemblyCacheItem::Release
  268. // ---------------------------------------------------------------------------
  269. STDMETHODIMP_(ULONG)
  270. CAssemblyCacheItem::Release()
  271. {
  272. ULONG lRet = ::SxspInterlockedDecrement (&m_cRef);
  273. if (!lRet)
  274. FUSION_DELETE_SINGLETON(this);
  275. return lRet;
  276. }