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.

482 lines
16 KiB

  1. /*----------------------------------------------------------------------
  2. REGISTRY.C
  3. Async tracing Registry reading routines
  4. Copyright (C) 1994 Microsoft Corporation
  5. All rights reserved.
  6. Authors:
  7. gordm Gord Mangione
  8. History:
  9. 01/30/95 gordm Created.
  10. ----------------------------------------------------------------------*/
  11. #ifndef WIN32_LEAN_AND_MEAN
  12. #define WIN32_LEAN_AND_MEAN
  13. #endif
  14. #define _DBGTRACE_DLL_IMPLEMENTATION
  15. #include <windows.h>
  16. #include "traceint.h"
  17. #include "randint.h"
  18. char szTraceFileName[MAX_PATH];
  19. char szDebugAsyncTrace[] = "SOFTWARE\\Microsoft\\MosTrace\\CurrentVersion\\DebugAsyncTrace";
  20. extern DbgTraceDLL DWORD __dwEnabledTraces;
  21. __inline BOOL GetRegDword( HKEY hKey, LPSTR pszValue, LPDWORD pdw )
  22. {
  23. DWORD cbData = sizeof( DWORD );
  24. DWORD dwType = REG_DWORD;
  25. return RegQueryValueEx(hKey,
  26. pszValue,
  27. NULL,
  28. &dwType,
  29. (LPBYTE)pdw,
  30. &cbData ) == ERROR_SUCCESS && dwType == REG_DWORD;
  31. }
  32. __inline BOOL GetRegString( HKEY hKey, LPSTR pszValue, LPBYTE buf, LPDWORD lpcbData )
  33. {
  34. DWORD dwType = REG_SZ;
  35. return RegQueryValueEx(hKey,
  36. pszValue,
  37. NULL,
  38. &dwType,
  39. buf,
  40. lpcbData ) == ERROR_SUCCESS && dwType == REG_SZ;
  41. }
  42. __inline BOOL GetRegMSZ( HKEY hKey, LPSTR pszValue, LPBYTE buf, LPDWORD lpcbData)
  43. {
  44. DWORD dwType = REG_MULTI_SZ;
  45. return RegQueryValueEx(hKey,
  46. pszValue,
  47. NULL,
  48. &dwType,
  49. buf,
  50. lpcbData ) == ERROR_SUCCESS && dwType == REG_MULTI_SZ;
  51. }
  52. BOOL GetTraceFlagsFromRegistry( void )
  53. {
  54. static char szNewTraceFileName[MAX_PATH];
  55. static char mszNewModules[MODULES_BUFFER_SIZE];
  56. DWORD dwNewEnabledTraces;
  57. DWORD dwNewTraceOutputType;
  58. DWORD dwNewAsyncTraceFlag;
  59. DWORD dwNewHeapIncrementCount;
  60. int nNewThreadPriority;
  61. long nNewFailRate;
  62. LONG cRandFailBuffer;
  63. HKEY hkConfig = NULL;
  64. BOOL bRC = FALSE;
  65. DWORD cbData;
  66. DWORD dwDisposition;
  67. __try
  68. {
  69. if ( RegCreateKeyEx(
  70. HKEY_LOCAL_MACHINE,
  71. szDebugAsyncTrace,
  72. 0,
  73. NULL,
  74. REG_OPTION_NON_VOLATILE,
  75. KEY_READ,
  76. NULL,
  77. &hkConfig,
  78. &dwDisposition) == ERROR_SUCCESS )
  79. {
  80. if ( GetRegDword( hkConfig,
  81. "MaxTraceFileSize",
  82. &dwMaxFileSize ) == FALSE )
  83. {
  84. dwMaxFileSize = DEFAULT_MAX_FILE_SIZE;
  85. }
  86. //
  87. // determine threshold count based on how we can fit in the file
  88. //
  89. PendQ.dwThresholdCount = dwMaxFileSize / AVERAGE_TRACE_SIZE;
  90. INT_TRACE( "PendQ.dwThresholdCount: %d\n", PendQ.dwThresholdCount );
  91. //
  92. // determine the modules to log
  93. //
  94. cbData = MODULES_BUFFER_SIZE;
  95. ZeroMemory(mszNewModules, sizeof(mszNewModules));
  96. if ( GetRegMSZ( hkConfig, "Modules", mszNewModules, &cbData ) == FALSE) {
  97. INT_TRACE( "GetRegMSZ: Modules failed: %d\n", GetLastError());
  98. INT_TRACE( "\tLogging all modules" );
  99. ZeroMemory(mszNewModules, MODULES_BUFFER_SIZE);
  100. }
  101. if ( GetRegDword( hkConfig,
  102. "EnabledTraces",
  103. &dwNewEnabledTraces ) == FALSE )
  104. {
  105. //
  106. // Optional reg entry
  107. // default is existing value of __dwEnabledTraces
  108. //
  109. INT_TRACE( "GetRegDword: EnabledTraces failed: %d\n", GetLastError() );
  110. dwNewEnabledTraces = __dwEnabledTraces;
  111. }
  112. if ( GetRegDword( hkConfig,
  113. "OutputTraceType",
  114. &dwNewTraceOutputType ) == FALSE )
  115. {
  116. //
  117. // Optional reg entry
  118. // default is existing value of dwTraceOutputType
  119. //
  120. INT_TRACE( "GetRegDword: OutputTraceType failed: %d\n", GetLastError() );
  121. dwNewTraceOutputType = dwTraceOutputType;
  122. }
  123. // If ouput is disabled, clear the EnabledTraces bitmap
  124. if (dwNewTraceOutputType == TRACE_OUTPUT_DISABLED )
  125. dwNewEnabledTraces = 0;
  126. if ( GetRegDword( hkConfig,
  127. "AsyncTraceFlag",
  128. &dwNewAsyncTraceFlag ) == FALSE )
  129. {
  130. //
  131. // Optional reg entry
  132. // default is existing value of dwAsyncTraceFlag
  133. //
  134. INT_TRACE( "GetRegDword: AsyncTraceFlag failed: %d\n", GetLastError() );
  135. dwNewAsyncTraceFlag = dwAsyncTraceFlag;
  136. }
  137. if (GetRegDword(hkConfig,
  138. "HeapIncrementCount",
  139. (LPDWORD)&dwNewHeapIncrementCount ) == FALSE ||
  140. dwNewHeapIncrementCount == 0 )
  141. {
  142. //
  143. // optional reg entry
  144. // default is the number buffers in 64KB
  145. //
  146. dwNewHeapIncrementCount = 0x10000 / sizeof(TRACEBUF);
  147. }
  148. InterlockedExchange( (long *)&dwIncrementSize, (long)dwNewHeapIncrementCount );
  149. if ( GetRegDword( hkConfig,
  150. "AsyncThreadPriority",
  151. (LPDWORD)&nNewThreadPriority ) == FALSE )
  152. {
  153. //
  154. // optional reg entry
  155. //
  156. nNewThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
  157. }
  158. else switch( nNewThreadPriority )
  159. {
  160. //
  161. // if successful verify the resulting value
  162. //
  163. case THREAD_PRIORITY_IDLE:
  164. case THREAD_PRIORITY_BELOW_NORMAL:
  165. case THREAD_PRIORITY_NORMAL:
  166. case THREAD_PRIORITY_ABOVE_NORMAL:
  167. case THREAD_PRIORITY_HIGHEST:
  168. break;
  169. default:
  170. ASSERT( FALSE );
  171. nNewThreadPriority = THREAD_PRIORITY_BELOW_NORMAL;
  172. }
  173. if (GetRegDword(hkConfig,
  174. "FailureRate",
  175. (LPDWORD)&nNewFailRate ) == FALSE)
  176. {
  177. //
  178. // optional reg entry
  179. // default is to disable failure
  180. //
  181. nNewFailRate = kDontFail;
  182. }
  183. InterlockedExchange( &nFailRate, nNewFailRate );
  184. cbData = MAX_PATH;
  185. if ( !GetRegString( hkConfig,
  186. "FailureFile",
  187. g_szRandFailFile,
  188. &cbData ) ) {
  189. *g_szRandFailFile = '\0';
  190. }
  191. if ( GetRegDword( hkConfig,
  192. "FailureBuffer",
  193. (LPDWORD)&cRandFailBuffer ))
  194. {
  195. g_cCallStack = cRandFailBuffer;
  196. } else
  197. g_cCallStack = 1; // default value
  198. cbData = sizeof(szNewTraceFileName);
  199. if ( GetRegString( hkConfig,
  200. "TraceFile",
  201. szNewTraceFileName,
  202. &cbData ) == FALSE )
  203. {
  204. //
  205. // Only fail if user specifies FILE based tracing
  206. //
  207. if ( dwNewTraceOutputType & TRACE_OUTPUT_FILE )
  208. {
  209. INT_TRACE( "GetRegString: TraceFile failed: %d\n", GetLastError() );
  210. return bRC = FALSE;
  211. }
  212. }
  213. bRC = TRUE;
  214. }
  215. }
  216. __finally
  217. {
  218. //
  219. // preserve the original error code
  220. //
  221. DWORD dwLastError = GetLastError();
  222. BOOL fLeaveCritSec = FALSE;
  223. if ( bRC == TRUE )
  224. {
  225. BOOL bNewFileName = lstrcmpi( szNewTraceFileName, szTraceFileName ) != 0;
  226. BOOL bNewTraces = dwNewEnabledTraces != __dwEnabledTraces;
  227. BOOL bNewFlags = dwNewAsyncTraceFlag != dwAsyncTraceFlag;
  228. BOOL bNewOutput = dwNewTraceOutputType != dwTraceOutputType;
  229. BOOL bNewModules = memcmp(mszModules, mszNewModules, MODULES_BUFFER_SIZE) != 0;
  230. INT_TRACE( "GetTraceFlags... 0x%08X, 0x%08X, 0x%08X, %s\n",
  231. dwNewAsyncTraceFlag,
  232. dwNewEnabledTraces,
  233. dwNewTraceOutputType,
  234. szNewTraceFileName );
  235. INT_TRACE( "bNewFileName:%d bNewTraces:%d bNewOutput:%d bNewFlags:%d bNewModules:%d\n",
  236. bNewFileName,
  237. bNewTraces,
  238. bNewOutput,
  239. bNewFlags,
  240. bNewModules );
  241. if ( bNewFileName || bNewTraces || bNewOutput || bNewFlags || bNewModules )
  242. {
  243. if ( __dwEnabledTraces )
  244. {
  245. //
  246. // not the initial time thru
  247. //
  248. fLeaveCritSec = TRUE;
  249. if ( dwAsyncTraceFlag )
  250. {
  251. FlushAsyncTrace();
  252. }
  253. EnterCriticalSection( &critSecWrite );
  254. }
  255. if ( PendQ.hFile != INVALID_HANDLE_VALUE )
  256. {
  257. //
  258. // if the file name changed or tracing was disabled or the
  259. // file tracing disabled, then close the currently open file
  260. //
  261. if( bNewFileName ||
  262. dwNewEnabledTraces == 0 ||
  263. IsTraceFile( dwNewTraceOutputType ) == FALSE )
  264. {
  265. BOOL bSuccess;
  266. EnterCriticalSection( &critSecWrite );
  267. bSuccess = CloseHandle( PendQ.hFile );
  268. INT_TRACE( "CloseHandle: %d, GetLastError: %d\n",
  269. bSuccess, GetLastError() );
  270. PendQ.hFile = INVALID_HANDLE_VALUE;
  271. LeaveCriticalSection( &critSecWrite );
  272. }
  273. }
  274. if ( IsTraceFile( dwNewTraceOutputType ) )
  275. {
  276. if (bNewFileName ||
  277. IsTraceFile( dwTraceOutputType ) == FALSE ||
  278. dwNewEnabledTraces != 0 &&
  279. PendQ.hFile == INVALID_HANDLE_VALUE )
  280. {
  281. PendQ.hFile = CreateFile(szNewTraceFileName,
  282. GENERIC_WRITE,
  283. FILE_SHARE_READ|FILE_SHARE_WRITE,
  284. NULL,
  285. OPEN_ALWAYS,
  286. FILE_ATTRIBUTE_NORMAL,
  287. NULL );
  288. if ( PendQ.hFile != INVALID_HANDLE_VALUE )
  289. {
  290. lstrcpy( szTraceFileName, szNewTraceFileName );
  291. }
  292. else
  293. {
  294. INT_TRACE( "CreateFile failed for %s 0x%X\n",
  295. szNewTraceFileName,
  296. GetLastError() );
  297. }
  298. }
  299. }
  300. //
  301. // set the new priority for the writer thread
  302. //
  303. if ( nNewThreadPriority != nAsyncThreadPriority )
  304. {
  305. nAsyncThreadPriority = nNewThreadPriority;
  306. SetThreadPriority( PendQ.hWriteThread, nAsyncThreadPriority );
  307. }
  308. //
  309. // set the new list of modules to log
  310. //
  311. if ( bNewModules ) {
  312. memcpy(mszModules, mszNewModules, MODULES_BUFFER_SIZE);
  313. }
  314. dwTraceOutputType = dwNewTraceOutputType;
  315. dwAsyncTraceFlag = dwNewAsyncTraceFlag;
  316. InterlockedExchange( &__dwEnabledTraces, dwNewEnabledTraces );
  317. if ( fLeaveCritSec )
  318. {
  319. //
  320. // not the initial time thru
  321. //
  322. LeaveCriticalSection( &critSecWrite );
  323. }
  324. }
  325. }
  326. if ( hkConfig != NULL )
  327. {
  328. RegCloseKey( hkConfig );
  329. }
  330. SetLastError( dwLastError );
  331. }
  332. return bRC;
  333. }
  334. #define NUM_REG_THREAD_OBJECTS 2
  335. DWORD RegNotifyThread( LPDWORD lpdw )
  336. {
  337. HANDLE Handles[NUM_REG_THREAD_OBJECTS];
  338. HKEY hKey;
  339. DWORD dw;
  340. Handles[0] = hShutdownEvent;
  341. INT_TRACE( "RegNotifyThread 0x%X\n", GetCurrentThreadId() );
  342. Handles[1] = CreateEvent( NULL, FALSE, FALSE, NULL );
  343. if ( Handles[1] == NULL )
  344. {
  345. ASSERT( FALSE );
  346. INT_TRACE( "RegNotifyThread CreateEvent failed 0x%X\n", GetLastError() );
  347. return 1;
  348. }
  349. if ( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  350. szDebugAsyncTrace,
  351. 0,
  352. KEY_READ,
  353. &hKey ) != ERROR_SUCCESS )
  354. {
  355. INT_TRACE( "RegNotifyThread RegOpenKeyEx failed 0x%X\n", GetLastError() );
  356. CloseHandle( Handles[1] );
  357. return 1;
  358. }
  359. for ( ;; )
  360. {
  361. if ( RegNotifyChangeKeyValue(hKey,
  362. FALSE,
  363. REG_NOTIFY_CHANGE_ATTRIBUTES |
  364. REG_NOTIFY_CHANGE_LAST_SET,
  365. Handles[1],
  366. TRUE ) != ERROR_SUCCESS )
  367. {
  368. INT_TRACE( "RegNotifyThread RegNotify... failed 0x%X\n", GetLastError() );
  369. RegCloseKey( hKey );
  370. CloseHandle( Handles[1] );
  371. return 1;
  372. }
  373. dw = WaitForMultipleObjects(NUM_REG_THREAD_OBJECTS,
  374. Handles,
  375. FALSE,
  376. INFINITE );
  377. switch( dw )
  378. {
  379. //
  380. // normal signalled event
  381. //
  382. case WAIT_OBJECT_0:
  383. RegCloseKey( hKey );
  384. CloseHandle( Handles[1] );
  385. INT_TRACE( "Exiting RegNotifyThread for hShutdownEvent\n" );
  386. return 0;
  387. //
  388. // signalled that our registry keys have changed
  389. //
  390. case WAIT_OBJECT_0+1:
  391. GetTraceFlagsFromRegistry();
  392. break;
  393. default:
  394. INT_TRACE( "RegNotifyThread WFMO: dw: 0x%X, Error: 0x%X\n", dw, GetLastError() );
  395. ASSERT( FALSE );
  396. RegCloseKey( hKey );
  397. CloseHandle( Handles[1] );
  398. return 1;
  399. }
  400. }
  401. INT_TRACE( "Exiting RegNotifyThread abnormally\n" );
  402. RegCloseKey( hKey );
  403. CloseHandle( Handles[1] );
  404. return 2;
  405. }