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.

498 lines
12 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1995 - 1999
  3. Module Name:
  4. util.c
  5. Abstract:
  6. Various helper and debug functions shared between platforms.
  7. Author:
  8. Mario Goertzel [MarioGo]
  9. Revision History:
  10. MarioGo 95/10/21 Bits 'n pieces
  11. --*/
  12. #include <precomp.hxx>
  13. #include <stdarg.h>
  14. #ifdef DEBUGRPC
  15. BOOL ValidateError(
  16. IN unsigned int Status,
  17. IN unsigned int Count,
  18. IN const int ErrorList[])
  19. /*++
  20. Routine Description
  21. Tests that 'Status' is one of an expected set of error codes.
  22. Used on debug builds as part of the VALIDATE() macro.
  23. Example:
  24. VALIDATE(EventStatus)
  25. {
  26. RPC_P_CONNECTION_CLOSED,
  27. RPC_P_RECEIVE_FAILED,
  28. RPC_P_CONNECTION_SHUTDOWN
  29. // more error codes here
  30. } END_VALIDATE;
  31. This function is called with the RpcStatus and expected errors codes
  32. as parameters. If RpcStatus is not one of the expected error
  33. codes and it not zero a message will be printed to the debugger
  34. and the function will return false. The VALIDATE macro ASSERT's the
  35. return value.
  36. Arguments:
  37. Status - Status code in question.
  38. Count - number of variable length arguments
  39. ... - One or more expected status codes. Terminated with 0 (RPC_S_OK).
  40. Return Value:
  41. TRUE - Status code is in the list or the status is 0.
  42. FALSE - Status code is not in the list.
  43. --*/
  44. {
  45. unsigned i;
  46. for (i = 0; i < Count; i++)
  47. {
  48. if (ErrorList[i] == (int) Status)
  49. {
  50. return TRUE;
  51. }
  52. }
  53. PrintToDebugger("RPC Assertion: unexpected failure %lu (0lx%08x)\n",
  54. (unsigned long)Status, (unsigned long)Status);
  55. return(FALSE);
  56. }
  57. #endif // DEBUGRPC
  58. //------------------------------------------------------------------------
  59. #ifdef RPC_ENABLE_WMI_TRACE
  60. #include <wmistr.h>
  61. #include <evntrace.h>
  62. #include "wmlum.h" // private header from clustering
  63. extern "C"
  64. {
  65. DWORD __stdcall
  66. I_RpcEnableWmiTrace(
  67. PWML_TRACE fn,
  68. WMILIB_REG_STRUCT ** pHandle
  69. );
  70. }
  71. typedef DWORD (*WMI_TRACE_FN)();
  72. PWML_TRACE WmiTraceFn = 0;
  73. WMILIB_REG_STRUCT WmiTraceData;
  74. GUID WmiMessageGuid = { /* 41de81c0-aa28-460b-a455-c23809e7c170 */
  75. 0x41de81c0,
  76. 0xaa28,
  77. 0x460b,
  78. {0xa4, 0x55, 0xc2, 0x38, 0x09, 0xe7, 0xc1, 0x70}
  79. };
  80. DWORD __stdcall
  81. I_RpcEnableWmiTrace(
  82. PWML_TRACE fn,
  83. WMILIB_REG_STRUCT ** pHandle
  84. )
  85. {
  86. WmiTraceFn = fn;
  87. *pHandle = &WmiTraceData;
  88. return 0;
  89. }
  90. #endif
  91. BOOL fEnableLog = TRUE;
  92. C_ASSERT(sizeof(LUID) == sizeof(__int64));
  93. struct RPC_EVENT * RpcEvents;
  94. long EventArrayLength = MAX_RPC_EVENT;
  95. long NextEvent = 0;
  96. BOOL DisableEvents = 0;
  97. boolean SubjectExceptions[256];
  98. boolean VerbExceptions[256];
  99. #define LOG_VAR( x ) &(x), sizeof(x)
  100. HANDLE hLogFile = 0;
  101. struct RPC_EVENT_LOG
  102. {
  103. DWORD Thread;
  104. union
  105. {
  106. struct
  107. {
  108. unsigned char Subject;
  109. unsigned char Verb;
  110. };
  111. DWORD ZeroSet;
  112. };
  113. void * SubjectPointer;
  114. void * ObjectPointer;
  115. ULONG_PTR Data;
  116. void * EventStackTrace[STACKTRACE_DEPTH];
  117. };
  118. void
  119. TrulyLogEvent(
  120. IN unsigned char Subject,
  121. IN unsigned char Verb,
  122. IN void * SubjectPointer,
  123. IN void * ObjectPointer,
  124. IN ULONG_PTR Data,
  125. IN BOOL fCaptureStackTrace,
  126. IN int AdditionalFramesToSkip
  127. )
  128. {
  129. if (DisableEvents != SubjectExceptions[Subject] ||
  130. DisableEvents != VerbExceptions[Verb])
  131. {
  132. return;
  133. }
  134. //
  135. // Allocate the event table if it isn't already there.
  136. //
  137. if (!RpcEvents)
  138. {
  139. struct RPC_EVENT * Temp = (struct RPC_EVENT *) HeapAlloc( GetProcessHeap(),
  140. HEAP_ZERO_MEMORY,
  141. EventArrayLength * sizeof(RPC_EVENT) );
  142. HANDLE LocalFile;
  143. if (!Temp)
  144. {
  145. return;
  146. }
  147. if (InterlockedCompareExchangePointer((void **) &RpcEvents, Temp, 0) != 0)
  148. {
  149. HeapFree(GetProcessHeap(), 0, Temp);
  150. }
  151. /*
  152. if (wcsstr(GetCommandLine(), L"fs.exe") != NULL)
  153. {
  154. LocalFile = CreateFile(L"d:\\rpcclnt.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
  155. FILE_ATTRIBUTE_NORMAL, NULL);
  156. if (LocalFile != INVALID_HANDLE_VALUE)
  157. {
  158. hLogFile = LocalFile;
  159. }
  160. else
  161. {
  162. if (hLogFile == 0)
  163. {
  164. DbgPrint("ERROR: Could not create RPC log file: %d\n", GetLastError());
  165. }
  166. // else
  167. // somebody already set it - ignore
  168. }
  169. }
  170. else if (wcsstr(GetCommandLine(), L"fssvr.exe") != NULL)
  171. {
  172. LocalFile = CreateFile(L"d:\\rpcsvr.log", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
  173. FILE_ATTRIBUTE_NORMAL, NULL);
  174. if (LocalFile != INVALID_HANDLE_VALUE)
  175. {
  176. hLogFile = LocalFile;
  177. }
  178. else
  179. {
  180. if (hLogFile == 0)
  181. {
  182. DbgPrint("ERROR: Could not create RPC log file: %d\n", GetLastError());
  183. }
  184. // else
  185. // somebody already set it - ignore
  186. }
  187. }
  188. */
  189. /*
  190. DisableEvents = TRUE;
  191. SubjectExceptions[SU_ADDRESS] = TRUE;
  192. VerbExceptions[EV_CREATE] = TRUE;
  193. VerbExceptions[EV_DELETE] = TRUE;
  194. */
  195. /*
  196. SubjectExceptions[SU_HEAP] = TRUE;
  197. SubjectExceptions[SU_EVENT] = TRUE;
  198. SubjectExceptions[SU_BCACHE] = TRUE;
  199. */
  200. /*
  201. DisableEvents = TRUE;
  202. SubjectExceptions['a'] = TRUE;
  203. SubjectExceptions['g'] = TRUE;
  204. SubjectExceptions['G'] = TRUE;
  205. SubjectExceptions['W'] = TRUE;
  206. SubjectExceptions['X'] = TRUE;
  207. SubjectExceptions['Y'] = TRUE;
  208. SubjectExceptions['Z'] = TRUE;
  209. SubjectExceptions['w'] = TRUE;
  210. SubjectExceptions['x'] = TRUE;
  211. SubjectExceptions['y'] = TRUE;
  212. SubjectExceptions['z'] = TRUE;
  213. VerbExceptions['t'] = TRUE;
  214. VerbExceptions['G'] = TRUE;
  215. VerbExceptions['g'] = TRUE;
  216. VerbExceptions['w'] = TRUE;
  217. VerbExceptions['x'] = TRUE;
  218. VerbExceptions['y'] = TRUE;
  219. VerbExceptions['z'] = TRUE;
  220. VerbExceptions['W'] = TRUE;
  221. VerbExceptions['X'] = TRUE;
  222. VerbExceptions['Y'] = TRUE;
  223. VerbExceptions['Z'] = TRUE;
  224. */
  225. }
  226. unsigned index = InterlockedIncrement(&NextEvent);
  227. index %= EventArrayLength;
  228. RpcEvents[index].Time = GetTickCount();
  229. RpcEvents[index].Verb = Verb;
  230. RpcEvents[index].Subject = Subject;
  231. RpcEvents[index].Thread = (short) GetCurrentThreadId();
  232. RpcEvents[index].SubjectPointer = SubjectPointer;
  233. RpcEvents[index].ObjectPointer = ObjectPointer;
  234. RpcEvents[index].Data = Data;
  235. CallTestHook( TH_RPC_LOG_EVENT, &RpcEvents[index], 0 );
  236. #ifdef RPC_ENABLE_WMI_TRACE
  237. if (WmiTraceData.EnableFlags)
  238. {
  239. TraceMessage(
  240. WmiTraceData.LoggerHandle,
  241. TRACE_MESSAGE_SEQUENCE | TRACE_MESSAGE_GUID | TRACE_MESSAGE_SYSTEMINFO | TRACE_MESSAGE_TIMESTAMP,
  242. &WmiMessageGuid,
  243. Verb,
  244. LOG_VAR(Subject),
  245. LOG_VAR(SubjectPointer),
  246. LOG_VAR(ObjectPointer),
  247. LOG_VAR(Data),
  248. 0
  249. );
  250. }
  251. #endif
  252. #if i386
  253. if (fCaptureStackTrace)
  254. {
  255. ULONG ignore;
  256. RtlCaptureStackBackTrace(
  257. 1 + AdditionalFramesToSkip,
  258. STACKTRACE_DEPTH,
  259. (void **) &RpcEvents[index].EventStackTrace,
  260. &ignore);
  261. }
  262. else
  263. #endif
  264. {
  265. RpcEvents[index].EventStackTrace[0] = 0;
  266. }
  267. if (hLogFile)
  268. {
  269. DWORD BytesWritten;
  270. /*
  271. RPC_EVENT_LOG logEntry;
  272. RPC_EVENT *CurrentEvent = &RpcEvents[index];
  273. logEntry.Thread = CurrentEvent->Thread;
  274. logEntry.ZeroSet = 0;
  275. logEntry.Subject = CurrentEvent->Subject;
  276. logEntry.Verb = CurrentEvent->Verb;
  277. logEntry.Data = CurrentEvent->Data;
  278. logEntry.ObjectPointer = CurrentEvent->ObjectPointer;
  279. logEntry.SubjectPointer = CurrentEvent->SubjectPointer;
  280. memcpy(logEntry.EventStackTrace, CurrentEvent->EventStackTrace, sizeof(logEntry.EventStackTrace));
  281. WriteFile(hLogFile, &logEntry, sizeof(logEntry), &BytesWritten, NULL);
  282. */
  283. WriteFile(hLogFile, &RpcEvents[index], sizeof(RpcEvents[index]), &BytesWritten, NULL);
  284. }
  285. }
  286. void RPC_ENTRY
  287. I_RpcLogEvent (
  288. IN unsigned char Subject,
  289. IN unsigned char Verb,
  290. IN void * SubjectPointer,
  291. IN void * ObjectPointer,
  292. IN unsigned Data,
  293. IN BOOL fCaptureStackTrace,
  294. IN int AdditionalFramesToSkip
  295. )
  296. {
  297. LogEvent(Subject, Verb, SubjectPointer, ObjectPointer, Data,
  298. fCaptureStackTrace, AdditionalFramesToSkip);
  299. }
  300. #if 0
  301. BOOL
  302. IsLoggingEnabled()
  303. {
  304. RPC_CHAR ModulePath[ MAX_PATH ];
  305. RPC_CHAR * ModuleName;
  306. //
  307. // Find out the .EXE name.
  308. //
  309. if (!GetModuleFileName( NULL, ModulePath, sizeof(ModulePath)))
  310. {
  311. return FALSE;
  312. }
  313. signed i;
  314. for (i=RpcpStringLength(ModulePath)-1; i >= 0; --i)
  315. {
  316. if (ModulePath[i] == '\\')
  317. {
  318. break;
  319. }
  320. }
  321. ModuleName = ModulePath + i + 1;
  322. //
  323. // See whether logging should be enabled.
  324. //
  325. HANDLE hImeo;
  326. HANDLE hMyProcessOptions;
  327. DWORD Error;
  328. DWORD Value;
  329. DWORD Length = sizeof(Value);
  330. DWORD Type;
  331. Error = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  332. RPC_CONST_STRING("Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"),
  333. 0,
  334. KEY_READ,
  335. &hImeo
  336. );
  337. if (Error)
  338. {
  339. return FALSE;
  340. }
  341. Error = RegOpenKeyEx( hImeo,
  342. ModuleName,
  343. 0,
  344. KEY_READ,
  345. &hMyProcessOptions
  346. );
  347. RegCloseKey( hImeo );
  348. if (Error)
  349. {
  350. return FALSE;
  351. }
  352. Error = RegQueryValueEx( hMyProcessOptions,
  353. RPC_CONST_STRING("Enable RPC Logging"),
  354. 0,
  355. &Type,
  356. &Value,
  357. &Length
  358. );
  359. RegCloseKey( hMyProcessOptions );
  360. if (Error)
  361. {
  362. return FALSE;
  363. }
  364. if (Type == REG_DWORD && Value)
  365. {
  366. return TRUE;
  367. }
  368. if (Type == REG_SZ && 0 == RpcpStringCompare((RPC_CHAR *) Value, RPC_CONST_CHAR('Y')))
  369. {
  370. return TRUE;
  371. }
  372. return FALSE;
  373. }
  374. #endif
  375. extern "C" int __cdecl _purecall(void)
  376. {
  377. #ifdef DEBUGRPC
  378. ASSERT(!"PureVirtualCalled");
  379. #endif
  380. return 0;
  381. }
  382. const RPC_CHAR *
  383. FastGetImageBaseName (
  384. void
  385. )
  386. /*++
  387. Routine Description
  388. Retrieves the image base name with touching minimal amount of
  389. other memory.
  390. Arguments:
  391. Return Value:
  392. A pointer to LDR private string with the image name. Don't write or
  393. delete it!
  394. --*/
  395. {
  396. PLIST_ENTRY Module;
  397. PLDR_DATA_TABLE_ENTRY Entry;
  398. Module = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
  399. Entry = CONTAINING_RECORD(Module,
  400. LDR_DATA_TABLE_ENTRY,
  401. InLoadOrderLinks);
  402. return Entry->BaseDllName.Buffer;
  403. }