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.

474 lines
12 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-2001 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. #include "stdafx.h"
  11. #include "Common.h"
  12. #include "Allocate.h"
  13. #include "AtlTraceModuleManager.h"
  14. #pragma comment(lib, "advapi32.lib")
  15. bool CAtlAllocator::Init(const CHAR *pszFileName, DWORD dwMaxSize)
  16. {
  17. // REVIEW:
  18. // We're relying on syncronization provided by the startup code (CRT DllMain/WinMain)
  19. Close();
  20. ATLASSERT(!m_hMap && !m_pBufferStart);
  21. SECURITY_DESCRIPTOR sd;
  22. SECURITY_ATTRIBUTES sa, *psa = NULL;
  23. if(!(GetVersion() & 0x80000000))
  24. {
  25. ::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
  26. ::SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
  27. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  28. sa.lpSecurityDescriptor = &sd;
  29. sa.bInheritHandle = FALSE;
  30. psa = &sa;
  31. }
  32. __try
  33. {
  34. m_hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, psa,
  35. PAGE_READWRITE | SEC_RESERVE, 0, dwMaxSize, pszFileName);
  36. if(!m_hMap)
  37. __leave;
  38. DWORD dwErr = ::GetLastError();
  39. m_pBufferStart = (BYTE *)
  40. MapViewOfFile(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  41. if(!m_pBufferStart)
  42. __leave;
  43. SYSTEM_INFO si;
  44. GetSystemInfo(&si);
  45. if(dwErr == ERROR_ALREADY_EXISTS)
  46. {
  47. m_pProcess = reinterpret_cast<CAtlTraceProcess *>(m_pBufferStart);
  48. // Looks like it's already mapped into this process space.
  49. // Let's do some checking...
  50. if(IsBadReadPtr(m_pProcess, sizeof(CAtlTraceProcess)) ||
  51. IsBadReadPtr(m_pProcess->Base(), sizeof(CAtlTraceProcess)) ||
  52. 0 != memcmp(m_pBufferStart, m_pProcess->Base(), m_pProcess->m_dwFrontAlloc))
  53. {
  54. // something's not right
  55. __leave;
  56. }
  57. // sure looks valid
  58. m_pProcess->IncRef();
  59. m_pProcess = static_cast<CAtlTraceProcess *>(m_pProcess->Base());
  60. UnmapViewOfFile(m_pBufferStart);
  61. m_pBufferStart = reinterpret_cast<BYTE *>(m_pProcess);
  62. }
  63. else
  64. {
  65. // This is just in case sizeof(CAtlTraceProcess) is
  66. // ever > dwPageSize (doubtful that could ever
  67. // happen, but it's easy enough to avoid here)
  68. DWORD dwCurrAlloc = si.dwPageSize;
  69. while(dwCurrAlloc < sizeof(CAtlTraceProcess))
  70. dwCurrAlloc += si.dwPageSize;
  71. if(!VirtualAlloc(m_pBufferStart, dwCurrAlloc, MEM_COMMIT, PAGE_READWRITE))
  72. __leave;
  73. m_pProcess = new(m_pBufferStart) CAtlTraceProcess(dwMaxSize);
  74. m_pProcess->m_dwFrontAlloc = dwCurrAlloc;
  75. m_pProcess->m_dwCurrFront = sizeof(CAtlTraceProcess);
  76. }
  77. m_dwPageSize = si.dwPageSize;
  78. m_bValid = true;
  79. }
  80. __finally
  81. {
  82. if(!m_bValid)
  83. {
  84. if(m_pBufferStart)
  85. {
  86. UnmapViewOfFile(m_pBufferStart);
  87. m_pBufferStart = NULL;
  88. }
  89. if(m_hMap)
  90. {
  91. CloseHandle(m_hMap);
  92. m_hMap = NULL;
  93. }
  94. }
  95. }
  96. return m_bValid;
  97. }
  98. bool CAtlAllocator::Open(const CHAR *pszFileName)
  99. {
  100. Close();
  101. __try
  102. {
  103. m_hMap = OpenFileMappingA(FILE_MAP_WRITE, FALSE, pszFileName);
  104. if(!m_hMap)
  105. __leave;
  106. m_pBufferStart = (BYTE *)
  107. MapViewOfFile(m_hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  108. if(!m_pBufferStart)
  109. __leave;
  110. m_pProcess = reinterpret_cast<CAtlTraceProcess *>(m_pBufferStart);
  111. m_pProcess->IncRef();
  112. SYSTEM_INFO si;
  113. GetSystemInfo(&si);
  114. m_dwPageSize = si.dwPageSize;
  115. m_bValid = true;
  116. }
  117. __finally
  118. {
  119. if(!m_bValid)
  120. {
  121. if(m_pBufferStart)
  122. {
  123. UnmapViewOfFile(m_pBufferStart);
  124. m_pBufferStart = NULL;
  125. }
  126. if(m_hMap)
  127. {
  128. CloseHandle(m_hMap);
  129. m_hMap = NULL;
  130. }
  131. m_pProcess = NULL;
  132. }
  133. }
  134. return m_bValid;
  135. }
  136. void CAtlAllocator::Close(bool bForceUnmap)
  137. {
  138. if(m_bValid)
  139. {
  140. if(m_pProcess->DecRef() == 0 || bForceUnmap)
  141. UnmapViewOfFile(m_pBufferStart);
  142. m_pBufferStart = NULL;
  143. CloseHandle(m_hMap);
  144. m_hMap = NULL;
  145. m_bValid = false;
  146. }
  147. }
  148. CAtlTraceModule *CAtlAllocator::GetModule(int iModule) const
  149. {
  150. if( iModule == -1 )
  151. {
  152. return NULL;
  153. }
  154. ATLASSERT(iModule < m_pProcess->ModuleCount());
  155. if(iModule < m_pProcess->ModuleCount())
  156. {
  157. BYTE *pb = reinterpret_cast<BYTE *>(m_pProcess) + sizeof(CAtlTraceProcess);
  158. return reinterpret_cast<CAtlTraceModule *>(pb) + iModule;
  159. }
  160. else
  161. return NULL;
  162. }
  163. /*
  164. CAtlTraceCategory *CAtlAllocator::GetCategory(unsigned nModule, unsigned nCategory) const
  165. {
  166. ATLASSERT(nModule < m_pProcess->ModuleCount());
  167. if(nModule < m_pProcess->ModuleCount())
  168. {
  169. BYTE *pb = reinterpret_cast<BYTE *>(m_pProcess) + sizeof(CAtlTraceProcess);
  170. CAtlTraceModule *pModule = reinterpret_cast<CAtlTraceModule *>(pb) + nModule;
  171. if(IsValidCategoryIndex(pModule->m_nFirstCategory))
  172. {
  173. unsigned nOldIndex, nIndex = pModule->m_nFirstCategory;
  174. CAtlTraceCategory *pCategory;
  175. do
  176. {
  177. pCategory = GetCategoryByIndex(nIndex);
  178. if(pCategory->m_nCategory == nCategory)
  179. return pCategory;
  180. nOldIndex = nIndex;
  181. nIndex = pCategory->m_nNext;
  182. }
  183. while(nOldIndex != nIndex);
  184. }
  185. }
  186. return NULL;
  187. }
  188. */
  189. /*
  190. bool CAtlAllocator::IsValidCategoryIndex(unsigned nIndex) const
  191. {
  192. return nIndex < m_pProcess->CategoryCount();
  193. }
  194. */
  195. CAtlTraceCategory *CAtlAllocator::GetCategory(int iCategory) const
  196. {
  197. if(iCategory == m_pProcess->CategoryCount())
  198. return NULL;
  199. ATLASSERT((iCategory < m_pProcess->CategoryCount()) || (iCategory == -1));
  200. CAtlTraceCategory *pCategory = NULL;
  201. if(iCategory >= 0)
  202. {
  203. BYTE *pb = reinterpret_cast<BYTE *>(m_pProcess) + m_pProcess->MaxSize();
  204. pCategory = reinterpret_cast<CAtlTraceCategory *>(pb) - iCategory - 1;
  205. }
  206. return pCategory;
  207. }
  208. int CAtlAllocator::GetCategoryCount(int iModule) const
  209. {
  210. UINT nCategories = 0;
  211. CAtlTraceModule* pModule = GetModule(iModule);
  212. ATLASSERT(pModule != NULL);
  213. if(pModule != NULL)
  214. {
  215. nCategories = GetCategoryCount( *pModule );
  216. }
  217. return nCategories;
  218. }
  219. int CAtlAllocator::GetCategoryCount(const CAtlTraceModule& rModule) const
  220. {
  221. UINT nCategories = 0;
  222. int iCategory = rModule.m_iFirstCategory;
  223. while( iCategory != -1 )
  224. {
  225. CAtlTraceCategory* pCategory = GetCategory( iCategory );
  226. nCategories++;
  227. iCategory = pCategory->m_iNextCategory;
  228. }
  229. return nCategories;
  230. }
  231. int CAtlAllocator::GetModuleCount() const
  232. {
  233. ATLASSERT(m_pProcess);
  234. return m_pProcess->ModuleCount();
  235. }
  236. const ULONG kModuleBatchSize = 10;
  237. int CAtlAllocator::AddModule(HINSTANCE hInst)
  238. {
  239. // bug bug bug - overlap onto the categories!!??
  240. CAtlTraceProcess *pProcess = GetProcess();
  241. int iFoundModule = -1;
  242. while( iFoundModule == -1 )
  243. {
  244. for(int iModule = 0; (iModule < pProcess->ModuleCount()) && (iFoundModule == -1); iModule++)
  245. {
  246. CAtlTraceModule *pModule = GetModule(iModule);
  247. ATLASSERT(pModule != NULL);
  248. bool bFound = pModule->TryAllocate();
  249. if( bFound )
  250. {
  251. pModule->Reset(hInst);
  252. pModule->m_iFirstCategory = -1;
  253. pModule->MarkValid( pProcess->GetNextCookie() );
  254. iFoundModule = iModule;
  255. }
  256. }
  257. if( iFoundModule == -1 )
  258. {
  259. ULONG nNewAllocSize = kModuleBatchSize*sizeof( CAtlTraceModule );
  260. void* pNewModules = reinterpret_cast<BYTE *>(pProcess) + pProcess->m_dwFrontAlloc;
  261. VirtualAlloc(pNewModules, nNewAllocSize, MEM_COMMIT, PAGE_READWRITE);
  262. pProcess->m_dwFrontAlloc += nNewAllocSize;
  263. for( ULONG iNewModule = 0; iNewModule < kModuleBatchSize; iNewModule++ )
  264. {
  265. CAtlTraceModule* pNewModule = static_cast< CAtlTraceModule* >( pNewModules )+iNewModule;
  266. new( pNewModule ) CAtlTraceModule;
  267. }
  268. pProcess->IncModuleCount( kModuleBatchSize );
  269. }
  270. }
  271. return iFoundModule;
  272. }
  273. const ULONG kCategoryBatchSize = 10;
  274. int CAtlAllocator::AddCategory(int iModule, const WCHAR *szCategoryName)
  275. {
  276. int iFoundCategory = -1;
  277. CAtlTraceProcess *pProcess = GetProcess();
  278. CAtlTraceModule *pModule = GetModule(iModule);
  279. if(pModule)
  280. {
  281. pModule->TryAddRef();
  282. while( iFoundCategory == -1 )
  283. {
  284. for(int iCategory = 0; (iCategory < pProcess->CategoryCount()) && (iFoundCategory == -1); iCategory++)
  285. {
  286. CAtlTraceCategory *pCategory = GetCategory( iCategory );
  287. ATLASSERT(pCategory != NULL);
  288. bool bFound = pCategory->TryAllocate();
  289. if( bFound )
  290. {
  291. pCategory->Reset( szCategoryName, pModule->m_nCookie );
  292. pCategory->m_iNextCategory = pModule->m_iFirstCategory;
  293. pCategory->MarkValid( pProcess->GetNextCookie() );
  294. pModule->m_iFirstCategory = iCategory;
  295. ::InterlockedIncrement( &pModule->m_nCategories );
  296. iFoundCategory = iCategory;
  297. }
  298. }
  299. if( iFoundCategory == -1 )
  300. {
  301. ULONG nNewAllocSize = kCategoryBatchSize*sizeof( CAtlTraceCategory );
  302. void* pNewCategories = reinterpret_cast<BYTE *>(pProcess) + pProcess->MaxSize()-pProcess->m_dwBackAlloc-nNewAllocSize;
  303. VirtualAlloc(pNewCategories, nNewAllocSize, MEM_COMMIT, PAGE_READWRITE);
  304. pProcess->m_dwBackAlloc += nNewAllocSize;
  305. for( ULONG iNewCategory = 0; iNewCategory < kCategoryBatchSize; iNewCategory++ )
  306. {
  307. CAtlTraceCategory* pNewCategory = static_cast< CAtlTraceCategory* >( pNewCategories )+iNewCategory;
  308. new( pNewCategory ) CAtlTraceCategory;
  309. }
  310. pProcess->IncCategoryCount( kCategoryBatchSize );
  311. }
  312. }
  313. pModule->Release();
  314. }
  315. pProcess->m_bLoaded = false;
  316. return( iFoundCategory );
  317. }
  318. bool CAtlAllocator::RemoveModule(int iModule)
  319. {
  320. CAtlTraceModule* pModule = GetModule(iModule);
  321. if(pModule)
  322. {
  323. int iCategory = pModule->m_iFirstCategory;
  324. while( iCategory != -1 )
  325. {
  326. CAtlTraceCategory* pCategory = GetCategory( iCategory );
  327. iCategory = pCategory->m_iNextCategory;
  328. ::InterlockedDecrement( &pModule->m_nCategories );
  329. pModule->m_iFirstCategory = iCategory;
  330. pCategory->Release();
  331. }
  332. pModule->Release();
  333. return true;
  334. }
  335. return false;
  336. }
  337. void CAtlAllocator::CleanUp()
  338. {
  339. Close();
  340. }
  341. void CAtlAllocator::TakeSnapshot()
  342. {
  343. if( m_bSnapshot )
  344. {
  345. ReleaseSnapshot();
  346. }
  347. int nModules = GetModuleCount();
  348. for( int iModule = 0; iModule < nModules; iModule++ )
  349. {
  350. CAtlTraceModule* pModule = GetModule( iModule );
  351. bool bValidModule = pModule->TryAddRef();
  352. if( bValidModule )
  353. {
  354. CTraceSnapshot::CModuleInfo module;
  355. module.m_dwModule = DWORD_PTR( iModule )+1;
  356. module.m_iFirstCategory = m_snapshot.m_adwCategories.GetSize();
  357. module.m_nCategories = pModule->m_nCategories;
  358. int iCategory = pModule->m_iFirstCategory;
  359. bool bCategoriesValid = true;
  360. int nCategories = 0;
  361. while( (iCategory != -1) && bCategoriesValid )
  362. {
  363. CAtlTraceCategory* pCategory = GetCategory( iCategory );
  364. bool bValidCategory = pCategory->TryAddRef();
  365. if( bValidCategory )
  366. {
  367. if( pCategory->m_nModuleCookie != pModule->m_nCookie )
  368. {
  369. bValidCategory = false;
  370. pCategory->Release();
  371. }
  372. else
  373. {
  374. m_snapshot.m_adwCategories.Add( DWORD_PTR( iCategory ) );
  375. nCategories++;
  376. iCategory = pCategory->m_iNextCategory;
  377. }
  378. }
  379. if( !bValidCategory )
  380. {
  381. bCategoriesValid = false;
  382. }
  383. }
  384. if( !bCategoriesValid )
  385. {
  386. for( int iCategoryIndex = nCategories-1; iCategoryIndex >= 0; iCategoryIndex-- )
  387. {
  388. DWORD_PTR dwCategory = m_snapshot.m_adwCategories[module.m_iFirstCategory+iCategoryIndex];
  389. m_snapshot.m_adwCategories.RemoveAt( module.m_iFirstCategory+iCategoryIndex );
  390. GetCategory( int( dwCategory ) )->Release();
  391. }
  392. pModule->Release();
  393. }
  394. else
  395. {
  396. m_snapshot.m_aModules.Add( module );
  397. }
  398. }
  399. }
  400. m_bSnapshot = true;
  401. }
  402. void CAtlAllocator::ReleaseSnapshot()
  403. {
  404. if( m_bSnapshot )
  405. {
  406. for( int iModule = 0; iModule < m_snapshot.m_aModules.GetSize(); iModule++ )
  407. {
  408. GetModule( int( m_snapshot.m_aModules[iModule].m_dwModule-1 ) )->Release();
  409. }
  410. for( int iCategory = 0; iCategory < m_snapshot.m_adwCategories.GetSize(); iCategory++ )
  411. {
  412. GetCategory( int( m_snapshot.m_adwCategories[iCategory] ) )->Release();
  413. }
  414. m_bSnapshot = false;
  415. }
  416. }