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.

4189 lines
99 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. symbols.c
  5. Abstract:
  6. This function implements a generic simple symbol handler.
  7. Author:
  8. Wesley Witt (wesw) 1-Sep-1994
  9. Environment:
  10. User Mode
  11. --*/
  12. #include "private.h"
  13. #include "symbols.h"
  14. #include "globals.h"
  15. #include <dbhpriv.h>
  16. #include "fecache.hpp"
  17. BOOL
  18. IMAGEAPI
  19. SympGetSymNextPrev(
  20. IN HANDLE hProcess,
  21. IN OUT PIMAGEHLP_SYMBOL64 Symbol,
  22. IN int Direction
  23. );
  24. #ifndef _DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  25. PSYMBOL_ENTRY
  26. IMAGEAPI
  27. AllocSym(
  28. IN PMODULE_ENTRY mi,
  29. IN DWORD64 addr,
  30. IN LPSTR name
  31. );
  32. VOID
  33. CompleteSymbolTable(
  34. IN PMODULE_ENTRY mi
  35. );
  36. #endif // !_DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  37. typedef struct _STORE_OLD_CB {
  38. BOOL cb64;
  39. union{
  40. PSYM_ENUMSYMBOLS_CALLBACK UserCallBackRoutine;
  41. PSYM_ENUMSYMBOLS_CALLBACK64 UserCallBackRoutine64;
  42. };
  43. PVOID UserContext;
  44. } STORE_OLD_CB;
  45. BOOL
  46. ImgHlpDummyCB(
  47. PSYMBOL_INFO pSymInfo,
  48. ULONG SymbolSize,
  49. PVOID UserContext
  50. )
  51. {
  52. STORE_OLD_CB *pOld = (STORE_OLD_CB *) UserContext;
  53. if (pSymInfo->Flags & SYMF_REGREL) {
  54. LARGE_INTEGER li;
  55. li.HighPart = pSymInfo->Register;
  56. li.LowPart = (ULONG) pSymInfo->Address;
  57. pSymInfo->Address = li.QuadPart;
  58. }
  59. if (pOld->cb64) {
  60. return (*pOld->UserCallBackRoutine64) (
  61. pSymInfo->Name,
  62. pSymInfo->Address,
  63. SymbolSize,
  64. pOld->UserContext );
  65. } else {
  66. return (*pOld->UserCallBackRoutine) (
  67. pSymInfo->Name,
  68. (ULONG) pSymInfo->Address,
  69. SymbolSize,
  70. pOld->UserContext );
  71. }
  72. }
  73. void
  74. symcpy2(
  75. PSYMBOL_INFO SymInfo,
  76. PSYMBOL_ENTRY SymEntry
  77. )
  78. {
  79. SymInfo->Address = SymEntry->Address;
  80. SymInfo->Flags = SymEntry->Flags;
  81. SymInfo->TypeIndex = SymEntry->TypeIndex;
  82. SymInfo->ModBase = SymEntry->ModBase;
  83. SymInfo->NameLen = SymEntry->NameLength;
  84. SymInfo->Size = SymEntry->Size;
  85. SymInfo->Register = SymEntry->Register;
  86. if (SymEntry->Name &&
  87. (strlen(SymEntry->Name) < SymInfo->MaxNameLen)) {
  88. strcpy(SymInfo->Name, SymEntry->Name);
  89. }
  90. }
  91. BOOL
  92. TestOutputString(
  93. PCHAR sz
  94. )
  95. {
  96. CHAR c;
  97. __try {
  98. c = *sz;
  99. } __except(EXCEPTION_EXECUTE_HANDLER) {
  100. SetLastError(ERROR_INVALID_PARAMETER);
  101. return FALSE;
  102. }
  103. return TRUE;
  104. }
  105. BOOL
  106. InitOutputString(
  107. PCHAR sz
  108. )
  109. {
  110. BOOL rc;
  111. rc = TestOutputString(sz);
  112. if (rc)
  113. *sz = 0;
  114. return rc;
  115. }
  116. BOOL
  117. DoEnumCallback(
  118. PPROCESS_ENTRY pe,
  119. PSYMBOL_INFO pSymInfo,
  120. ULONG SymSize,
  121. PROC EnumCallback,
  122. PVOID UserContext,
  123. BOOL Use64,
  124. BOOL UsesUnicode
  125. )
  126. {
  127. BOOL rc = FALSE;
  128. if (pSymInfo)
  129. {
  130. if (Use64 || (!UsesUnicode))
  131. {
  132. rc = (*(PSYM_ENUMERATESYMBOLS_CALLBACK)EnumCallback) (
  133. pSymInfo,
  134. SymSize,
  135. UserContext);
  136. }
  137. else
  138. {
  139. PWSTR pszTmp = AnsiToUnicode(pSymInfo->Name);
  140. if (pszTmp)
  141. {
  142. strncpy(pSymInfo->Name, (LPSTR) pszTmp,
  143. min(pSymInfo->MaxNameLen, wcslen(pszTmp)));
  144. *((LPWSTR) &pSymInfo->Name[min(pSymInfo->MaxNameLen, wcslen(pszTmp)) - 1 ]) = 0;
  145. rc = (*(PSYM_ENUMERATESYMBOLS_CALLBACK)EnumCallback) (
  146. pSymInfo,
  147. SymSize,
  148. UserContext );
  149. MemFree(pszTmp);
  150. }
  151. }
  152. }
  153. return rc;
  154. }
  155. BOOL
  156. IMAGEAPI
  157. SymInitialize(
  158. IN HANDLE hProcess,
  159. IN LPSTR UserSearchPath,
  160. IN BOOL InvadeProcess
  161. )
  162. /*++
  163. Routine Description:
  164. This function initializes the symbol handler for
  165. a process. The process is identified by the
  166. process handle passed into this function.
  167. Arguments:
  168. hProcess - Process handle. If InvadeProcess is FALSE
  169. then this can be any unique value that identifies
  170. the process to the symbol handler.
  171. UserSearchPath - Pointer to a string of paths separated by semicolons.
  172. These paths are used to search for symbol files.
  173. The value NULL is acceptable.
  174. InvadeProcess - If this is set to TRUE then the process identified
  175. by the process handle is "invaded" and it's loaded
  176. module list is enumerated. Each module is added
  177. to the symbol handler and symbols are attempted
  178. to be loaded.
  179. Return Value:
  180. TRUE - The symbol handler was successfully initialized.
  181. FALSE - The initialization failed. Call GetLastError to
  182. discover the cause of the failure.
  183. --*/
  184. {
  185. PPROCESS_ENTRY pe;
  186. __try {
  187. if (!g.SymInitialized) {
  188. g.SymInitialized = TRUE;
  189. g.cProcessList = 0;
  190. InitializeListHead( &g.ProcessList );
  191. }
  192. *g.DebugToken = 0;
  193. GetEnvironmentVariable(DEBUG_TOKEN, g.DebugToken, sizeof(g.DebugToken) / sizeof(g.DebugToken[0]));
  194. _strlwr(g.DebugToken);
  195. if (FindProcessEntry( hProcess )) {
  196. SetLastError( ERROR_INVALID_HANDLE );
  197. return TRUE;
  198. }
  199. pe = (PPROCESS_ENTRY) MemAlloc( sizeof(PROCESS_ENTRY) );
  200. if (!pe) {
  201. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  202. return FALSE;
  203. }
  204. ZeroMemory( pe, sizeof(PROCESS_ENTRY) );
  205. pe->hProcess = hProcess;
  206. pe->pid = (int) GetPID(hProcess);
  207. g.cProcessList++;
  208. InitializeListHead( &pe->ModuleList );
  209. InsertTailList( &g.ProcessList, &pe->ListEntry );
  210. if (!SymSetSearchPath( hProcess, UserSearchPath )) {
  211. //
  212. // last error code was set by SymSetSearchPath, so just return
  213. //
  214. SymCleanup( hProcess );
  215. return FALSE;
  216. }
  217. if (!diaInit()) {
  218. SymCleanup( hProcess );
  219. return FALSE;
  220. }
  221. if (InvadeProcess) {
  222. DWORD DosError = GetProcessModules(hProcess, InternalGetModule, NULL);
  223. if (DosError) {
  224. SymCleanup( hProcess );
  225. SetLastError( DosError );
  226. return FALSE;
  227. }
  228. }
  229. } __except (EXCEPTION_EXECUTE_HANDLER) {
  230. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  231. return FALSE;
  232. }
  233. return TRUE;
  234. }
  235. BOOL
  236. IMAGEAPI
  237. SymCleanup(
  238. HANDLE hProcess
  239. )
  240. /*++
  241. Routine Description:
  242. This function cleans up the symbol handler's data structures
  243. for a previously initialized process.
  244. Arguments:
  245. hProcess - Process handle.
  246. Return Value:
  247. TRUE - The symbol handler was successfully cleaned up.
  248. FALSE - The cleanup failed. Call GetLastError to
  249. discover the cause of the failure.
  250. --*/
  251. {
  252. PPROCESS_ENTRY pe;
  253. PLIST_ENTRY next;
  254. PMODULE_ENTRY mi;
  255. BOOL rc = TRUE;
  256. HeapDump("SymCleanup(before cleanup)\n");
  257. __try {
  258. pe = FindProcessEntry(hProcess);
  259. if (!pe) {
  260. SetLastError( ERROR_INVALID_HANDLE );
  261. return FALSE;
  262. }
  263. next = pe->ModuleList.Flink;
  264. if (next) {
  265. while (next != &pe->ModuleList) {
  266. mi = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
  267. next = mi->ListEntry.Flink;
  268. FreeModuleEntry(pe, mi);
  269. }
  270. }
  271. CloseSymbolServer();
  272. if (pe->SymbolSearchPath) {
  273. MemFree(pe->SymbolSearchPath);
  274. }
  275. RemoveEntryList(&pe->ListEntry);
  276. MemFree(pe);
  277. g.cProcessList--;
  278. // Assume that things are shutting down and
  279. // dump all the function entry caches.
  280. ClearFeCaches();
  281. } __except (EXCEPTION_EXECUTE_HANDLER) {
  282. ImagepSetLastErrorFromStatus(GetExceptionCode());
  283. rc = FALSE;
  284. }
  285. HeapDump("SymCleanup(after cleanup)\n");
  286. return rc;
  287. }
  288. DWORD
  289. IMAGEAPI
  290. SymSetOptions(
  291. DWORD UserOptions
  292. )
  293. /*++
  294. Routine Description:
  295. This function changes the symbol handler's option mask.
  296. Arguments:
  297. UserOptions - The new options mask.
  298. Return Value:
  299. The new mask is returned.
  300. --*/
  301. {
  302. g.SymOptions = UserOptions;
  303. SetSymbolServerCallback(g.SymOptions & SYMOPT_DEBUG ? TRUE : FALSE);
  304. DoCallback(NULL, CBA_SET_OPTIONS, &g.SymOptions);
  305. return g.SymOptions;
  306. }
  307. DWORD
  308. IMAGEAPI
  309. SymGetOptions(
  310. VOID
  311. )
  312. /*++
  313. Routine Description:
  314. This function queries the symbol handler's option mask.
  315. Arguments:
  316. None.
  317. Return Value:
  318. The current options mask is returned.
  319. --*/
  320. {
  321. return g.SymOptions;
  322. }
  323. ULONG
  324. IMAGEAPI
  325. SymSetContext(
  326. HANDLE hProcess,
  327. PIMAGEHLP_STACK_FRAME StackFrame,
  328. PIMAGEHLP_CONTEXT Context
  329. )
  330. {
  331. PPROCESS_ENTRY pe;
  332. pe = FindProcessEntry(hProcess);
  333. if (pe) {
  334. pe->pContext = Context;
  335. pe->StackFrame = *StackFrame;
  336. return diaSetModFromIP(pe);
  337. }
  338. return FALSE;
  339. };
  340. BOOL
  341. SympEnumerateModules(
  342. IN HANDLE hProcess,
  343. IN PROC EnumModulesCallback,
  344. IN PVOID UserContext,
  345. IN BOOL Use64
  346. )
  347. /*++
  348. Routine Description:
  349. This is the worker function for the 32 and 64 bit versions.
  350. Arguments:
  351. hProcess - Process handle, must have been previously registered
  352. with SymInitialize.
  353. EnumModulesCallback - Callback pointer that is called once for each
  354. module that is enumerated. If the enum callback
  355. returns FALSE then the enumeration is terminated.
  356. UserContext - This data is simply passed on to the callback function
  357. and is completly user defined.
  358. Use64 - Supplies flag which determines whether to use the 32 bit
  359. or 64 bit callback prototype.
  360. Return Value:
  361. TRUE - The modules were successfully enumerated.
  362. FALSE - The enumeration failed. Call GetLastError to
  363. discover the cause of the failure.
  364. --*/
  365. {
  366. PPROCESS_ENTRY pe;
  367. PMODULE_ENTRY mi;
  368. PLIST_ENTRY Next;
  369. __try {
  370. pe = FindProcessEntry( hProcess );
  371. if (!pe) {
  372. SetLastError( ERROR_INVALID_HANDLE );
  373. return FALSE;
  374. }
  375. Next = pe->ModuleList.Flink;
  376. if (Next) {
  377. while (Next != &pe->ModuleList) {
  378. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  379. Next = mi->ListEntry.Flink;
  380. if (Use64) {
  381. if ( !(*(PSYM_ENUMMODULES_CALLBACK64)EnumModulesCallback) (
  382. mi->ModuleName,
  383. mi->BaseOfDll,
  384. UserContext
  385. )) {
  386. break;
  387. }
  388. } else {
  389. if ( !(*(PSYM_ENUMMODULES_CALLBACK)EnumModulesCallback) (
  390. mi->ModuleName,
  391. (DWORD)mi->BaseOfDll,
  392. UserContext
  393. )) {
  394. break;
  395. }
  396. }
  397. }
  398. }
  399. } __except (EXCEPTION_EXECUTE_HANDLER) {
  400. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  401. return FALSE;
  402. }
  403. return TRUE;
  404. }
  405. BOOL
  406. dbhfnModSymInfo(
  407. IN HANDLE hp,
  408. IN OUT PDBH_MODSYMINFO p
  409. )
  410. {
  411. PMODULE_ENTRY mi;
  412. PPROCESS_ENTRY pe;
  413. assert(p->function == dbhModSymInfo);
  414. pe = FindProcessEntry(hp);
  415. if (!pe) {
  416. SetLastError( ERROR_INVALID_HANDLE );
  417. return FALSE;
  418. }
  419. if (p->sizeofstruct != sizeof(DBH_MODSYMINFO)) {
  420. SetLastError(ERROR_INVALID_PARAMETER);
  421. return FALSE;
  422. }
  423. mi = GetModuleForPC(pe, p->addr, FALSE);
  424. if (!mi) {
  425. SetLastError(ERROR_MOD_NOT_FOUND);
  426. return FALSE;
  427. }
  428. p->type = mi->SymType;
  429. *p->file = 0;
  430. switch (p->type)
  431. {
  432. case SymPdb:
  433. case SymDia:
  434. if (mi->LoadedPdbName)
  435. strcpy(p->file, mi->LoadedPdbName);
  436. break;
  437. default:
  438. if (mi->LoadedImageName)
  439. strcpy(p->file, mi->LoadedImageName);
  440. break;
  441. }
  442. return TRUE;
  443. }
  444. BOOL
  445. dbhfnDiaVersion(
  446. IN OUT PDBH_DIAVERSION p
  447. )
  448. {
  449. PMODULE_ENTRY mi;
  450. assert(p->function == dbhDiaVersion);
  451. if (p->sizeofstruct != sizeof(DBH_DIAVERSION)) {
  452. SetLastError(ERROR_INVALID_PARAMETER);
  453. return FALSE;
  454. }
  455. p->ver = diaVersion();
  456. return TRUE;
  457. }
  458. BOOL
  459. IMAGEAPI
  460. dbghelp(
  461. IN HANDLE hp,
  462. IN OUT PVOID data
  463. )
  464. {
  465. DWORD *function;
  466. if (!data) {
  467. SetLastError(ERROR_INVALID_PARAMETER);
  468. return FALSE;
  469. }
  470. __try {
  471. function = (DWORD *)data;
  472. switch (*function)
  473. {
  474. case dbhModSymInfo:
  475. return dbhfnModSymInfo(hp, (PDBH_MODSYMINFO)data);
  476. case dbhDiaVersion:
  477. return dbhfnDiaVersion((PDBH_DIAVERSION)data);
  478. default:
  479. SetLastError(ERROR_INVALID_PARAMETER);
  480. return FALSE;
  481. }
  482. } __except (EXCEPTION_EXECUTE_HANDLER) {
  483. ImagepSetLastErrorFromStatus(GetExceptionCode());
  484. return FALSE;
  485. }
  486. return FALSE;
  487. }
  488. BOOL
  489. IMAGEAPI
  490. SymEnumerateModules(
  491. IN HANDLE hProcess,
  492. IN PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,
  493. IN PVOID UserContext
  494. )
  495. /*++
  496. Routine Description:
  497. This function enumerates all of the modules that are currently
  498. loaded into the symbol handler. This is the 32 bit wrapper.
  499. Arguments:
  500. hProcess - Process handle, must have been previously registered
  501. with SymInitialize.
  502. EnumModulesCallback - Callback pointer that is called once for each
  503. module that is enumerated. If the enum callback
  504. returns FALSE then the enumeration is terminated.
  505. UserContext - This data is simply passed on to the callback function
  506. and is completly user defined.
  507. Return Value:
  508. TRUE - The modules were successfully enumerated.
  509. FALSE - The enumeration failed. Call GetLastError to
  510. discover the cause of the failure.
  511. --*/
  512. {
  513. return SympEnumerateModules(hProcess, (PROC)EnumModulesCallback, UserContext, FALSE);
  514. }
  515. BOOL
  516. IMAGEAPI
  517. SymEnumerateModules64(
  518. IN HANDLE hProcess,
  519. IN PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,
  520. IN PVOID UserContext
  521. )
  522. /*++
  523. Routine Description:
  524. This function enumerates all of the modules that are currently
  525. loaded into the symbol handler. This is the 64 bit wrapper.
  526. Arguments:
  527. hProcess - Process handle, must have been previously registered
  528. with SymInitialize.
  529. EnumModulesCallback - Callback pointer that is called once for each
  530. module that is enumerated. If the enum callback
  531. returns FALSE then the enumeration is terminated.
  532. UserContext - This data is simply passed on to the callback function
  533. and is completly user defined.
  534. Return Value:
  535. TRUE - The modules were successfully enumerated.
  536. FALSE - The enumeration failed. Call GetLastError to
  537. discover the cause of the failure.
  538. --*/
  539. {
  540. return SympEnumerateModules(hProcess, (PROC)EnumModulesCallback, UserContext, TRUE);
  541. }
  542. DWORD
  543. CalcItemSize(
  544. PDWORD64 pAddr,
  545. PDWORD64 pAddrsBase,
  546. UINT_PTR count
  547. )
  548. {
  549. PDWORD64 p;
  550. PDWORD64 pAddrEnd;
  551. if (!pAddr)
  552. return 0;
  553. pAddrEnd = pAddrsBase + count;
  554. for (p = pAddr + 1; p <= pAddrEnd; p++) {
  555. if (*p != *pAddr)
  556. return (DWORD)(*p - *pAddr);
  557. }
  558. return 0;
  559. }
  560. BOOL
  561. MatchModuleName(
  562. PMODULE_ENTRY mi,
  563. LPSTR mask
  564. )
  565. {
  566. if (!strcmpre(mi->AliasName, mask, FALSE))
  567. return TRUE;
  568. if (!strcmpre(mi->ModuleName, mask, FALSE))
  569. return TRUE;
  570. return FALSE;
  571. }
  572. BOOL
  573. SympEnumerateSymbols(
  574. IN HANDLE hProcess,
  575. IN ULONG64 BaseOfDll,
  576. IN LPSTR Mask,
  577. IN PROC EnumSymbolsCallback,
  578. IN PVOID UserContext,
  579. IN BOOL Use64,
  580. IN BOOL CallBackUsesUnicode
  581. )
  582. /*++
  583. Routine Description:
  584. This function enumerates all of the symbols contained the module
  585. specified by the BaseOfDll argument.
  586. Arguments:
  587. hProcess - Process handle, must have been previously registered
  588. with SymInitialize
  589. BaseOfDll - Base address of the DLL that symbols are to be
  590. enumerated for
  591. EnumSymbolsCallback - User specified callback routine for enumeration
  592. notification
  593. UserContext - Pass thru variable, this is simply passed thru to the
  594. callback function
  595. Use64 - Supplies flag which determines whether to use the 32 bit
  596. or 64 bit callback prototype.
  597. Return Value:
  598. TRUE - The symbols were successfully enumerated.
  599. FALSE - The enumeration failed. Call GetLastError to
  600. discover the cause of the failure.
  601. --*/
  602. {
  603. PPROCESS_ENTRY pe;
  604. PLIST_ENTRY Next;
  605. PMODULE_ENTRY mi;
  606. DWORD i;
  607. PSYMBOL_ENTRY sym;
  608. LPSTR szSymName;
  609. SYMBOL_ENTRY SymEntry={0};
  610. CHAR Buffer[2500];
  611. LPSTR p;
  612. CHAR modmask[200];
  613. BOOL rc;
  614. int pass;
  615. BOOL fCase;
  616. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED | LS_FAIL_IF_LOADED};
  617. __try {
  618. pe = FindProcessEntry( hProcess );
  619. if (!pe) {
  620. SetLastError( ERROR_INVALID_HANDLE );
  621. return FALSE;
  622. }
  623. p = 0;
  624. modmask[0] = 0;
  625. if (Mask)
  626. p = strchr(Mask, '!');
  627. if (p > Mask) {
  628. memcpy(modmask, Mask, (int)(p - Mask));
  629. modmask[p-Mask] = 0;
  630. Mask = p + 1;
  631. } else if (!BaseOfDll) {
  632. rc = diaEnumerateSymbols(pe,
  633. NULL,
  634. Mask,
  635. EnumSymbolsCallback,
  636. UserContext,
  637. Use64,
  638. CallBackUsesUnicode);
  639. if (!rc && pe->ipmi && pe->ipmi->code == ERROR_CANCELLED) {
  640. pe->ipmi->code = 0;
  641. return TRUE;
  642. }
  643. return rc;
  644. }
  645. for (pass = 0; pass < 2; pass++) {
  646. Next = pe->ModuleList.Flink;
  647. if (Next) {
  648. while (Next != &pe->ModuleList) {
  649. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  650. Next = mi->ListEntry.Flink;
  651. if (BaseOfDll) {
  652. if (mi->BaseOfDll != BaseOfDll)
  653. continue;
  654. } else if (!MatchModuleName(mi, modmask)) {
  655. continue;
  656. }
  657. if (!LoadSymbols(hProcess, mi, flags[pass]))
  658. continue;
  659. if (mi->dia) {
  660. rc = diaEnumerateSymbols(pe,
  661. mi,
  662. Mask,
  663. EnumSymbolsCallback,
  664. UserContext,
  665. Use64,
  666. CallBackUsesUnicode);
  667. if (!rc) {
  668. if (mi->code == ERROR_CANCELLED) {
  669. mi->code = 0;
  670. return TRUE;
  671. }
  672. return rc;
  673. }
  674. continue;
  675. }
  676. fCase = (g.SymOptions & SYMOPT_CASE_INSENSITIVE) ? FALSE : TRUE;
  677. for (i = 0; i < mi->numsyms; i++) {
  678. PSYMBOL_INFO SymInfo = (PSYMBOL_INFO) &Buffer[0];
  679. sym = &mi->symbolTable[i];
  680. if (Mask && *Mask && strcmpre(sym->Name, Mask, fCase))
  681. continue;
  682. mi->TmpSym.Name[0] = 0;
  683. strncat( mi->TmpSym.Name, sym->Name, TMP_SYM_LEN );
  684. SymEntry = *sym;
  685. SymEntry.Name = mi->TmpSym.Name;
  686. SymInfo->MaxNameLen = sizeof(Buffer) - sizeof(SYMBOL_INFO);
  687. symcpy2(SymInfo, &SymEntry);
  688. SymInfo->ModBase = mi->BaseOfDll;
  689. if (!DoEnumCallback(
  690. pe,
  691. SymInfo,
  692. sym->Size,
  693. EnumSymbolsCallback,
  694. UserContext,
  695. Use64,
  696. CallBackUsesUnicode)) {
  697. break;
  698. }
  699. }
  700. break;
  701. }
  702. }
  703. }
  704. } __except (EXCEPTION_EXECUTE_HANDLER) {
  705. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  706. return FALSE;
  707. }
  708. return TRUE;
  709. }
  710. BOOL
  711. IMAGEAPI
  712. SymEnumerateSymbols(
  713. IN HANDLE hProcess,
  714. IN ULONG BaseOfDll,
  715. IN PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback,
  716. IN PVOID UserContext
  717. )
  718. /*++
  719. Routine Description:
  720. This function enumerates all of the symbols contained the module
  721. specified by the BaseOfDll argument.
  722. Arguments:
  723. hProcess - Process handle, must have been previously registered
  724. with SymInitialize
  725. BaseOfDll - Base address of the DLL that symbols are to be
  726. enumerated for
  727. EnumSymbolsCallback - User specified callback routine for enumeration
  728. notification
  729. UserContext - Pass thru variable, this is simply passed thru to the
  730. callback function
  731. Return Value:
  732. TRUE - The symbols were successfully enumerated.
  733. FALSE - The enumeration failed. Call GetLastError to
  734. discover the cause of the failure.
  735. --*/
  736. {
  737. STORE_OLD_CB OldCB;
  738. OldCB.UserCallBackRoutine = EnumSymbolsCallback;
  739. OldCB.UserContext = UserContext;
  740. OldCB.cb64 = FALSE;
  741. return SympEnumerateSymbols(hProcess,
  742. BaseOfDll,
  743. NULL,
  744. (PROC) (EnumSymbolsCallback ? &ImgHlpDummyCB : NULL),
  745. (PVOID) &OldCB,
  746. FALSE,
  747. FALSE);
  748. }
  749. BOOL
  750. IMAGEAPI
  751. SymEnumerateSymbolsW(
  752. IN HANDLE hProcess,
  753. IN ULONG BaseOfDll,
  754. IN PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback,
  755. IN PVOID UserContext
  756. )
  757. {
  758. STORE_OLD_CB OldCB;
  759. OldCB.UserCallBackRoutine = (PSYM_ENUMSYMBOLS_CALLBACK) EnumSymbolsCallback;
  760. OldCB.UserContext = UserContext;
  761. OldCB.cb64 = FALSE;
  762. return SympEnumerateSymbols(hProcess,
  763. BaseOfDll,
  764. NULL,
  765. (PROC) (EnumSymbolsCallback ? &ImgHlpDummyCB : NULL),
  766. (PVOID) &OldCB,
  767. FALSE,
  768. FALSE);
  769. }
  770. BOOL
  771. IMAGEAPI
  772. SymEnumerateSymbols64(
  773. IN HANDLE hProcess,
  774. IN ULONG64 BaseOfDll,
  775. IN PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,
  776. IN PVOID UserContext
  777. )
  778. {
  779. STORE_OLD_CB OldCB;
  780. OldCB.UserCallBackRoutine64 = EnumSymbolsCallback;
  781. OldCB.UserContext = UserContext;
  782. OldCB.cb64 = TRUE;
  783. return SympEnumerateSymbols(hProcess,
  784. BaseOfDll,
  785. NULL,
  786. (PROC) (EnumSymbolsCallback ? &ImgHlpDummyCB : NULL),
  787. (PVOID) &OldCB,
  788. FALSE,
  789. FALSE);
  790. }
  791. BOOL
  792. IMAGEAPI
  793. SymEnumerateSymbolsW64(
  794. IN HANDLE hProcess,
  795. IN ULONG64 BaseOfDll,
  796. IN PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback,
  797. IN PVOID UserContext
  798. )
  799. {
  800. STORE_OLD_CB OldCB;
  801. OldCB.UserCallBackRoutine64 = (PSYM_ENUMSYMBOLS_CALLBACK64) EnumSymbolsCallback;
  802. OldCB.UserContext = UserContext;
  803. OldCB.cb64 = TRUE;
  804. return SympEnumerateSymbols(hProcess,
  805. BaseOfDll,
  806. NULL,
  807. (PROC) (EnumSymbolsCallback ? &ImgHlpDummyCB : NULL),
  808. (PVOID) &OldCB,
  809. FALSE,
  810. FALSE);
  811. }
  812. BOOL
  813. SympGetSymFromAddr(
  814. IN HANDLE hProcess,
  815. IN DWORD64 Address,
  816. OUT PDWORD64 Displacement,
  817. OUT PSYMBOL_ENTRY SymRet
  818. )
  819. /*++
  820. Routine Description:
  821. This function finds an entry in the symbol table based on an address.
  822. This is the common worker function for the 32 and 64 bit API.
  823. Arguments:
  824. hProcess - Process handle, must have been previously registered
  825. with SymInitialize.
  826. Address - Address of the desired symbol.
  827. Displacement - This value is set to the offset from the beginning
  828. of the symbol.
  829. sym - Returns the found symbol
  830. Return Value:
  831. TRUE - The symbol was located.
  832. FALSE - The symbol was not found. Call GetLastError to
  833. discover the cause of the failure.
  834. --*/
  835. {
  836. PPROCESS_ENTRY pe;
  837. PMODULE_ENTRY mi;
  838. PSYMBOL_ENTRY psym;
  839. __try {
  840. pe = FindProcessEntry( hProcess );
  841. if (!pe) {
  842. SetLastError( ERROR_INVALID_HANDLE );
  843. return FALSE;
  844. }
  845. mi = GetModuleForPC( pe, Address, FALSE );
  846. if (mi == NULL) {
  847. SetLastError( ERROR_MOD_NOT_FOUND );
  848. return FALSE;
  849. }
  850. if (!LoadSymbols(hProcess, mi, 0)) {
  851. SetLastError( ERROR_MOD_NOT_FOUND );
  852. return FALSE;
  853. }
  854. psym = GetSymFromAddr( Address, Displacement, mi );
  855. if (psym) {
  856. *SymRet = *psym;
  857. } else {
  858. SetLastError( ERROR_INVALID_ADDRESS );
  859. return FALSE;
  860. }
  861. } __except (EXCEPTION_EXECUTE_HANDLER) {
  862. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  863. return FALSE;
  864. }
  865. return TRUE;
  866. }
  867. BOOL
  868. IMAGEAPI
  869. SymGetSymFromAddr64(
  870. IN HANDLE hProcess,
  871. IN DWORD64 Address,
  872. OUT PDWORD64 Displacement,
  873. OUT PIMAGEHLP_SYMBOL64 Symbol
  874. )
  875. /*++
  876. Routine Description:
  877. This function finds an entry in the symbol table based on an address.
  878. Arguments:
  879. hProcess - Process handle, must have been previously registered
  880. with SymInitialize.
  881. Address - Address of the desired symbol.
  882. Displacement - This value is set to the offset from the beginning
  883. of the symbol.
  884. Symbol - Returns the found symbol
  885. Return Value:
  886. TRUE - The symbol was located.
  887. FALSE - The symbol was not found. Call GetLastError to
  888. discover the cause of the failure.
  889. --*/
  890. {
  891. SYMBOL_ENTRY sym;
  892. if (SympGetSymFromAddr(hProcess, Address, Displacement, &sym)) {
  893. symcpy64(Symbol, &sym);
  894. return TRUE;
  895. } else {
  896. return FALSE;
  897. }
  898. }
  899. BOOL
  900. IMAGEAPI
  901. SymGetSymFromAddr(
  902. IN HANDLE hProcess,
  903. IN DWORD Address,
  904. OUT PDWORD Displacement,
  905. OUT PIMAGEHLP_SYMBOL Symbol
  906. )
  907. /*++
  908. Routine Description:
  909. This function finds an entry in the symbol table based on an address.
  910. Arguments:
  911. hProcess - Process handle, must have been previously registered
  912. with SymInitialize.
  913. Address - Address of the desired symbol.
  914. Displacement - This value is set to the offset from the beginning
  915. of the symbol.
  916. Symbol - Returns the found symbol
  917. Return Value:
  918. TRUE - The symbol was located.
  919. FALSE - The symbol was not found. Call GetLastError to
  920. discover the cause of the failure.
  921. --*/
  922. {
  923. SYMBOL_ENTRY sym;
  924. DWORD64 qDisplacement;
  925. if (SympGetSymFromAddr(hProcess, Address, &qDisplacement, &sym)) {
  926. symcpy32(Symbol, &sym);
  927. if (Displacement) {
  928. *Displacement = (DWORD)qDisplacement;
  929. }
  930. return TRUE;
  931. } else {
  932. return FALSE;
  933. }
  934. }
  935. #ifndef _DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  936. #if 0
  937. VOID
  938. DumpMiSymbolTable(
  939. PMODULE_ENTRY mi
  940. )
  941. {
  942. PSYMBOL_ENTRY sym;
  943. if ( !mi )
  944. return;
  945. sym = mi->symbolTable;
  946. for ( sym = mi->symbolTable; sym < &mi->symbolTable[mi->numsyms] ; sym++ ) {
  947. dprint("sym: %40s 0x%I64x %ld\n", sym->Name, sym->Address, sym->Size );
  948. }
  949. return;
  950. } // DumpMiSymbolTable()
  951. #endif // 0
  952. #ifdef __cplusplus
  953. extern "C"
  954. #endif
  955. BOOL
  956. SymSetSymWithAddr64(
  957. IN HANDLE hProcess,
  958. IN DWORD64 Address,
  959. IN LPSTR SymString,
  960. OUT PIMAGEHLP_SYMBOL64 Symbol
  961. )
  962. /*++
  963. Routine Description:
  964. This function allocates an entry in the symbol table based on an address.
  965. Arguments:
  966. hProcess - Process handle, must have been previously registered
  967. with SymInitialize.
  968. Address - Address of the desired symbol.
  969. SymString - Symbol name.
  970. Return Value:
  971. TRUE - The symbol was allocated.
  972. FALSE - The symbol was not allocated. all GetLastError to
  973. discover the cause of the failure.
  974. --*/
  975. {
  976. PPROCESS_ENTRY pe;
  977. PMODULE_ENTRY mi;
  978. PSYMBOL_ENTRY psym;
  979. BOOL ret;
  980. DWORD64 displacement;
  981. if ( !SymString ) {
  982. SetLastError( ERROR_INVALID_PARAMETER );
  983. return FALSE;
  984. }
  985. ret = TRUE;
  986. __try {
  987. pe = FindProcessEntry( hProcess );
  988. if (!pe) {
  989. SetLastError( ERROR_INVALID_HANDLE ), ret = FALSE;
  990. __leave;
  991. }
  992. mi = GetModuleForPC( pe, Address, FALSE );
  993. if (mi == NULL) {
  994. SetLastError( ERROR_MOD_NOT_FOUND ), ret = FALSE;
  995. __leave;
  996. }
  997. if (!LoadSymbols(hProcess, mi, 0)) {
  998. SetLastError( ERROR_MOD_NOT_FOUND ), ret = FALSE;
  999. __leave;
  1000. }
  1001. //
  1002. // Let's verify that this address is not already used...
  1003. // If yes, returns FALSE. The caller could parse the LastError.
  1004. //
  1005. psym = GetSymFromAddr( Address, &displacement, mi );
  1006. if ( psym ) {
  1007. pprint(pe, "SymSetSymWithAddr64: symbol %s already exists at this address 0x%I64x\n", psym->Name, Address );
  1008. SetLastError( ERROR_ALREADY_EXISTS ), ret = FALSE;
  1009. __leave;
  1010. }
  1011. //
  1012. // Allocate a new entry.
  1013. // This allocation is under imagehlp rules.
  1014. // Meaning that if the symbols table has overflow,
  1015. // we will not allocate an entry. This implementation]
  1016. // does not use a specific bucket of entries.
  1017. //
  1018. psym = AllocSym( mi, Address, SymString );
  1019. if ( !psym ) {
  1020. SetLastError( ERROR_INVALID_ADDRESS ), ret = FALSE;
  1021. __leave;
  1022. }
  1023. psym->Flags |= SYMF_USER_GENERATED;
  1024. symcpy64(Symbol, psym);
  1025. CompleteSymbolTable( mi );
  1026. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1027. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1028. ret = FALSE;
  1029. }
  1030. return ret;
  1031. } // SymSetSymWithAddr64()
  1032. #endif // !_DBGHELP_USER_GENERATED_SYMBOLS_NOTSUPPORTED
  1033. BOOL
  1034. SympGetSymFromName(
  1035. IN HANDLE hProcess,
  1036. IN LPSTR Name,
  1037. OUT PSYMBOL_ENTRY SymRet
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. This function finds an entry in the symbol table based on a name.
  1042. Arguments:
  1043. hProcess - Process handle, must have been previously registered
  1044. with SymInitialize.
  1045. SymName - A string containing the symbol name.
  1046. sym - Returns the located symbol
  1047. Return Value:
  1048. TRUE - The symbol was located.
  1049. FALSE - The symbol was not found. Call GetLastError to
  1050. discover the cause of the failure.
  1051. --*/
  1052. {
  1053. LPSTR p;
  1054. PPROCESS_ENTRY pe;
  1055. PMODULE_ENTRY mi = NULL;
  1056. PLIST_ENTRY Next;
  1057. PSYMBOL_ENTRY psym;
  1058. IMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl64;
  1059. int pass;
  1060. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED};
  1061. __try {
  1062. pe = FindProcessEntry( hProcess );
  1063. if (!pe) {
  1064. SetLastError( ERROR_INVALID_HANDLE );
  1065. return FALSE;
  1066. }
  1067. // first check for fully qualified symbol name I.E. mod!sym
  1068. p = strchr( Name, '!' );
  1069. if (p > Name) {
  1070. LPSTR ModName = (LPSTR)MemAlloc(p - Name + 1);
  1071. if (!ModName) {
  1072. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1073. return FALSE;
  1074. }
  1075. memcpy(ModName, Name, (int)(p - Name));
  1076. ModName[p-Name] = 0;
  1077. //
  1078. // the caller wants to look in a specific module
  1079. //
  1080. mi = FindModule(hProcess, pe, ModName, TRUE);
  1081. MemFree(ModName);
  1082. if (mi != NULL) {
  1083. psym = FindSymbolByName( pe, mi, p+1 );
  1084. if (psym) {
  1085. *SymRet = *psym;
  1086. return TRUE;
  1087. }
  1088. }
  1089. SetLastError( ERROR_MOD_NOT_FOUND );
  1090. return FALSE;
  1091. }
  1092. // now check, using context information
  1093. psym = FindSymbolByName( pe, NULL, Name );
  1094. if (psym) {
  1095. *SymRet = *psym;
  1096. return TRUE;
  1097. }
  1098. // now just look in every module
  1099. for (pass = 0; pass < 2; pass++) {
  1100. Next = pe->ModuleList.Flink;
  1101. while (Next != &pe->ModuleList) {
  1102. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  1103. Next = mi->ListEntry.Flink;
  1104. if (pass && DoSymbolCallback(pe,
  1105. CBA_DEFERRED_SYMBOL_LOAD_CANCEL,
  1106. mi,
  1107. &idsl64,
  1108. NULL))
  1109. {
  1110. break;
  1111. }
  1112. if (!LoadSymbols(hProcess, mi, flags[pass]))
  1113. continue;
  1114. psym = FindSymbolByName( pe, mi, Name );
  1115. if (psym) {
  1116. *SymRet = *psym;
  1117. return TRUE;
  1118. }
  1119. }
  1120. }
  1121. SetLastError( ERROR_MOD_NOT_FOUND );
  1122. return FALSE;
  1123. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1124. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1125. return FALSE;
  1126. }
  1127. SetLastError( ERROR_INVALID_FUNCTION );
  1128. return FALSE;
  1129. }
  1130. BOOL
  1131. IMAGEAPI
  1132. SymGetSymFromName64(
  1133. IN HANDLE hProcess,
  1134. IN LPSTR Name,
  1135. OUT PIMAGEHLP_SYMBOL64 Symbol
  1136. )
  1137. /*++
  1138. Routine Description:
  1139. This function finds an entry in the symbol table based on a name.
  1140. Arguments:
  1141. hProcess - Process handle, must have been previously registered
  1142. with SymInitialize.
  1143. SymName - A string containing the symbol name.
  1144. Symbol - Returns found symbol
  1145. Return Value:
  1146. TRUE - The symbol was located.
  1147. FALSE - The symbol was not found. Call GetLastError to
  1148. discover the cause of the failure.
  1149. --*/
  1150. {
  1151. SYMBOL_ENTRY sym;
  1152. if (SympGetSymFromName(hProcess, Name, &sym)) {
  1153. symcpy64(Symbol, &sym);
  1154. return TRUE;
  1155. } else {
  1156. return FALSE;
  1157. }
  1158. }
  1159. BOOL
  1160. IMAGEAPI
  1161. SymGetSymFromName(
  1162. IN HANDLE hProcess,
  1163. IN LPSTR Name,
  1164. OUT PIMAGEHLP_SYMBOL Symbol
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. This function finds an entry in the symbol table based on a name.
  1169. Arguments:
  1170. hProcess - Process handle, must have been previously registered
  1171. with SymInitialize.
  1172. SymName - A string containing the symbol name.
  1173. Symbol - Returns found symbol
  1174. Return Value:
  1175. TRUE - The symbol was located.
  1176. FALSE - The symbol was not found. Call GetLastError to
  1177. discover the cause of the failure.
  1178. --*/
  1179. {
  1180. SYMBOL_ENTRY sym;
  1181. if (SympGetSymFromName(hProcess, Name, &sym)) {
  1182. symcpy32(Symbol, &sym);
  1183. return TRUE;
  1184. } else {
  1185. return FALSE;
  1186. }
  1187. }
  1188. BOOL
  1189. IMAGEAPI
  1190. SymGetSymNext(
  1191. IN HANDLE hProcess,
  1192. IN OUT PIMAGEHLP_SYMBOL Symbol32
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. This function finds the next symbol in the symbol table that falls
  1197. sequentially after the symbol passed in.
  1198. Arguments:
  1199. hProcess - Process handle, must have been previously registered
  1200. with SymInitialize.
  1201. Symbol - Starting symbol.
  1202. Return Value:
  1203. Non NULL pointer - The symbol was located.
  1204. NULL pointer - The symbol was not found. Call GetLastError to
  1205. discover the cause of the failure.
  1206. --*/
  1207. {
  1208. PIMAGEHLP_SYMBOL64 Symbol64;
  1209. BOOL r = FALSE;
  1210. Symbol64 = (PIMAGEHLP_SYMBOL64)MemAlloc(sizeof(IMAGEHLP_SYMBOL64) + Symbol32->MaxNameLength);
  1211. if (Symbol64) {
  1212. SympConvertSymbol32To64(Symbol32, Symbol64);
  1213. if (SympGetSymNextPrev(hProcess, Symbol64, 1)) {
  1214. SympConvertSymbol64To32(Symbol64, Symbol32);
  1215. r = TRUE;
  1216. }
  1217. MemFree(Symbol64);
  1218. }
  1219. return r;
  1220. }
  1221. BOOL
  1222. IMAGEAPI
  1223. SymGetSymNext64(
  1224. IN HANDLE hProcess,
  1225. IN OUT PIMAGEHLP_SYMBOL64 Symbol
  1226. )
  1227. /*++
  1228. Routine Description:
  1229. This function finds the next symbol in the symbol table that falls
  1230. sequentially after the symbol passed in.
  1231. Arguments:
  1232. hProcess - Process handle, must have been previously registered
  1233. with SymInitialize.
  1234. Symbol - Starting symbol.
  1235. Return Value:
  1236. Non NULL pointer - The symbol was located.
  1237. NULL pointer - The symbol was not found. Call GetLastError to
  1238. discover the cause of the failure.
  1239. --*/
  1240. {
  1241. return SympGetSymNextPrev(hProcess, Symbol, 1);
  1242. }
  1243. BOOL
  1244. IMAGEAPI
  1245. SymGetSymPrev(
  1246. IN HANDLE hProcess,
  1247. IN OUT PIMAGEHLP_SYMBOL Symbol32
  1248. )
  1249. /*++
  1250. Routine Description:
  1251. This function finds the next symbol in the symbol table that falls
  1252. sequentially after the symbol passed in.
  1253. Arguments:
  1254. hProcess - Process handle, must have been previously registered
  1255. with SymInitialize.
  1256. Symbol - Starting symbol.
  1257. Return Value:
  1258. Non NULL pointer - The symbol was located.
  1259. NULL pointer - The symbol was not found. Call GetLastError to
  1260. discover the cause of the failure.
  1261. --*/
  1262. {
  1263. PIMAGEHLP_SYMBOL64 Symbol64;
  1264. BOOL r = FALSE;
  1265. Symbol64 = (PIMAGEHLP_SYMBOL64)MemAlloc(sizeof(IMAGEHLP_SYMBOL64) + Symbol32->MaxNameLength);
  1266. if (Symbol64) {
  1267. SympConvertSymbol32To64(Symbol32, Symbol64);
  1268. if (SympGetSymNextPrev(hProcess, Symbol64, -1)) {
  1269. SympConvertSymbol64To32(Symbol64, Symbol32);
  1270. r = TRUE;
  1271. }
  1272. MemFree(Symbol64);
  1273. }
  1274. return r;
  1275. }
  1276. BOOL
  1277. IMAGEAPI
  1278. SymGetSymPrev64(
  1279. IN HANDLE hProcess,
  1280. IN OUT PIMAGEHLP_SYMBOL64 Symbol
  1281. )
  1282. /*++
  1283. Routine Description:
  1284. This function finds the next symbol in the symbol table that falls
  1285. sequentially after the symbol passed in.
  1286. Arguments:
  1287. hProcess - Process handle, must have been previously registered
  1288. with SymInitialize.
  1289. Symbol - Starting symbol.
  1290. Return Value:
  1291. Non NULL pointer - The symbol was located.
  1292. NULL pointer - The symbol was not found. Call GetLastError to
  1293. discover the cause of the failure.
  1294. --*/
  1295. {
  1296. return SympGetSymNextPrev(hProcess, Symbol, -1);
  1297. }
  1298. BOOL
  1299. SympGetSymNextPrev(
  1300. IN HANDLE hProcess,
  1301. IN OUT PIMAGEHLP_SYMBOL64 Symbol,
  1302. IN int Direction
  1303. )
  1304. /*++
  1305. Routine Description:
  1306. Common code for SymGetSymNext and SymGetSymPrev.
  1307. Arguments:
  1308. hProcess - Process handle, must have been previously registered
  1309. with SymInitialize.
  1310. Symbol - Starting symbol.
  1311. Dir - Supplies direction to search
  1312. Return Value:
  1313. Non NULL pointer - The symbol was located.
  1314. NULL pointer - The symbol was not found. Call GetLastError to
  1315. discover the cause of the failure.
  1316. --*/
  1317. {
  1318. PPROCESS_ENTRY pe;
  1319. PMODULE_ENTRY mi;
  1320. ULONG64 Displacement;
  1321. PSYMBOL_ENTRY sym;
  1322. SYMBOL_ENTRY SymEntry = {0};
  1323. __try {
  1324. pe = FindProcessEntry( hProcess );
  1325. if (!pe) {
  1326. SetLastError( ERROR_INVALID_HANDLE );
  1327. return FALSE;
  1328. }
  1329. mi = GetModuleForPC( pe, Symbol->Address, FALSE );
  1330. if (mi == NULL) {
  1331. SetLastError( ERROR_MOD_NOT_FOUND );
  1332. return FALSE;
  1333. }
  1334. if (!LoadSymbols(hProcess, mi, 0)) {
  1335. SetLastError( ERROR_MOD_NOT_FOUND );
  1336. return FALSE;
  1337. }
  1338. if (mi->dia) {
  1339. sym = diaGetSymNextPrev(mi, Symbol->Address, Direction);
  1340. if (!sym) {
  1341. SetLastError( ERROR_INVALID_ADDRESS );
  1342. return FALSE;
  1343. }
  1344. symcpy64(Symbol, sym);
  1345. } else {
  1346. sym = GetSymFromAddr( Symbol->Address, &Displacement, mi );
  1347. if (!sym) {
  1348. SetLastError( ERROR_INVALID_ADDRESS );
  1349. return FALSE;
  1350. }
  1351. if (Direction > 0 && sym+1 >= mi->symbolTable+mi->numsyms) {
  1352. SetLastError( ERROR_INVALID_ADDRESS );
  1353. return FALSE;
  1354. } else if (Direction < 0 && sym-1 < mi->symbolTable) {
  1355. SetLastError( ERROR_INVALID_ADDRESS );
  1356. return FALSE;
  1357. }
  1358. symcpy64( Symbol, sym + Direction);
  1359. }
  1360. return TRUE;
  1361. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1362. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1363. return FALSE;
  1364. }
  1365. return FALSE;
  1366. }
  1367. BOOL
  1368. IMAGEAPI
  1369. SymGetLineFromAddr64(
  1370. IN HANDLE hProcess,
  1371. IN DWORD64 dwAddr,
  1372. OUT PDWORD pdwDisplacement,
  1373. OUT PIMAGEHLP_LINE64 Line
  1374. )
  1375. /*++
  1376. Routine Description:
  1377. This function finds a source file and line number entry for the
  1378. line closest to the given address.
  1379. Arguments:
  1380. hProcess - Process handle, must have been previously registered
  1381. with SymInitialize.
  1382. dwAddr - Supplies an address for which a line is to be
  1383. located.
  1384. pdwDisplacement - Returns the offset between the given address
  1385. and the first instruction of the line.
  1386. Line - Returns the line and file information.
  1387. Return Value:
  1388. TRUE - A line was located.
  1389. FALSE - The line was not found. Call GetLastError to
  1390. discover the cause of the failure.
  1391. --*/
  1392. {
  1393. PPROCESS_ENTRY pe;
  1394. PMODULE_ENTRY mi;
  1395. __try {
  1396. if (Line->SizeOfStruct != sizeof(IMAGEHLP_LINE64)) {
  1397. SetLastError(ERROR_INVALID_PARAMETER);
  1398. return FALSE;
  1399. }
  1400. pe = FindProcessEntry( hProcess );
  1401. if (!pe) {
  1402. SetLastError( ERROR_INVALID_HANDLE );
  1403. return FALSE;
  1404. }
  1405. mi = GetModuleForPC( pe, dwAddr, FALSE );
  1406. if (mi == NULL) {
  1407. SetLastError( ERROR_MOD_NOT_FOUND );
  1408. return FALSE;
  1409. }
  1410. if (!LoadSymbols(hProcess, mi, 0)) {
  1411. SetLastError( ERROR_MOD_NOT_FOUND );
  1412. return FALSE;
  1413. }
  1414. if (!GetLineFromAddr(mi, dwAddr, pdwDisplacement, Line)) {
  1415. SetLastError( ERROR_INVALID_ADDRESS );
  1416. return FALSE;
  1417. }
  1418. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1419. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1420. return FALSE;
  1421. }
  1422. return TRUE;
  1423. }
  1424. BOOL
  1425. IMAGEAPI
  1426. SymGetLineFromAddr(
  1427. IN HANDLE hProcess,
  1428. IN DWORD dwAddr,
  1429. OUT PDWORD pdwDisplacement,
  1430. OUT PIMAGEHLP_LINE Line32
  1431. )
  1432. {
  1433. IMAGEHLP_LINE64 Line64;
  1434. Line64.SizeOfStruct = sizeof(Line64);
  1435. if (SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &Line64)) {
  1436. SympConvertLine64To32(&Line64, Line32);
  1437. return TRUE;
  1438. } else {
  1439. return FALSE;
  1440. }
  1441. }
  1442. BOOL
  1443. IMAGEAPI
  1444. SymGetLineFromName64(
  1445. IN HANDLE hProcess,
  1446. IN LPSTR ModuleName,
  1447. IN LPSTR FileName,
  1448. IN DWORD dwLineNumber,
  1449. OUT PLONG plDisplacement,
  1450. IN OUT PIMAGEHLP_LINE64 Line
  1451. )
  1452. /*++
  1453. Routine Description:
  1454. This function finds an entry in the source file and line-number
  1455. information based on a particular filename and line number.
  1456. A module name can be given if the search is to be restricted to
  1457. a specific module.
  1458. The filename can be omitted if a pure line number search is desired,
  1459. in which case Line must be a previously filled out line number
  1460. struct. The module and file that Line->Address lies in is used
  1461. to look up the new line number. This cannot be used when a module
  1462. name is given.
  1463. Arguments:
  1464. hProcess - Process handle, must have been previously registered
  1465. with SymInitialize.
  1466. ModuleName - Module name or NULL.
  1467. FileName - File name or NULL.
  1468. dwLineNumber - Line number of interest.
  1469. plDisplacement - Difference between requested line number and
  1470. returned line number.
  1471. Line - Line information input and return.
  1472. Return Value:
  1473. TRUE - A line was located.
  1474. FALSE - A line was not found. Call GetLastError to
  1475. discover the cause of the failure.
  1476. --*/
  1477. {
  1478. PPROCESS_ENTRY pe;
  1479. PMODULE_ENTRY mi = NULL;
  1480. PLIST_ENTRY Next;
  1481. IMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl64;
  1482. int pass;
  1483. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED | LS_LOAD_LINES};
  1484. __try {
  1485. if (Line->SizeOfStruct != sizeof(IMAGEHLP_LINE64)) {
  1486. SetLastError(ERROR_INVALID_PARAMETER);
  1487. return FALSE;
  1488. }
  1489. pe = FindProcessEntry( hProcess );
  1490. if (!pe) {
  1491. SetLastError( ERROR_INVALID_HANDLE );
  1492. return FALSE;
  1493. }
  1494. if (ModuleName != NULL) {
  1495. //
  1496. // The caller wants to look in a specific module.
  1497. // A filename must be given in this case because it doesn't
  1498. // make sense to do an address-driven search when a module
  1499. // is explicitly specified since the address also specifies
  1500. // a module.
  1501. //
  1502. if (FileName == NULL) {
  1503. SetLastError(ERROR_INVALID_PARAMETER);
  1504. return FALSE;
  1505. }
  1506. mi = FindModule(hProcess, pe, ModuleName, TRUE);
  1507. if (mi != NULL &&
  1508. FindLineByName( mi, FileName, dwLineNumber, plDisplacement, Line )) {
  1509. return TRUE;
  1510. }
  1511. SetLastError( ERROR_MOD_NOT_FOUND );
  1512. return FALSE;
  1513. }
  1514. if (FileName == NULL) {
  1515. // Only a line number has been given, implying that
  1516. // it's a line in the same file as the given line is currently in.
  1517. mi = GetModuleForPC( pe, Line->Address, FALSE );
  1518. if (mi == NULL) {
  1519. SetLastError( ERROR_MOD_NOT_FOUND );
  1520. return FALSE;
  1521. }
  1522. if (!LoadSymbols(hProcess, mi, LS_LOAD_LINES)) {
  1523. SetLastError( ERROR_MOD_NOT_FOUND );
  1524. return FALSE;
  1525. }
  1526. if (FindLineByName( mi, FileName, dwLineNumber,
  1527. plDisplacement, Line )) {
  1528. return TRUE;
  1529. }
  1530. SetLastError( ERROR_MOD_NOT_FOUND );
  1531. return FALSE;
  1532. }
  1533. Next = pe->ModuleList.Flink;
  1534. if (!Next) {
  1535. SetLastError( ERROR_MOD_NOT_FOUND );
  1536. return FALSE;
  1537. }
  1538. for (pass = 0; pass < 2; pass++) {
  1539. Next = pe->ModuleList.Flink;
  1540. while (Next != &pe->ModuleList) {
  1541. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  1542. Next = mi->ListEntry.Flink;
  1543. if (pass && DoSymbolCallback(pe,
  1544. CBA_DEFERRED_SYMBOL_LOAD_CANCEL,
  1545. mi,
  1546. &idsl64,
  1547. NULL))
  1548. {
  1549. break;
  1550. }
  1551. if (!LoadSymbols(hProcess, mi, flags[pass]))
  1552. continue;
  1553. if (FindLineByName( mi, FileName, dwLineNumber, plDisplacement, Line ))
  1554. return TRUE;
  1555. }
  1556. }
  1557. SetLastError( ERROR_MOD_NOT_FOUND );
  1558. return FALSE;
  1559. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1560. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1561. return FALSE;
  1562. }
  1563. SetLastError( ERROR_INVALID_FUNCTION );
  1564. return FALSE;
  1565. }
  1566. BOOL
  1567. IMAGEAPI
  1568. SymGetLineFromName(
  1569. IN HANDLE hProcess,
  1570. IN LPSTR ModuleName,
  1571. IN LPSTR FileName,
  1572. IN DWORD dwLineNumber,
  1573. OUT PLONG plDisplacement,
  1574. IN OUT PIMAGEHLP_LINE Line32
  1575. )
  1576. {
  1577. IMAGEHLP_LINE64 Line64;
  1578. Line64.SizeOfStruct = sizeof(Line64);
  1579. SympConvertLine32To64(Line32, &Line64);
  1580. if (SymGetLineFromName64(hProcess,
  1581. ModuleName,
  1582. FileName,
  1583. dwLineNumber,
  1584. plDisplacement,
  1585. &Line64)) {
  1586. return SympConvertLine64To32(&Line64, Line32);
  1587. } else {
  1588. return FALSE;
  1589. }
  1590. }
  1591. BOOL
  1592. IMAGEAPI
  1593. SymGetLineNext64(
  1594. IN HANDLE hProcess,
  1595. IN OUT PIMAGEHLP_LINE64 Line
  1596. )
  1597. /*++
  1598. Routine Description:
  1599. This function returns line address information for the line immediately
  1600. following the line given.
  1601. Arguments:
  1602. hProcess - Process handle, must have been previously registered
  1603. with SymInitialize.
  1604. Line - Supplies line number information for the line
  1605. prior to the one being located.
  1606. Return Value:
  1607. TRUE - A line was located. The Key, LineNumber and Address
  1608. of Line are updated.
  1609. FALSE - No such line exists. Call GetLastError to
  1610. discover the cause of the failure.
  1611. --*/
  1612. {
  1613. PPROCESS_ENTRY pe;
  1614. PMODULE_ENTRY mi;
  1615. PSOURCE_LINE SrcLine;
  1616. PSOURCE_ENTRY Src;
  1617. __try {
  1618. if (Line->SizeOfStruct != sizeof(IMAGEHLP_LINE64)) {
  1619. SetLastError(ERROR_INVALID_PARAMETER);
  1620. return FALSE;
  1621. }
  1622. pe = FindProcessEntry( hProcess );
  1623. if (!pe) {
  1624. SetLastError( ERROR_INVALID_HANDLE );
  1625. return FALSE;
  1626. }
  1627. mi = GetModuleForPC( pe, Line->Address, FALSE );
  1628. if (mi == NULL) {
  1629. SetLastError( ERROR_MOD_NOT_FOUND );
  1630. return FALSE;
  1631. }
  1632. if (!LoadSymbols(hProcess, mi, 0)) {
  1633. SetLastError( ERROR_MOD_NOT_FOUND );
  1634. return FALSE;
  1635. }
  1636. if (mi->dia)
  1637. return diaGetLineNext(mi, Line);
  1638. // Use existing information to look up module and then
  1639. // locate the file information. The key could be extended
  1640. // to make this unnecessary but it's done as a validation step
  1641. // more than as a way to save a DWORD.
  1642. SrcLine = (PSOURCE_LINE)Line->Key;
  1643. for (Src = mi->SourceFiles; Src != NULL; Src = Src->Next) {
  1644. if (SrcLine >= Src->LineInfo &&
  1645. SrcLine < Src->LineInfo+Src->Lines) {
  1646. break;
  1647. }
  1648. }
  1649. if (Src == NULL) {
  1650. SetLastError(ERROR_INVALID_PARAMETER);
  1651. return FALSE;
  1652. }
  1653. if (SrcLine == Src->LineInfo+Src->Lines-1) {
  1654. SetLastError(ERROR_NO_MORE_ITEMS);
  1655. return FALSE;
  1656. }
  1657. SrcLine++;
  1658. Line->Key = SrcLine;
  1659. Line->LineNumber = SrcLine->Line;
  1660. Line->Address = SrcLine->Addr;
  1661. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1662. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1663. return FALSE;
  1664. }
  1665. return TRUE;
  1666. }
  1667. BOOL
  1668. IMAGEAPI
  1669. SymGetLineNext(
  1670. IN HANDLE hProcess,
  1671. IN OUT PIMAGEHLP_LINE Line32
  1672. )
  1673. {
  1674. IMAGEHLP_LINE64 Line64;
  1675. Line64.SizeOfStruct = sizeof(Line64);
  1676. SympConvertLine32To64(Line32, &Line64);
  1677. if (SymGetLineNext64(hProcess, &Line64)) {
  1678. return SympConvertLine64To32(&Line64, Line32);
  1679. } else {
  1680. return FALSE;
  1681. }
  1682. }
  1683. BOOL
  1684. IMAGEAPI
  1685. SymGetLinePrev64(
  1686. IN HANDLE hProcess,
  1687. IN OUT PIMAGEHLP_LINE64 Line
  1688. )
  1689. /*++
  1690. Routine Description:
  1691. This function returns line address information for the line immediately
  1692. before the line given.
  1693. Arguments:
  1694. hProcess - Process handle, must have been previously registered
  1695. with SymInitialize.
  1696. Line - Supplies line number information for the line
  1697. after the one being located.
  1698. Return Value:
  1699. TRUE - A line was located. The Key, LineNumber and Address
  1700. of Line are updated.
  1701. FALSE - No such line exists. Call GetLastError to
  1702. discover the cause of the failure.
  1703. --*/
  1704. {
  1705. PPROCESS_ENTRY pe;
  1706. PMODULE_ENTRY mi;
  1707. PSOURCE_LINE SrcLine;
  1708. PSOURCE_ENTRY Src;
  1709. __try {
  1710. if (Line->SizeOfStruct != sizeof(IMAGEHLP_LINE64)) {
  1711. SetLastError(ERROR_INVALID_PARAMETER);
  1712. return FALSE;
  1713. }
  1714. pe = FindProcessEntry( hProcess );
  1715. if (!pe) {
  1716. SetLastError( ERROR_INVALID_HANDLE );
  1717. return FALSE;
  1718. }
  1719. mi = GetModuleForPC( pe, Line->Address, FALSE );
  1720. if (mi == NULL) {
  1721. SetLastError( ERROR_MOD_NOT_FOUND );
  1722. return FALSE;
  1723. }
  1724. if (!LoadSymbols(hProcess, mi, 0)) {
  1725. SetLastError( ERROR_MOD_NOT_FOUND );
  1726. return FALSE;
  1727. }
  1728. if (mi->dia)
  1729. return diaGetLinePrev(mi, Line);
  1730. // Use existing information to look up module and then
  1731. // locate the file information. The key could be extended
  1732. // to make this unnecessary but it's done as a validation step
  1733. // more than as a way to save a DWORD.
  1734. SrcLine = (PSOURCE_LINE)Line->Key;
  1735. for (Src = mi->SourceFiles; Src != NULL; Src = Src->Next) {
  1736. if (SrcLine >= Src->LineInfo &&
  1737. SrcLine < Src->LineInfo+Src->Lines) {
  1738. break;
  1739. }
  1740. }
  1741. if (Src == NULL) {
  1742. SetLastError(ERROR_INVALID_PARAMETER);
  1743. return FALSE;
  1744. }
  1745. if (SrcLine == Src->LineInfo) {
  1746. SetLastError(ERROR_NO_MORE_ITEMS);
  1747. return FALSE;
  1748. }
  1749. SrcLine--;
  1750. Line->Key = SrcLine;
  1751. Line->LineNumber = SrcLine->Line;
  1752. Line->Address = SrcLine->Addr;
  1753. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1754. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1755. return FALSE;
  1756. }
  1757. return TRUE;
  1758. }
  1759. BOOL
  1760. IMAGEAPI
  1761. SymGetLinePrev(
  1762. IN HANDLE hProcess,
  1763. IN OUT PIMAGEHLP_LINE Line32
  1764. )
  1765. {
  1766. IMAGEHLP_LINE64 Line64;
  1767. Line64.SizeOfStruct = sizeof(Line64);
  1768. SympConvertLine32To64(Line32, &Line64);
  1769. if (SymGetLinePrev64(hProcess, &Line64)) {
  1770. return SympConvertLine64To32(&Line64, Line32);
  1771. } else {
  1772. return FALSE;
  1773. }
  1774. }
  1775. BOOL
  1776. IMAGEAPI
  1777. SymMatchFileName(
  1778. IN LPSTR FileName,
  1779. IN LPSTR Match,
  1780. OUT LPSTR *FileNameStop,
  1781. OUT LPSTR *MatchStop
  1782. )
  1783. /*++
  1784. Routine Description:
  1785. This function attempts to match a string against a filename and path.
  1786. The match string is allowed to be a suffix of the complete filename,
  1787. so this function is useful for matching a plain filename against
  1788. a fully qualified filename.
  1789. Matching begins from the end of both strings and proceeds backwards.
  1790. Matching is case-insensitive and equates \ with /.
  1791. Arguments:
  1792. FileName - Filename to match against.
  1793. Match - String to match against filename.
  1794. FileNameStop - Returns pointer into FileName where matching stopped.
  1795. May be one before FileName for full matches.
  1796. May be NULL.
  1797. MatchStop - Returns pointer info Match where matching stopped.
  1798. May be one before Match for full matches.
  1799. May be NULL.
  1800. Return Value:
  1801. TRUE - Match is a matching suffix of FileName.
  1802. FALSE - Mismatch.
  1803. --*/
  1804. {
  1805. LPSTR pF, pM;
  1806. pF = FileName+strlen(FileName)-1;
  1807. pM = Match+strlen(Match)-1;
  1808. while (pF >= FileName && pM >= Match) {
  1809. int chF, chM;
  1810. chF = tolower(*pF);
  1811. chF = chF == '\\' ? '/' : chF;
  1812. chM = tolower(*pM);
  1813. chM = chM == '\\' ? '/' : chM;
  1814. if (chF != chM) {
  1815. break;
  1816. }
  1817. pF--;
  1818. pM--;
  1819. }
  1820. if (FileNameStop != NULL) {
  1821. *FileNameStop = pF;
  1822. }
  1823. if (MatchStop != NULL) {
  1824. *MatchStop = pM;
  1825. }
  1826. return pM < Match;
  1827. }
  1828. BOOL
  1829. IMAGEAPI
  1830. SymRegisterFunctionEntryCallback(
  1831. IN HANDLE hProcess,
  1832. IN PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction,
  1833. IN PVOID UserContext
  1834. )
  1835. /*++
  1836. Routine Description:
  1837. Set the address of a callback routine to access extended function
  1838. table entries directly. This function is useful when debugging
  1839. Alpha processes where RUNTIME_FUNCTION_ENTRYs are available from
  1840. sources other than in the image. Two existing examples are:
  1841. 1) Access to dynamic function tables for run-time code
  1842. 2) Access to function tables for ROM images
  1843. Arguments:
  1844. hProcess - Process handle, must have been previously registered
  1845. with SymInitialize.
  1846. DirectFunctionTableRoutine - Address of direct function table callback routine.
  1847. On alpha this routine must return a pointer to the
  1848. RUNTIME_FUNCTION_ENTRY containing the specified address.
  1849. If no such entry is available, it must return NULL.
  1850. Return Value:
  1851. TRUE - The callback was successfully registered
  1852. FALSE - The initialization failed. Most likely failure is that
  1853. the hProcess parameter is invalid. Call GetLastError()
  1854. for specific error codes.
  1855. --*/
  1856. {
  1857. PPROCESS_ENTRY pe = NULL;
  1858. __try {
  1859. if (!CallbackFunction) {
  1860. SetLastError(ERROR_INVALID_PARAMETER);
  1861. return FALSE;
  1862. }
  1863. pe = FindProcessEntry( hProcess );
  1864. if (!pe) {
  1865. SetLastError(ERROR_INVALID_PARAMETER);
  1866. return FALSE;
  1867. }
  1868. pe->pFunctionEntryCallback32 = CallbackFunction;
  1869. pe->pFunctionEntryCallback64 = NULL;
  1870. pe->FunctionEntryUserContext = (ULONG64)UserContext;
  1871. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1872. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1873. return FALSE;
  1874. }
  1875. return TRUE;
  1876. }
  1877. BOOL
  1878. IMAGEAPI
  1879. SymRegisterFunctionEntryCallback64(
  1880. IN HANDLE hProcess,
  1881. IN PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction,
  1882. IN ULONG64 UserContext
  1883. )
  1884. /*++
  1885. Routine Description:
  1886. See SymRegisterFunctionEntryCallback64
  1887. --*/
  1888. {
  1889. PPROCESS_ENTRY pe = NULL;
  1890. __try {
  1891. if (!CallbackFunction) {
  1892. SetLastError(ERROR_INVALID_PARAMETER);
  1893. return FALSE;
  1894. }
  1895. pe = FindProcessEntry( hProcess );
  1896. if (!pe) {
  1897. SetLastError(ERROR_INVALID_PARAMETER);
  1898. return FALSE;
  1899. }
  1900. pe->pFunctionEntryCallback32 = NULL;
  1901. pe->pFunctionEntryCallback64 = CallbackFunction;
  1902. pe->FunctionEntryUserContext = (ULONG64)UserContext;
  1903. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1904. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1905. return FALSE;
  1906. }
  1907. return TRUE;
  1908. }
  1909. LPVOID
  1910. IMAGEAPI
  1911. SymFunctionTableAccess(
  1912. HANDLE hProcess,
  1913. DWORD AddrBase
  1914. )
  1915. {
  1916. return SymFunctionTableAccess64(hProcess, EXTEND64(AddrBase));
  1917. }
  1918. LPVOID
  1919. IMAGEAPI
  1920. SymFunctionTableAccess64(
  1921. HANDLE hProcess,
  1922. DWORD64 AddrBase
  1923. )
  1924. /*++
  1925. Routine Description:
  1926. This function finds a function table entry or FPO record for an address.
  1927. Arguments:
  1928. hProcess - Process handle, must have been previously registered
  1929. with SymInitialize.
  1930. AddrBase - Supplies an address for which a function table entry
  1931. or FPO entry is to be located.
  1932. Return Value:
  1933. Non NULL pointer - The symbol was located.
  1934. NULL pointer - The symbol was not found. Call GetLastError to
  1935. discover the cause of the failure.
  1936. --*/
  1937. {
  1938. PPROCESS_ENTRY pe;
  1939. PMODULE_ENTRY mi;
  1940. PVOID rtf;
  1941. ULONG_PTR rva;
  1942. DWORD bias;
  1943. DWORD MachineType;
  1944. __try {
  1945. pe = FindProcessEntry( hProcess );
  1946. if (!pe) {
  1947. SetLastError( ERROR_INVALID_HANDLE );
  1948. return NULL;
  1949. }
  1950. // Dynamically generated function table entries
  1951. // may not be in a module, so failing to
  1952. // find a module is not a fatal error.
  1953. mi = GetModuleForPC( pe, AddrBase, FALSE );
  1954. if (mi != NULL) {
  1955. if (!LoadSymbols(hProcess, mi, 0)) {
  1956. SetLastError( ERROR_MOD_NOT_FOUND );
  1957. return NULL;
  1958. }
  1959. MachineType = mi->MachineType;
  1960. } else {
  1961. // We need to guess what kind of machine we
  1962. // should be working with. First see if ntdll
  1963. // is loaded and if so use its machine type.
  1964. mi = FindModule(hProcess, pe, "ntdll", TRUE);
  1965. if (mi != NULL) {
  1966. MachineType = mi->MachineType;
  1967. } else if (pe->ModuleList.Flink != NULL) {
  1968. // Try the first module's type.
  1969. mi = CONTAINING_RECORD( pe->ModuleList.Flink,
  1970. MODULE_ENTRY, ListEntry );
  1971. } else {
  1972. // Use the complation machine.
  1973. #if defined(_M_IX86)
  1974. MachineType = IMAGE_FILE_MACHINE_I386;
  1975. #elif defined(_M_IA64)
  1976. MachineType = IMAGE_FILE_MACHINE_IA64;
  1977. #elif defined(_M_AXP64)
  1978. MachineType = IMAGE_FILE_MACHINE_AXP64;
  1979. #elif defined(_M_ALPHA)
  1980. MachineType = IMAGE_FILE_MACHINE_ALPHA;
  1981. #elif defined(_M_AMD64)
  1982. MachineType = IMAGE_FILE_MACHINE_AMD64;
  1983. #else
  1984. #error( "unknown target machine" );
  1985. #endif
  1986. }
  1987. }
  1988. switch (MachineType) {
  1989. default:
  1990. rtf = NULL;
  1991. break;
  1992. case IMAGE_FILE_MACHINE_I386:
  1993. rtf = NULL;
  1994. if (mi == NULL) {
  1995. SetLastError( ERROR_MOD_NOT_FOUND );
  1996. break;
  1997. }
  1998. DWORD64 caddr;
  1999. if (!mi->pFpoData)
  2000. break;
  2001. caddr = ConvertOmapToSrc( mi, AddrBase, &bias, TRUE );
  2002. if (caddr)
  2003. AddrBase = caddr + bias;
  2004. rtf = SwSearchFpoData( (ULONG)(AddrBase - mi->BaseOfDll), mi->pFpoData, mi->dwEntries );
  2005. if (rtf && mi->cOmapFrom && mi->pFpoDataOmap) {
  2006. rva = (ULONG_PTR)rtf - (ULONG_PTR)mi->pFpoData;
  2007. rtf = (PBYTE)mi->pFpoDataOmap + rva;
  2008. }
  2009. break;
  2010. case IMAGE_FILE_MACHINE_ALPHA:
  2011. rtf = LookupFunctionEntryAxp32(hProcess, (DWORD)AddrBase);
  2012. break;
  2013. case IMAGE_FILE_MACHINE_IA64:
  2014. rtf = LookupFunctionEntryIa64(hProcess, AddrBase);
  2015. break;
  2016. case IMAGE_FILE_MACHINE_AXP64:
  2017. rtf = LookupFunctionEntryAxp64(hProcess, AddrBase);
  2018. break;
  2019. case IMAGE_FILE_MACHINE_AMD64:
  2020. rtf = LookupFunctionEntryAmd64(hProcess, AddrBase);
  2021. break;
  2022. }
  2023. if (!rtf) {
  2024. SetLastError( ERROR_INVALID_ADDRESS );
  2025. return NULL;
  2026. }
  2027. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2028. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2029. return NULL;
  2030. }
  2031. return rtf;
  2032. }
  2033. BOOL
  2034. IMAGEAPI
  2035. SymGetModuleInfo64(
  2036. IN HANDLE hProcess,
  2037. IN DWORD64 dwAddr,
  2038. OUT PIMAGEHLP_MODULE64 ModuleInfo
  2039. )
  2040. {
  2041. PPROCESS_ENTRY pe;
  2042. PMODULE_ENTRY mi;
  2043. DWORD SizeOfStruct;
  2044. __try {
  2045. pe = FindProcessEntry( hProcess );
  2046. if (!pe) {
  2047. SetLastError( ERROR_INVALID_HANDLE );
  2048. return FALSE;
  2049. }
  2050. mi = GetModuleForPC( pe, dwAddr, FALSE );
  2051. if (mi == NULL) {
  2052. SetLastError( ERROR_MOD_NOT_FOUND );
  2053. return FALSE;
  2054. }
  2055. SizeOfStruct = ModuleInfo->SizeOfStruct;
  2056. if (SizeOfStruct > sizeof(IMAGEHLP_MODULE64)) {
  2057. SetLastError( ERROR_INVALID_PARAMETER );
  2058. return FALSE;
  2059. }
  2060. ZeroMemory( ModuleInfo, SizeOfStruct);
  2061. ModuleInfo->SizeOfStruct = SizeOfStruct;
  2062. ModuleInfo->BaseOfImage = mi->BaseOfDll;
  2063. ModuleInfo->ImageSize = mi->DllSize;
  2064. ModuleInfo->NumSyms = mi->numsyms;
  2065. ModuleInfo->CheckSum = mi->CheckSum;
  2066. ModuleInfo->TimeDateStamp = mi->TimeDateStamp;
  2067. ModuleInfo->SymType = mi->SymType;
  2068. ModuleInfo->ModuleName[0] = 0;
  2069. strncat( ModuleInfo->ModuleName, mi->ModuleName,
  2070. sizeof(ModuleInfo->ModuleName) - 1 );
  2071. if (mi->ImageName) {
  2072. strcpy( ModuleInfo->ImageName, mi->ImageName );
  2073. }
  2074. if (mi->LoadedImageName) {
  2075. strcpy( ModuleInfo->LoadedImageName, mi->LoadedImageName );
  2076. }
  2077. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2078. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2079. return FALSE;
  2080. }
  2081. return TRUE;
  2082. }
  2083. BOOL
  2084. IMAGEAPI
  2085. SymGetModuleInfoW(
  2086. IN HANDLE hProcess,
  2087. IN DWORD dwAddr,
  2088. OUT PIMAGEHLP_MODULEW wModInfo
  2089. )
  2090. {
  2091. IMAGEHLP_MODULE aModInfo;
  2092. if (wModInfo->SizeOfStruct != sizeof(IMAGEHLP_MODULEW)) {
  2093. SetLastError(ERROR_INVALID_PARAMETER);
  2094. return FALSE;
  2095. }
  2096. ZeroMemory(wModInfo, sizeof(IMAGEHLP_MODULEW));
  2097. wModInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULEW);
  2098. if (!SympConvertUnicodeModule32ToAnsiModule32(
  2099. wModInfo, &aModInfo))
  2100. {
  2101. SetLastError(ERROR_INVALID_PARAMETER);
  2102. return FALSE;
  2103. }
  2104. if (!SymGetModuleInfo(hProcess, dwAddr, &aModInfo)) {
  2105. return FALSE;
  2106. }
  2107. if (!SympConvertAnsiModule32ToUnicodeModule32(
  2108. &aModInfo, wModInfo)) {
  2109. return FALSE;
  2110. }
  2111. return TRUE;
  2112. }
  2113. BOOL
  2114. IMAGEAPI
  2115. SymGetModuleInfoW64(
  2116. IN HANDLE hProcess,
  2117. IN DWORD64 dwAddr,
  2118. OUT PIMAGEHLP_MODULEW64 wModInfo
  2119. )
  2120. {
  2121. IMAGEHLP_MODULE64 aModInfo;
  2122. if (!SympConvertUnicodeModule64ToAnsiModule64(
  2123. wModInfo, &aModInfo)) {
  2124. return FALSE;
  2125. }
  2126. if (!SymGetModuleInfo64(hProcess, dwAddr, &aModInfo)) {
  2127. return FALSE;
  2128. }
  2129. if (!SympConvertAnsiModule64ToUnicodeModule64(
  2130. &aModInfo, wModInfo)) {
  2131. return FALSE;
  2132. }
  2133. return TRUE;
  2134. }
  2135. BOOL
  2136. IMAGEAPI
  2137. SymGetModuleInfo(
  2138. IN HANDLE hProcess,
  2139. IN DWORD dwAddr,
  2140. OUT PIMAGEHLP_MODULE ModuleInfo
  2141. )
  2142. {
  2143. PPROCESS_ENTRY pe;
  2144. PMODULE_ENTRY mi;
  2145. DWORD SizeOfStruct;
  2146. __try {
  2147. pe = FindProcessEntry( hProcess );
  2148. if (!pe) {
  2149. SetLastError( ERROR_INVALID_HANDLE );
  2150. return FALSE;
  2151. }
  2152. mi = GetModuleForPC( pe,
  2153. dwAddr == (DWORD)-1 ? (DWORD64)-1 : dwAddr, FALSE );
  2154. if (mi == NULL) {
  2155. SetLastError( ERROR_MOD_NOT_FOUND );
  2156. return FALSE;
  2157. }
  2158. SizeOfStruct = ModuleInfo->SizeOfStruct;
  2159. if (SizeOfStruct > sizeof(IMAGEHLP_MODULE)) {
  2160. SetLastError( ERROR_INVALID_PARAMETER );
  2161. return FALSE;
  2162. }
  2163. ZeroMemory( ModuleInfo, SizeOfStruct);
  2164. ModuleInfo->SizeOfStruct = SizeOfStruct;
  2165. ModuleInfo->BaseOfImage = (DWORD)mi->BaseOfDll;
  2166. ModuleInfo->ImageSize = mi->DllSize;
  2167. ModuleInfo->NumSyms = mi->numsyms;
  2168. ModuleInfo->CheckSum = mi->CheckSum;
  2169. ModuleInfo->TimeDateStamp = mi->TimeDateStamp;
  2170. ModuleInfo->SymType = mi->SymType;
  2171. ModuleInfo->ModuleName[0] = 0;
  2172. strncat( ModuleInfo->ModuleName, mi->ModuleName,
  2173. sizeof(ModuleInfo->ModuleName) - 1 );
  2174. if (mi->ImageName) {
  2175. strcpy( ModuleInfo->ImageName, mi->ImageName );
  2176. }
  2177. if (mi->LoadedImageName) {
  2178. strcpy( ModuleInfo->LoadedImageName, mi->LoadedImageName );
  2179. }
  2180. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2181. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2182. return FALSE;
  2183. }
  2184. return TRUE;
  2185. }
  2186. DWORD64
  2187. IMAGEAPI
  2188. SymGetModuleBase64(
  2189. IN HANDLE hProcess,
  2190. IN DWORD64 dwAddr
  2191. )
  2192. {
  2193. PPROCESS_ENTRY pe;
  2194. PMODULE_ENTRY mi;
  2195. __try {
  2196. pe = FindProcessEntry( hProcess );
  2197. if (!pe) {
  2198. return 0;
  2199. }
  2200. mi = GetModuleForPC( pe, dwAddr, FALSE );
  2201. if (mi == NULL) {
  2202. return 0;
  2203. }
  2204. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2205. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2206. return FALSE;
  2207. }
  2208. return mi->BaseOfDll;
  2209. }
  2210. DWORD
  2211. IMAGEAPI
  2212. SymGetModuleBase(
  2213. IN HANDLE hProcess,
  2214. IN DWORD dwAddr
  2215. )
  2216. {
  2217. return (ULONG)SymGetModuleBase64(hProcess, dwAddr);
  2218. }
  2219. BOOL
  2220. IMAGEAPI
  2221. SymUnloadModule64(
  2222. IN HANDLE hProcess,
  2223. IN DWORD64 BaseOfDll
  2224. )
  2225. /*++
  2226. Routine Description:
  2227. Remove the symbols for an image from a process' symbol table.
  2228. Arguments:
  2229. hProcess - Supplies the token which refers to the process
  2230. BaseOfDll - Supplies the offset to the image as supplies by the
  2231. LOAD_DLL_DEBUG_EVENT and UNLOAD_DLL_DEBUG_EVENT.
  2232. Return Value:
  2233. Returns TRUE if the module's symbols were successfully unloaded.
  2234. Returns FALSE if the symbol handler does not recognize hProcess or
  2235. no image was loaded at the given offset.
  2236. --*/
  2237. {
  2238. PPROCESS_ENTRY pe;
  2239. PLIST_ENTRY next;
  2240. PMODULE_ENTRY mi;
  2241. __try {
  2242. pe = FindProcessEntry(hProcess);
  2243. if (!pe) {
  2244. return FALSE;
  2245. }
  2246. next = pe->ModuleList.Flink;
  2247. if (next) {
  2248. while (next != &pe->ModuleList) {
  2249. mi = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
  2250. if (mi->BaseOfDll == BaseOfDll) {
  2251. RemoveEntryList(next);
  2252. FreeModuleEntry(pe, mi);
  2253. ZeroMemory(pe->DiaCache, sizeof(pe->DiaCache));
  2254. ZeroMemory(pe->DiaLargeData, sizeof(pe->DiaLargeData));
  2255. return TRUE;
  2256. }
  2257. next = mi->ListEntry.Flink;
  2258. }
  2259. }
  2260. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2261. ImagepSetLastErrorFromStatus(GetExceptionCode());
  2262. return FALSE;
  2263. }
  2264. return FALSE;
  2265. }
  2266. BOOL
  2267. IMAGEAPI
  2268. SymUnloadModule(
  2269. IN HANDLE hProcess,
  2270. IN DWORD BaseOfDll
  2271. )
  2272. {
  2273. return SymUnloadModule64(hProcess, BaseOfDll);
  2274. }
  2275. DWORD64
  2276. IMAGEAPI
  2277. SymLoadModuleEx(
  2278. IN HANDLE hProcess,
  2279. IN HANDLE hFile,
  2280. IN PSTR ImageName,
  2281. IN PSTR ModuleName,
  2282. IN DWORD64 BaseOfDll,
  2283. IN DWORD DllSize,
  2284. IN PMODLOAD_DATA Data,
  2285. IN DWORD Flags
  2286. )
  2287. /*++
  2288. Routine Description:
  2289. Loads the symbols for an image for use by the other Sym functions.
  2290. Arguments:
  2291. hProcess - Supplies unique process identifier.
  2292. hFile -
  2293. ImageName - Supplies the name of the image file.
  2294. ModuleName - ???? Supplies the module name that will be returned by
  2295. enumeration functions ????
  2296. BaseOfDll - Supplies loaded base address of image.
  2297. DllSize
  2298. Return Value:
  2299. --*/
  2300. {
  2301. __try {
  2302. return InternalLoadModule( hProcess, ImageName, ModuleName, BaseOfDll, DllSize, hFile, Data, Flags );
  2303. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2304. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2305. return 0;
  2306. }
  2307. }
  2308. DWORD64
  2309. IMAGEAPI
  2310. SymLoadModule64(
  2311. IN HANDLE hProcess,
  2312. IN HANDLE hFile,
  2313. IN PSTR ImageName,
  2314. IN PSTR ModuleName,
  2315. IN DWORD64 BaseOfDll,
  2316. IN DWORD DllSize
  2317. )
  2318. {
  2319. return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, DllSize, NULL, 0);
  2320. }
  2321. DWORD
  2322. IMAGEAPI
  2323. SymLoadModule(
  2324. IN HANDLE hProcess,
  2325. IN HANDLE hFile,
  2326. IN PSTR ImageName,
  2327. IN PSTR ModuleName,
  2328. IN DWORD BaseOfDll,
  2329. IN DWORD DllSize
  2330. )
  2331. {
  2332. return (DWORD)SymLoadModule64( hProcess, hFile, ImageName, ModuleName, BaseOfDll, DllSize );
  2333. }
  2334. BOOL
  2335. IMAGEAPI
  2336. SymUnDName(
  2337. IN PIMAGEHLP_SYMBOL sym,
  2338. OUT LPSTR UnDecName,
  2339. OUT DWORD UnDecNameLength
  2340. )
  2341. {
  2342. __try {
  2343. if (SymUnDNameInternal( UnDecName,
  2344. UnDecNameLength-1,
  2345. sym->Name,
  2346. strlen(sym->Name),
  2347. IMAGE_FILE_MACHINE_UNKNOWN,
  2348. TRUE )) {
  2349. return TRUE;
  2350. } else {
  2351. return FALSE;
  2352. }
  2353. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2354. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2355. return FALSE;
  2356. }
  2357. }
  2358. BOOL
  2359. IMAGEAPI
  2360. SymUnDName64(
  2361. IN PIMAGEHLP_SYMBOL64 sym,
  2362. OUT LPSTR UnDecName,
  2363. OUT DWORD UnDecNameLength
  2364. )
  2365. {
  2366. __try {
  2367. if (SymUnDNameInternal( UnDecName,
  2368. UnDecNameLength-1,
  2369. sym->Name,
  2370. strlen(sym->Name),
  2371. IMAGE_FILE_MACHINE_UNKNOWN,
  2372. TRUE )) {
  2373. return TRUE;
  2374. } else {
  2375. return FALSE;
  2376. }
  2377. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2378. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2379. return FALSE;
  2380. }
  2381. }
  2382. BOOL
  2383. IMAGEAPI
  2384. SymGetSearchPath(
  2385. IN HANDLE hProcess,
  2386. OUT LPSTR SearchPath,
  2387. IN DWORD SearchPathLength
  2388. )
  2389. /*++
  2390. Routine Description:
  2391. This function looks up the symbol search path associated with a process.
  2392. Arguments:
  2393. hProcess - Supplies the token associated with a process.
  2394. Return Value:
  2395. A pointer to the search path. Returns NULL if the process is not
  2396. know to the symbol handler.
  2397. --*/
  2398. {
  2399. PPROCESS_ENTRY pe;
  2400. __try {
  2401. pe = FindProcessEntry( hProcess );
  2402. if (!pe) {
  2403. return FALSE;
  2404. }
  2405. SearchPath[0] = 0;
  2406. strncat( SearchPath, pe->SymbolSearchPath, SearchPathLength );
  2407. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2408. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2409. return FALSE;
  2410. }
  2411. return TRUE;
  2412. }
  2413. BOOL
  2414. IMAGEAPI
  2415. SymSetSearchPath(
  2416. HANDLE hProcess,
  2417. LPSTR UserSearchPath
  2418. )
  2419. /*++
  2420. Routine Description:
  2421. This functions sets the searh path to be used by the symbol loader
  2422. for the given process. If UserSearchPath is not supplied, a default
  2423. path will be used.
  2424. Arguments:
  2425. hProcess - Supplies the process token associated with a symbol table.
  2426. UserSearchPath - Supplies the new search path to associate with the
  2427. process. If this argument is NULL, the following path is generated:
  2428. .;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%
  2429. It is ok if any or all of the environment variables is missing.
  2430. Return Value:
  2431. A pointer to the new search path. The user should not modify this string.
  2432. Returns NULL if the process is not known to the symbol handler.
  2433. --*/
  2434. {
  2435. PPROCESS_ENTRY pe;
  2436. LPSTR p;
  2437. DWORD cbSymPath;
  2438. DWORD cb;
  2439. char ExpandedSearchPath[MAX_PATH];
  2440. __try {
  2441. pe = FindProcessEntry( hProcess );
  2442. if (!pe) {
  2443. return FALSE;
  2444. }
  2445. if (pe->SymbolSearchPath) {
  2446. MemFree(pe->SymbolSearchPath);
  2447. }
  2448. if (UserSearchPath) {
  2449. cbSymPath = ExpandEnvironmentStrings(UserSearchPath,
  2450. ExpandedSearchPath,
  2451. sizeof(ExpandedSearchPath) / sizeof(ExpandedSearchPath[0]));
  2452. if (cbSymPath < sizeof(ExpandedSearchPath)/sizeof(ExpandedSearchPath[0])) {
  2453. pe->SymbolSearchPath = StringDup(ExpandedSearchPath);
  2454. } else {
  2455. pe->SymbolSearchPath = (LPSTR)MemAlloc( cbSymPath );
  2456. ExpandEnvironmentStrings(UserSearchPath,
  2457. pe->SymbolSearchPath,
  2458. cbSymPath );
  2459. }
  2460. } else {
  2461. //
  2462. // ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%
  2463. //
  2464. cbSymPath = 3; // ".;" and ";" between env vars.
  2465. //
  2466. // GetEnvironmentVariable returns the size of the string
  2467. // INCLUDING the '\0' in this case.
  2468. //
  2469. cbSymPath += GetEnvironmentVariable( SYMBOL_PATH, NULL, 0 );
  2470. cbSymPath += GetEnvironmentVariable( ALTERNATE_SYMBOL_PATH, NULL, 0 );
  2471. p = pe->SymbolSearchPath = (LPSTR) MemAlloc( cbSymPath );
  2472. if (!p) {
  2473. return FALSE;
  2474. }
  2475. *p++ = '.';
  2476. --cbSymPath;
  2477. cb = GetEnvironmentVariable(SYMBOL_PATH, p+1, cbSymPath-1);
  2478. if (cb) {
  2479. *p = ';';
  2480. p += cb+1;
  2481. cbSymPath -= cb+1;
  2482. }
  2483. cb = GetEnvironmentVariable(ALTERNATE_SYMBOL_PATH,
  2484. p+1, cbSymPath-1);
  2485. if (cb) {
  2486. *p = ';';
  2487. p += cb+1;
  2488. }
  2489. *p = 0;
  2490. }
  2491. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2492. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2493. return FALSE;
  2494. }
  2495. CloseSymbolServer();
  2496. return TRUE;
  2497. }
  2498. BOOL
  2499. IMAGEAPI
  2500. EnumerateLoadedModules(
  2501. IN HANDLE hProcess,
  2502. IN PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
  2503. IN PVOID UserContext
  2504. )
  2505. {
  2506. LOADED_MODULE lm;
  2507. DWORD status = NO_ERROR;
  2508. __try {
  2509. lm.EnumLoadedModulesCallback32 = EnumLoadedModulesCallback;
  2510. lm.EnumLoadedModulesCallback64 = NULL;
  2511. lm.Context = UserContext;
  2512. status = GetProcessModules( hProcess, (PINTERNAL_GET_MODULE)LoadedModuleEnumerator, (PVOID)&lm );
  2513. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2514. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2515. return FALSE;
  2516. }
  2517. return (status == NO_ERROR);
  2518. }
  2519. BOOL
  2520. IMAGEAPI
  2521. EnumerateLoadedModules64(
  2522. IN HANDLE hProcess,
  2523. IN PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,
  2524. IN PVOID UserContext
  2525. )
  2526. {
  2527. LOADED_MODULE lm;
  2528. DWORD status = NO_ERROR;
  2529. __try {
  2530. lm.EnumLoadedModulesCallback64 = EnumLoadedModulesCallback;
  2531. lm.EnumLoadedModulesCallback32 = NULL;
  2532. lm.Context = UserContext;
  2533. status = GetProcessModules(hProcess,
  2534. (PINTERNAL_GET_MODULE)LoadedModuleEnumerator,
  2535. (PVOID)&lm );
  2536. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2537. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2538. return FALSE;
  2539. }
  2540. return (status == NO_ERROR);
  2541. }
  2542. BOOL
  2543. IMAGEAPI
  2544. SymRegisterCallback(
  2545. IN HANDLE hProcess,
  2546. IN PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
  2547. IN PVOID UserContext
  2548. )
  2549. {
  2550. PPROCESS_ENTRY pe = NULL;
  2551. __try {
  2552. if (!CallbackFunction) {
  2553. SetLastError(ERROR_INVALID_PARAMETER);
  2554. return FALSE;
  2555. }
  2556. pe = FindProcessEntry( hProcess );
  2557. if (!pe) {
  2558. SetLastError(ERROR_INVALID_PARAMETER);
  2559. return FALSE;
  2560. }
  2561. pe->pCallbackFunction32 = CallbackFunction;
  2562. pe->pCallbackFunction64 = NULL;
  2563. pe->CallbackUserContext = (ULONG64)UserContext;
  2564. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2565. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2566. return FALSE;
  2567. }
  2568. return TRUE;
  2569. }
  2570. BOOL
  2571. IMAGEAPI
  2572. SymRegisterCallback64(
  2573. IN HANDLE hProcess,
  2574. IN PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,
  2575. IN ULONG64 UserContext
  2576. )
  2577. {
  2578. PPROCESS_ENTRY pe = NULL;
  2579. __try {
  2580. if (!CallbackFunction) {
  2581. SetLastError(ERROR_INVALID_PARAMETER);
  2582. return FALSE;
  2583. }
  2584. pe = FindProcessEntry( hProcess );
  2585. if (!pe) {
  2586. SetLastError(ERROR_INVALID_PARAMETER);
  2587. return FALSE;
  2588. }
  2589. pe->pCallbackFunction32 = NULL;
  2590. pe->pCallbackFunction64 = CallbackFunction;
  2591. pe->CallbackUserContext = UserContext;
  2592. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2593. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2594. return FALSE;
  2595. }
  2596. return TRUE;
  2597. }
  2598. void
  2599. InitModuleEntry(
  2600. PMODULE_ENTRY mi
  2601. )
  2602. {
  2603. ZeroMemory(mi, sizeof(MODULE_ENTRY));
  2604. mi->si.MaxNameLen = 2048;
  2605. }
  2606. BOOL
  2607. SympConvertAnsiModule32ToUnicodeModule32(
  2608. PIMAGEHLP_MODULE aMod32,
  2609. PIMAGEHLP_MODULEW wMod32
  2610. )
  2611. {
  2612. ZeroMemory(wMod32, sizeof(*wMod32));
  2613. wMod32->SizeOfStruct = sizeof(*wMod32);
  2614. wMod32->BaseOfImage = aMod32->BaseOfImage;
  2615. wMod32->ImageSize = aMod32->ImageSize;
  2616. wMod32->TimeDateStamp = aMod32->TimeDateStamp;
  2617. wMod32->CheckSum = aMod32->CheckSum;
  2618. wMod32->NumSyms = aMod32->NumSyms;
  2619. wMod32->SymType = aMod32->SymType;
  2620. if (!ansi2wcs(aMod32->ModuleName, wMod32->ModuleName, 256))
  2621. return FALSE;
  2622. if (!ansi2wcs(aMod32->ImageName, wMod32->ImageName, 256))
  2623. return FALSE;
  2624. if (!ansi2wcs(aMod32->LoadedImageName, wMod32->LoadedImageName, 256))
  2625. return FALSE;
  2626. return TRUE;
  2627. }
  2628. BOOL
  2629. SympConvertUnicodeModule32ToAnsiModule32(
  2630. PIMAGEHLP_MODULEW wMod32,
  2631. PIMAGEHLP_MODULE aMod32
  2632. )
  2633. {
  2634. ZeroMemory(aMod32, sizeof(*aMod32));
  2635. aMod32->SizeOfStruct = sizeof(*aMod32);
  2636. aMod32->BaseOfImage = wMod32->BaseOfImage;
  2637. aMod32->ImageSize = wMod32->ImageSize;
  2638. aMod32->TimeDateStamp = wMod32->TimeDateStamp;
  2639. aMod32->CheckSum = wMod32->CheckSum;
  2640. aMod32->NumSyms = wMod32->NumSyms;
  2641. aMod32->SymType = wMod32->SymType;
  2642. if (!wcs2ansi(wMod32->ModuleName, aMod32->ModuleName, lengthof(wMod32->ModuleName)))
  2643. return FALSE;
  2644. if (!wcs2ansi(wMod32->ImageName, aMod32->ImageName, lengthof(wMod32->ImageName)))
  2645. return FALSE;
  2646. if (!wcs2ansi(wMod32->LoadedImageName, aMod32->LoadedImageName, lengthof(wMod32->LoadedImageName)))
  2647. return FALSE;
  2648. return TRUE;
  2649. }
  2650. BOOL
  2651. SympConvertAnsiModule64ToUnicodeModule64(
  2652. PIMAGEHLP_MODULE64 aMod64,
  2653. PIMAGEHLP_MODULEW64 wMod64
  2654. )
  2655. {
  2656. ZeroMemory(wMod64, sizeof(*wMod64));
  2657. wMod64->SizeOfStruct = sizeof(*wMod64);
  2658. wMod64->BaseOfImage = aMod64->BaseOfImage;
  2659. wMod64->ImageSize = aMod64->ImageSize;
  2660. wMod64->TimeDateStamp = aMod64->TimeDateStamp;
  2661. wMod64->CheckSum = aMod64->CheckSum;
  2662. wMod64->NumSyms = aMod64->NumSyms;
  2663. wMod64->SymType = aMod64->SymType;
  2664. if (!ansi2wcs(aMod64->ModuleName, wMod64->ModuleName, 256))
  2665. return FALSE;
  2666. if (!ansi2wcs(aMod64->ImageName, wMod64->ImageName, 256))
  2667. return FALSE;
  2668. if (!ansi2wcs(aMod64->LoadedImageName, wMod64->LoadedImageName, 256))
  2669. return FALSE;
  2670. return TRUE;
  2671. }
  2672. BOOL
  2673. SympConvertUnicodeModule64ToAnsiModule64(
  2674. PIMAGEHLP_MODULEW64 wMod64,
  2675. PIMAGEHLP_MODULE64 aMod64
  2676. )
  2677. {
  2678. ZeroMemory(aMod64, sizeof(*aMod64));
  2679. aMod64->SizeOfStruct = sizeof(*aMod64);
  2680. aMod64->BaseOfImage = wMod64->BaseOfImage;
  2681. aMod64->ImageSize = wMod64->ImageSize;
  2682. aMod64->TimeDateStamp = wMod64->TimeDateStamp;
  2683. aMod64->CheckSum = wMod64->CheckSum;
  2684. aMod64->NumSyms = wMod64->NumSyms;
  2685. aMod64->SymType = wMod64->SymType;
  2686. if (!wcs2ansi(wMod64->ModuleName, aMod64->ModuleName, lengthof(wMod64->ModuleName)))
  2687. return FALSE;
  2688. if (!wcs2ansi(wMod64->ImageName, aMod64->ImageName, lengthof(wMod64->ImageName)))
  2689. return FALSE;
  2690. if (!wcs2ansi(wMod64->LoadedImageName, aMod64->LoadedImageName, lengthof(wMod64->LoadedImageName)))
  2691. return FALSE;
  2692. return TRUE;
  2693. }
  2694. BOOL
  2695. CopySymbolEntryFromSymbolInfo(
  2696. PSYMBOL_ENTRY se,
  2697. PSYMBOL_INFO si
  2698. )
  2699. {
  2700. se->Size = si->SizeOfStruct;
  2701. se->Flags = si->Flags;
  2702. se->Address = si->Address;
  2703. if (si->Name && se->Name)
  2704. strcpy(se->Name, si->Name);
  2705. se->NameLength = si->NameLen;
  2706. // segment is not used
  2707. // offset is not used
  2708. se->TypeIndex = si->TypeIndex;
  2709. se->ModBase = si->ModBase;
  2710. se->Register = si->Register;
  2711. if (si->Register) {
  2712. ((LARGE_INTEGER *) &se->Address)->HighPart = si->Register;
  2713. }
  2714. return TRUE;
  2715. }
  2716. BOOL
  2717. IMAGEAPI
  2718. SymFromAddr(
  2719. IN HANDLE hProcess,
  2720. IN DWORD64 Address,
  2721. OUT PDWORD64 Displacement,
  2722. IN OUT PSYMBOL_INFO Symbol
  2723. )
  2724. {
  2725. SYMBOL_ENTRY SymEntry={0};
  2726. if (SympGetSymFromAddr(hProcess, Address, Displacement, &SymEntry)) {
  2727. symcpy2(Symbol, &SymEntry);
  2728. return TRUE;
  2729. } else {
  2730. return FALSE;
  2731. }
  2732. }
  2733. BOOL
  2734. IMAGEAPI
  2735. SymFromName(
  2736. IN HANDLE hProcess,
  2737. IN LPSTR Name,
  2738. OUT PSYMBOL_INFO Symbol
  2739. )
  2740. {
  2741. SYMBOL_ENTRY sym;
  2742. if (SympGetSymFromName(hProcess, Name, &sym)) {
  2743. symcpy2(Symbol, &sym);
  2744. return TRUE;
  2745. } else {
  2746. return FALSE;
  2747. }
  2748. }
  2749. BOOL
  2750. IMAGEAPI
  2751. SymEnumSymbols(
  2752. IN HANDLE hProcess,
  2753. IN ULONG64 BaseOfDll,
  2754. IN PCSTR Mask,
  2755. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  2756. IN PVOID UserContext
  2757. )
  2758. {
  2759. return SympEnumerateSymbols(hProcess,
  2760. BaseOfDll,
  2761. (LPSTR)Mask,
  2762. (PROC) EnumSymbolsCallback,
  2763. UserContext,
  2764. FALSE,
  2765. FALSE);
  2766. }
  2767. BOOL
  2768. IMAGEAPI
  2769. SymEnumSym(
  2770. IN HANDLE hProcess,
  2771. IN ULONG64 BaseOfDll,
  2772. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  2773. IN PVOID UserContext
  2774. )
  2775. {
  2776. return SymEnumSymbols(hProcess,
  2777. BaseOfDll,
  2778. NULL,
  2779. EnumSymbolsCallback,
  2780. UserContext);
  2781. }
  2782. BOOL
  2783. IMAGEAPI
  2784. SymEnumTypes(
  2785. IN HANDLE hProcess,
  2786. IN ULONG64 BaseOfDll,
  2787. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  2788. IN PVOID UserContext
  2789. )
  2790. {
  2791. PPROCESS_ENTRY pe;
  2792. PLIST_ENTRY Next;
  2793. PMODULE_ENTRY mi;
  2794. pe = FindProcessEntry( hProcess );
  2795. if (!pe) {
  2796. SetLastError( ERROR_INVALID_HANDLE );
  2797. return FALSE;
  2798. }
  2799. mi = NULL;
  2800. Next = pe->ModuleList.Flink;
  2801. if (Next) {
  2802. while (Next != &pe->ModuleList) {
  2803. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  2804. if (!mi)
  2805. break;
  2806. Next = mi->ListEntry.Flink;
  2807. if (mi->BaseOfDll == BaseOfDll)
  2808. break;
  2809. }
  2810. }
  2811. if (!mi) {
  2812. return FALSE;
  2813. }
  2814. return diaEnumUDT(mi, "", EnumSymbolsCallback, UserContext);
  2815. }
  2816. BOOL
  2817. IMAGEAPI
  2818. SymGetTypeFromName(
  2819. IN HANDLE hProcess,
  2820. IN ULONG64 BaseOfDll,
  2821. IN LPSTR Name,
  2822. OUT PSYMBOL_INFO Symbol
  2823. )
  2824. {
  2825. PPROCESS_ENTRY pe;
  2826. PLIST_ENTRY Next;
  2827. PMODULE_ENTRY mi;
  2828. pe = FindProcessEntry( hProcess );
  2829. if (!pe) {
  2830. SetLastError( ERROR_INVALID_HANDLE );
  2831. return FALSE;
  2832. }
  2833. mi = NULL;
  2834. Next = pe->ModuleList.Flink;
  2835. if (Next) {
  2836. while (Next != &pe->ModuleList) {
  2837. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  2838. if (!mi)
  2839. break;
  2840. Next = mi->ListEntry.Flink;
  2841. if (mi->BaseOfDll == BaseOfDll)
  2842. break;
  2843. }
  2844. }
  2845. if (!mi || mi->BaseOfDll != BaseOfDll) {
  2846. LPSTR p;
  2847. // first check for fully qualified symbol name I.E. mod!sym
  2848. p = strchr( Name, '!' );
  2849. if (p > Name) {
  2850. LPSTR ModName = (LPSTR)MemAlloc(p - Name + 1);
  2851. if (!ModName) {
  2852. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  2853. return FALSE;
  2854. }
  2855. memcpy(ModName, Name, (int)(p - Name));
  2856. ModName[p-Name] = 0;
  2857. //
  2858. // the caller wants to look in a specific module
  2859. //
  2860. mi = FindModule(hProcess, pe, ModName, TRUE);
  2861. MemFree(ModName);
  2862. if (mi == NULL) {
  2863. return FALSE;
  2864. }
  2865. Name = p+1;
  2866. }
  2867. }
  2868. if (diaGetTiForUDT(mi, Name, Symbol)) {
  2869. return TRUE;
  2870. } else {
  2871. return FALSE;
  2872. }
  2873. return FALSE;
  2874. }
  2875. BOOL
  2876. strcmpre(
  2877. LPSTR pStr,
  2878. LPSTR pRE,
  2879. BOOL fCase
  2880. )
  2881. {
  2882. DWORD rc;
  2883. CHAR sz[MAX_SYM_NAME + 2];
  2884. PWSTR wStr = NULL;
  2885. PWSTR wRE = NULL;
  2886. rc = TRUE;
  2887. wStr = AnsiToUnicode(pStr);
  2888. if (!wStr)
  2889. goto exit;;
  2890. wRE = AnsiToUnicode(pRE);
  2891. if (!wRE)
  2892. goto exit;
  2893. rc = CompareRE(wStr, wRE, fCase);
  2894. if (rc == S_OK)
  2895. rc = FALSE;
  2896. else
  2897. rc = TRUE;
  2898. exit:
  2899. if (wStr) MemFree(wStr);
  2900. if (wRE) MemFree(wRE);
  2901. return (BOOL)rc;
  2902. }
  2903. BOOL
  2904. IMAGEAPI
  2905. SymMatchString(
  2906. IN LPSTR string,
  2907. IN LPSTR expression,
  2908. IN BOOL fCase
  2909. )
  2910. {
  2911. return !strcmpre(string, expression, fCase);
  2912. }
  2913. BOOL
  2914. SymEnumSourceFiles(
  2915. IN HANDLE hProcess,
  2916. IN ULONG64 ModBase,
  2917. IN LPSTR Mask,
  2918. IN PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,
  2919. IN PVOID UserContext
  2920. )
  2921. {
  2922. PPROCESS_ENTRY pe;
  2923. PLIST_ENTRY Next;
  2924. PMODULE_ENTRY mi;
  2925. DWORD i;
  2926. PSYMBOL_ENTRY sym;
  2927. LPSTR szSymName;
  2928. SYMBOL_ENTRY SymEntry={0};
  2929. CHAR Buffer[2500];
  2930. LPSTR p;
  2931. CHAR modmask[200];
  2932. BOOL rc;
  2933. int pass;
  2934. BOOL fCase;
  2935. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED | LS_FAIL_IF_LOADED};
  2936. if (!cbSrcFiles) {
  2937. SetLastError(ERROR_INVALID_PARAMETER);
  2938. return FALSE;
  2939. }
  2940. __try {
  2941. pe = FindProcessEntry(hProcess);
  2942. if (!pe) {
  2943. SetLastError( ERROR_INVALID_HANDLE );
  2944. return FALSE;
  2945. }
  2946. p = 0;
  2947. modmask[0] = 0;
  2948. if (Mask)
  2949. p = strchr(Mask, '!');
  2950. if (p > Mask) {
  2951. memcpy(modmask, Mask, (int)(p - Mask));
  2952. modmask[p-Mask] = 0;
  2953. Mask = p + 1;
  2954. }
  2955. for (pass = 0; pass < 2; pass++) {
  2956. Next = pe->ModuleList.Flink;
  2957. if (Next) {
  2958. while (Next != &pe->ModuleList) {
  2959. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  2960. Next = mi->ListEntry.Flink;
  2961. if (ModBase) {
  2962. if (mi->BaseOfDll != ModBase)
  2963. continue;
  2964. } else if (!MatchModuleName(mi, modmask)) {
  2965. continue;
  2966. }
  2967. if (!LoadSymbols(hProcess, mi, flags[pass]))
  2968. continue;
  2969. if (mi->dia) {
  2970. rc = diaEnumSourceFiles(mi, Mask, cbSrcFiles, UserContext);
  2971. if (!rc) {
  2972. if (mi->code == ERROR_CANCELLED) {
  2973. mi->code = 0;
  2974. return TRUE;
  2975. }
  2976. return rc;
  2977. }
  2978. continue;
  2979. }
  2980. #if 0
  2981. fCase = (g.SymOptions & SYMOPT_CASE_INSENSITIVE) ? FALSE : TRUE;
  2982. for (i = 0; i < mi->numsyms; i++) {
  2983. PSYMBOL_INFO SymInfo = (PSYMBOL_INFO) &Buffer[0];
  2984. sym = &mi->symbolTable[i];
  2985. if (Mask && *Mask && strcmpre(sym->Name, Mask, fCase))
  2986. continue;
  2987. }
  2988. #endif
  2989. }
  2990. }
  2991. }
  2992. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2993. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2994. return FALSE;
  2995. }
  2996. return TRUE;
  2997. }
  2998. PWSTR
  2999. AnsiToUnicode(
  3000. PSTR pszAnsi
  3001. )
  3002. {
  3003. UINT uSizeUnicode;
  3004. PWSTR pwszUnicode;
  3005. if (!pszAnsi) {
  3006. return NULL;
  3007. }
  3008. uSizeUnicode = (strlen(pszAnsi) + 1) * sizeof(wchar_t);
  3009. pwszUnicode = (PWSTR)MemAlloc(uSizeUnicode);
  3010. if (*pszAnsi && pwszUnicode) {
  3011. ZeroMemory(pwszUnicode, uSizeUnicode);
  3012. if (!MultiByteToWideChar(CP_ACP, MB_COMPOSITE,
  3013. pszAnsi, strlen(pszAnsi),
  3014. pwszUnicode, uSizeUnicode)) {
  3015. // Error. Free the string, return NULL.
  3016. MemFree(pwszUnicode);
  3017. pwszUnicode = NULL;
  3018. }
  3019. }
  3020. return pwszUnicode;
  3021. }
  3022. BOOL
  3023. wcs2ansi(
  3024. PWSTR pwsz,
  3025. PSTR psz,
  3026. DWORD pszlen
  3027. )
  3028. {
  3029. BOOL rc;
  3030. int len;
  3031. assert(psz && pwsz);
  3032. len = wcslen(pwsz);
  3033. if (!len) {
  3034. *psz = 0;
  3035. return TRUE;
  3036. }
  3037. rc = WideCharToMultiByte(CP_ACP,
  3038. WC_SEPCHARS | WC_COMPOSITECHECK,
  3039. pwsz,
  3040. len,
  3041. psz,
  3042. pszlen,
  3043. NULL,
  3044. NULL);
  3045. if (!rc)
  3046. return FALSE;
  3047. psz[len] = 0;
  3048. return TRUE;
  3049. }
  3050. BOOL
  3051. ansi2wcs(
  3052. PSTR psz,
  3053. PWSTR pwsz,
  3054. DWORD pwszlen
  3055. )
  3056. {
  3057. BOOL rc;
  3058. int len;
  3059. assert(psz && pwsz);
  3060. len = strlen(psz);
  3061. if (!len) {
  3062. *pwsz = 0L;
  3063. return TRUE;
  3064. }
  3065. rc = MultiByteToWideChar(CP_ACP,
  3066. MB_COMPOSITE,
  3067. psz,
  3068. len,
  3069. pwsz,
  3070. pwszlen);
  3071. if (!rc)
  3072. return FALSE;
  3073. pwsz[len] = 0;
  3074. return TRUE;
  3075. }
  3076. PSTR
  3077. UnicodeToAnsi(
  3078. PWSTR pwszUnicode
  3079. )
  3080. {
  3081. UINT uSizeAnsi;
  3082. PSTR pszAnsi;
  3083. if (!pwszUnicode) {
  3084. return NULL;
  3085. }
  3086. uSizeAnsi = wcslen(pwszUnicode) + 1;
  3087. pszAnsi = (PSTR)MemAlloc(uSizeAnsi);
  3088. if (*pwszUnicode && pszAnsi) {
  3089. ZeroMemory(pszAnsi, uSizeAnsi);
  3090. if (!WideCharToMultiByte(CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK,
  3091. pwszUnicode, wcslen(pwszUnicode),
  3092. pszAnsi, uSizeAnsi, NULL, NULL)) {
  3093. // Error. Free the string, return NULL.
  3094. free(pszAnsi);
  3095. pszAnsi = NULL;
  3096. }
  3097. }
  3098. return pszAnsi;
  3099. }
  3100. #if 0
  3101. BOOL
  3102. CopyAnsiToUnicode(
  3103. PWSTR pszDest,
  3104. PSTR pszSrc,
  3105. DWORD dwCharCountSizeOfDest
  3106. )
  3107. {
  3108. PWSTR pszTmp = AnsiToUnicode(pszSrc);
  3109. if (!pszTmp) {
  3110. return FALSE;
  3111. } else {
  3112. wcsncpy(pszDest, pszTmp, dwCharCountSizeOfDest);
  3113. return TRUE;
  3114. }
  3115. }
  3116. BOOL
  3117. CopyUnicodeToAnsi(
  3118. PSTR pszDest,
  3119. PWSTR pszSrc,
  3120. DWORD dwCharCountSizeOfDest
  3121. )
  3122. {
  3123. PSTR pszTmp = UnicodeToAnsi(pszSrc);
  3124. if (!pszTmp) {
  3125. return FALSE;
  3126. } else {
  3127. strncpy(pszDest, pszTmp, dwCharCountSizeOfDest);
  3128. return TRUE;
  3129. }
  3130. }
  3131. #endif
  3132. BOOL
  3133. IMAGEAPI
  3134. SymGetTypeInfo(
  3135. IN HANDLE hProcess,
  3136. IN DWORD64 ModBase,
  3137. IN ULONG TypeId,
  3138. IN IMAGEHLP_SYMBOL_TYPE_INFO GetType,
  3139. OUT PVOID pInfo
  3140. )
  3141. {
  3142. HRESULT err;
  3143. err = diaGetSymbolInfo(hProcess, ModBase, TypeId, GetType, pInfo);
  3144. SetLastError((ULONG) err);
  3145. return (err==S_OK);
  3146. }
  3147. //#ifdef _WIN64
  3148. #if 0
  3149. BOOL __cdecl PDBOpenTpi(PDB* ppdb, const char* szMode, TPI** pptpi) {return FALSE;}
  3150. BOOL __cdecl PDBCopyTo(PDB* ppdb, const char* szTargetPdb, DWORD dwCopyFilter, DWORD dwReserved){return FALSE;}
  3151. BOOL __cdecl PDBClose(PDB* ppdb) {return FALSE;}
  3152. BOOL __cdecl ModQueryImod(Mod* pmod, USHORT* pimod) {return FALSE;}
  3153. BOOL __cdecl ModQueryLines(Mod* pmod, BYTE* pbLines, long* pcb) {return FALSE;}
  3154. BOOL __cdecl DBIQueryModFromAddr(DBI* pdbi, USHORT isect, long off, Mod** ppmod, USHORT* pisect, long* poff, long* pcb){return FALSE;}
  3155. BOOL __cdecl ModClose(Mod* pmod){return FALSE;}
  3156. BOOL __cdecl DBIQueryNextMod(DBI* pdbi, Mod* pmod, Mod** ppmodNext) {return FALSE;}
  3157. BYTE* __cdecl GSINextSym (GSI* pgsi, BYTE* pbSym) {return NULL;}
  3158. BOOL __cdecl PDBOpen(char* szPDB,char* szMode,SIG sigInitial,EC* pec,char szError[cbErrMax],PDB** pppdb) {return FALSE;}
  3159. BOOL __cdecl TypesClose(TPI* ptpi){return FALSE;}
  3160. BOOL __cdecl GSIClose(GSI* pgsi){return FALSE;}
  3161. BOOL __cdecl DBIClose(DBI* pdbi){return FALSE;}
  3162. BYTE* __cdecl GSINearestSym (GSI* pgsi, USHORT isect, long off, long* pdisp){return NULL;}
  3163. BOOL __cdecl PDBOpenValidate(char* szPDB,char* szPath,char* szMode,SIG sig,AGE age,EC* pec,char szError[cbErrMax],PDB** pppdb){return FALSE;}
  3164. BOOL __cdecl PDBOpenDBI(PDB* ppdb, const char* szMode, const char* szTarget, DBI** ppdbi){return FALSE;}
  3165. BOOL __cdecl DBIOpenPublics(DBI* pdbi, GSI **ppgsi){return FALSE;}
  3166. BOOL __cdecl DBIQuerySecMap(DBI* pdbi, BYTE* pb, long* pcb){return FALSE;}
  3167. #endif