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.

627 lines
16 KiB

  1. /*++ /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. pcmreader.cpp
  5. Abstract:
  6. implementation of PrecompiledManifestReader
  7. Author:
  8. Xiaoyu Wu (xiaoyuw) June 2000
  9. Revision History:
  10. --*/
  11. #include "stdinc.h"
  12. #include "pcm.h"
  13. /* main function of this class
  14. pwcText in XML_NODE_INFO is not allocated in the code because we use file mapping
  15. */
  16. HRESULT
  17. CPrecompiledManifestReader::InvokeNodeFactory(PCWSTR pcmFileName, IXMLNodeFactory * pXMLNodeFactory)
  18. {
  19. HRESULT hr = NOERROR;
  20. PCMHeader pcmHeader;
  21. PCM_RecordHeader pcmRecordHeader;
  22. typedef XML_NODE_INFO* PXML_NODE_INFO;
  23. PXML_NODE_INFO* ppNodes = NULL; // array of PXML_NODE_INFO
  24. XML_NODE_INFO* pXMLData = NULL;
  25. ULONG i, j;
  26. BOOL fEmpty = FALSE;
  27. if ((!pcmFileName) || (!pXMLNodeFactory))
  28. return E_INVALIDARG;
  29. hr = OpenForRead(pcmFileName);
  30. if (FAILED(hr))
  31. goto Exit;
  32. hr = ReadPCMHeader(&pcmHeader);
  33. if (FAILED(hr))
  34. goto Exit;
  35. if ( pcmHeader.iVersion != 1) { // wrong version number
  36. ::FusionpDbgPrintEx(
  37. FUSION_DBG_LEVEL_ERROR,
  38. "SXS.DLL: Wrong Version of Precompiled manifest file %S in %S()\n", pcmFileName, __FUNCTION__);
  39. hr = E_FAIL;
  40. goto Exit;
  41. }
  42. // by allocate the maximum PXML_NODE_INFO, this space would be reused
  43. ppNodes = FUSION_NEW_ARRAY(PXML_NODE_INFO, pcmHeader.usMaxNodeCount);
  44. if (!ppNodes) {
  45. hr = E_OUTOFMEMORY;
  46. goto Exit;
  47. }
  48. pXMLData = FUSION_NEW_ARRAY(XML_NODE_INFO, pcmHeader.usMaxNodeCount);
  49. if (!pXMLData){
  50. hr = E_OUTOFMEMORY;
  51. goto Exit;
  52. }
  53. memset(pXMLData, 0, sizeof(XML_NODE_INFO)*pcmHeader.usMaxNodeCount);
  54. // setup the pointer array and data
  55. for (i=0;i<pcmHeader.usMaxNodeCount; i++)
  56. ppNodes[i] = &pXMLData[i];
  57. for ( i=0; i<pcmHeader.ulRecordCount; i++) {
  58. hr = ReadPCMRecordHeader(&pcmRecordHeader);
  59. if (FAILED(hr))
  60. goto Exit;
  61. switch(pcmRecordHeader.typeID) {
  62. case ENDCHILDREN_PRECOMP_MANIFEST :
  63. hr = ReadPCMRecord(ppNodes, &pcmRecordHeader, &fEmpty); // fEmpty would be set
  64. break;
  65. case CREATENODE_PRECOMP_MANIFEST :
  66. hr = ReadPCMRecord(ppNodes, &pcmRecordHeader, NULL); // m_ulLineNumber would be Set
  67. break;
  68. case BEGINCHILDREN_PRECOMP_MANIFEST :
  69. hr = ReadPCMRecord(ppNodes, &pcmRecordHeader, NULL);
  70. break;
  71. default:
  72. ::FusionpDbgPrintEx(
  73. FUSION_DBG_LEVEL_ERROR,
  74. "SXS.DLL: %S() failed for invalid typeID in PCM Record", __FUNCTION__);
  75. hr = E_UNEXPECTED;
  76. } // end of swtich
  77. if (FAILED(hr))
  78. goto Exit;
  79. switch (pcmRecordHeader.typeID){
  80. case CREATENODE_PRECOMP_MANIFEST:
  81. hr = pXMLNodeFactory->CreateNode(this, NULL, (USHORT)(pcmRecordHeader.NodeCount), ppNodes);
  82. // "this" is passed in CreateNode because it has implemented IXMLNodeSource
  83. break;
  84. case BEGINCHILDREN_PRECOMP_MANIFEST:
  85. hr = pXMLNodeFactory->BeginChildren(NULL, *ppNodes);
  86. break;
  87. case ENDCHILDREN_PRECOMP_MANIFEST :
  88. hr = pXMLNodeFactory->EndChildren(NULL, fEmpty, *ppNodes);
  89. break;
  90. default:
  91. ::FusionpDbgPrintEx(
  92. FUSION_DBG_LEVEL_ERROR,
  93. "SXS.DLL: %S() failed for invalid typeID in PCM Record", __FUNCTION__);
  94. hr = E_UNEXPECTED;
  95. break;
  96. }// end of switch
  97. if ( FAILED(hr))
  98. goto Exit;
  99. } // end of for
  100. hr = Close();
  101. if ( FAILED(hr))
  102. goto Exit;
  103. hr = NOERROR;
  104. Exit:
  105. if (pXMLData)
  106. {
  107. FUSION_DELETE_ARRAY(pXMLData);
  108. pXMLData = NULL;
  109. }
  110. if (ppNodes)
  111. {
  112. FUSION_DELETE_ARRAY(ppNodes);
  113. ppNodes = NULL;
  114. }
  115. return hr;
  116. }
  117. // helper functions
  118. HRESULT
  119. CPrecompiledManifestReader::ReadPCMHeader(PCMHeader* pHeader)
  120. {
  121. HRESULT hr = NOERROR;
  122. if ( ! pHeader )
  123. return E_INVALIDARG;
  124. ASSERT(m_lpMapAddress);
  125. hr = this->Read((PVOID)pHeader, sizeof(PCMHeader), NULL);
  126. if ( FAILED(hr))
  127. goto Exit;
  128. if ( pHeader->iVersion != 1 ){ // wrong file header, stop
  129. ::FusionpDbgPrintEx(
  130. FUSION_DBG_LEVEL_ERROR,
  131. "SXS.DLL: Wrong Version of Precompiled manifest file in %S()\n", __FUNCTION__);
  132. hr = E_UNEXPECTED;
  133. goto Exit;
  134. }
  135. hr = NOERROR;
  136. Exit:
  137. return hr;
  138. }
  139. HRESULT
  140. CPrecompiledManifestReader::ReadPCMRecordHeader(PCM_RecordHeader * pHeader)
  141. {
  142. HRESULT hr = NOERROR;
  143. if (!pHeader)
  144. return E_INVALIDARG;
  145. ASSERT(m_lpMapAddress);
  146. return this->Read((PVOID)pHeader, sizeof(PCM_RecordHeader), NULL);
  147. }
  148. inline void FromPCMXMLNodeToXMLNode(XML_NODE_INFO * pNode, PCM_XML_NODE_INFO * pPCMNode)
  149. {
  150. ASSERT(pNode && pPCMNode);
  151. pNode->dwSize = pPCMNode->dwSize;
  152. pNode->dwType = pPCMNode->dwType;
  153. pNode->dwSubType = pPCMNode->dwSubType;
  154. pNode->fTerminal = pPCMNode->fTerminal;
  155. pNode->ulLen = pPCMNode->ulLen;
  156. pNode->ulNsPrefixLen= pPCMNode->ulNsPrefixLen;
  157. pNode->pwcText = NULL;
  158. return;
  159. }
  160. HRESULT
  161. CPrecompiledManifestReader::ReadPCMRecord(XML_NODE_INFO ** ppNodes,
  162. PCM_RecordHeader * pRecordHeader, PVOID param)
  163. {
  164. HRESULT hr = NOERROR;
  165. ULONG i, strOffset;
  166. PVOID pData, ptr;
  167. PCM_XML_NODE_INFO pcmNode;
  168. if ( !ppNodes || !pRecordHeader)
  169. return E_INVALIDARG;
  170. // point to the data in the mapped file
  171. pData = (BYTE *)m_lpMapAddress + m_dwFilePointer;
  172. switch (pRecordHeader->typeID){
  173. default:
  174. ::FusionpDbgPrintEx(
  175. FUSION_DBG_LEVEL_ERROR,
  176. "SXS.DLL: %S() failed for invalid typeID in PCM Record", __FUNCTION__);
  177. hr = E_UNEXPECTED;
  178. goto Exit;
  179. break;
  180. case CREATENODE_PRECOMP_MANIFEST:
  181. memcpy(PVOID(&m_ulLineNumberFromCreateNodeRecord), (BYTE *)pData + pRecordHeader->NodeCount * sizeof(PCM_XML_NODE_INFO), sizeof(ULONG));
  182. break;
  183. case BEGINCHILDREN_PRECOMP_MANIFEST:
  184. break;
  185. case ENDCHILDREN_PRECOMP_MANIFEST :
  186. ASSERT(param);
  187. memcpy(param, (BYTE *)pData + pRecordHeader->NodeCount * sizeof(PCM_XML_NODE_INFO), sizeof(BOOL));
  188. break;
  189. } // end of switch
  190. ptr = pData;
  191. for (i=0; i< pRecordHeader->NodeCount; i++) {
  192. //memcpy((PVOID)ppNodes[i], ptr, sizeof(PCM_XML_NODE_INFO));
  193. memcpy((PVOID)&pcmNode, ptr, sizeof(PCM_XML_NODE_INFO));
  194. FromPCMXMLNodeToXMLNode(ppNodes[i], &pcmNode); // void func
  195. // reset pwcText
  196. strOffset=pcmNode.offset;
  197. ppNodes[i]->pwcText = (WCHAR*)((BYTE *)pData + strOffset);
  198. ppNodes[i]->pNode = NULL;
  199. ppNodes[i]->pReserved = NULL;
  200. ptr = (BYTE *)ptr + sizeof(PCM_XML_NODE_INFO);
  201. }
  202. // reset the pointer of file
  203. m_dwFilePointer += pRecordHeader->RecordSize;
  204. hr = NOERROR;
  205. Exit:
  206. return hr;
  207. }
  208. HRESULT
  209. CPrecompiledManifestReader::Close()
  210. {
  211. HRESULT hr = NOERROR;
  212. if (m_lpMapAddress)
  213. if ( ! ::UnmapViewOfFile(m_lpMapAddress)) {
  214. // continue the close process even hr is not NOERROR
  215. hr = HRESULT_FROM_WIN32(::FusionpGetLastWin32Error());
  216. }
  217. if (m_hFileMapping != INVALID_HANDLE_VALUE)
  218. if ( ! ::CloseHandle(m_hFileMapping)) {
  219. // UnmapViewOfFile is done successfully
  220. if ( hr == NOERROR )
  221. hr = HRESULT_FROM_WIN32(::FusionpGetLastWin32Error());
  222. }
  223. if (m_hFile != INVALID_HANDLE_VALUE)
  224. if ( ! ::CloseHandle(m_hFile)) {
  225. // UnmapViewOfFile and CloseHandle(filemapping) is done successfully
  226. if ( hr == NOERROR )
  227. hr = HRESULT_FROM_WIN32(::FusionpGetLastWin32Error());
  228. }
  229. if ( FAILED(hr))
  230. goto Exit;
  231. this->Reset();
  232. hr = NOERROR;
  233. Exit:
  234. return hr;
  235. }
  236. VOID CPrecompiledManifestReader::Reset()
  237. {
  238. m_lpMapAddress = NULL;
  239. m_hFileMapping = INVALID_HANDLE_VALUE;
  240. m_hFile = INVALID_HANDLE_VALUE;
  241. m_dwFilePointer = 0;
  242. return;
  243. }
  244. HRESULT
  245. CPrecompiledManifestReader::OpenForRead(
  246. PCWSTR pszPath,
  247. DWORD dwShareMode,
  248. DWORD dwCreationDisposition,
  249. DWORD dwFlagsAndAttributes
  250. )
  251. {
  252. HRESULT hr = NOERROR;
  253. if (pszPath == NULL)
  254. return E_INVALIDARG;
  255. if (m_hFile != INVALID_HANDLE_VALUE){
  256. hr = E_UNEXPECTED;
  257. goto Exit;
  258. }
  259. m_hFile = ::CreateFileW(
  260. pszPath,
  261. GENERIC_READ,
  262. dwShareMode,
  263. NULL,
  264. dwCreationDisposition,
  265. dwFlagsAndAttributes,
  266. NULL);
  267. if (m_hFile == INVALID_HANDLE_VALUE){
  268. ::FusionpDbgPrintEx(
  269. FUSION_DBG_LEVEL_ERROR,
  270. "SXS.DLL: %S() failed; GetLastError() = %d\n", __FUNCTION__, ::FusionpGetLastWin32Error());
  271. hr = E_UNEXPECTED;
  272. goto Exit;
  273. }
  274. m_dwFileSize = GetFileSize(m_hFile, NULL);
  275. if ( m_dwFileSize== INVALID_FILE_SIZE ) {
  276. ::FusionpDbgPrintEx(
  277. FUSION_DBG_LEVEL_ERROR,
  278. "SXS.DLL: %S() call GetFileSize failed, GetLastError() = %d\n", __FUNCTION__, ::FusionpGetLastWin32Error());
  279. hr = E_UNEXPECTED;
  280. goto Exit;
  281. }
  282. // open filemapping
  283. ASSERT(m_hFileMapping == INVALID_HANDLE_VALUE);
  284. if (m_hFileMapping != INVALID_HANDLE_VALUE){
  285. hr = E_UNEXPECTED;
  286. goto Exit;
  287. }
  288. m_hFileMapping = ::CreateFileMappingW(m_hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  289. if (m_hFileMapping == INVALID_HANDLE_VALUE){
  290. hr = HRESULT_FROM_WIN32(::FusionpGetLastWin32Error());
  291. goto Exit;
  292. }
  293. // map view of file
  294. ASSERT(m_lpMapAddress == NULL);
  295. if ( m_lpMapAddress ) {
  296. hr = E_UNEXPECTED;
  297. goto Exit;
  298. }
  299. m_lpMapAddress = MapViewOfFile(m_hFileMapping, FILE_MAP_READ, 0, 0, 0); // mpa the whole file
  300. if (!m_lpMapAddress) {
  301. hr = E_FAIL;
  302. goto Exit;
  303. }
  304. hr = NOERROR;
  305. Exit:
  306. if ( FAILED(hr))
  307. Close();
  308. return hr;
  309. }
  310. // IStream methods:
  311. HRESULT
  312. CPrecompiledManifestReader::Read(void *pv, ULONG cb, ULONG *pcbRead)
  313. {
  314. DWORD dwData;
  315. ULONG cbRead;
  316. if (pcbRead)
  317. *pcbRead = 0;
  318. if (!pv)
  319. return E_INVALIDARG;
  320. if ( m_dwFilePointer >= m_dwFileSize ) // read at the file end
  321. return HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
  322. dwData = m_dwFileSize - m_dwFilePointer;
  323. cbRead = (cb <= dwData) ? cb : dwData;
  324. memcpy(pv, (BYTE *)m_lpMapAddress + m_dwFilePointer, cbRead);
  325. m_dwFilePointer += cbRead;
  326. if (pcbRead)
  327. *pcbRead = cbRead;
  328. return NOERROR;
  329. }
  330. HRESULT
  331. CPrecompiledManifestReader::Write(void const *pv, ULONG cb, ULONG *pcbWritten)
  332. {
  333. if (pcbWritten)
  334. *pcbWritten = 0;
  335. ASSERT(FALSE);
  336. return E_NOTIMPL;
  337. }
  338. HRESULT
  339. CPrecompiledManifestReader::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
  340. {
  341. if (plibNewPosition)
  342. plibNewPosition->QuadPart = 0;
  343. ASSERT(FALSE);
  344. return E_NOTIMPL;
  345. }
  346. HRESULT
  347. CPrecompiledManifestReader::SetSize(ULARGE_INTEGER libNewSize)
  348. {
  349. ASSERT(FALSE);
  350. return E_NOTIMPL;
  351. }
  352. HRESULT
  353. CPrecompiledManifestReader::CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
  354. {
  355. if (pcbWritten)
  356. pcbWritten->QuadPart = 0;
  357. ASSERT(FALSE);
  358. return E_NOTIMPL;
  359. }
  360. HRESULT
  361. CPrecompiledManifestReader::Commit(DWORD grfCommitFlags)
  362. {
  363. ASSERT(FALSE);
  364. return E_NOTIMPL;
  365. }
  366. HRESULT
  367. CPrecompiledManifestReader::Revert()
  368. {
  369. ASSERT(FALSE);
  370. return E_NOTIMPL;
  371. }
  372. HRESULT
  373. CPrecompiledManifestReader::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  374. {
  375. ASSERT(FALSE);
  376. return E_NOTIMPL;
  377. }
  378. HRESULT
  379. CPrecompiledManifestReader::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
  380. {
  381. ASSERT(FALSE);
  382. return E_NOTIMPL;
  383. }
  384. HRESULT
  385. CPrecompiledManifestReader::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
  386. {
  387. ASSERT(FALSE);
  388. return E_NOTIMPL;
  389. }
  390. HRESULT
  391. CPrecompiledManifestReader::Clone(IStream **ppIStream)
  392. {
  393. if ( ppIStream )
  394. *ppIStream = NULL;
  395. ASSERT(FALSE);
  396. return E_NOTIMPL;
  397. }
  398. // IXMLNodeSource methods, only GetLineNumber are implemented got PCM purpose
  399. HRESULT
  400. CPrecompiledManifestReader::SetFactory(IXMLNodeFactory *pNodeFactory)
  401. {
  402. ASSERT(FALSE);
  403. return E_NOTIMPL;
  404. }
  405. HRESULT
  406. CPrecompiledManifestReader::GetFactory(IXMLNodeFactory** ppNodeFactory)
  407. {
  408. if (ppNodeFactory)
  409. *ppNodeFactory = NULL;
  410. ASSERT(FALSE);
  411. return E_NOTIMPL;
  412. }
  413. HRESULT
  414. CPrecompiledManifestReader::Abort(BSTR bstrErrorInfo)
  415. {
  416. ASSERT(FALSE);
  417. return E_NOTIMPL;
  418. }
  419. ULONG
  420. CPrecompiledManifestReader::GetLineNumber(void)
  421. {
  422. ASSERT(m_ulLineNumberFromCreateNodeRecord != (ULONG)-1);
  423. ULONG tmp = m_ulLineNumberFromCreateNodeRecord;
  424. // do not reset it to be (-1) because the caller may call this function more than once
  425. //m_ulLineNumberFromCreateNodeRecord = (ULONG)-1;
  426. return tmp;
  427. }
  428. ULONG
  429. CPrecompiledManifestReader::GetLinePosition(void)
  430. {
  431. ASSERT(FALSE);
  432. return ULONG(-1);
  433. }
  434. ULONG
  435. CPrecompiledManifestReader::GetAbsolutePosition(void)
  436. {
  437. ASSERT(FALSE);
  438. return ULONG(-1);
  439. }
  440. HRESULT
  441. CPrecompiledManifestReader::GetLineBuffer(const WCHAR **ppwcBuf, ULONG *pulLen, ULONG *pulStartPos)
  442. {
  443. if (ppwcBuf)
  444. *ppwcBuf = NULL;
  445. if (pulLen)
  446. * pulLen = 0;
  447. if (pulStartPos)
  448. *pulStartPos = NULL;
  449. ASSERT(FALSE);
  450. return E_NOTIMPL;
  451. }
  452. HRESULT
  453. CPrecompiledManifestReader::GetLastError(void)
  454. {
  455. ASSERT(FALSE);
  456. return E_NOTIMPL;
  457. }
  458. HRESULT
  459. CPrecompiledManifestReader::GetErrorInfo(BSTR *pbstrErrorInfo)
  460. {
  461. ASSERT(FALSE);
  462. return E_NOTIMPL;
  463. }
  464. ULONG
  465. CPrecompiledManifestReader::GetFlags()
  466. {
  467. ASSERT(FALSE);
  468. return ULONG(-1);
  469. }
  470. HRESULT
  471. CPrecompiledManifestReader::GetURL(const WCHAR **ppwcBuf)
  472. {
  473. if (ppwcBuf)
  474. *ppwcBuf = NULL;
  475. ASSERT(FALSE);
  476. return E_NOTIMPL;
  477. }
  478. // IUnknown method implementation
  479. ULONG
  480. CPrecompiledManifestReader::AddRef()
  481. {
  482. ULONG ulResult = ::SxspInterlockedIncrement(&m_cRef);
  483. return ulResult;
  484. }
  485. ULONG
  486. CPrecompiledManifestReader::Release()
  487. {
  488. ULONG ulResult = ::SxspInterlockedDecrement(&m_cRef);
  489. if (ulResult == 0 )
  490. {
  491. FUSION_DELETE_SINGLETON(this);
  492. }
  493. return ulResult;
  494. }
  495. HRESULT
  496. CPrecompiledManifestReader::QueryInterface(REFIID riid, LPVOID *ppvObj)
  497. {
  498. HRESULT hr = NOERROR;
  499. IUnknown *pIUnknown = NULL;
  500. if (ppvObj != NULL)
  501. *ppvObj = NULL;
  502. if (ppvObj == NULL){
  503. hr = E_POINTER;
  504. goto Exit;
  505. }
  506. if (riid == __uuidof(this))
  507. *ppvObj = this;
  508. else if ((riid == IID_IUnknown) ||
  509. (riid == IID_ISequentialStream) ||
  510. (riid == IID_IStream))
  511. pIUnknown = static_cast<IStream *>(this);
  512. else if ( riid == IID_IXMLNodeSource )
  513. pIUnknown = static_cast<IXMLNodeSource *>(this);
  514. else
  515. {
  516. hr = E_NOINTERFACE;
  517. goto Exit;
  518. }
  519. AddRef();
  520. if (pIUnknown != NULL)
  521. *ppvObj = pIUnknown;
  522. hr = NOERROR;
  523. Exit:
  524. return hr;
  525. }