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.

594 lines
14 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // triage.ini searching code
  4. //
  5. // Copyright (C) Microsoft Corporation, 2001.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. CTriager *g_pTriager = NULL;
  11. typedef struct TRIAGE_LIST {
  12. TRIAGE_DATA TriageData;
  13. struct TRIAGE_LIST * Next;
  14. } TRIAGE_LIST;
  15. void DeleteList(TRIAGE_LIST* Start)
  16. {
  17. TRIAGE_LIST * Next = NULL;
  18. while (Start)
  19. {
  20. Next = Start->Next;
  21. free(Start);
  22. Start = Next;
  23. }
  24. }
  25. TRIAGE_LIST* InsertEntry(
  26. TRIAGE_LIST* Start,
  27. PTRIAGE_DATA pData
  28. )
  29. {
  30. TRIAGE_LIST* NewEntry;
  31. NewEntry = (TRIAGE_LIST*) malloc(sizeof(TRIAGE_LIST));
  32. if (!NewEntry)
  33. {
  34. DeleteList(Start);
  35. return NULL;
  36. }
  37. NewEntry->TriageData = *pData;
  38. TRIAGE_LIST *InsertAfter, *InsertBefore;
  39. InsertAfter = NULL; InsertBefore = Start;
  40. NewEntry->Next = InsertBefore;
  41. if (InsertAfter)
  42. {
  43. InsertAfter->Next = NewEntry;
  44. } else
  45. {
  46. return NewEntry;
  47. }
  48. return Start;
  49. }
  50. #define TRIAGE_FILE_OCA 0
  51. #define TRIAGE_FILE_OSSPECIFIC 1
  52. #define TRIAGE_FILE_DEFAULT 2
  53. PCHAR
  54. GetTriageFileName(
  55. ULONG TriageType
  56. )
  57. {
  58. static CHAR szTriageFileName[MAX_PATH+50];
  59. PCHAR ExeDir;
  60. ExeDir = &szTriageFileName[0];
  61. *ExeDir = 0;
  62. // Get the directory the debugger executable is in.
  63. if (!GetModuleFileName(NULL, ExeDir, MAX_PATH))
  64. {
  65. // Error. Use the current directory.
  66. strcpy(ExeDir, ".");
  67. } else
  68. {
  69. // Remove the executable name.
  70. PCHAR pszTmp = strrchr(ExeDir, '\\');
  71. if (pszTmp)
  72. {
  73. *pszTmp = 0;
  74. }
  75. }
  76. switch (TriageType)
  77. {
  78. case TRIAGE_FILE_OSSPECIFIC:
  79. {
  80. PSTR OsDir;
  81. if (g_TargetBuild <= 1381)
  82. {
  83. OsDir = "\\nt4fre";
  84. } else if (g_TargetBuild <= 2195)
  85. {
  86. OsDir = "\\w2kfre";
  87. } else
  88. {
  89. OsDir = "\\winxp";
  90. }
  91. CatString(ExeDir, OsDir, sizeof(szTriageFileName));
  92. CatString(ExeDir, "\\triage.ini", sizeof(szTriageFileName));
  93. break;
  94. }
  95. case TRIAGE_FILE_OCA:
  96. CatString(ExeDir, "\\triage\\oca.ini", sizeof(szTriageFileName));
  97. break;
  98. case TRIAGE_FILE_DEFAULT:
  99. CatString(ExeDir, "\\triage\\triage.ini", sizeof(szTriageFileName));
  100. }
  101. return &szTriageFileName[0];
  102. }
  103. int __cdecl
  104. TriageDataCmp(const void* Data1, const void* Data2)
  105. {
  106. TRIAGE_DATA *Triage1 , *Triage2;
  107. int ret;
  108. Triage1 = (TRIAGE_DATA*) Data1;
  109. Triage2 = (TRIAGE_DATA*) Data2;
  110. ret=_stricmp(Triage1->Module, Triage2->Module);
  111. if (!ret)
  112. {
  113. ret = _stricmp(Triage1->Routine, Triage2->Routine);
  114. }
  115. return ret;
  116. }
  117. CTriager::CTriager()
  118. {
  119. CHAR FileLine[256];
  120. PCHAR pTriageFile;
  121. HANDLE hFile;
  122. ULONG Err;
  123. ULONG BytesRead;
  124. ULONG FileSize;
  125. PCHAR FileRead;
  126. PCHAR line;
  127. ULONG Index;
  128. ULONG TriageType;
  129. ULONG EntryCount;
  130. TRIAGE_DATA Entry;
  131. TRIAGE_LIST *Start, *Trav;
  132. Start = NULL;
  133. EntryCount = 0;
  134. TriageType = TRIAGE_FILE_OCA;
  135. //
  136. // We will always try to load the oca.ini file to get the connection
  137. // strings.
  138. // Then we will load the OS specific version of triage.ini when present
  139. // (it's an internal version of the file only) and load the default
  140. // triage\triage.ini if the specific one could not be opened.
  141. //
  142. GatherTriageInfo:
  143. pTriageFile = GetTriageFileName(TriageType);
  144. hFile = CreateFile(pTriageFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  145. if (hFile != INVALID_HANDLE_VALUE)
  146. {
  147. FileSize = GetFileSize(hFile, NULL);
  148. FileRead = (PCHAR) malloc(FileSize+1);
  149. if (!FileRead)
  150. {
  151. CloseHandle(hFile);
  152. return;
  153. }
  154. if (!ReadFile(hFile, FileRead, FileSize, &BytesRead, NULL))
  155. {
  156. CloseHandle(hFile);
  157. free( FileRead );
  158. return;
  159. }
  160. FileRead[FileSize] = 0;
  161. Index = 0;
  162. while (Index < FileSize)
  163. {
  164. ULONG LineLen = 0;
  165. line = &FileRead[Index];
  166. while (*line && (*line != '\n'))
  167. {
  168. if (*line != ' ' && *line > 0x20)
  169. {
  170. FileLine[LineLen++] = *line;
  171. }
  172. ++line;
  173. ++Index;
  174. }
  175. FileLine[LineLen] = 0;
  176. ++Index; // skip newline
  177. if (FileLine[0] == '\0' || FileLine[0] == ';')
  178. {
  179. continue;
  180. }
  181. PCHAR Followup;
  182. PCHAR Bang;
  183. if ((Followup = strchr(FileLine,'=')))
  184. {
  185. *Followup++ = 0;
  186. Entry.fModulPartial = 1;
  187. Entry.fRoutinePartial = 1;
  188. if (Bang = strchr(FileLine, '!'))
  189. {
  190. // An entry of type module[*]!routine[*]=followup
  191. // ^ ^
  192. // Bang Followup
  193. *Bang++ = 0;
  194. ULONG eq = (ULONG) ((ULONG64)Followup - (ULONG64)Bang);
  195. ULONG modbreak = (ULONG) ((ULONG64)Bang - (ULONG64)&FileLine[0]);
  196. Entry.fModulPartial = 0;
  197. FillStringBuffer(FileLine, 0, Entry.Module, sizeof(Entry.Module), NULL);
  198. if (*(Bang-2) == '*')
  199. {
  200. Entry.fModulPartial = 1;
  201. Entry.Module[modbreak-2] = 0;
  202. }
  203. modbreak++;
  204. Entry.fRoutinePartial = 0;
  205. FillStringBuffer(Bang, 0, Entry.Routine, sizeof(Entry.Routine), NULL);
  206. if (*(Followup-2)=='*')
  207. {
  208. Entry.Routine[eq-2] = 0;
  209. Entry.fRoutinePartial = 1;
  210. }
  211. }
  212. else
  213. {
  214. ULONG eq = (ULONG) ((ULONG64)Followup - (ULONG64)&FileLine[0]);
  215. Entry.Routine[0] = 0;
  216. Entry.fModulPartial = FALSE;
  217. FillStringBuffer(FileLine, 0, Entry.Module, sizeof(Entry.Module), NULL);
  218. if (*(Followup-2)=='*')
  219. {
  220. Entry.fModulPartial = TRUE;
  221. Entry.Module[eq-2] = 0;
  222. }
  223. if (!_stricmp(Entry.Routine, "default"))
  224. {
  225. Entry.Routine[0] = 0;
  226. }
  227. }
  228. CopyString(Entry.Followup , Followup, sizeof(Entry.Followup));
  229. // dprintf("%s\n Mod %s Rou %s\n", FileLine, Entry.Module, Entry.Routine);
  230. Start = InsertEntry(Start, &Entry);
  231. if (Start)
  232. {
  233. ++EntryCount;
  234. }
  235. else
  236. {
  237. EntryCount = 0;
  238. break;
  239. }
  240. }
  241. }
  242. free( FileRead );
  243. CloseHandle(hFile);
  244. }
  245. else
  246. {
  247. if (TriageType == TRIAGE_FILE_OSSPECIFIC)
  248. {
  249. TriageType = TRIAGE_FILE_DEFAULT;
  250. goto GatherTriageInfo;
  251. }
  252. }
  253. if (TriageType == TRIAGE_FILE_OCA)
  254. {
  255. TriageType = TRIAGE_FILE_OSSPECIFIC;
  256. goto GatherTriageInfo;
  257. }
  258. //
  259. // Now copy it to array for fast access;
  260. //
  261. if (EntryCount)
  262. {
  263. m_pTriageData = (PTRIAGE_DATA) malloc(EntryCount * sizeof(TRIAGE_DATA));
  264. if (!m_pTriageData)
  265. {
  266. DeleteList(Start);
  267. return;
  268. }
  269. m_EntryCount = EntryCount;
  270. Trav = Start;
  271. for (ULONG i = 0; i < m_EntryCount && Trav; ++i, Trav = Trav->Next)
  272. {
  273. m_pTriageData[i] = Trav->TriageData;
  274. }
  275. DeleteList(Start);
  276. qsort(m_pTriageData, m_EntryCount, sizeof(*m_pTriageData), &TriageDataCmp);
  277. } else
  278. {
  279. m_pTriageData = NULL;
  280. m_EntryCount = 0;
  281. }
  282. }
  283. CTriager::~CTriager()
  284. {
  285. if (m_pTriageData)
  286. {
  287. free(m_pTriageData);
  288. }
  289. }
  290. void
  291. CTriager::PrintTraigeInfo()
  292. {
  293. dprintf("Triage data %lx entries:\n"
  294. "Module Routine Followup\n",
  295. m_EntryCount);
  296. for (ULONG i = 0; i < m_EntryCount; ++i)
  297. {
  298. dprintf("%-15s%c%-29s%c%s\n",
  299. m_pTriageData[i].Module,
  300. m_pTriageData[i].fModulPartial ? '*' : ' ',
  301. m_pTriageData[i].Routine,
  302. m_pTriageData[i].fRoutinePartial ? '*' : ' ',
  303. m_pTriageData[i].Followup );
  304. }
  305. }
  306. ULONG
  307. CTriager::MatchSymbol(
  308. PSTR Module,
  309. PSTR Routine
  310. )
  311. {
  312. int Hi, Lo, Mid;
  313. int BestMatch;
  314. int cmp1, cmp2;
  315. TRIAGE_DATA *Trav;
  316. if (m_EntryCount == 0)
  317. {
  318. return -1;
  319. }
  320. Lo = 0;
  321. Hi = m_EntryCount-1;
  322. while (Lo <= Hi)
  323. {
  324. Mid = (Lo + Hi) / 2;
  325. Trav = &m_pTriageData[Mid];
  326. #if 0
  327. dprintf("%3lx: M: %s%c R: %s%c F: %s\n", Mid,m_pTriageData[Mid].Module,
  328. m_pTriageData[Mid].fModulPartial ? '*' : ' ',
  329. m_pTriageData[Mid].Routine,
  330. m_pTriageData[Mid].fRoutinePartial ? '*' : ' ',
  331. m_pTriageData[Mid].Followup);
  332. #endif //0
  333. cmp1 = _stricmp(m_pTriageData[Mid].Module, Module);
  334. if (!cmp1)
  335. {
  336. cmp1 = _stricmp(m_pTriageData[Mid].Routine, Routine);
  337. }
  338. if (!cmp1)
  339. {
  340. return Mid;
  341. }
  342. else if (cmp1 > 0)
  343. {
  344. Hi = Mid - 1;
  345. }
  346. else
  347. {
  348. Lo = Mid + 1;
  349. }
  350. }
  351. // Backtrace from mid till we find good prefix match
  352. if (Lo >= (int)m_EntryCount)
  353. {
  354. Lo = m_EntryCount-1;
  355. }
  356. while (Lo)
  357. {
  358. if (m_pTriageData[Lo].fRoutinePartial ||
  359. m_pTriageData[Lo].fModulPartial)
  360. {
  361. // dprintf("- %3lx: M: %s R: %s F: %s\n",
  362. // Lo, m_pTriageData[Lo].Module,
  363. // m_pTriageData[Lo].Routine,m_pTriageData[Lo].Followup);
  364. if (!m_pTriageData[Lo].Routine || !Routine)
  365. {
  366. cmp2 = 0;
  367. }
  368. else if (m_pTriageData[Lo].fRoutinePartial)
  369. {
  370. cmp2 = _strnicmp(m_pTriageData[Lo].Routine, Routine,
  371. strlen(m_pTriageData[Lo].Routine));
  372. }
  373. else
  374. {
  375. cmp2 = _stricmp(m_pTriageData[Lo].Routine, Routine);
  376. }
  377. if (m_pTriageData[Lo].fModulPartial)
  378. {
  379. cmp1 = _strnicmp(m_pTriageData[Lo].Module, Module,
  380. strlen(m_pTriageData[Lo].Module));
  381. }
  382. else
  383. {
  384. cmp1 = _stricmp(m_pTriageData[Lo].Module, Module);
  385. }
  386. if (!cmp1 && !cmp2)
  387. {
  388. return Lo;
  389. }
  390. }
  391. --Lo;
  392. }
  393. return -1;
  394. }
  395. ULONG
  396. CTriager::GetFollowup(
  397. PSTR FollowupBuffer,
  398. ULONG FollowupBufferSize,
  399. PSTR SymbolName
  400. )
  401. {
  402. CHAR Module[100], Routine[2048];
  403. ULONG index;
  404. PCHAR Bang;
  405. ULONG ret;
  406. if (!SymbolName)
  407. {
  408. return TRIAGE_FOLLOWUP_FAIL;
  409. }
  410. Bang = strchr(SymbolName, '!');
  411. if (!Bang)
  412. {
  413. CopyString(Module, SymbolName, sizeof(Module));
  414. Routine[0] = 0;
  415. }
  416. else
  417. {
  418. ULONG len = (ULONG) ((ULONG64) Bang - (ULONG64)SymbolName);
  419. if (len > sizeof(Module)-1)
  420. {
  421. len = sizeof(Module)-1;
  422. }
  423. strncpy(Module,SymbolName, len);
  424. Module[len]=0;
  425. CopyString(Routine, Bang+1, sizeof(Routine));
  426. }
  427. //
  428. // Make sure we followup on image name instead of module name
  429. //
  430. ULONG Index;
  431. ULONG64 Base;
  432. if (strcmp(Module, "nt") &&
  433. (S_OK == g_ExtSymbols->
  434. GetModuleByModuleName(Module, 0, &Index, &Base)))
  435. {
  436. CHAR ImageBuffer[MAX_PATH];
  437. if (g_ExtSymbols->
  438. GetModuleNames(Index, Base,
  439. ImageBuffer, sizeof(ImageBuffer), NULL,
  440. NULL, 0, NULL,
  441. NULL, 0, NULL) == S_OK)
  442. {
  443. PCHAR Break = strrchr(ImageBuffer, '\\');
  444. if (Break)
  445. {
  446. CopyString(ImageBuffer, Break + 1, sizeof(ImageBuffer));
  447. }
  448. CopyString(Module, ImageBuffer, sizeof(Module));
  449. if (Break = strchr(Module, '.'))
  450. {
  451. *Break = 0;
  452. }
  453. }
  454. }
  455. PCHAR Followup;
  456. Followup = g_pTriager->GetFollowupStr(Module, Routine);
  457. if (Followup)
  458. {
  459. ret = TRIAGE_FOLLOWUP_SUCCESS;
  460. if (!strcmp(Followup, "ignore"))
  461. {
  462. ret = TRIAGE_FOLLOWUP_IGNORE;
  463. }
  464. }
  465. else
  466. {
  467. Followup = g_pTriager->GetFollowupStr("default", "");
  468. ret = TRIAGE_FOLLOWUP_DEFAULT;
  469. }
  470. if (Followup)
  471. {
  472. strncpy(FollowupBuffer, Followup, FollowupBufferSize);
  473. FollowupBuffer[FollowupBufferSize-1] = 0;
  474. return ret;
  475. }
  476. else
  477. {
  478. return TRIAGE_FOLLOWUP_FAIL;
  479. }
  480. }
  481. void
  482. CTriager::GetFollowupDate(
  483. PSTR Module,
  484. PSTR Routine,
  485. PULONG Start,
  486. PULONG End)
  487. {
  488. ULONG Index;
  489. CHAR DateEntry[32];
  490. PCHAR Break;
  491. PCHAR Stop;
  492. *Start = 0;
  493. *End = 0;
  494. if ((Index = MatchSymbol(Module, Routine)) >= m_EntryCount)
  495. {
  496. return;
  497. }
  498. CopyString(DateEntry, m_pTriageData[Index].Followup, sizeof(DateEntry));
  499. if (Break = strchr(DateEntry, ','))
  500. {
  501. *Start = strtoul(Break+1, &Stop, 16);
  502. *Break = 0;
  503. }
  504. *End = strtoul(DateEntry, &Stop, 16);
  505. //dprintf("%08lx\n %08lx\n", *Start, *End);
  506. return;
  507. }