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.

660 lines
19 KiB

  1. //***************************************************************************
  2. //
  3. // (c) 2001 by Microsoft Corp. All Rights Reserved.
  4. //
  5. //***************************************************************************
  6. #include "precomp.h"
  7. #include <wbemcomn.h>
  8. #include "a51tools.h"
  9. #include "objheap.h"
  10. #include "index.h"
  11. #include "creposit.h"
  12. //*******************************************************************
  13. //*******************************************************************
  14. long CObjectHeap::Initialize(CPageSource * pAbstractSource,
  15. WCHAR * wszBaseName,
  16. DWORD dwBaseNameLen)
  17. {
  18. if (m_bInit)
  19. return ERROR_SUCCESS;
  20. long lRes;
  21. lRes = m_Heap.Initialize(pAbstractSource);
  22. if(lRes != ERROR_SUCCESS)
  23. return lRes;
  24. lRes = m_Index.Initialize(dwBaseNameLen, wszBaseName, pAbstractSource);
  25. if(lRes != ERROR_SUCCESS)
  26. return lRes;
  27. m_bInit = TRUE;
  28. return lRes;
  29. }
  30. //*******************************************************************
  31. //*******************************************************************
  32. long CObjectHeap::Uninitialize(DWORD dwShutDownFlags)
  33. {
  34. if (!m_bInit)
  35. return ERROR_SUCCESS;
  36. m_Index.Shutdown(dwShutDownFlags);
  37. m_Heap.Shutdown(dwShutDownFlags);
  38. m_bInit = FALSE;
  39. return ERROR_SUCCESS;
  40. }
  41. //*******************************************************************
  42. //*******************************************************************
  43. void CObjectHeap::InvalidateCache()
  44. {
  45. m_Index.InvalidateCache();
  46. m_Heap.InvalidateCache();
  47. }
  48. //*******************************************************************
  49. //*******************************************************************
  50. long CObjectHeap::GetIndexFileName(LPCWSTR wszFilePath, CFileName& wszIndexFileName)
  51. {
  52. WIN32_FIND_DATAW wfd;
  53. long lRes = m_Index.FindFirst(wszFilePath, &wfd, NULL);
  54. if(lRes != ERROR_SUCCESS)
  55. {
  56. return lRes;
  57. }
  58. StringCchCopyW(wszIndexFileName, wszIndexFileName.Length(), wfd.cFileName);
  59. return ERROR_SUCCESS;
  60. }
  61. //*******************************************************************
  62. //*******************************************************************
  63. long CObjectHeap::GetFileInfo(LPCWSTR wszFilePath, TPage *pnPage, TOffset* pnOffset,
  64. DWORD* pdwLength)
  65. {
  66. CFileName wszIndexFileName;
  67. if(wszIndexFileName == NULL)
  68. return ERROR_OUTOFMEMORY;
  69. long lRes = GetIndexFileName(wszFilePath, wszIndexFileName);
  70. if(lRes != ERROR_SUCCESS)
  71. return lRes;
  72. return ParseInfoFromIndexFile(wszIndexFileName, pnPage, pnOffset, pdwLength);
  73. }
  74. //*******************************************************************
  75. //*******************************************************************
  76. long CObjectHeap::ParseInfoFromIndexFile(LPCWSTR wszIndexFileName,
  77. TPage *pnPage,
  78. TOffset* pnOffset,
  79. DWORD* pdwLength)
  80. {
  81. WCHAR* pDot = wcschr(wszIndexFileName, L'.');
  82. if(pDot == NULL)
  83. return ERROR_INVALID_PARAMETER;
  84. WCHAR* pwc = pDot+1;
  85. *pnPage = 0;
  86. while(*pwc && *pwc != L'.')
  87. {
  88. *pnPage = (*pnPage * 10) + (*pwc - '0');
  89. pwc++;
  90. }
  91. if(*pwc != L'.')
  92. return ERROR_INVALID_PARAMETER;
  93. pwc++;
  94. *pnOffset = 0;
  95. while(*pwc && *pwc != L'.')
  96. {
  97. *pnOffset = (*pnOffset * 10) + (*pwc - '0');
  98. pwc++;
  99. }
  100. if(*pwc != L'.')
  101. return ERROR_INVALID_PARAMETER;
  102. pwc++;
  103. *pdwLength = 0;
  104. while(*pwc && *pwc != L'.')
  105. {
  106. *pdwLength = (*pdwLength * 10) + (*pwc - '0');
  107. pwc++;
  108. }
  109. return ERROR_SUCCESS;
  110. }
  111. //*******************************************************************
  112. //*******************************************************************
  113. long CObjectHeap::CreateIndexFile(LPCWSTR wszFilePath,
  114. TPage nPage,
  115. TOffset nOffset,
  116. DWORD dwLength)
  117. {
  118. //
  119. // Simply append the numbers to the file path
  120. //
  121. CFileName wszIndexFilePath;
  122. if(wszIndexFilePath == NULL)
  123. return ERROR_OUTOFMEMORY;
  124. StringCchPrintfW(wszIndexFilePath, wszIndexFilePath.Length(), L"%s.%u.%u.%u",
  125. wszFilePath, nPage, nOffset, dwLength);
  126. return CreateZeroLengthFile(wszIndexFilePath);
  127. }
  128. //*******************************************************************
  129. //*******************************************************************
  130. long CObjectHeap::DeleteIndexFile(LPCWSTR wszFilePath, LPCWSTR wszIndexFileName)
  131. {
  132. //
  133. // Construct the full path to the index file by concatenating the directory
  134. // of the original file with the name
  135. //
  136. CFileName wszIndexFilePath;
  137. if(wszIndexFilePath == NULL)
  138. return ERROR_OUTOFMEMORY;
  139. WCHAR* pwcLastSlash = wcsrchr(wszFilePath, L'\\');
  140. if(pwcLastSlash == NULL)
  141. return ERROR_INVALID_PARAMETER;
  142. int nPrefixLen = (pwcLastSlash - wszFilePath + 1);
  143. memcpy(wszIndexFilePath, wszFilePath, nPrefixLen * sizeof(WCHAR));
  144. StringCchCopyW(wszIndexFilePath + nPrefixLen, wszIndexFilePath.Length() - nPrefixLen, wszIndexFileName);
  145. return DeleteZeroLengthFile(wszIndexFilePath);
  146. }
  147. //*******************************************************************
  148. //*******************************************************************
  149. long CObjectHeap::CreateZeroLengthFile(LPCWSTR wszFilePath)
  150. {
  151. return m_Index.Create(wszFilePath);
  152. }
  153. //*******************************************************************
  154. //*******************************************************************
  155. long CObjectHeap::DeleteZeroLengthFile(LPCWSTR wszFilePath)
  156. {
  157. return m_Index.Delete(wszFilePath);
  158. }
  159. //*******************************************************************
  160. //*******************************************************************
  161. long CObjectHeap::WriteAllocation(DWORD dwDataLength, BYTE* pData, TPage *pnPage, TOffset *pnOffset)
  162. {
  163. return m_Heap.WriteNewBuffer(dwDataLength, pData, pnPage, pnOffset);
  164. }
  165. //*******************************************************************
  166. //*******************************************************************
  167. long CObjectHeap::WriteExistingAllocation(TPage nOldPage, TOffset nOldOffset, DWORD dwDataLength, BYTE *pBuffer, DWORD *pnNewPage, DWORD *pnNewOffset)
  168. {
  169. return m_Heap.WriteExistingBuffer(dwDataLength, pBuffer, nOldPage, nOldOffset, pnNewPage, pnNewOffset);
  170. }
  171. //*******************************************************************
  172. //*******************************************************************
  173. long CObjectHeap::ReadAllocation(TPage nPage, TOffset nOffset, DWORD dwDataLength, BYTE* pBuffer)
  174. {
  175. //
  176. // Prepare a buffer with the complete allocation
  177. //
  178. BYTE* pAllocation;
  179. DWORD dwReadLength;
  180. long lRes = m_Heap.ReadBuffer(nPage, nOffset, &pAllocation, &dwReadLength);
  181. if(lRes != ERROR_SUCCESS)
  182. return lRes;
  183. if (dwReadLength != dwDataLength)
  184. {
  185. _ASSERT(0, L"WinMgmt: Buffer length is not the expected length!\n");
  186. }
  187. memcpy(pBuffer, pAllocation, dwDataLength);
  188. delete [] pAllocation;
  189. return ERROR_SUCCESS;
  190. }
  191. //*******************************************************************
  192. //*******************************************************************
  193. long CObjectHeap::WriteObject(LPCWSTR wszFilePath1, LPCWSTR wszFilePath2, DWORD dwBufferLen, BYTE* pBuffer)
  194. {
  195. if (!m_bInit)
  196. return ERROR_INVALID_OPERATION;
  197. long lRes;
  198. if(dwBufferLen == 0)
  199. {
  200. //
  201. // We do not use the heap for 0-length files, we create them directly
  202. //
  203. return CreateZeroLengthFile(wszFilePath1);
  204. }
  205. //
  206. // Now, check if this file already exists
  207. //
  208. CFileName wszIndexFileName1;
  209. if(wszIndexFileName1 == NULL)
  210. return ERROR_OUTOFMEMORY;
  211. lRes = GetIndexFileName(wszFilePath1, wszIndexFileName1);
  212. if(lRes != ERROR_FILE_NOT_FOUND && lRes != ERROR_SUCCESS)
  213. return lRes;
  214. if(lRes == ERROR_SUCCESS)
  215. {
  216. //
  217. // Already there.
  218. //
  219. TPage nOldPage;
  220. TOffset nOldOffset;
  221. DWORD dwOldLength;
  222. TPage nNewPage;
  223. TOffset nNewOffset;
  224. lRes = ParseInfoFromIndexFile(wszIndexFileName1, &nOldPage, &nOldOffset, &dwOldLength);
  225. if(lRes != ERROR_SUCCESS)
  226. return lRes;
  227. //
  228. // Enough space in place --- just write the data and update the
  229. // length
  230. //
  231. lRes = WriteExistingAllocation(nOldPage, nOldOffset, dwBufferLen, pBuffer, &nNewPage, &nNewOffset);
  232. if(lRes != ERROR_SUCCESS)
  233. return lRes;
  234. if((dwOldLength != dwBufferLen) || (nOldPage != nNewPage) || (nOldOffset != nNewOffset))
  235. {
  236. //
  237. // One of the bits of the path has changed so we need to re-create the index
  238. //
  239. lRes = DeleteIndexFile(wszFilePath1, wszIndexFileName1);
  240. if(lRes != ERROR_SUCCESS)
  241. return lRes;
  242. lRes = CreateIndexFile(wszFilePath1, nNewPage, nNewOffset, dwBufferLen);
  243. if(lRes != ERROR_SUCCESS)
  244. return lRes;
  245. if (wszFilePath2)
  246. {
  247. CFileName wszIndexFileName2;
  248. if(wszIndexFileName2 == NULL)
  249. return ERROR_OUTOFMEMORY;
  250. lRes = GetIndexFileName(wszFilePath2, wszIndexFileName2);
  251. if(lRes != ERROR_SUCCESS)
  252. return lRes;
  253. lRes = DeleteIndexFile(wszFilePath2, wszIndexFileName2);
  254. if(lRes != ERROR_SUCCESS)
  255. return lRes;
  256. lRes = CreateIndexFile(wszFilePath2, nNewPage, nNewOffset, dwBufferLen);
  257. if(lRes != ERROR_SUCCESS)
  258. return lRes;
  259. }
  260. }
  261. return ERROR_SUCCESS;
  262. }
  263. //
  264. // it wasn't there
  265. //
  266. TPage nPage;
  267. TOffset nOffset;
  268. lRes = WriteAllocation(dwBufferLen, pBuffer, &nPage, &nOffset);
  269. if(lRes != ERROR_SUCCESS)
  270. return lRes;
  271. lRes = CreateIndexFile(wszFilePath1, nPage, nOffset, dwBufferLen);
  272. if(lRes != ERROR_SUCCESS)
  273. return lRes;
  274. if (wszFilePath2)
  275. lRes = CreateIndexFile(wszFilePath2, nPage, nOffset, dwBufferLen);
  276. return lRes;
  277. }
  278. //***********************************************************************
  279. //***********************************************************************
  280. long CObjectHeap::WriteLink(LPCWSTR wszLinkPath)
  281. {
  282. if (!m_bInit)
  283. return ERROR_INVALID_OPERATION;
  284. return CreateZeroLengthFile(wszLinkPath);
  285. }
  286. //*******************************************************************
  287. //*******************************************************************
  288. long CObjectHeap::ReadObject(LPCWSTR wszFilePath, DWORD* pdwLength, BYTE** ppBuffer)
  289. {
  290. if (!m_bInit)
  291. return ERROR_INVALID_OPERATION;
  292. long lRes;
  293. //
  294. // Find the file
  295. //
  296. TPage nPage;
  297. TOffset nOffset;
  298. lRes = GetFileInfo(wszFilePath, &nPage, &nOffset, pdwLength);
  299. if(lRes != ERROR_SUCCESS)
  300. return lRes;
  301. //
  302. // Read the allocation
  303. //
  304. *ppBuffer = (BYTE*)TempAlloc(*pdwLength);
  305. if(*ppBuffer == NULL)
  306. return ERROR_OUTOFMEMORY;
  307. lRes = ReadAllocation(nPage, nOffset, *pdwLength, *ppBuffer);
  308. if(lRes != ERROR_SUCCESS)
  309. {
  310. TempFree(*ppBuffer);
  311. return lRes;
  312. }
  313. return ERROR_SUCCESS;
  314. }
  315. //*******************************************************************
  316. //*******************************************************************
  317. long CObjectHeap::DeleteLink(LPCWSTR wszFilePath)
  318. {
  319. if (!m_bInit)
  320. return ERROR_INVALID_OPERATION;
  321. //
  322. // Find the index file
  323. //
  324. CFileName wszIndexFileName;
  325. if(wszIndexFileName == NULL)
  326. return ERROR_OUTOFMEMORY;
  327. long lRes = GetIndexFileName(wszFilePath, wszIndexFileName);
  328. if(lRes != ERROR_SUCCESS)
  329. {
  330. return lRes;
  331. }
  332. //If we have any index information at the end of the path we need to add that to
  333. //the main path and delete that. The delete requires an accurate path.
  334. CFileName wszActualFileName;
  335. if(wszActualFileName == NULL)
  336. return ERROR_OUTOFMEMORY;
  337. StringCchCopyW(wszActualFileName, wszActualFileName.Length(), wszFilePath);
  338. wchar_t *wszDot = wcschr(wszIndexFileName, L'.');
  339. if (wszDot != NULL)
  340. StringCchCatW(wszActualFileName, wszActualFileName.Length(), wszDot);
  341. return DeleteZeroLengthFile(wszActualFileName);
  342. }
  343. //*******************************************************************
  344. //*******************************************************************
  345. long CObjectHeap::DeleteObject(LPCWSTR wszFilePath)
  346. {
  347. if (!m_bInit)
  348. return ERROR_INVALID_OPERATION;
  349. //
  350. // Find the index file
  351. //
  352. CFileName wszIndexFileName;
  353. if(wszIndexFileName == NULL)
  354. return ERROR_OUTOFMEMORY;
  355. long lRes = GetIndexFileName(wszFilePath, wszIndexFileName);
  356. if(lRes != ERROR_SUCCESS)
  357. return lRes;
  358. //
  359. // Delete the allocation
  360. //
  361. TPage nPage;
  362. TOffset nOffset;
  363. DWORD dwLength;
  364. lRes = ParseInfoFromIndexFile(wszIndexFileName, &nPage, &nOffset, &dwLength);
  365. if(lRes == ERROR_INVALID_PARAMETER)
  366. {
  367. _ASSERT(0, L"WinMgmt: Deleting an object that does not have details of where object is!\n");
  368. return ERROR_INVALID_OPERATION;
  369. }
  370. lRes = m_Heap.DeleteBuffer(nPage, nOffset);
  371. if(lRes != ERROR_SUCCESS)
  372. return lRes;
  373. //
  374. // Delete the index itself
  375. //
  376. lRes = DeleteIndexFile(wszFilePath, wszIndexFileName);
  377. if(lRes != ERROR_SUCCESS)
  378. return lRes;
  379. return ERROR_SUCCESS;
  380. }
  381. long CObjectHeap::DeleteNode(LPCWSTR wszNodeName)
  382. {
  383. long lRes = 0;
  384. void *handle;
  385. CFileName wszFileName;
  386. if (wszFileName == 0)
  387. return ERROR_OUTOFMEMORY;
  388. CFileName wszFullFileName;
  389. if (wszFullFileName == 0)
  390. return ERROR_OUTOFMEMORY;
  391. lRes = IndexEnumerationBegin(wszNodeName, &handle);
  392. if (lRes == ERROR_NO_MORE_FILES)
  393. lRes = 0;
  394. if (lRes)
  395. return lRes;
  396. while ((lRes = IndexEnumerationNext(handle, wszFileName, true)) == ERROR_SUCCESS)
  397. {
  398. StringCchCopyW(wszFullFileName, MAX_PATH, g_Glob.GetRootDir());
  399. StringCchCatW(wszFullFileName, MAX_PATH, L"\\");
  400. StringCchCatW(wszFullFileName, MAX_PATH, wszFileName);
  401. lRes = DeleteZeroLengthFile(wszFullFileName);
  402. if (lRes)
  403. {
  404. break;
  405. }
  406. TPage nPage;
  407. TOffset nOffset;
  408. DWORD dwLength;
  409. lRes = ParseInfoFromIndexFile(wszFullFileName+g_Glob.GetRootDirLen(), &nPage, &nOffset, &dwLength);
  410. if(lRes != ERROR_INVALID_PARAMETER)
  411. {
  412. if (!KeyRootInstancePath(wszFullFileName+g_Glob.GetRootDirLen()+1))
  413. {
  414. lRes = m_Heap.DeleteBuffer(nPage, nOffset);
  415. if(lRes != ERROR_SUCCESS)
  416. {
  417. break;
  418. }
  419. }
  420. }
  421. }
  422. IndexEnumerationEnd(handle);
  423. if (lRes == ERROR_NO_MORE_FILES)
  424. lRes = 0;
  425. return lRes;
  426. }
  427. bool CObjectHeap::KeyRootInstancePath(const wchar_t *wszPath)
  428. {
  429. WCHAR* pDot = wcschr(wszPath, L'\\');
  430. if(pDot == NULL)
  431. return false;
  432. pDot++;
  433. pDot = wcschr(pDot, L'\\');
  434. if(pDot == NULL)
  435. return false;
  436. pDot++;
  437. if ((*pDot == L'I') && (*(pDot+1) == L'_'))
  438. return true;
  439. else
  440. return false;
  441. }
  442. long CObjectHeap::ObjectEnumerationBegin(const wchar_t *wszSearchPrefix, void **ppHandle)
  443. {
  444. return IndexEnumerationBegin(wszSearchPrefix, ppHandle);
  445. }
  446. long CObjectHeap::ObjectEnumerationEnd(void *pHandle)
  447. {
  448. return IndexEnumerationEnd(pHandle);
  449. }
  450. long CObjectHeap::ObjectEnumerationNext(void *pHandle, CFileName &wszFileName, BYTE **ppBlob, DWORD *pdwSize)
  451. {
  452. if (!m_bInit)
  453. return ERROR_INVALID_OPERATION;
  454. long lRes = m_Index.IndexEnumerationNext(pHandle, wszFileName);
  455. if (lRes == ERROR_SUCCESS)
  456. {
  457. //We need to retrieve the object from the heap!
  458. TPage nPage;
  459. TOffset nOffset;
  460. DWORD dwLength;
  461. lRes = ParseInfoFromIndexFile(wszFileName, &nPage, &nOffset, &dwLength);
  462. if(lRes == ERROR_INVALID_PARAMETER)
  463. lRes = ERROR_SUCCESS; //This is a plain enumeration, no blobs associated with it
  464. else
  465. {
  466. //Remove extra stuff from end of string...
  467. for (int nCount = 0, nIndex = wcslen(wszFileName); nCount != 3; nIndex --)
  468. {
  469. if (wszFileName[nIndex-1] == L'.')
  470. {
  471. if (++nCount == 3)
  472. wszFileName[nIndex-1] = L'\0';
  473. }
  474. }
  475. DWORD dwSize = 0;
  476. lRes = m_Heap.ReadBuffer(nPage, nOffset, ppBlob, &dwSize);
  477. if ((lRes == ERROR_SUCCESS) && (dwSize != dwLength))
  478. {
  479. _ASSERT(0, L"WinMgmt: Buffer size is not the expected length!\n");
  480. }
  481. *pdwSize = dwLength;
  482. }
  483. }
  484. return lRes;
  485. }
  486. long CObjectHeap::ObjectEnumerationFree(void *pHandle, BYTE *pBlob)
  487. {
  488. if (!m_bInit)
  489. return ERROR_INVALID_OPERATION;
  490. delete [] pBlob;
  491. return ERROR_SUCCESS;
  492. }
  493. long CObjectHeap::IndexEnumerationBegin(const wchar_t *wszSearchPrefix, void **ppHandle)
  494. {
  495. if (!m_bInit)
  496. return ERROR_INVALID_OPERATION;
  497. return m_Index.IndexEnumerationBegin(wszSearchPrefix, ppHandle);
  498. }
  499. long CObjectHeap::IndexEnumerationEnd(void *pHandle)
  500. {
  501. if (!m_bInit)
  502. return ERROR_INVALID_OPERATION;
  503. return m_Index.IndexEnumerationEnd(pHandle);
  504. }
  505. long CObjectHeap::IndexEnumerationNext(void *pHandle, CFileName &wszFileName, bool bCopyFullPath)
  506. {
  507. if (!m_bInit)
  508. return ERROR_INVALID_OPERATION;
  509. long lRes = m_Index.IndexEnumerationNext(pHandle, wszFileName, bCopyFullPath);
  510. if ((lRes == ERROR_SUCCESS) && !bCopyFullPath)
  511. {
  512. wchar_t *pDot = wcschr(wszFileName, L'.');
  513. if (pDot)
  514. *pDot = L'\0';
  515. }
  516. return lRes;
  517. }
  518. long CObjectHeap::FlushCaches()
  519. {
  520. long lRes = m_Index.FlushCaches();
  521. if (lRes == 0)
  522. lRes = m_Heap.FlushCaches();
  523. return lRes;
  524. }
  525. long CObjectHeap::ReadNextIndex(CFileName &wszSearch, CFileName &wszNextIndex)
  526. {
  527. if (!m_bInit)
  528. return ERROR_INVALID_OPERATION;
  529. return m_Index.ReadNextIndex(wszSearch, wszNextIndex);
  530. }