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.

568 lines
15 KiB

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