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.

506 lines
13 KiB

  1. #include <windows.h>
  2. #ifdef __XFILES_TEST_PAGE_MANAGER
  3. #include <stdio.h>
  4. #include <unk.h>
  5. #include <arrtempl.h>
  6. #include <FlexArry.h>
  7. #include "pagemgr.h"
  8. #include <wbemutil.h>
  9. //#define PF_VERBOSE_LOGGING
  10. //*****************************************************************************
  11. //*****************************************************************************
  12. CPageFile::CPageFile(const char *pszFile)
  13. : m_bInTransaction (false), m_pszFile(pszFile)
  14. {
  15. }
  16. //*****************************************************************************
  17. //*****************************************************************************
  18. CPageFile::~CPageFile()
  19. {
  20. }
  21. //*****************************************************************************
  22. //*****************************************************************************
  23. ULONG CPageFile::AddRef( )
  24. {
  25. return 0;
  26. }
  27. //*****************************************************************************
  28. //*****************************************************************************
  29. ULONG CPageFile::Release( )
  30. {
  31. return 0;
  32. }
  33. DWORD CPageFile::RetrievePage(DWORD dwId, Page **ppPage)
  34. {
  35. #ifdef PF_VERBOSE_LOGGING
  36. ERRORTRACE((LOG_REPDRV, "%s: Retrieving page 0x%08X\n", m_pszFile, dwId));
  37. #endif
  38. DWORD dwRes = ERROR_FILE_NOT_FOUND;
  39. PAGETABLE::iterator iter = m_aTransactionPageTable.find(dwId);
  40. if (iter != m_aTransactionPageTable.end())
  41. {
  42. *ppPage = iter->second;
  43. dwRes = ERROR_SUCCESS;
  44. }
  45. else
  46. {
  47. iter = m_aMasterPageTable.find(dwId);
  48. if (iter != m_aMasterPageTable.end())
  49. {
  50. *ppPage = iter->second;
  51. dwRes = ERROR_SUCCESS;
  52. }
  53. }
  54. return dwRes;
  55. }
  56. //*****************************************************************************
  57. //*****************************************************************************
  58. DWORD CPageFile::StorePage(Page *pPage)
  59. {
  60. #ifdef PF_VERBOSE_LOGGING
  61. ERRORTRACE((LOG_REPDRV, "%s: Storing page 0x%08X, %s\n", m_pszFile, pPage->dwPageId, (pPage->bActive?"": "DELETED")));
  62. #endif
  63. if (!m_bInTransaction)
  64. {
  65. OutputDebugString(L"Storing page outside a transaction!\n");
  66. DebugBreak();
  67. }
  68. DWORD dwRes = ERROR_FILE_NOT_FOUND;
  69. PAGETABLE::iterator iter = m_aTransactionPageTable.find(pPage->dwPageId);
  70. if (iter != m_aTransactionPageTable.end())
  71. {
  72. Page *pExistingPage = iter->second;
  73. if (!pExistingPage->bActive)
  74. {
  75. //We should not be storing a page over the top of a deleted page!!!
  76. DebugBreak();
  77. dwRes = ERROR_INVALID_OPERATION;
  78. }
  79. else
  80. {
  81. CopyMemory(pExistingPage, pPage, sizeof(Page));
  82. dwRes = ERROR_SUCCESS;
  83. }
  84. }
  85. else
  86. {
  87. dwRes = ERROR_SUCCESS;
  88. Page *pNewPage = new Page;
  89. if (pNewPage == NULL)
  90. {
  91. dwRes = ERROR_OUTOFMEMORY;
  92. }
  93. else
  94. {
  95. CopyMemory(pNewPage, pPage, sizeof(Page));
  96. m_aTransactionPageTable[pNewPage->dwPageId] = pNewPage;
  97. }
  98. }
  99. return dwRes;
  100. }
  101. //*****************************************************************************
  102. //*****************************************************************************
  103. DWORD CPageFile::GetPage(
  104. DWORD dwId,
  105. DWORD dwFlags,
  106. LPVOID pPage
  107. )
  108. {
  109. Page *pExistingPage;
  110. DWORD dwRes = RetrievePage(dwId, &pExistingPage);
  111. if ((dwRes == ERROR_SUCCESS) && (pExistingPage->bActive))
  112. {
  113. CopyMemory(pPage, pExistingPage->aPage, WMIREP_PAGE_SIZE);
  114. }
  115. else if (dwRes == ERROR_SUCCESS)
  116. {
  117. //Should not be retrieving a deleted page!!!!!
  118. DebugBreak();
  119. dwRes = ERROR_INVALID_OPERATION;
  120. }
  121. return dwRes;
  122. }
  123. //*****************************************************************************
  124. //*****************************************************************************
  125. DWORD CPageFile::PutPage(
  126. DWORD dwId,
  127. DWORD dwFlags,
  128. LPVOID pbPage
  129. )
  130. {
  131. Page *pExistingPage;
  132. DWORD dwRes = RetrievePage(dwId, &pExistingPage);
  133. if (dwRes == ERROR_SUCCESS)
  134. {
  135. if (!pExistingPage->bActive)
  136. {
  137. //Should not be retrieving a deleted page!!!!!
  138. DebugBreak();
  139. dwRes = ERROR_INVALID_OPERATION;
  140. }
  141. else
  142. {
  143. Page *pNewPage = new Page;
  144. if (pNewPage == NULL)
  145. {
  146. dwRes = ERROR_OUTOFMEMORY;
  147. }
  148. else
  149. {
  150. pNewPage->bActive = true;
  151. pNewPage->dwPageId = dwId;
  152. CopyMemory(pNewPage->aPage, pbPage, WMIREP_PAGE_SIZE);
  153. dwRes = StorePage(pNewPage);
  154. delete pNewPage;
  155. }
  156. }
  157. }
  158. return dwRes;
  159. }
  160. //*****************************************************************************
  161. //*****************************************************************************
  162. DWORD CPageFile::NewPage(
  163. DWORD dwFlags,
  164. DWORD dwCount,
  165. DWORD *pdwFirstId
  166. )
  167. {
  168. DWORD dwFreeId = 0;
  169. if (dwCount > 1)
  170. {
  171. //This is a multi-page item, so we get the last used ID and the position
  172. //is the end of the list
  173. DWORD dwTranFree = 0;
  174. DWORD dwMasterFree = 0;
  175. if (m_aTransactionPageTable.size())
  176. {
  177. PAGETABLE::iterator it = m_aTransactionPageTable.end();
  178. it--;
  179. dwTranFree = it->first + 1;
  180. }
  181. if (m_aMasterPageTable.size())
  182. {
  183. PAGETABLE::iterator it = m_aMasterPageTable.end();
  184. it--;
  185. dwMasterFree = it->first + 1;
  186. }
  187. if (dwTranFree > dwMasterFree)
  188. {
  189. dwFreeId = dwTranFree;
  190. }
  191. else
  192. {
  193. dwFreeId = dwMasterFree;
  194. }
  195. }
  196. else if (dwFlags == 1)
  197. {
  198. //Allocation of admin page
  199. dwFreeId = 0;
  200. }
  201. else
  202. {
  203. //Grab the first one from the free list
  204. PAGEFREELIST::iterator it = m_aFreeList.begin();
  205. if (it != m_aFreeList.end())
  206. {
  207. dwFreeId = it->first;
  208. m_aFreeList.erase(it);
  209. }
  210. else
  211. {
  212. //We have nothing in the free list, so grab the next ID from
  213. //the transaction and master pages and use the largest one.
  214. DWORD dwTranFree = 0;
  215. DWORD dwMasterFree = 0;
  216. if (m_aTransactionPageTable.size())
  217. {
  218. PAGETABLE::iterator it = m_aTransactionPageTable.end();
  219. it--;
  220. dwTranFree = it->first + 1;
  221. }
  222. if (m_aMasterPageTable.size())
  223. {
  224. PAGETABLE::iterator it = m_aMasterPageTable.end();
  225. it--;
  226. dwMasterFree = it->first + 1;
  227. }
  228. if (dwTranFree > dwMasterFree)
  229. {
  230. dwFreeId = dwTranFree;
  231. }
  232. else
  233. {
  234. dwFreeId = dwMasterFree;
  235. }
  236. }
  237. }
  238. //Record the ID for the caller
  239. *pdwFirstId = dwFreeId;
  240. //Loop through the number of pages required
  241. while (dwCount--)
  242. {
  243. Page *pPage = new Page;
  244. if (pPage == NULL)
  245. return ERROR_OUTOFMEMORY;
  246. pPage->dwPageId = dwFreeId++;
  247. pPage->bActive = true;
  248. StorePage(pPage);
  249. delete pPage;
  250. }
  251. return ERROR_SUCCESS;
  252. }
  253. //*****************************************************************************
  254. //*****************************************************************************
  255. DWORD CPageFile::FreePage(
  256. DWORD dwFlags,
  257. DWORD dwId
  258. )
  259. {
  260. if (dwId == 0)
  261. DebugBreak();
  262. DWORD dwRes = ERROR_FILE_NOT_FOUND;
  263. Page *pPage;
  264. dwRes = RetrievePage(dwId, &pPage);
  265. if ((dwRes == ERROR_FILE_NOT_FOUND) || (!pPage->bActive))
  266. {
  267. //Should not be freeing a not-found or already deleted page
  268. DebugBreak();
  269. dwRes = ERROR_INVALID_OPERATION;
  270. }
  271. else
  272. {
  273. Page *pNewPage = new Page;
  274. pNewPage->bActive = false;
  275. pNewPage->dwPageId = dwId;
  276. StorePage(pNewPage);
  277. delete pNewPage;
  278. }
  279. return dwRes;
  280. }
  281. DWORD CPageFile::BeginTran()
  282. {
  283. #ifdef PF_VERBOSE_LOGGING
  284. ERRORTRACE((LOG_REPDRV, "%s: Begin Transaction\n", m_pszFile));
  285. #endif
  286. if (m_bInTransaction)
  287. {
  288. OutputDebugString(L"WinMgmt: Nested transasctions are NOT supported!\n");
  289. DebugBreak();
  290. }
  291. m_bInTransaction = true;
  292. return ERROR_SUCCESS;
  293. }
  294. DWORD CPageFile::CommitTran()
  295. {
  296. #ifdef PF_VERBOSE_LOGGING
  297. ERRORTRACE((LOG_REPDRV, "%s: Commit Transaction\n", m_pszFile));
  298. #endif
  299. if (!m_bInTransaction)
  300. {
  301. OutputDebugString(L"WinMgmt: Commiting a transaction when we are NOT in a transaction!\n");
  302. DebugBreak();
  303. }
  304. PAGETABLE::iterator it;
  305. while (m_aTransactionPageTable.size())
  306. {
  307. it = m_aTransactionPageTable.begin();
  308. PAGETABLE::iterator masterIt = m_aMasterPageTable.find(it->first);
  309. if (masterIt != m_aMasterPageTable.end())
  310. {
  311. //replace it
  312. if (it->second->bActive)
  313. {
  314. #ifdef PF_VERBOSE_LOGGING
  315. ERRORTRACE((LOG_REPDRV, "%s: Replacing existing page in master page list <0x%08X>\n", m_pszFile, it->first));
  316. #endif
  317. CopyMemory(masterIt->second, it->second, sizeof(Page));
  318. }
  319. else
  320. {
  321. //Deleted page and add id to free list!
  322. #ifdef PF_VERBOSE_LOGGING
  323. ERRORTRACE((LOG_REPDRV, "%s: Deleting page in master page list <0x%08X>\n", m_pszFile, it->first));
  324. #endif
  325. m_aFreeList[it->first] = it->first;
  326. delete masterIt->second;
  327. m_aMasterPageTable.erase(masterIt);
  328. }
  329. delete it->second;
  330. }
  331. else
  332. {
  333. #ifdef PF_VERBOSE_LOGGING
  334. ERRORTRACE((LOG_REPDRV, "%s: Creating new page in master page list <0x%08X>\n", m_pszFile, it->first));
  335. #endif
  336. m_aMasterPageTable[it->first] = it->second;
  337. }
  338. m_aTransactionPageTable.erase(it);
  339. }
  340. m_bInTransaction = false;
  341. #ifdef PF_VERBOSE_LOGGING
  342. ERRORTRACE((LOG_REPDRV, "%s: Commit Transaction completed\n", m_pszFile));
  343. #endif
  344. return ERROR_SUCCESS;
  345. }
  346. DWORD CPageFile::AbortTran()
  347. {
  348. #ifdef PF_VERBOSE_LOGGING
  349. ERRORTRACE((LOG_REPDRV, "%s: Abort Transaction\n", m_pszFile));
  350. #endif
  351. PAGETABLE::iterator it;
  352. while (m_aTransactionPageTable.size())
  353. {
  354. it = m_aTransactionPageTable.begin();
  355. #ifdef PF_VERBOSE_LOGGING
  356. ERRORTRACE((LOG_REPDRV, "%s: Rolling back page <0x%08X>\n", m_pszFile, it->first));
  357. #endif
  358. delete it->second;
  359. m_aTransactionPageTable.erase(it);
  360. }
  361. m_bInTransaction = false;
  362. #ifdef PF_VERBOSE_LOGGING
  363. ERRORTRACE((LOG_REPDRV, "%s: Abort Transaction\n", m_pszFile));
  364. #endif
  365. return ERROR_SUCCESS;
  366. }
  367. //*****************************************************************************
  368. //*****************************************************************************
  369. CPageSource::CPageSource()
  370. : m_pHeap(0)
  371. {
  372. }
  373. //*****************************************************************************
  374. //*****************************************************************************
  375. CPageSource::~CPageSource()
  376. {
  377. }
  378. //*****************************************************************************
  379. //*****************************************************************************
  380. DWORD CPageSource::Init(
  381. DWORD dwCachePages,
  382. DWORD dwCheckpointTime, // milliseconds
  383. DWORD dwPageSize
  384. )
  385. {
  386. m_pHeap = new CPageFile("ObjHeap");
  387. m_pIndex = new CPageFile("Index");
  388. return ERROR_SUCCESS;
  389. }
  390. //*****************************************************************************
  391. //*****************************************************************************
  392. DWORD CPageSource::Shutdown(DWORD dwShutdownType )
  393. {
  394. delete m_pHeap;
  395. delete m_pIndex;
  396. return ERROR_SUCCESS;
  397. }
  398. //*****************************************************************************
  399. //*****************************************************************************
  400. DWORD CPageSource::GetBTreePageFile(OUT CPageFile **pPF)
  401. {
  402. *pPF = m_pIndex;
  403. return ERROR_SUCCESS;
  404. }
  405. //*****************************************************************************
  406. //*****************************************************************************
  407. DWORD CPageSource::GetObjectHeapPageFile(OUT CPageFile **pPF)
  408. {
  409. *pPF = m_pHeap;
  410. return ERROR_SUCCESS;
  411. }
  412. // Transactions
  413. //*****************************************************************************
  414. //*****************************************************************************
  415. DWORD CPageSource::BeginTrans()
  416. {
  417. m_pIndex->BeginTran();
  418. return m_pHeap->BeginTran();
  419. }
  420. //*****************************************************************************
  421. //*****************************************************************************
  422. DWORD CPageSource::CommitTrans()
  423. {
  424. m_pIndex->CommitTran();
  425. return m_pHeap->CommitTran();
  426. }
  427. //*****************************************************************************
  428. //*****************************************************************************
  429. DWORD CPageSource::RollbackTrans()
  430. {
  431. m_pIndex->AbortTran();
  432. return m_pHeap->AbortTran();
  433. }
  434. //*****************************************************************************
  435. //*****************************************************************************
  436. DWORD CPageSource::Flush()
  437. {
  438. return ERROR_SUCCESS;;
  439. }
  440. //*****************************************************************************
  441. //*****************************************************************************
  442. DWORD CPageSource::LastCommitVersion(DWORD *pdwCommitted)
  443. {
  444. return ERROR_SUCCESS;
  445. }
  446. //*****************************************************************************
  447. //*****************************************************************************
  448. DWORD CPageSource::CurrentVersion(DWORD *pdwCurrent)
  449. {
  450. return ERROR_SUCCESS;
  451. }
  452. // Checkpoint
  453. //*****************************************************************************
  454. //*****************************************************************************
  455. DWORD CPageSource::Checkpoint()
  456. {
  457. return ERROR_SUCCESS;
  458. }
  459. //*****************************************************************************
  460. //*****************************************************************************
  461. DWORD CPageSource::Dump(FILE *f)
  462. {
  463. return ERROR_SUCCESS;
  464. }
  465. #endif /* __XFILES_TEST_PAGE_MANAGER */