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.

425 lines
12 KiB

  1. /***
  2. *init.cpp - RTC support
  3. *
  4. * Copyright (c) 1998-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *
  7. *Revision History:
  8. * 07-28-98 JWM Module incorporated into CRTs (from KFrei)
  9. * 10-12-98 KBF Moved _RTC_IsEnabled here from UserAPI, and fixed it
  10. * 10-13-98 KBF Added _RTC_SetOutOfMemFunc
  11. * 10-28-98 KBF Added _RTC_Shutdown to prevent locks on FreeLibrary
  12. * 11-03-98 KBF added throw() to eliminate C++ EH code & improved
  13. * termination code
  14. * 11-24-98 KBF Added additional callback to _RTC_MSPtrMemCheckN
  15. * 11-25-98 KBF Fixed initialization problem
  16. * 12-03-98 KBF Added APISet callback, and changed MSPtrMemCheckN
  17. * to CheckMem
  18. * 05-11-99 KBF Error if RTC support define not enabled
  19. * 05-26-99 KBF General cleanup - RTClv cut, _RTC_ADVMEM for reenabling
  20. * -RTCm later
  21. * 08-03-99 KBF Fixed some pretty bad handle leaks, code cleanup &
  22. * commenting
  23. * 11-30-99 PML Compile /Wp64 clean.
  24. *
  25. ****/
  26. #ifndef _RTC
  27. #error RunTime Check support not enabled!
  28. #endif
  29. #include "rtcpriv.h"
  30. #pragma intrinsic(memset)
  31. #ifdef _RTC_ADVMEM
  32. // This is the process wide global data struct pointer
  33. // It must maintain backward compatibility at all times!
  34. _RTC_globals *_RTC_globptr = 0;
  35. // This is only actually used for shadow memory, but it doesn't really hurt
  36. // And it serves as a placeholder for future work
  37. CRITICAL_SECTION _RTC_memlock;
  38. HashTable<_RTC_HeapBlock> *_RTC_heapblocks = 0;
  39. _RTC_Container *_RTC_memhier = 0;
  40. shadowtag *_RTC_shadow = 0;
  41. index_elem *_RTC_pageidx = 0;
  42. bool *_RTC_pi_array = 0;
  43. bool _RTC_shadowmemory = false;
  44. # define FUNCCOUNT 4
  45. #else
  46. # define FUNCCOUNT 1
  47. #endif // _RTC_ADVMEM
  48. #ifdef _RTC_ADVMEM
  49. static _RTC_Funcs this_image;
  50. static char name[40] = "#--------RTCSubsystem"; // scoped name for process wide synchronization
  51. static HANDLE init_mutex = INVALID_HANDLE_VALUE; // mutex for initialization & termination only
  52. static HANDLE work_mutex = INVALID_HANDLE_VALUE; // mutex for all RTC stuff
  53. static HANDLE sharedmem = INVALID_HANDLE_VALUE; // the memory mapped file
  54. static void *funcs[FUNCCOUNT] = { // List of function pointers that the CRT need hooks too
  55. # ifdef _RTC_ADVMEM
  56. &_RTC_APISet, &_RTC_Allocate, &_RTC_Free, &_RTC_CheckMem_API
  57. # else
  58. 0
  59. # endif
  60. };
  61. static _RTC_globals * GetRTCGlobalData() throw();
  62. static void _RTC_NotifyOfGlobChange() throw();
  63. static void SetErrors() throw();
  64. static void InitMemoryTracking(bool advmem) throw();
  65. static void InitGlobals() throw();
  66. static void GetGlobals() throw();
  67. static void SetSMName(char which);
  68. #endif
  69. #if 0
  70. void DBGdumpbin(void *addr, char *buf)
  71. {
  72. unsigned int x = (unsigned int)addr;
  73. for (int i = 0; i < 8; i++)
  74. {
  75. buf[7-i] = x & 15;
  76. if (buf[7-i] < 10)
  77. buf[7-i] += '0';
  78. else
  79. buf[7-i] += 'a' - 10;
  80. x = x >> 4;
  81. }
  82. }
  83. #endif
  84. // This initializes the basics of the RTC subsystem
  85. void __cdecl
  86. _RTC_InitBase(void)
  87. {
  88. static bool init = false;
  89. if (init)
  90. return;
  91. init = true;
  92. _RTC_SetErrorFunc(_CRT_RTC_INIT(0, 0, 0, _RTC_CURRENT_VERSION, 0));
  93. }
  94. void __cdecl
  95. _RTC_Shutdown(void)
  96. {
  97. _CRT_RTC_INIT(0, 0, 0, _RTC_CURRENT_VERSION, 1);
  98. }
  99. #ifdef _RTC_ADVMEM
  100. // This initializes the shadow memory subsystem
  101. void __cdecl
  102. _RTC_InitAdvMem(void)
  103. {
  104. ACQUIRE(INIT_MUTEX);
  105. if (_RTC_shadowmemory)
  106. {
  107. _RTC_SetErrorFunc(_CRT_RTC_INIT(init_mutex, funcs, FUNCCOUNT, _RTC_CURRENT_VERSION, 0));
  108. return;
  109. }
  110. ACQUIRE(WORK_MUTEX);
  111. GetGlobals();
  112. InitGlobals();
  113. if (_RTC_shadowmemory)
  114. {
  115. _RTC_SetErrorFunc(_CRT_RTC_INIT(init_mutex, funcs, FUNCCOUNT, _RTC_CURRENT_VERSION, 0));
  116. return;
  117. }
  118. _RTC_shadowmemory = true;
  119. if (!_RTC_shadow)
  120. _RTC_MS_Init();
  121. InitMemoryTracking(true);
  122. MEMORY_BASIC_INFORMATION mbi;
  123. if (VirtualQuery(&_RTC_SetErrorFunc, &mbi, sizeof(mbi)))
  124. _RTC_NotifyOthersOfChange((void*)mbi.AllocationBase);
  125. RELEASE(WORK_MUTEX);
  126. RELEASE(INIT_MUTEX);
  127. }
  128. #endif
  129. #ifdef _RTC_ADVMEM
  130. // Remove this image from the list of running images...
  131. void __cdecl
  132. _RTC_Shutdown(void)
  133. {
  134. static bool run = false;
  135. MEMORY_BASIC_INFORMATION mbi, img_mbi;
  136. _RTC_Funcs *curfunc, *prev;
  137. if (!_RTC_globptr || run)
  138. return;
  139. run = true;
  140. __try
  141. {
  142. if (_RTC_Lock(INIT_MUTEX)) { __try
  143. {
  144. if (_RTC_Lock(WORK_MUTEX)) { __try
  145. {
  146. _CRT_RTC_INIT(init_mutex, funcs, FUNCCOUNT, _RTC_CURRENT_VERSION, 1);
  147. curfunc = _RTC_globptr->callbacks;
  148. prev = 0;
  149. VirtualQuery(&this_image, &img_mbi, sizeof(img_mbi));
  150. while (curfunc)
  151. {
  152. VirtualQuery(curfunc, &mbi, sizeof(mbi));
  153. if (mbi.BaseAddress == img_mbi.BaseAddress)
  154. {
  155. if (prev)
  156. prev->next = curfunc->next;
  157. else
  158. _RTC_globptr->callbacks = curfunc->next;
  159. } else if (mbi.State != MEM_COMMIT)
  160. {
  161. if (prev)
  162. prev->next = 0;
  163. else
  164. _RTC_globptr->callbacks = 0;
  165. OutputDebugString("RTC Shutdown problem detected...");
  166. break;
  167. } else
  168. prev = curfunc;
  169. curfunc = curfunc->next;
  170. }
  171. } __finally { _RTC_Unlock(WORK_MUTEX); } }
  172. } __finally { _RTC_Unlock(INIT_MUTEX); } }
  173. } __finally
  174. {
  175. CloseHandle(init_mutex);
  176. CloseHandle(work_mutex);
  177. if (_RTC_globptr)
  178. UnmapViewOfFile(_RTC_globptr);
  179. CloseHandle(sharedmem);
  180. init_mutex = work_mutex = sharedmem = INVALID_HANDLE_VALUE;
  181. }
  182. }
  183. static void
  184. GetGlobals() throw()
  185. {
  186. static bool init = false;
  187. if (init)
  188. return;
  189. init = true;
  190. // Setup the error types for this instance
  191. for (int i = 0; i < _RTC_ILLEGAL; i++)
  192. _RTC_ErrorLevels[i] = 1;
  193. if (!_RTC_globptr)
  194. _RTC_globptr = GetRTCGlobalData();
  195. if(_RTC_globptr)
  196. _RTC_NotifyOfGlobChange();
  197. }
  198. static void
  199. InitGlobals() throw()
  200. {
  201. static bool init = false;
  202. if (init)
  203. return;
  204. init = true;
  205. #ifdef _RTC_ADVMEM
  206. if (!_RTC_heap2)
  207. {
  208. _RTC_heap2 = new _RTC_SimpleHeap(8);
  209. _RTC_heap4 = new _RTC_SimpleHeap(16);
  210. _RTC_heap8 = new _RTC_SimpleHeap(32);
  211. }
  212. #endif
  213. // Add this module to the list of callbacks
  214. MEMORY_BASIC_INFORMATION mbi;
  215. if (_RTC_globptr && VirtualQuery(&_RTC_SetErrorFunc, &mbi, sizeof(mbi)))
  216. {
  217. this_image.err = 0;
  218. this_image.next = _RTC_globptr->callbacks;
  219. this_image.notify = &_RTC_NotifyOfGlobChange;
  220. this_image.allocationBase = mbi.AllocationBase;
  221. #ifdef _RTC_ADVMEM
  222. this_image.shadowoff = 0;
  223. #endif
  224. _RTC_globptr->callbacks = &this_image;
  225. }
  226. }
  227. static void
  228. InitMemoryTracking(bool advmem) throw()
  229. {
  230. static bool init = false;
  231. if (init)
  232. return;
  233. init = true;
  234. // Build the memory block hash table
  235. void *hbmem = VirtualAlloc(0, 65521 * sizeof(_RTC_HeapBlock*),
  236. MEM_RESERVE | MEM_COMMIT,
  237. PAGE_READWRITE);
  238. _RTC_heapblocks = new HashTable<_RTC_HeapBlock>(65521, hbmem);
  239. _RTC_MSAllocShadow((memptr)hbmem, 65521 * sizeof(_RTC_HeapBlock*), IDX_STATE_ILLEGAL);
  240. _RTC_memhier = new _RTC_Container(0);
  241. _RTC_MSAllocateGlobals();
  242. _RTC_SetErrorFunc(_CRT_RTC_INIT(init_mutex, funcs, 2 + (advmem ? 2 : 0), _RTC_CURRENT_VERSION, 0));
  243. }
  244. #endif
  245. // This is code to post process wide values...
  246. #ifdef _RTC_ADVMEM
  247. static void
  248. SetSMName(char which)
  249. {
  250. name[0] = which;
  251. if (name[1] != '-')
  252. return;
  253. DWORD pid = GetCurrentProcessId();
  254. char *num = &(name[1]);
  255. for (int i = 0; i < 8; i++)
  256. {
  257. *num = (char)('A' + (pid & 0xF));
  258. num++;
  259. pid >>= 4;
  260. }
  261. }
  262. bool
  263. _RTC_Lock(int work) // currently work = 1, init = 0
  264. {
  265. HANDLE mutex = (work == WORK_MUTEX) ? work_mutex : init_mutex;
  266. char chr = (work == WORK_MUTEX) ? 'W' : 'I';
  267. if (mutex == INVALID_HANDLE_VALUE)
  268. {
  269. SetSMName(chr);
  270. mutex = CreateMutex(NULL, FALSE, name);
  271. if (mutex == INVALID_HANDLE_VALUE)
  272. return false;
  273. }
  274. WaitForSingleObject(mutex, INFINITE);
  275. return true;
  276. }
  277. void
  278. _RTC_Unlock(int work)
  279. {
  280. ReleaseMutex((work == WORK_MUTEX) ? work_mutex : init_mutex);
  281. }
  282. static _RTC_globals*
  283. GetRTCGlobalData() throw()
  284. {
  285. // Try to open the memory mapped file
  286. // If it's not created, create it & init it to zeroes
  287. SetSMName('F');
  288. sharedmem = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
  289. 0, _RTC_GLOBALS_SIZE, name);
  290. if (!sharedmem)
  291. return 0;
  292. DWORD lastErr = GetLastError();
  293. _RTC_globals* data = (_RTC_globals *)MapViewOfFile(sharedmem,
  294. FILE_MAP_ALL_ACCESS,
  295. 0, 0, 0);
  296. if (!data)
  297. return 0;
  298. if (lastErr != ERROR_ALREADY_EXISTS)
  299. {
  300. memset(data, 0, sizeof(_RTC_globals));
  301. }
  302. return data;
  303. }
  304. // This function should be called when data in the global pointer has changed
  305. // This stuff is highly version sensitive! Be careful!
  306. static void
  307. _RTC_NotifyOfGlobChange() throw()
  308. {
  309. _RTC_memlock = _RTC_globptr->memlock;
  310. #ifdef _RTC_ADVMEM
  311. _RTC_heap2 = _RTC_globptr->heap2;
  312. _RTC_heap4 = _RTC_globptr->heap4;
  313. _RTC_heap8 = _RTC_globptr->heap8;
  314. _RTC_shadow = _RTC_globptr->shadow;
  315. _RTC_pageidx = _RTC_globptr->pageidx;
  316. _RTC_pi_array = _RTC_globptr->pi_array;
  317. _RTC_memhier = _RTC_globptr->memhier;
  318. _RTC_heapblocks = _RTC_globptr->heapblocks;
  319. _RTC_shadowmemory = _RTC_globptr->shadowmemory;
  320. #endif
  321. }
  322. // This function should be called when local data has changed
  323. // and needs copied to global data
  324. // This stuff is highly version sensitive! Be careful!
  325. void
  326. _RTC_NotifyOthersOfChange(void *addr)
  327. {
  328. _RTC_globptr->memlock = _RTC_memlock;
  329. #ifdef _RTC_ADVMEM
  330. _RTC_globptr->heap2 = _RTC_heap2;
  331. _RTC_globptr->heap4 = _RTC_heap4;
  332. _RTC_globptr->heap8 = _RTC_heap8;
  333. _RTC_globptr->shadow = _RTC_shadow;
  334. _RTC_globptr->heapblocks = _RTC_heapblocks;
  335. _RTC_globptr->memhier = _RTC_memhier;
  336. _RTC_globptr->pageidx = _RTC_pageidx;
  337. _RTC_globptr->pi_array = _RTC_pi_array;
  338. _RTC_globptr->shadowmemory = _RTC_shadowmemory;
  339. #endif
  340. for (_RTC_Funcs *f = _RTC_globptr->callbacks; f; f = f->next)
  341. if (f->allocationBase != addr)
  342. f->notify();
  343. }
  344. void __cdecl
  345. _RTC_SetOutOfMemFunc(int (*func)(void))
  346. {
  347. if (!_RTC_Lock())
  348. return;
  349. __try {
  350. MEMORY_BASIC_INFORMATION mbi;
  351. if (VirtualQuery(&_RTC_SetErrorFunc, &mbi, sizeof(mbi)))
  352. {
  353. for (_RTC_Funcs *f = _RTC_globptr->callbacks; f; f = f->next)
  354. {
  355. if (f->allocationBase == mbi.AllocationBase)
  356. {
  357. f->shadowoff = func;
  358. break;
  359. }
  360. }
  361. }
  362. }__finally{
  363. _RTC_Unlock();
  364. }
  365. }
  366. #endif // _RTC_ADVMEM