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.

917 lines
19 KiB

  1. #include "ct.h"
  2. #include <conio.h>
  3. #include <stdio.h>
  4. #define MAX_TOKEN_LEN 1024
  5. char g_szToken[MAX_TOKEN_LEN];
  6. char g_szTokenLink[MAX_TOKEN_LEN];
  7. int g_TokenLen = 0;
  8. int g_TagsCount = 0;
  9. int g_TagsMax = 0;
  10. #define TAGS_DELTA 128
  11. #define CALL_DELTA 4
  12. PTag* g_pTags; // in order
  13. /*************************************************************************
  14. * SkipSpaces
  15. *
  16. * skips all the white chars from the current position down.
  17. *
  18. *************************************************************************/
  19. void
  20. SkipSpaces(
  21. DWORD* pi,
  22. char* p)
  23. {
  24. DWORD i = *pi;
  25. while (p[i] == ' ' || p[i] == '\t') {
  26. i++;
  27. }
  28. *pi = i;
  29. }
  30. char g_szFunction[ 256 ];
  31. char g_szClass[ 256 ];
  32. /*************************************************************************
  33. * LinkName2Name
  34. *
  35. *************************************************************************/
  36. void
  37. LinkName2Name(
  38. char* szLinkName,
  39. char* szName)
  40. {
  41. /*
  42. * the link name is expected like ?Function@Class@@Params
  43. * to be converted to Class::Function
  44. */
  45. static CHAR arrOperators[][8] =
  46. {
  47. "",
  48. "",
  49. "new",
  50. "delete",
  51. "=",
  52. ">>",
  53. "<<",
  54. "!",
  55. "==",
  56. "!="
  57. };
  58. DWORD dwCrr = 0;
  59. DWORD dwCrrFunction = 0;
  60. DWORD dwCrrClass = 0;
  61. DWORD dwSize;
  62. BOOL fIsCpp = FALSE;
  63. BOOL fHasClass = FALSE;
  64. BOOL fIsContructor = FALSE;
  65. BOOL fIsDestructor = FALSE;
  66. BOOL fIsNew = FALSE;
  67. BOOL fIsDelete = FALSE;
  68. BOOL fIsOperator = FALSE;
  69. DWORD dwOperatorIndex = 0;
  70. if (*szLinkName == '@')
  71. szLinkName++;
  72. dwSize = lstrlen(szLinkName);
  73. /*
  74. * skip '?'
  75. */
  76. while (dwCrr < dwSize) {
  77. if (szLinkName[dwCrr] == '?') {
  78. dwCrr++;
  79. fIsCpp = TRUE;
  80. }
  81. break;
  82. }
  83. /*
  84. * check to see if this is a special function (like ??0)
  85. */
  86. if (fIsCpp) {
  87. if (szLinkName[dwCrr] == '?') {
  88. dwCrr++;
  89. /*
  90. * the next digit should tell as the function type
  91. */
  92. if (isdigit(szLinkName[dwCrr])) {
  93. switch (szLinkName[dwCrr]) {
  94. case '0':
  95. fIsContructor = TRUE;
  96. break;
  97. case '1':
  98. fIsDestructor = TRUE;
  99. break;
  100. default:
  101. fIsOperator = TRUE;
  102. dwOperatorIndex = szLinkName[dwCrr] - '0';
  103. break;
  104. }
  105. dwCrr++;
  106. }
  107. }
  108. }
  109. /*
  110. * get the function name
  111. */
  112. while (dwCrr < dwSize) {
  113. if (szLinkName[dwCrr] != '@') {
  114. g_szFunction[dwCrrFunction] = szLinkName[dwCrr];
  115. dwCrrFunction++;
  116. dwCrr++;
  117. } else {
  118. break;
  119. }
  120. }
  121. g_szFunction[dwCrrFunction] = '\0';
  122. if (fIsCpp) {
  123. /*
  124. * skip '@'
  125. */
  126. if (dwCrr < dwSize) {
  127. if (szLinkName[dwCrr] == '@') {
  128. dwCrr++;
  129. }
  130. }
  131. /*
  132. * get the class name (if any)
  133. */
  134. while (dwCrr < dwSize) {
  135. if (szLinkName[dwCrr] != '@') {
  136. fHasClass = TRUE;
  137. g_szClass[dwCrrClass] = szLinkName[dwCrr];
  138. dwCrrClass++;
  139. dwCrr++;
  140. } else {
  141. break;
  142. }
  143. }
  144. g_szClass[dwCrrClass] = '\0';
  145. }
  146. /*
  147. * print the new name
  148. */
  149. if (fIsContructor) {
  150. sprintf(szName, "%s::%s", g_szFunction, g_szFunction);
  151. } else if (fIsDestructor) {
  152. sprintf(szName, "%s::~%s", g_szFunction, g_szFunction);
  153. } else if (fIsOperator) {
  154. sprintf(szName, "%s::operator %s", g_szFunction, arrOperators[dwOperatorIndex]);
  155. } else if (fHasClass) {
  156. sprintf(szName, "%s::%s", g_szClass, g_szFunction);
  157. } else {
  158. sprintf(szName, "%s", g_szFunction);
  159. }
  160. }
  161. /*************************************************************************
  162. * GetToken
  163. *
  164. *************************************************************************/
  165. int
  166. GetToken(
  167. DWORD* pi,
  168. char* p)
  169. {
  170. DWORD i = *pi;
  171. SkipSpaces(&i, p);
  172. g_TokenLen = 0;
  173. while (p[i] != '\n' && p[i] != '\r' &&
  174. p[i] != ' ' && p[i] != '\t') {
  175. g_szTokenLink[g_TokenLen++] = p[i];
  176. i++;
  177. }
  178. g_szTokenLink[g_TokenLen++] = 0;
  179. LinkName2Name(g_szTokenLink, g_szToken);
  180. g_TokenLen = lstrlen(g_szToken);
  181. *pi = i;
  182. return g_TokenLen;
  183. }
  184. /*************************************************************************
  185. * DumpTags
  186. *
  187. *************************************************************************/
  188. void
  189. DumpTags(
  190. void)
  191. {
  192. PTag pTag;
  193. int i;
  194. LogMsg(LM_PRINT, "Dump tags\n"
  195. "--------------------------------------");
  196. for (i = 0; i < g_TagsCount; i++)
  197. {
  198. pTag = g_pTags[i];
  199. LogMsg(LM_PRINT, "%8x %s", pTag, pTag->pszTag);
  200. }
  201. LogMsg(LM_PRINT, "--------------------------------------\n");
  202. }
  203. /*************************************************************************
  204. * FindTag
  205. *
  206. *************************************************************************/
  207. PTag
  208. FindTag(
  209. char* pszTag,
  210. int* pPos)
  211. {
  212. int l, m, r;
  213. int val;
  214. if (g_TagsCount == 0) {
  215. if (pPos != NULL)
  216. *pPos = 0;
  217. return NULL;
  218. }
  219. l = 0;
  220. r = g_TagsCount - 1;
  221. while (l <= r) {
  222. m = (r + l) / 2;
  223. val = lstrcmp(pszTag, g_pTags[m]->pszTag);
  224. if (val == 0) {
  225. if (pPos != NULL)
  226. *pPos = m;
  227. return g_pTags[m];
  228. }
  229. if (val < 0)
  230. r = m - 1;
  231. else
  232. l = m + 1;
  233. }
  234. if (pPos != NULL)
  235. if (val < 0)
  236. *pPos = m;
  237. else
  238. *pPos = m + 1;
  239. return NULL;
  240. }
  241. /*************************************************************************
  242. * ResortTags
  243. *
  244. *************************************************************************/
  245. void
  246. ResortTags(
  247. PTag pTag)
  248. {
  249. PTag* pArray;
  250. int pos;
  251. g_TagsCount--;
  252. FindTag(pTag->pszTag, &pos);
  253. pArray = g_pTags + pos;
  254. memmove(pArray + 1, pArray, sizeof(PTag) * (g_TagsCount - pos));
  255. memmove(pArray, &pTag, sizeof(PTag));
  256. g_TagsCount++;
  257. }
  258. /*************************************************************************
  259. * IsInArray
  260. *
  261. *************************************************************************/
  262. BOOL
  263. IsInArray(
  264. PTag* ppTags,
  265. int nCount,
  266. PTag pTag)
  267. {
  268. int i;
  269. for (i = 0; i < nCount; i++) {
  270. if (ppTags[i] == pTag)
  271. return TRUE;
  272. }
  273. return FALSE;
  274. }
  275. /*************************************************************************
  276. * AddToArray
  277. *
  278. *************************************************************************/
  279. BOOL
  280. AddToArray(
  281. DWORD* pCount,
  282. DWORD* pMax,
  283. PVOID* ppArray,
  284. DWORD size,
  285. PVOID pElem,
  286. UINT delta)
  287. {
  288. PVOID pArray;
  289. if (*pCount == *pMax) {
  290. if (*pCount == 0) {
  291. pArray = Alloc(delta * size);
  292. } else {
  293. pArray = ReAlloc(
  294. *ppArray,
  295. *pMax * size,
  296. (*pMax + delta) * size);
  297. }
  298. if (pArray == NULL) {
  299. LogMsg(LM_ERROR, "Out of memory in AddToArray");
  300. return FALSE;
  301. }
  302. *ppArray = pArray;
  303. (*pMax) += delta;
  304. } else {
  305. pArray = *ppArray;
  306. }
  307. memmove((char*)pArray + *pCount * size, &pElem, size);
  308. (*pCount)++;
  309. return TRUE;
  310. }
  311. /*************************************************************************
  312. * GetTag
  313. *
  314. *************************************************************************/
  315. PTag
  316. GetTag(
  317. DWORD* pi,
  318. char* p)
  319. {
  320. PTag pTag;
  321. /*
  322. * parse the token first
  323. */
  324. GetToken(pi, p);
  325. /*
  326. * if the there is a ptag for the token just return it
  327. */
  328. pTag = FindTag(g_szToken, NULL);
  329. if (pTag != NULL)
  330. return pTag;
  331. /*
  332. * create a ptag for the token
  333. */
  334. pTag = (PTag)Alloc(sizeof(Tag));
  335. if (pTag == NULL)
  336. return NULL;
  337. pTag->pszTag = (char*)Alloc((g_TokenLen + 1) * sizeof(char));
  338. lstrcpy(pTag->pszTag, g_szToken);
  339. if (AddToArray(
  340. &g_TagsCount,
  341. &g_TagsMax,
  342. (PVOID*)&g_pTags,
  343. sizeof(PTag),
  344. pTag,
  345. TAGS_DELTA)) {
  346. ResortTags(pTag);
  347. }
  348. return pTag;
  349. }
  350. /*************************************************************************
  351. * ProcessLine
  352. *
  353. *************************************************************************/
  354. BOOL
  355. ProcessLine(
  356. int nLine,
  357. DWORD* pi,
  358. char* p,
  359. char* pEnd)
  360. {
  361. DWORD i = *pi;
  362. int ind;
  363. PTag pTag;
  364. PTag pTagC;
  365. /*
  366. * ignore the first 4 tokens of a line
  367. */
  368. for (ind = 0; ind < 4; ind++)
  369. GetToken(&i, p);
  370. pTag = GetTag(&i, p);
  371. if (pTag) {
  372. while (p[i] != '\n' && p[i] != '\r') {
  373. pTagC = GetTag(&i, p);
  374. if (pTagC) {
  375. if (!IsInArray(pTag->ppCall, pTag->uCallCount, pTagC)) {
  376. AddToArray(
  377. &pTag->uCallCount,
  378. &pTag->uCallMax,
  379. (PVOID*)&pTag->ppCall,
  380. sizeof(PTag),
  381. (PVOID)pTagC,
  382. CALL_DELTA);
  383. }
  384. if (!IsInArray(pTagC->ppCallee, pTagC->uCalleeCount, pTag)) {
  385. AddToArray(
  386. &pTagC->uCalleeCount,
  387. &pTagC->uCalleeMax,
  388. (PVOID*)&pTagC->ppCallee,
  389. sizeof(PTag),
  390. (PVOID)pTag,
  391. CALL_DELTA);
  392. }
  393. }
  394. }
  395. while (p[i] == '\n' || p[i] == '\r') {
  396. i++;
  397. }
  398. *pi = i;
  399. }
  400. return TRUE;
  401. }
  402. /*************************************************************************
  403. * RemoveWalkFlags
  404. *
  405. *************************************************************************/
  406. void
  407. RemoveWalkFlags(
  408. void)
  409. {
  410. PTag pTag;
  411. int i;
  412. for (i = 0; i < g_TagsCount; i++) {
  413. pTag = g_pTags[i];
  414. pTag->bWalked = FALSE;
  415. }
  416. }
  417. #ifndef _CTUI
  418. /*************************************************************************
  419. * ListCallerTreeRec
  420. *
  421. *************************************************************************/
  422. void
  423. ListCallerTreeRec(
  424. PTag pTag,
  425. int nLevels,
  426. int nIndent)
  427. {
  428. int i;
  429. PTag pTagC;
  430. char szIndent[256];
  431. /*
  432. * prepare for indentation
  433. */
  434. if (nIndent > 0) {
  435. memset(szIndent, ' ', nIndent);
  436. szIndent[nIndent] = 0;
  437. LogMsg(LM_PRINT, "%s%s", szIndent, pTag->pszTag);
  438. }
  439. /*
  440. * return if we're done with the levels
  441. */
  442. if (nLevels == 0)
  443. return;
  444. /*
  445. * return if we get into recursion
  446. */
  447. if (pTag->bWalked == TRUE)
  448. return;
  449. pTag->bWalked = TRUE;
  450. if (nIndent > 0)
  451. nIndent++;
  452. /*
  453. * recurse on the children
  454. */
  455. for (i = 0; i < (int)pTag->uCallCount; i++) {
  456. pTagC = pTag->ppCall[i];
  457. ListCallerTreeRec(pTagC, nLevels - 1, nIndent);
  458. }
  459. return;
  460. }
  461. /*************************************************************************
  462. * ListCallerTree
  463. *
  464. *************************************************************************/
  465. void
  466. ListCallerTree(
  467. char* pszTag,
  468. int nLevels,
  469. BOOL bIndent)
  470. {
  471. int i;
  472. PTag pTag;
  473. PTag pTagC;
  474. pTag = FindTag(pszTag, NULL);
  475. if (pTag == NULL) {
  476. LogMsg(LM_ERROR, "Tag %s not found", pszTag);
  477. return;
  478. }
  479. LogMsg(LM_PRINT, "-------------------------------------\n"
  480. "%s calls:", pTag->pszTag);
  481. if (nLevels <= 0)
  482. return;
  483. pTag->bWalked = TRUE;
  484. for (i = 0; i < (int)pTag->uCallCount; i++) {
  485. pTagC = pTag->ppCall[i];
  486. ListCallerTreeRec(pTagC, nLevels - 1, bIndent);
  487. }
  488. RemoveWalkFlags();
  489. LogMsg(LM_PRINT, "-------------------------------------\n");
  490. return;
  491. }
  492. /*************************************************************************
  493. * ListCalleeTreeRec
  494. *
  495. *************************************************************************/
  496. void
  497. ListCalleeTreeRec(
  498. PTag pTag,
  499. int nLevels,
  500. int nIndent)
  501. {
  502. int i;
  503. PTag pTagC;
  504. char szIndent[256];
  505. /*
  506. * prepare for indentation
  507. */
  508. if (nIndent > 0) {
  509. memset(szIndent, ' ', nIndent);
  510. szIndent[nIndent] = 0;
  511. LogMsg(LM_PRINT, "%s%s", szIndent, pTag->pszTag);
  512. }
  513. /*
  514. * return if we're done with the levels
  515. */
  516. if (nLevels == 0)
  517. return;
  518. /*
  519. * return if we get into recursion
  520. */
  521. if (pTag->bWalked == TRUE)
  522. return;
  523. pTag->bWalked = TRUE;
  524. if (nIndent > 0)
  525. nIndent++;
  526. /*
  527. * recurse on the children
  528. */
  529. for (i = 0; i < (int)pTag->uCalleeCount; i++) {
  530. pTagC = pTag->ppCallee[i];
  531. ListCalleeTreeRec(pTagC, nLevels - 1, nIndent);
  532. }
  533. return;
  534. }
  535. /*************************************************************************
  536. * ListCalleeTree
  537. *
  538. *************************************************************************/
  539. void
  540. ListCalleeTree(
  541. char* pszTag,
  542. int nLevels,
  543. BOOL bIndent)
  544. {
  545. int i;
  546. PTag pTag;
  547. PTag pTagC;
  548. pTag = FindTag(pszTag, NULL);
  549. if (pTag == NULL) {
  550. LogMsg(LM_ERROR, "Tag %s not found", pszTag);
  551. return;
  552. }
  553. LogMsg(LM_PRINT, "-------------------------------------\n"
  554. "%s is called by:", pTag->pszTag);
  555. if (nLevels <= 0)
  556. return;
  557. pTag->bWalked = TRUE;
  558. for (i = 0; i < (int)pTag->uCalleeCount; i++) {
  559. pTagC = pTag->ppCallee[i];
  560. ListCalleeTreeRec(pTagC, nLevels - 1, bIndent);
  561. }
  562. RemoveWalkFlags();
  563. LogMsg(LM_PRINT, "-------------------------------------\n");
  564. return;
  565. }
  566. #endif // _CTUI
  567. /*************************************************************************
  568. * ProcessInputFile
  569. *
  570. *************************************************************************/
  571. int
  572. ProcessInputFile(
  573. PFILEMAP pfm)
  574. {
  575. DWORD i;
  576. int nLine = 0;
  577. i = 0;
  578. while (i < (DWORD)(pfm->pmapEnd - pfm->pmap - 2)) {
  579. ProcessLine(nLine++, &i, pfm->pmap, pfm->pmapEnd);
  580. }
  581. return 0;
  582. }
  583. /*************************************************************************
  584. * FreeMemory
  585. *
  586. *************************************************************************/
  587. void
  588. FreeMemory(
  589. void)
  590. {
  591. PTag pTag;
  592. int i;
  593. for (i = 0; i < g_TagsCount; i++) {
  594. pTag = g_pTags[i];
  595. Free(pTag->pszTag);
  596. if (pTag->ppCall) {
  597. Free(pTag->ppCall);
  598. }
  599. if (pTag->ppCallee) {
  600. Free(pTag->ppCallee);
  601. }
  602. Free(pTag);
  603. }
  604. Free(g_pTags);
  605. FreeMemManag();
  606. }
  607. #ifndef _CTUI
  608. /*************************************************************************
  609. * StartsWith
  610. *
  611. *************************************************************************/
  612. BOOL
  613. StartsWith(
  614. char* pszStart,
  615. char* pszTag)
  616. {
  617. int lenS, lenT, i;
  618. lenS = lstrlen(pszStart);
  619. lenT = lstrlen(pszTag);
  620. if (lenS > lenT) {
  621. return FALSE;
  622. }
  623. for (i = 0; i < lenS; i++) {
  624. if (pszStart[i] != pszTag[i]) {
  625. return FALSE;
  626. }
  627. }
  628. return TRUE;
  629. }
  630. /*************************************************************************
  631. * CheckUserRule
  632. *
  633. * Display functions that do not start with NtUser/zzz/xxx and call
  634. * functions that start with zzz/xxx
  635. *
  636. *************************************************************************/
  637. void
  638. CheckUserRule(
  639. void)
  640. {
  641. int i, j;
  642. PTag pTag;
  643. PTag pTagC;
  644. LogMsg(LM_PRINT, "-------------------------------------\n"
  645. "Check for ntuser rule in the kernel\n");
  646. /*
  647. * walk the tags to find a non xxx/zzz function that directly
  648. * calls an xxx/zzz function
  649. */
  650. for (i = 0; i < g_TagsCount; i++) {
  651. pTag = g_pTags[i];
  652. if (StartsWith("xxx", pTag->pszTag) ||
  653. StartsWith("zzz", pTag->pszTag) ||
  654. StartsWith("NtUser", pTag->pszTag)) {
  655. continue;
  656. }
  657. /*
  658. * see if we didn't already display a message for this tag
  659. */
  660. if (pTag->bWalked) {
  661. continue;
  662. }
  663. for (j = 0; j < (int)pTag->uCallCount; j++) {
  664. pTagC = pTag->ppCall[j];
  665. if (!StartsWith("xxx", pTagC->pszTag) &&
  666. !StartsWith("zzz", pTagC->pszTag)) {
  667. continue;
  668. }
  669. LogMsg(LM_PRINT, "%-40s calls : %s",
  670. pTag->pszTag, pTagC->pszTag);
  671. break;
  672. }
  673. }
  674. RemoveWalkFlags();
  675. }
  676. /*************************************************************************
  677. * CheckUnnecessaryXXX
  678. *
  679. * Display functions that do not start with NtUser/zzz/xxx and call
  680. * functions that start with zzz/xxx
  681. *
  682. *************************************************************************/
  683. void
  684. CheckUnnecessaryXXX(
  685. void)
  686. {
  687. int i, j;
  688. PTag pTag;
  689. PTag pTagC;
  690. LogMsg(LM_PRINT, "-------------------------------------\n"
  691. "Check for unnecessary xxx functions in the kernel\n");
  692. /*
  693. * walk the tags to find a non xxx/zzz function that directly
  694. * calls an xxx/zzz function
  695. */
  696. for (i = 0; i < g_TagsCount; i++) {
  697. pTag = g_pTags[i];
  698. if (!StartsWith("xxx", pTag->pszTag) &&
  699. !StartsWith("zzz", pTag->pszTag)) {
  700. continue;
  701. }
  702. /*
  703. * see if we didn't already display a message for this tag
  704. */
  705. if (pTag->bWalked) {
  706. continue;
  707. }
  708. for (j = 0; j < (int)pTag->uCallCount; j++) {
  709. pTagC = pTag->ppCall[j];
  710. if (StartsWith("xxx", pTagC->pszTag) ||
  711. StartsWith("zzz", pTagC->pszTag) ||
  712. StartsWith("LeaveCrit", pTagC->pszTag)) {
  713. break;
  714. }
  715. }
  716. if (j >= (int)pTag->uCallCount) {
  717. LogMsg(LM_PRINT, "%-40s should not be an xxx/zzz function",
  718. pTag->pszTag);
  719. }
  720. }
  721. RemoveWalkFlags();
  722. }
  723. #else // _CTUI
  724. /*************************************************************************
  725. * PopulateCombo
  726. *
  727. *************************************************************************/
  728. void
  729. PopulateCombo(
  730. HWND hwnd)
  731. {
  732. PTag pTag;
  733. int i;
  734. for (i = 0; i < g_TagsCount; i++) {
  735. pTag = g_pTags[i];
  736. SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)pTag->pszTag);
  737. }
  738. }
  739. #endif // _CTUI