Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5176 lines
129 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. #if (_WIN32_IE < 0x0400)
  13. #undef _WIN32_IE
  14. #define _WIN32_IE 0x0400
  15. #endif
  16. #include "private.h"
  17. #include "symbols.h"
  18. #include "globals.h"
  19. #include <shlobj.h>
  20. #include <dbhpriv.h>
  21. #include "fecache.hpp"
  22. // common conversion routines
  23. PSYMBOL_ENTRY
  24. si2se(
  25. PSYMBOL_INFO si,
  26. PSYMBOL_ENTRY se
  27. )
  28. {
  29. se->Size = si->SizeOfStruct;
  30. se->Flags = si->Flags;
  31. se->Address = si->Address;
  32. se->Size = si->Size;
  33. if (si->Name)
  34. if (se->Name)
  35. strcpy(se->Name, si->Name); // SECURITY: Don't know size of target buffer.
  36. else
  37. se->Name = si->Name;
  38. se->NameLength = si->NameLen;
  39. // segment is not used
  40. // offset is not used
  41. se->TypeIndex = si->TypeIndex;
  42. se->ModBase = si->ModBase;
  43. se->Register = si->Register;
  44. if (si->Register) {
  45. ((LARGE_INTEGER *) &se->Address)->HighPart = si->Register;
  46. }
  47. return se;
  48. }
  49. PSYMBOL_INFO
  50. se2si(
  51. PSYMBOL_ENTRY se,
  52. PSYMBOL_INFO si
  53. )
  54. {
  55. si->Address = se->Address;
  56. si->Flags = se->Flags;
  57. si->TypeIndex = se->TypeIndex;
  58. si->ModBase = se->ModBase;
  59. si->NameLen = se->NameLength;
  60. si->Size = se->Size;
  61. si->Register = se->Register;
  62. if (se->Name && (strlen(se->Name) < si->MaxNameLen))
  63. CopyString(si->Name, se->Name, si->MaxNameLen);
  64. return si;
  65. }
  66. PIMAGEHLP_SYMBOL
  67. se2sym(
  68. PSYMBOL_ENTRY se,
  69. PIMAGEHLP_SYMBOL sym
  70. )
  71. {
  72. assert(sym);
  73. sym->Address = 0;
  74. *sym->Name = 0;
  75. if (!se)
  76. return sym;
  77. sym->Address = (ULONG)se->Address;
  78. sym->Size = se->Size;
  79. sym->Flags = se->Flags;
  80. CatString(sym->Name, se->Name, sym->MaxNameLength);
  81. return sym;
  82. }
  83. PIMAGEHLP_SYMBOL64
  84. se2lsym(
  85. PSYMBOL_ENTRY se,
  86. PIMAGEHLP_SYMBOL64 lsym
  87. )
  88. {
  89. assert(lsym);
  90. lsym->Address = 0;
  91. *lsym->Name = 0;
  92. if (!se)
  93. return lsym;
  94. lsym->Address = se->Address;
  95. lsym->Size = se->Size;
  96. lsym->Flags = se->Flags;
  97. CatString(lsym->Name, se->Name, lsym->MaxNameLength);
  98. return lsym;
  99. }
  100. PIMAGEHLP_SYMBOL
  101. si2sym(
  102. PSYMBOL_INFO si,
  103. PIMAGEHLP_SYMBOL sym
  104. )
  105. {
  106. assert(sym);
  107. sym->Address = 0;
  108. *sym->Name = 0;
  109. if (!si)
  110. return sym;
  111. sym->Address = (ULONG)si->Address;
  112. sym->Size = si->Size;
  113. sym->Flags = si->Flags;
  114. sym->Flags ^= 0x7; // filter out bad flags
  115. CatString(sym->Name, si->Name, sym->MaxNameLength);
  116. return ((si->Address >> 32) == 0) ? sym : NULL;
  117. }
  118. PIMAGEHLP_SYMBOL64
  119. si2lsym(
  120. PSYMBOL_INFO si,
  121. PIMAGEHLP_SYMBOL64 lsym
  122. )
  123. {
  124. assert(lsym);
  125. lsym->Address = 0;
  126. *lsym->Name = 0;
  127. if (!si)
  128. return lsym;
  129. lsym->Address = si->Address;
  130. lsym->Size = si->Size;
  131. lsym->Flags = si->Flags;
  132. CatString(lsym->Name, si->Name, lsym->MaxNameLength);
  133. return lsym;
  134. }
  135. PSYMBOL_INFO
  136. si2si(
  137. PSYMBOL_INFO trg,
  138. PSYMBOL_INFO src
  139. )
  140. {
  141. ULONG len = trg->MaxNameLen;
  142. if (src->Name && (strlen(src->Name) < len))
  143. memcpy(trg->Name, src->Name, len * sizeof(trg->Name[0]));
  144. *trg = *src;
  145. trg->MaxNameLen = len;
  146. return trg;
  147. }
  148. PIMAGEHLP_SYMBOL
  149. lsym2sym(
  150. PIMAGEHLP_SYMBOL64 lsym,
  151. PIMAGEHLP_SYMBOL sym
  152. )
  153. {
  154. sym->Address = (DWORD)lsym->Address;
  155. sym->Size = lsym->Size;
  156. sym->Flags = lsym->Flags;
  157. sym->MaxNameLength = lsym->MaxNameLength;
  158. *sym->Name = 0;
  159. CatString(sym->Name, lsym->Name, sym->MaxNameLength);
  160. return ((lsym->Address >> 32) == 0) ? sym : NULL;
  161. }
  162. PIMAGEHLP_SYMBOL64
  163. sym2lsym(
  164. PIMAGEHLP_SYMBOL sym,
  165. PIMAGEHLP_SYMBOL64 lsym
  166. )
  167. {
  168. lsym->Address = sym->Address;
  169. lsym->Size = sym->Size;
  170. lsym->Flags = sym->Flags;
  171. lsym->MaxNameLength = sym->MaxNameLength;
  172. lsym->Name[0] = 0;
  173. CatString(lsym->Name, sym->Name, lsym->MaxNameLength);
  174. return lsym;
  175. }
  176. PIMAGEHLP_LINE
  177. lline2line( // SympConvertLine64To32(
  178. PIMAGEHLP_LINE64 lline,
  179. PIMAGEHLP_LINE line
  180. )
  181. {
  182. line->Key = lline->Key;
  183. line->LineNumber = lline->LineNumber;
  184. line->FileName = lline->FileName;
  185. line->Address = (DWORD)lline->Address;
  186. return ((lline->Address >> 32) == 0) ? line : NULL;
  187. }
  188. PIMAGEHLP_LINE64
  189. line2lline( // SympConvertLine32To64(
  190. PIMAGEHLP_LINE line,
  191. PIMAGEHLP_LINE64 lline
  192. )
  193. {
  194. lline->Key = line->Key;
  195. lline->LineNumber = line->LineNumber;
  196. lline->FileName = line->FileName;
  197. lline->Address = line->Address;
  198. return lline;
  199. }
  200. // other utility routines
  201. BOOL
  202. GetSymNextPrev(
  203. IN HANDLE hProcess,
  204. IN OUT PIMAGEHLP_SYMBOL64 Symbol,
  205. IN int Direction
  206. );
  207. typedef struct _STORE_OLD_CB {
  208. BOOL cb64;
  209. union{
  210. PSYM_ENUMSYMBOLS_CALLBACK UserCallBackRoutine;
  211. PSYM_ENUMSYMBOLS_CALLBACK64 UserCallBackRoutine64;
  212. };
  213. PVOID UserContext;
  214. } STORE_OLD_CB;
  215. BOOL
  216. ImgHlpDummyCB(
  217. PSYMBOL_INFO pSymInfo,
  218. ULONG SymbolSize,
  219. PVOID UserContext
  220. )
  221. {
  222. STORE_OLD_CB *pOld = (STORE_OLD_CB *) UserContext;
  223. if (pSymInfo->Flags & SYMFLAG_REGREL) {
  224. LARGE_INTEGER li;
  225. li.HighPart = pSymInfo->Register;
  226. li.LowPart = (ULONG) pSymInfo->Address;
  227. pSymInfo->Address = li.QuadPart;
  228. }
  229. if (pOld->cb64) {
  230. return (*pOld->UserCallBackRoutine64) (
  231. pSymInfo->Name,
  232. pSymInfo->Address,
  233. SymbolSize,
  234. pOld->UserContext );
  235. } else {
  236. return (*pOld->UserCallBackRoutine) (
  237. pSymInfo->Name,
  238. (ULONG) pSymInfo->Address,
  239. SymbolSize,
  240. pOld->UserContext );
  241. }
  242. }
  243. BOOL
  244. TestOutputString(
  245. PCHAR sz
  246. )
  247. {
  248. CHAR c;
  249. __try {
  250. c = *sz;
  251. } __except(EXCEPTION_EXECUTE_HANDLER) {
  252. SetLastError(ERROR_INVALID_PARAMETER);
  253. return false;
  254. }
  255. return true;
  256. }
  257. BOOL
  258. InitOutputString(
  259. PCHAR sz
  260. )
  261. {
  262. BOOL rc;
  263. rc = TestOutputString(sz);
  264. if (rc)
  265. *sz = 0;
  266. return rc;
  267. }
  268. char *
  269. TokenFromSymbolPath(
  270. char *path,
  271. char *token,
  272. int size
  273. )
  274. {
  275. char *next;
  276. *token = 0;
  277. if (!path)
  278. return NULL;
  279. next = strchr(path, ';');
  280. if (!next)
  281. CopyString(token, path, size);
  282. else
  283. CopyNString(token, path, (ULONG)(next - path), size);
  284. trim(token);
  285. if (next && !*++next)
  286. next = NULL;
  287. return next;
  288. }
  289. BOOL
  290. CreateSymbolPath(
  291. int pass,
  292. char *base,
  293. char *iext,
  294. char *node,
  295. char *ext,
  296. char *path,
  297. size_t size
  298. )
  299. {
  300. if (!path || !base || !*base || !node || !*node || !ext || !*ext)
  301. return false;
  302. CopyString(path, base, size);
  303. EnsureTrailingBackslash(path);
  304. switch (pass)
  305. {
  306. case 1:
  307. // add the "symbols" directory
  308. CatString(path, "symbols", size);
  309. EnsureTrailingBackslash(path);
  310. // pass through
  311. case 2:
  312. // add the image extension
  313. CatString(path, iext, size);
  314. // pass through
  315. case 0:
  316. EnsureTrailingBackslash(path);
  317. break;
  318. default:
  319. return false;
  320. }
  321. CatString(path, node, size);
  322. CatString(path, ext, size);
  323. return true;
  324. }
  325. BOOL
  326. DoEnumCallback(
  327. PPROCESS_ENTRY pe,
  328. PSYMBOL_INFO pSymInfo,
  329. ULONG SymSize,
  330. PROC EnumCallback,
  331. PVOID UserContext,
  332. BOOL Use64,
  333. BOOL UsesUnicode
  334. )
  335. {
  336. BOOL rc = false;
  337. if (pSymInfo)
  338. {
  339. if (Use64 || (!UsesUnicode))
  340. {
  341. rc = (*(PSYM_ENUMERATESYMBOLS_CALLBACK)EnumCallback) (
  342. pSymInfo,
  343. SymSize,
  344. UserContext);
  345. }
  346. else
  347. {
  348. PWSTR pszTmp = AnsiToUnicode(pSymInfo->Name);
  349. if (pszTmp)
  350. {
  351. strncpy(pSymInfo->Name, (LPSTR)pszTmp, // SECURITY: Don't know size of output buffer.
  352. min(pSymInfo->MaxNameLen, wcslen(pszTmp)));
  353. *((LPWSTR) &pSymInfo->Name[min(pSymInfo->MaxNameLen, wcslen(pszTmp)) - 1 ]) = 0;
  354. rc = (*(PSYM_ENUMERATESYMBOLS_CALLBACK)EnumCallback) (
  355. pSymInfo,
  356. SymSize,
  357. UserContext );
  358. MemFree(pszTmp);
  359. }
  360. }
  361. }
  362. return rc;
  363. }
  364. void OpenLogFile(char *file)
  365. {
  366. time_t stTime;
  367. char *szTime;
  368. if (g.hLog)
  369. return;
  370. g.hLog = _open(file, O_APPEND | O_CREAT | O_RDWR, S_IREAD | S_IWRITE);
  371. if (g.hLog == -1)
  372. g.hLog = 0;
  373. time(&stTime);
  374. szTime = ctime(&stTime);
  375. eprint("\n");
  376. dprint(szTime ? "new session: %s" : "new session:\n", szTime);
  377. }
  378. void CloseLogFile()
  379. {
  380. time_t stTime;
  381. char *szTime;
  382. if (!g.hLog)
  383. return;
  384. time(&stTime);
  385. szTime = ctime(&stTime);
  386. dprint(szTime ? "closing session: %s" : "closing session:\n", szTime);
  387. _close(g.hLog);
  388. g.hLog = 0;
  389. }
  390. BOOL
  391. IMAGEAPI
  392. SymInitialize(
  393. IN HANDLE hProcess,
  394. IN LPSTR UserSearchPath,
  395. IN BOOL InvadeProcess
  396. )
  397. /*++
  398. Routine Description:
  399. This function initializes the symbol handler for
  400. a process. The process is identified by the
  401. process handle passed into this function.
  402. Arguments:
  403. hProcess - Process handle. If InvadeProcess is false
  404. then this can be any unique value that identifies
  405. the process to the symbol handler.
  406. UserSearchPath - Pointer to a string of paths separated by semicolons.
  407. These paths are used to search for symbol files.
  408. The value NULL is acceptable.
  409. InvadeProcess - If this is set to true then the process identified
  410. by the process handle is "invaded" and it's loaded
  411. module list is enumerated. Each module is added
  412. to the symbol handler and symbols are attempted
  413. to be loaded.
  414. Return Value:
  415. true - The symbol handler was successfully initialized.
  416. false - The initialization failed. Call GetLastError to
  417. discover the cause of the failure.
  418. --*/
  419. {
  420. PPROCESS_ENTRY pe;
  421. char log[MAX_PATH];
  422. __try {
  423. if (!g.SymInitialized) {
  424. g.SymInitialized = true;
  425. g.cProcessList = 0;
  426. InitializeListHead( &g.ProcessList );
  427. }
  428. *g.DebugToken = 0;
  429. GetEnvironmentVariable(DBGHELP_TOKEN, g.DebugToken, sizeof(g.DebugToken) / sizeof(g.DebugToken[0]));
  430. _strlwr(g.DebugToken);
  431. if (GetEnvironmentVariable("DBGHELP_LOG", log, MAX_PATH))
  432. OpenLogFile(log);
  433. if (GetEnvironmentVariable("DBGHELP_DBGOUT", log, MAX_PATH))
  434. g.fdbgout = true;
  435. if (pe = FindProcessEntry( hProcess )) {
  436. pe->cRefs++;
  437. SetLastError( ERROR_INVALID_HANDLE );
  438. return true;
  439. }
  440. pe = (PPROCESS_ENTRY) MemAlloc( sizeof(PROCESS_ENTRY) );
  441. if (!pe) {
  442. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  443. return false;
  444. }
  445. ZeroMemory( pe, sizeof(PROCESS_ENTRY) );
  446. pe->NextModule = NULL;
  447. pe->hProcess = hProcess;
  448. pe->pid = (int) GetPID(hProcess);
  449. pe->cRefs = 1;
  450. g.cProcessList++;
  451. InitializeListHead( &pe->ModuleList );
  452. InsertTailList( &g.ProcessList, &pe->ListEntry );
  453. if (!SymSetSearchPath( hProcess, UserSearchPath )) {
  454. //
  455. // last error code was set by SymSetSearchPath, so just return
  456. //
  457. SymCleanup( hProcess );
  458. return false;
  459. }
  460. if (!diaInit()) {
  461. SymCleanup( hProcess );
  462. return false;
  463. }
  464. if (InvadeProcess) {
  465. DWORD DosError = GetProcessModules(hProcess, GetModule, NULL);
  466. if (DosError) {
  467. SymCleanup( hProcess );
  468. SetLastError( DosError );
  469. return false;
  470. }
  471. }
  472. srcsrvInit(hProcess);
  473. } __except (EXCEPTION_EXECUTE_HANDLER) {
  474. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  475. return false;
  476. }
  477. return true;
  478. }
  479. BOOL
  480. IMAGEAPI
  481. lSymCleanup(
  482. HANDLE hProcess
  483. )
  484. /*++
  485. Routine Description:
  486. This function cleans up the symbol handler's data structures
  487. for a previously initialized process.
  488. Arguments:
  489. hProcess - Process handle.
  490. Return Value:
  491. true - The symbol handler was successfully cleaned up.
  492. false - The cleanup failed. Call GetLastError to
  493. discover the cause of the failure.
  494. --*/
  495. {
  496. PPROCESS_ENTRY pe;
  497. PLIST_ENTRY next;
  498. PMODULE_ENTRY mi;
  499. PSOURCE_HINT sh;
  500. PSOURCE_HINT shnext;
  501. BOOL rc = true;
  502. HeapDump("SymCleanup(before cleanup)\n");
  503. __try {
  504. pe = FindProcessEntry(hProcess);
  505. if (!pe) {
  506. SetLastError( ERROR_INVALID_HANDLE );
  507. return false;
  508. }
  509. if (--pe->cRefs)
  510. return true;
  511. next = pe->ModuleList.Flink;
  512. if (next) {
  513. while (next != &pe->ModuleList) {
  514. mi = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
  515. next = mi->ListEntry.Flink;
  516. FreeModuleEntry(pe, mi);
  517. }
  518. }
  519. for (sh = pe->SourceHints; sh; sh = shnext) {
  520. shnext = sh->next;
  521. MemFree(sh->filename);
  522. MemFree(sh);
  523. }
  524. symsrvClose();
  525. MemFree(pe->SymbolSearchPath);
  526. RemoveEntryList(&pe->ListEntry);
  527. MemFree(pe);
  528. g.cProcessList--;
  529. diaCleanup();
  530. // Assume that things are shutting down and
  531. // dump all the function entry caches.
  532. ClearFeCaches();
  533. } __except (EXCEPTION_EXECUTE_HANDLER) {
  534. ImagepSetLastErrorFromStatus(GetExceptionCode());
  535. rc = false;
  536. }
  537. HeapDump("SymCleanup(after cleanup)\n");
  538. gfnSrcSrvCleanup(hProcess);
  539. CloseLogFile();
  540. return rc;
  541. }
  542. BOOL
  543. IMAGEAPI
  544. SymCleanup(
  545. HANDLE hProcess
  546. )
  547. {
  548. BOOL rc = false;
  549. __try {
  550. EnterCriticalSection(&g.threadlock);
  551. rc = lSymCleanup(hProcess);
  552. } __finally {
  553. LeaveCriticalSection(&g.threadlock);
  554. }
  555. return rc;
  556. }
  557. BOOL
  558. IMAGEAPI
  559. SymSetParentWindow(
  560. HWND hwnd
  561. )
  562. {
  563. g.hwndParent = hwnd;
  564. symsrvSetPrompts();
  565. return true;
  566. }
  567. BOOL IsDirectoryWritable(char *dir)
  568. {
  569. char fname[MAX_PATH + 1];
  570. if (!GetTempFileName(dir, "DBG", 0, fname))
  571. return false;
  572. DeleteFile(fname);
  573. return true;
  574. }
  575. typedef BOOL (*SHGETSPECIALFOLDERPATHA)(HWND, LPSTR, int, BOOL);
  576. BOOL GetCommonAppDataDirectory(char *dir)
  577. {
  578. char path[MAX_PATH + 1];
  579. static HMODULE hShell32 = 0;
  580. static SHGETSPECIALFOLDERPATHA fnSHGetSpecialFolderPathA = NULL;
  581. assert(dir);
  582. if (!hShell32) {
  583. hShell32 = LoadLibrary("shell32.dll");
  584. if (hShell32)
  585. fnSHGetSpecialFolderPathA = (SHGETSPECIALFOLDERPATHA)GetProcAddress(hShell32, "SHGetSpecialFolderPathA");
  586. else
  587. hShell32 = (HMODULE)INVALID_HANDLE_VALUE;
  588. }
  589. if (hShell32 == (HMODULE)INVALID_HANDLE_VALUE)
  590. return false;
  591. if (!fnSHGetSpecialFolderPathA)
  592. return false;
  593. if (!fnSHGetSpecialFolderPathA(NULL, path, CSIDL_COMMON_APPDATA, false))
  594. return false;
  595. CopyString(dir, path, MAX_PATH + 1);
  596. EnsureTrailingBackslash(dir);
  597. CatString(dir, "dbg", MAX_PATH + 1);
  598. if (!CreateDirectory(dir, NULL)) {
  599. if( GetLastError() != ERROR_ALREADY_EXISTS )
  600. return false;
  601. }
  602. return true;
  603. }
  604. PCHAR IMAGEAPI SymSetHomeDirectory(PCSTR dir)
  605. {
  606. char dstore[MAX_PATH + 1] = "";
  607. static char homedir[MAX_PATH + 1] = "";
  608. // If a valid new directory is passed, use it.
  609. // Otherwise, if the home directory has not
  610. // been initialized, do so.
  611. *homedir = 0;
  612. if (dir && *dir)
  613. {
  614. CopyStrArray(homedir, dir);
  615. }
  616. else if (!*g.HomeDir)
  617. {
  618. char path[MAX_PATH + 1];
  619. char drive[_MAX_DRIVE + 1];
  620. char dir[_MAX_DIR + 1];
  621. if (GetModuleFileName(NULL, path, DIMA(path))) {
  622. _splitpath(path, drive, dir, NULL, NULL);
  623. CopyStrArray(path, drive);
  624. CatStrArray(path, dir);
  625. RemoveTrailingBackslash(path);
  626. CopyStrArray(homedir, path);
  627. }
  628. }
  629. // If the home directory was changed, set it
  630. // and the new default downstream store.
  631. if (*homedir)
  632. {
  633. if (!IsDirectoryWritable(homedir)) {
  634. if(!GetCommonAppDataDirectory(homedir)) {
  635. CopyStrArray(homedir, g.HomeDir);
  636. return homedir;
  637. }
  638. }
  639. CopyStrArray(g.HomeDir, homedir);
  640. CopyStrArray(g.SymDir, homedir);
  641. EnsureTrailingBackslash(g.SymDir);
  642. CatStrArray(g.SymDir, "sym");
  643. symsrvSetDownstreamStore(g.SymDir);
  644. } else
  645. CopyStrArray(homedir, g.HomeDir);
  646. // Return the current home directory.
  647. return homedir;
  648. }
  649. PCHAR
  650. IMAGEAPI
  651. SymGetHomeDirectory(
  652. DWORD type,
  653. PSTR dir,
  654. size_t size
  655. )
  656. {
  657. char *tdir;
  658. static char sz[MAX_PATH + 1];
  659. if (!dir || type >= hdMax) {
  660. SetLastError(ERROR_INVALID_PARAMETER);
  661. return NULL;
  662. }
  663. switch(type)
  664. {
  665. case hdBase:
  666. tdir = g.HomeDir;
  667. break;
  668. case hdSym:
  669. tdir = g.SymDir;
  670. break;
  671. case hdSrc:
  672. tdir = g.SrcDir;
  673. break;
  674. }
  675. if (strlen(tdir) >= size) {
  676. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  677. return NULL;
  678. }
  679. CopyString(dir, tdir, size);
  680. return dir;
  681. }
  682. DWORD
  683. IMAGEAPI
  684. SymSetOptions(
  685. DWORD UserOptions
  686. )
  687. /*++
  688. Routine Description:
  689. This function changes the symbol handler's option mask.
  690. Arguments:
  691. UserOptions - The new options mask.
  692. Return Value:
  693. The new mask is returned.
  694. --*/
  695. {
  696. BOOL symsdebug;
  697. DWORD srcsopts;
  698. BOOL secure;
  699. secure = option(SYMOPT_SECURE);
  700. g.SymOptions = UserOptions;
  701. srcsopts = (g.fnSrcSrvGetOptions) ? gfnSrcSrvGetOptions() : 0;
  702. if (option(SYMOPT_DEBUG)) {
  703. srcsopts |= SRCSRVOPT_DEBUG;
  704. symsdebug = true;
  705. } else {
  706. srcsopts &= ~SRCSRVOPT_DEBUG;
  707. symsdebug = false;
  708. }
  709. gfnSrcSrvSetOptions(srcsopts);
  710. symsrvSetCallback((symsdebug || g.hLog) ? true : false);
  711. if (!secure) {
  712. if (option(SYMOPT_SECURE))
  713. symsrvSetOptions(SSRVOPT_SECURE, 1);
  714. } else if (!option(SYMOPT_SECURE))
  715. g.SymOptions |= SYMOPT_SECURE;
  716. DoCallback(NULL, CBA_SET_OPTIONS, &g.SymOptions);
  717. return g.SymOptions;
  718. }
  719. DWORD
  720. IMAGEAPI
  721. SymGetOptions(
  722. VOID
  723. )
  724. /*++
  725. Routine Description:
  726. This function queries the symbol handler's option mask.
  727. Arguments:
  728. None.
  729. Return Value:
  730. The current options mask is returned.
  731. --*/
  732. {
  733. return g.SymOptions;
  734. }
  735. BOOL
  736. IMAGEAPI
  737. SymSetContext(
  738. HANDLE hProcess,
  739. PIMAGEHLP_STACK_FRAME StackFrame,
  740. PIMAGEHLP_CONTEXT Context
  741. )
  742. {
  743. PPROCESS_ENTRY pe;
  744. pe = FindProcessEntry(hProcess);
  745. if (!pe)
  746. return false;
  747. pe->pContext = Context;
  748. pe->StackFrame = *StackFrame;
  749. return diaSetModFromIP(pe);
  750. };
  751. BOOL
  752. SympEnumerateModules(
  753. IN HANDLE hProcess,
  754. IN PROC EnumModulesCallback,
  755. IN PVOID UserContext,
  756. IN BOOL Use64
  757. )
  758. /*++
  759. Routine Description:
  760. This is the worker function for the 32 and 64 bit versions.
  761. Arguments:
  762. hProcess - Process handle, must have been previously registered
  763. with SymInitialize.
  764. EnumModulesCallback - Callback pointer that is called once for each
  765. module that is enumerated. If the enum callback
  766. returns false then the enumeration is terminated.
  767. UserContext - This data is simply passed on to the callback function
  768. and is completly user defined.
  769. Use64 - Supplies flag which determines whether to use the 32 bit
  770. or 64 bit callback prototype.
  771. Return Value:
  772. true - The modules were successfully enumerated.
  773. false - The enumeration failed. Call GetLastError to
  774. discover the cause of the failure.
  775. --*/
  776. {
  777. PPROCESS_ENTRY pe;
  778. PMODULE_ENTRY mi;
  779. PLIST_ENTRY Next;
  780. __try {
  781. pe = FindProcessEntry( hProcess );
  782. if (!pe) {
  783. SetLastError( ERROR_INVALID_HANDLE );
  784. return false;
  785. }
  786. Next = pe->ModuleList.Flink;
  787. if (Next) {
  788. while (Next != &pe->ModuleList) {
  789. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  790. Next = mi->ListEntry.Flink;
  791. if (Use64) {
  792. if ( !(*(PSYM_ENUMMODULES_CALLBACK64)EnumModulesCallback) (
  793. mi->ModuleName,
  794. mi->BaseOfDll,
  795. UserContext
  796. )) {
  797. break;
  798. }
  799. } else {
  800. if ( !(*(PSYM_ENUMMODULES_CALLBACK)EnumModulesCallback) (
  801. mi->ModuleName,
  802. (DWORD)mi->BaseOfDll,
  803. UserContext
  804. )) {
  805. break;
  806. }
  807. }
  808. }
  809. }
  810. } __except (EXCEPTION_EXECUTE_HANDLER) {
  811. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  812. return false;
  813. }
  814. return true;
  815. }
  816. BOOL
  817. dbhfnModSymInfo(
  818. IN HANDLE hp,
  819. IN OUT PDBH_MODSYMINFO p
  820. )
  821. {
  822. PMODULE_ENTRY mi;
  823. PPROCESS_ENTRY pe;
  824. assert(p->function == dbhModSymInfo);
  825. pe = FindProcessEntry(hp);
  826. if (!pe) {
  827. SetLastError( ERROR_INVALID_HANDLE );
  828. return false;
  829. }
  830. if (p->sizeofstruct != sizeof(DBH_MODSYMINFO)) {
  831. SetLastError(ERROR_INVALID_PARAMETER);
  832. return false;
  833. }
  834. mi = GetModuleForPC(pe, p->addr, false);
  835. if (!mi) {
  836. SetLastError(ERROR_MOD_NOT_FOUND);
  837. return false;
  838. }
  839. p->type = mi->SymType;
  840. *p->file = 0;
  841. switch (p->type)
  842. {
  843. case SymPdb:
  844. case SymDia:
  845. if (mi->LoadedPdbName)
  846. CopyStrArray(p->file, mi->LoadedPdbName);
  847. break;
  848. default:
  849. if (mi->LoadedImageName)
  850. CopyStrArray(p->file, mi->LoadedImageName);
  851. break;
  852. }
  853. return true;
  854. }
  855. BOOL
  856. dbhfnDiaVersion(
  857. IN OUT PDBH_DIAVERSION p
  858. )
  859. {
  860. PMODULE_ENTRY mi;
  861. assert(p->function == dbhDiaVersion);
  862. if (p->sizeofstruct != sizeof(DBH_DIAVERSION)) {
  863. SetLastError(ERROR_INVALID_PARAMETER);
  864. return false;
  865. }
  866. p->ver = diaVersion();
  867. return true;
  868. }
  869. BOOL
  870. dbhfnLoadPdb(
  871. IN OUT PDBH_LOADPDB p
  872. )
  873. {
  874. PIMGHLP_DEBUG_DATA idd;
  875. MODLOAD_DATA mld;
  876. int i;
  877. idd = InitIDD(
  878. (HANDLE)6969,
  879. 0,
  880. p->pdb,
  881. NULL,
  882. 100000,
  883. 0,
  884. &mld,
  885. 0,
  886. 0);
  887. if (!idd)
  888. return false;
  889. CopyString(idd->PdbFileName, p->pdb, MAX_PATH + 1);
  890. for (i = 0; i < 1000; i++) {
  891. dtrace("%d ", i);
  892. diaGetPdb(idd);
  893. if (idd->dia)
  894. diaRelease(idd->dia);
  895. idd->dia = NULL;
  896. }
  897. ReleaseDebugData(idd, IMGHLP_FREE_STANDARD);
  898. return true;
  899. }
  900. BOOL
  901. IMAGEAPI
  902. dbghelp(
  903. IN HANDLE hp,
  904. IN OUT PVOID data
  905. )
  906. {
  907. DWORD *function;
  908. if (!data) {
  909. SetLastError(ERROR_INVALID_PARAMETER);
  910. return false;
  911. }
  912. __try {
  913. function = (DWORD *)data;
  914. switch (*function)
  915. {
  916. case dbhModSymInfo:
  917. return dbhfnModSymInfo(hp, (PDBH_MODSYMINFO)data);
  918. case dbhDiaVersion:
  919. return dbhfnDiaVersion((PDBH_DIAVERSION)data);
  920. case dbhLoadPdb:
  921. return dbhfnLoadPdb((PDBH_LOADPDB)data);
  922. default:
  923. SetLastError(ERROR_INVALID_PARAMETER);
  924. return false;
  925. }
  926. } __except (EXCEPTION_EXECUTE_HANDLER) {
  927. ImagepSetLastErrorFromStatus(GetExceptionCode());
  928. return false;
  929. }
  930. return false;
  931. }
  932. BOOL
  933. IMAGEAPI
  934. SymEnumerateModules(
  935. IN HANDLE hProcess,
  936. IN PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,
  937. IN PVOID UserContext
  938. )
  939. /*++
  940. Routine Description:
  941. This function enumerates all of the modules that are currently
  942. loaded into the symbol handler. This is the 32 bit wrapper.
  943. Arguments:
  944. hProcess - Process handle, must have been previously registered
  945. with SymInitialize.
  946. EnumModulesCallback - Callback pointer that is called once for each
  947. module that is enumerated. If the enum callback
  948. returns false then the enumeration is terminated.
  949. UserContext - This data is simply passed on to the callback function
  950. and is completly user defined.
  951. Return Value:
  952. true - The modules were successfully enumerated.
  953. false - The enumeration failed. Call GetLastError to
  954. discover the cause of the failure.
  955. --*/
  956. {
  957. return SympEnumerateModules(hProcess, (PROC)EnumModulesCallback, UserContext, false);
  958. }
  959. BOOL
  960. IMAGEAPI
  961. SymEnumerateModules64(
  962. IN HANDLE hProcess,
  963. IN PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,
  964. IN PVOID UserContext
  965. )
  966. /*++
  967. Routine Description:
  968. This function enumerates all of the modules that are currently
  969. loaded into the symbol handler. This is the 64 bit wrapper.
  970. Arguments:
  971. hProcess - Process handle, must have been previously registered
  972. with SymInitialize.
  973. EnumModulesCallback - Callback pointer that is called once for each
  974. module that is enumerated. If the enum callback
  975. returns false then the enumeration is terminated.
  976. UserContext - This data is simply passed on to the callback function
  977. and is completly user defined.
  978. Return Value:
  979. true - The modules were successfully enumerated.
  980. false - The enumeration failed. Call GetLastError to
  981. discover the cause of the failure.
  982. --*/
  983. {
  984. return SympEnumerateModules(hProcess, (PROC)EnumModulesCallback, UserContext, true);
  985. }
  986. DWORD
  987. CalcItemSize(
  988. PDWORD64 pAddr,
  989. PDWORD64 pAddrsBase,
  990. UINT_PTR count
  991. )
  992. {
  993. PDWORD64 p;
  994. PDWORD64 pAddrEnd;
  995. if (!pAddr)
  996. return 0;
  997. pAddrEnd = pAddrsBase + count;
  998. for (p = pAddr + 1; p <= pAddrEnd; p++) {
  999. if (*p != *pAddr)
  1000. return (DWORD)(*p - *pAddr);
  1001. }
  1002. return 0;
  1003. }
  1004. BOOL
  1005. MatchModuleName(
  1006. PMODULE_ENTRY mi,
  1007. LPSTR mask
  1008. )
  1009. {
  1010. if (!strcmpre(mi->AliasName, mask, false))
  1011. return true;
  1012. if (!strcmpre(mi->ModuleName, mask, false))
  1013. return true;
  1014. return false;
  1015. }
  1016. BOOL
  1017. SympEnumerateSymbols(
  1018. IN HANDLE hProcess,
  1019. IN ULONG64 BaseOfDll,
  1020. IN LPSTR Mask,
  1021. IN PROC EnumSymbolsCallback,
  1022. IN PVOID UserContext,
  1023. IN BOOL Use64,
  1024. IN BOOL CallBackUsesUnicode
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. This function enumerates all of the symbols contained the module
  1029. specified by the BaseOfDll argument.
  1030. Arguments:
  1031. hProcess - Process handle, must have been previously registered
  1032. with SymInitialize
  1033. BaseOfDll - Base address of the DLL that symbols are to be
  1034. enumerated for
  1035. EnumSymbolsCallback - User specified callback routine for enumeration
  1036. notification
  1037. UserContext - Pass thru variable, this is simply passed thru to the
  1038. callback function
  1039. Use64 - Supplies flag which determines whether to use the 32 bit
  1040. or 64 bit callback prototype.
  1041. Return Value:
  1042. true - The symbols were successfully enumerated.
  1043. false - The enumeration failed. Call GetLastError to
  1044. discover the cause of the failure.
  1045. --*/
  1046. {
  1047. PPROCESS_ENTRY pe;
  1048. PLIST_ENTRY Next;
  1049. PMODULE_ENTRY mi;
  1050. DWORD i;
  1051. PSYMBOL_ENTRY sym;
  1052. char buf[2500];
  1053. LPSTR p;
  1054. CHAR modmask[200];
  1055. BOOL rc;
  1056. int pass;
  1057. BOOL fCase;
  1058. PSYMBOL_INFO si;
  1059. char match[MAX_SYM_NAME + 100];
  1060. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED | LS_FAIL_IF_LOADED};
  1061. __try {
  1062. pe = FindProcessEntry( hProcess );
  1063. if (!pe) {
  1064. SetLastError( ERROR_INVALID_HANDLE );
  1065. return false;
  1066. }
  1067. p = 0;
  1068. modmask[0] = 0;
  1069. if (Mask)
  1070. p = strchr(Mask, '!');
  1071. if (p > Mask) {
  1072. memcpy(modmask, Mask, (int)(p - Mask));
  1073. modmask[p-Mask] = 0;
  1074. Mask = p + 1;
  1075. } else if (!BaseOfDll) {
  1076. // search is scoped to current scope
  1077. rc = diaEnumerateSymbols(pe,
  1078. NULL,
  1079. Mask,
  1080. EnumSymbolsCallback,
  1081. UserContext,
  1082. Use64,
  1083. CallBackUsesUnicode);
  1084. if (!rc && pe->ipmi && pe->ipmi->code == ERROR_CANCELLED) {
  1085. pe->ipmi->code = 0;
  1086. return true;
  1087. }
  1088. return rc;
  1089. }
  1090. if (Mask && *Mask)
  1091. PrepRE4Srch(Mask, match);
  1092. else
  1093. *match = 0;
  1094. for (pass = 0; pass < 2; pass++) {
  1095. Next = pe->ModuleList.Flink;
  1096. if (Next) {
  1097. while (Next != &pe->ModuleList) {
  1098. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  1099. Next = mi->ListEntry.Flink;
  1100. if (BaseOfDll) {
  1101. if (mi->BaseOfDll != BaseOfDll)
  1102. continue;
  1103. } else if (!MatchModuleName(mi, modmask)) {
  1104. continue;
  1105. }
  1106. if (!LoadSymbols(hProcess, mi, flags[pass])) {
  1107. if (GetLastError() == ERROR_CANCELLED)
  1108. return false;
  1109. continue;
  1110. }
  1111. if (mi->dia) {
  1112. rc = diaEnumerateSymbols(pe,
  1113. mi,
  1114. Mask,
  1115. EnumSymbolsCallback,
  1116. UserContext,
  1117. Use64,
  1118. CallBackUsesUnicode);
  1119. }
  1120. if (mi->numsyms) {
  1121. fCase = option(SYMOPT_CASE_INSENSITIVE) ? false : true;
  1122. si = (PSYMBOL_INFO)buf;
  1123. ZeroMemory(buf, sizeof(buf));
  1124. si->MaxNameLen = sizeof(buf) - sizeof(SYMBOL_INFO);
  1125. for (i = 0; i < mi->numsyms; i++) {
  1126. sym = &mi->symbolTable[i];
  1127. if (*match && strcmpre(sym->Name, match, fCase))
  1128. continue;
  1129. se2si(sym, si);
  1130. si->ModBase = mi->BaseOfDll;
  1131. if (!DoEnumCallback(
  1132. pe,
  1133. si,
  1134. si->Size,
  1135. EnumSymbolsCallback,
  1136. UserContext,
  1137. Use64,
  1138. CallBackUsesUnicode)) {
  1139. break;
  1140. }
  1141. }
  1142. }
  1143. rc = vsEnumSymbols(pe,
  1144. mi,
  1145. Mask,
  1146. EnumSymbolsCallback,
  1147. UserContext,
  1148. Use64,
  1149. CallBackUsesUnicode);
  1150. if (!rc) {
  1151. if (mi->code == ERROR_CANCELLED) {
  1152. mi->code = 0;
  1153. return true;
  1154. }
  1155. return rc;
  1156. }
  1157. }
  1158. }
  1159. }
  1160. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1161. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1162. return false;
  1163. }
  1164. return true;
  1165. }
  1166. BOOL
  1167. IMAGEAPI
  1168. SymEnumerateSymbols(
  1169. IN HANDLE hProcess,
  1170. IN ULONG BaseOfDll,
  1171. IN PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback,
  1172. IN PVOID UserContext
  1173. )
  1174. /*++
  1175. Routine Description:
  1176. This function enumerates all of the symbols contained the module
  1177. specified by the BaseOfDll argument.
  1178. Arguments:
  1179. hProcess - Process handle, must have been previously registered
  1180. with SymInitialize
  1181. BaseOfDll - Base address of the DLL that symbols are to be
  1182. enumerated for
  1183. EnumSymbolsCallback - User specified callback routine for enumeration
  1184. notification
  1185. UserContext - Pass thru variable, this is simply passed thru to the
  1186. callback function
  1187. Return Value:
  1188. true - The symbols were successfully enumerated.
  1189. false - The enumeration failed. Call GetLastError to
  1190. discover the cause of the failure.
  1191. --*/
  1192. {
  1193. STORE_OLD_CB OldCB;
  1194. OldCB.UserCallBackRoutine = EnumSymbolsCallback;
  1195. OldCB.UserContext = UserContext;
  1196. OldCB.cb64 = false;
  1197. return SympEnumerateSymbols(hProcess,
  1198. BaseOfDll,
  1199. NULL,
  1200. (PROC) (EnumSymbolsCallback ? &ImgHlpDummyCB : NULL),
  1201. (PVOID) &OldCB,
  1202. false,
  1203. false);
  1204. }
  1205. BOOL
  1206. IMAGEAPI
  1207. SymEnumerateSymbolsW(
  1208. IN HANDLE hProcess,
  1209. IN ULONG BaseOfDll,
  1210. IN PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback,
  1211. IN PVOID UserContext
  1212. )
  1213. {
  1214. STORE_OLD_CB OldCB;
  1215. OldCB.UserCallBackRoutine = (PSYM_ENUMSYMBOLS_CALLBACK) EnumSymbolsCallback;
  1216. OldCB.UserContext = UserContext;
  1217. OldCB.cb64 = false;
  1218. return SympEnumerateSymbols(hProcess,
  1219. BaseOfDll,
  1220. NULL,
  1221. (PROC) (EnumSymbolsCallback ? &ImgHlpDummyCB : NULL),
  1222. (PVOID) &OldCB,
  1223. false,
  1224. false);
  1225. }
  1226. BOOL
  1227. IMAGEAPI
  1228. SymEnumerateSymbols64(
  1229. IN HANDLE hProcess,
  1230. IN ULONG64 BaseOfDll,
  1231. IN PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,
  1232. IN PVOID UserContext
  1233. )
  1234. {
  1235. STORE_OLD_CB OldCB;
  1236. OldCB.UserCallBackRoutine64 = EnumSymbolsCallback;
  1237. OldCB.UserContext = UserContext;
  1238. OldCB.cb64 = true;
  1239. return SympEnumerateSymbols(hProcess,
  1240. BaseOfDll,
  1241. NULL,
  1242. (PROC) (EnumSymbolsCallback ? &ImgHlpDummyCB : NULL),
  1243. (PVOID) &OldCB,
  1244. false,
  1245. false);
  1246. }
  1247. BOOL
  1248. IMAGEAPI
  1249. SymEnumerateSymbolsW64(
  1250. IN HANDLE hProcess,
  1251. IN ULONG64 BaseOfDll,
  1252. IN PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback,
  1253. IN PVOID UserContext
  1254. )
  1255. {
  1256. STORE_OLD_CB OldCB;
  1257. OldCB.UserCallBackRoutine64 = (PSYM_ENUMSYMBOLS_CALLBACK64) EnumSymbolsCallback;
  1258. OldCB.UserContext = UserContext;
  1259. OldCB.cb64 = true;
  1260. return SympEnumerateSymbols(hProcess,
  1261. BaseOfDll,
  1262. NULL,
  1263. (PROC) (EnumSymbolsCallback ? &ImgHlpDummyCB : NULL),
  1264. (PVOID) &OldCB,
  1265. false,
  1266. false);
  1267. }
  1268. PSYMBOL_INFO
  1269. SympGetSymFromAddr(
  1270. IN HANDLE hProcess,
  1271. IN DWORD64 Address,
  1272. OUT PDWORD64 Displacement
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. This function finds an entry in the symbol table based on an address.
  1277. This is the common worker function for the 32 and 64 bit API.
  1278. Arguments:
  1279. hProcess - Process handle, must have been previously registered
  1280. with SymInitialize.
  1281. Address - Address of the desired symbol.
  1282. Displacement - This value is set to the offset from the beginning
  1283. of the symbol.
  1284. Return Value:
  1285. PSYMBOL_INFO - relevent symbol information
  1286. --*/
  1287. {
  1288. PPROCESS_ENTRY pe;
  1289. PMODULE_ENTRY mi;
  1290. PSYMBOL_INFO si;
  1291. BOOL rc;
  1292. __try {
  1293. pe = FindProcessEntry(hProcess);
  1294. if (!pe)
  1295. return (PSYMBOL_INFO)(ULONG_PTR)error(ERROR_INVALID_HANDLE);
  1296. mi = GetModuleForPC(pe, Address, false);
  1297. if (!mi)
  1298. return (PSYMBOL_INFO)(ULONG_PTR)error(ERROR_MOD_NOT_FOUND);
  1299. if (!LoadSymbols(hProcess, mi, 0))
  1300. return (PSYMBOL_INFO)(ULONG_PTR)error(ERROR_MOD_NOT_FOUND);
  1301. #ifdef DEBUGSYMTAG
  1302. si = GetSymFromAddrByTag( Address, SymTagAnnotation, Displacement, mi );
  1303. if (si)
  1304. dprint("ANNOTATION: %xI64x %s %x\n", si->Address, si->Name, Displacement);
  1305. #endif
  1306. si = GetSymFromAddr( Address, Displacement, mi );
  1307. if (!si)
  1308. return (PSYMBOL_INFO)(ULONG_PTR)error(ERROR_INVALID_ADDRESS);
  1309. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1310. ImagepSetLastErrorFromStatus(GetExceptionCode());
  1311. return NULL;
  1312. }
  1313. #if 0
  1314. if (_stricmp(mi->ModuleName, "symstore"))
  1315. return si;
  1316. char sz[MAX_PATH + 1];
  1317. SymGetSourceFile(hProcess, Address, "d:\\db\\symsrv\\symstore\\symstore.cpp", sz);
  1318. #endif
  1319. return si;
  1320. }
  1321. BOOL
  1322. IMAGEAPI
  1323. SymGetSymFromAddr64(
  1324. IN HANDLE hProcess,
  1325. IN DWORD64 Address,
  1326. OUT PDWORD64 Displacement,
  1327. OUT PIMAGEHLP_SYMBOL64 Symbol
  1328. )
  1329. /*++
  1330. Routine Description:
  1331. This function finds an entry in the symbol table based on an address.
  1332. Arguments:
  1333. hProcess - Process handle, must have been previously registered
  1334. with SymInitialize.
  1335. Address - Address of the desired symbol.
  1336. Displacement - This value is set to the offset from the beginning
  1337. of the symbol.
  1338. Symbol - Returns the found symbol
  1339. Return Value:
  1340. true - The symbol was located.
  1341. false - The symbol was not found. Call GetLastError to
  1342. discover the cause of the failure.
  1343. --*/
  1344. {
  1345. PSYMBOL_INFO si;
  1346. si = SympGetSymFromAddr(hProcess, Address, Displacement);
  1347. if (!si)
  1348. return false;
  1349. si2lsym(si, Symbol);
  1350. return true;
  1351. }
  1352. BOOL
  1353. IMAGEAPI
  1354. SymGetSymFromAddr(
  1355. IN HANDLE hProcess,
  1356. IN DWORD Address,
  1357. OUT PDWORD Displacement,
  1358. OUT PIMAGEHLP_SYMBOL Symbol
  1359. )
  1360. /*++
  1361. Routine Description:
  1362. This function finds an entry in the symbol table based on an address.
  1363. Arguments:
  1364. hProcess - Process handle, must have been previously registered
  1365. with SymInitialize.
  1366. Address - Address of the desired symbol.
  1367. Displacement - This value is set to the offset from the beginning
  1368. of the symbol.
  1369. Symbol - Returns the found symbol
  1370. Return Value:
  1371. true - The symbol was located.
  1372. false - The symbol was not found. Call GetLastError to
  1373. discover the cause of the failure.
  1374. --*/
  1375. {
  1376. PSYMBOL_INFO si;
  1377. DWORD64 qDisplacement;
  1378. si = SympGetSymFromAddr(hProcess, Address, &qDisplacement);
  1379. if (!si)
  1380. return false;
  1381. si2sym(si, Symbol);
  1382. if (Displacement)
  1383. *Displacement = (DWORD)qDisplacement;
  1384. return true;
  1385. }
  1386. PSYMBOL_INFO
  1387. SympGetSymFromName(
  1388. IN HANDLE hProcess,
  1389. IN LPSTR Name
  1390. )
  1391. /*++
  1392. Routine Description:
  1393. This function finds an entry in the symbol table based on a name.
  1394. Arguments:
  1395. hProcess - Process handle, must have been previously registered
  1396. with SymInitialize.
  1397. SymName - A string containing the symbol name.
  1398. sym - Returns the located symbol
  1399. Return Value:
  1400. true - The symbol was located.
  1401. false - The symbol was not found. Call GetLastError to
  1402. discover the cause of the failure.
  1403. --*/
  1404. {
  1405. LPSTR p;
  1406. PPROCESS_ENTRY pe;
  1407. PMODULE_ENTRY mi = NULL;
  1408. PLIST_ENTRY Next;
  1409. IMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl64;
  1410. int pass;
  1411. PSYMBOL_INFO si;
  1412. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED};
  1413. __try {
  1414. pe = FindProcessEntry( hProcess );
  1415. if (!pe) {
  1416. SetLastError( ERROR_INVALID_HANDLE );
  1417. return false;
  1418. }
  1419. // first check for fully qualified symbol name I.E. mod!sym
  1420. p = strchr( Name, '!' );
  1421. if (p > Name) {
  1422. LPSTR ModName = (LPSTR)MemAlloc(p - Name + 1);
  1423. if (!ModName) {
  1424. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1425. return false;
  1426. }
  1427. memcpy(ModName, Name, (int)(p - Name));
  1428. ModName[p-Name] = 0;
  1429. //
  1430. // the caller wants to look in a specific module
  1431. //
  1432. mi = FindModule(hProcess, pe, ModName, true);
  1433. MemFree(ModName);
  1434. if (mi != NULL) {
  1435. si = FindSymbolByName( pe, mi, p+1 );
  1436. if (si)
  1437. return si;
  1438. }
  1439. SetLastError( ERROR_MOD_NOT_FOUND );
  1440. return false;
  1441. }
  1442. // now check, using context information
  1443. si = FindSymbolByName( pe, NULL, Name );
  1444. if (si)
  1445. return si;
  1446. // now just look in every module
  1447. for (pass = 0; pass < 2; pass++) {
  1448. Next = pe->ModuleList.Flink;
  1449. while (Next != &pe->ModuleList) {
  1450. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  1451. Next = mi->ListEntry.Flink;
  1452. if (!LoadSymbols(hProcess, mi, flags[pass])) {
  1453. if (GetLastError() == ERROR_CANCELLED)
  1454. return false;
  1455. continue;
  1456. }
  1457. si = FindSymbolByName( pe, mi, Name );
  1458. if (si)
  1459. return si;
  1460. }
  1461. }
  1462. SetLastError( ERROR_MOD_NOT_FOUND );
  1463. return false;
  1464. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1465. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1466. return false;
  1467. }
  1468. SetLastError( ERROR_INVALID_FUNCTION );
  1469. return NULL;
  1470. }
  1471. BOOL
  1472. IMAGEAPI
  1473. SymGetSymFromName64(
  1474. IN HANDLE hProcess,
  1475. IN LPSTR Name,
  1476. OUT PIMAGEHLP_SYMBOL64 Symbol
  1477. )
  1478. /*++
  1479. Routine Description:
  1480. This function finds an entry in the symbol table based on a name.
  1481. Arguments:
  1482. hProcess - Process handle, must have been previously registered
  1483. with SymInitialize.
  1484. SymName - A string containing the symbol name.
  1485. Symbol - Returns found symbol
  1486. Return Value:
  1487. true - The symbol was located.
  1488. false - The symbol was not found. Call GetLastError to
  1489. discover the cause of the failure.
  1490. --*/
  1491. {
  1492. PSYMBOL_INFO si;
  1493. si = SympGetSymFromName(hProcess, Name);
  1494. if (!si)
  1495. return false;
  1496. si2lsym(si, Symbol);
  1497. return true;
  1498. }
  1499. BOOL
  1500. IMAGEAPI
  1501. SymGetSymFromName(
  1502. IN HANDLE hProcess,
  1503. IN LPSTR Name,
  1504. OUT PIMAGEHLP_SYMBOL Symbol
  1505. )
  1506. /*++
  1507. Routine Description:
  1508. This function finds an entry in the symbol table based on a name.
  1509. Arguments:
  1510. hProcess - Process handle, must have been previously registered
  1511. with SymInitialize.
  1512. SymName - A string containing the symbol name.
  1513. Symbol - Returns found symbol
  1514. Return Value:
  1515. true - The symbol was located.
  1516. false - The symbol was not found. Call GetLastError to
  1517. discover the cause of the failure.
  1518. --*/
  1519. {
  1520. PSYMBOL_INFO si;
  1521. si = SympGetSymFromName(hProcess, Name);
  1522. if (!si)
  1523. return false;
  1524. si2sym(si,Symbol);
  1525. return true;
  1526. }
  1527. BOOL
  1528. IMAGEAPI
  1529. SymGetSymNext(
  1530. IN HANDLE hProcess,
  1531. IN OUT PIMAGEHLP_SYMBOL Symbol32
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. This function finds the next symbol in the symbol table that falls
  1536. sequentially after the symbol passed in.
  1537. Arguments:
  1538. hProcess - Process handle, must have been previously registered
  1539. with SymInitialize.
  1540. Symbol - Starting symbol.
  1541. Return Value:
  1542. Non NULL pointer - The symbol was located.
  1543. NULL pointer - The symbol was not found. Call GetLastError to
  1544. discover the cause of the failure.
  1545. --*/
  1546. {
  1547. PIMAGEHLP_SYMBOL64 Symbol64;
  1548. BOOL rc = false;
  1549. Symbol64 = (PIMAGEHLP_SYMBOL64)MemAlloc(sizeof(IMAGEHLP_SYMBOL64) + Symbol32->MaxNameLength);
  1550. if (Symbol64) {
  1551. sym2lsym(Symbol32, Symbol64);
  1552. if (SymGetSymNext64(hProcess, Symbol64)) {
  1553. lsym2sym(Symbol64, Symbol32);
  1554. rc = true;
  1555. }
  1556. MemFree(Symbol64);
  1557. }
  1558. return rc;
  1559. }
  1560. BOOL
  1561. IMAGEAPI
  1562. SymGetSymNext64(
  1563. IN HANDLE hProcess,
  1564. IN OUT PIMAGEHLP_SYMBOL64 Symbol
  1565. )
  1566. /*++
  1567. Routine Description:
  1568. This function finds the next symbol in the symbol table that falls
  1569. sequentially after the symbol passed in.
  1570. Arguments:
  1571. hProcess - Process handle, must have been previously registered
  1572. with SymInitialize.
  1573. Symbol - Starting symbol.
  1574. Return Value:
  1575. Non NULL pointer - The symbol was located.
  1576. NULL pointer - The symbol was not found. Call GetLastError to
  1577. discover the cause of the failure.
  1578. --*/
  1579. {
  1580. return GetSymNextPrev(hProcess, Symbol, 1);
  1581. }
  1582. BOOL
  1583. IMAGEAPI
  1584. SymGetSymPrev(
  1585. IN HANDLE hProcess,
  1586. IN OUT PIMAGEHLP_SYMBOL Symbol32
  1587. )
  1588. /*++
  1589. Routine Description:
  1590. This function finds the next symbol in the symbol table that falls
  1591. sequentially after the symbol passed in.
  1592. Arguments:
  1593. hProcess - Process handle, must have been previously registered
  1594. with SymInitialize.
  1595. Symbol - Starting symbol.
  1596. Return Value:
  1597. Non NULL pointer - The symbol was located.
  1598. NULL pointer - The symbol was not found. Call GetLastError to
  1599. discover the cause of the failure.
  1600. --*/
  1601. {
  1602. PIMAGEHLP_SYMBOL64 Symbol64;
  1603. BOOL rc = false;
  1604. Symbol64 = (PIMAGEHLP_SYMBOL64)MemAlloc(sizeof(IMAGEHLP_SYMBOL64) + Symbol32->MaxNameLength);
  1605. if (Symbol64) {
  1606. sym2lsym(Symbol32, Symbol64);
  1607. if (SymGetSymPrev64(hProcess, Symbol64)) {
  1608. lsym2sym(Symbol64, Symbol32);
  1609. rc = true;
  1610. }
  1611. MemFree(Symbol64);
  1612. }
  1613. return rc;
  1614. }
  1615. BOOL
  1616. IMAGEAPI
  1617. SymGetSymPrev64(
  1618. IN HANDLE hProcess,
  1619. IN OUT PIMAGEHLP_SYMBOL64 Symbol
  1620. )
  1621. /*++
  1622. Routine Description:
  1623. This function finds the next symbol in the symbol table that falls
  1624. sequentially after the symbol passed in.
  1625. Arguments:
  1626. hProcess - Process handle, must have been previously registered
  1627. with SymInitialize.
  1628. Symbol - Starting symbol.
  1629. Return Value:
  1630. Non NULL pointer - The symbol was located.
  1631. NULL pointer - The symbol was not found. Call GetLastError to
  1632. discover the cause of the failure.
  1633. --*/
  1634. {
  1635. return GetSymNextPrev(hProcess, Symbol, -1);
  1636. }
  1637. BOOL
  1638. GetSymNextPrev(
  1639. IN HANDLE hProcess,
  1640. IN OUT PIMAGEHLP_SYMBOL64 Symbol,
  1641. IN int Direction
  1642. )
  1643. /*++
  1644. Routine Description:
  1645. Common code for SymGetSymNext and SymGetSymPrev.
  1646. Arguments:
  1647. hProcess - Process handle, must have been previously registered
  1648. with SymInitialize.
  1649. Symbol - Starting symbol.
  1650. Dir - Supplies direction to search
  1651. Return Value:
  1652. Non NULL pointer - The symbol was located.
  1653. NULL pointer - The symbol was not found. Call GetLastError to
  1654. discover the cause of the failure.
  1655. --*/
  1656. {
  1657. PPROCESS_ENTRY pe;
  1658. PMODULE_ENTRY mi;
  1659. ULONG64 disp;
  1660. ULONG64 addr;
  1661. PSYMBOL_INFO si;
  1662. PSYMBOL_INFO vssi;
  1663. PSYMBOL_ENTRY se;
  1664. SYMBOL_ENTRY SymEntry = {0};
  1665. __try {
  1666. pe = FindProcessEntry( hProcess );
  1667. if (!pe) {
  1668. SetLastError( ERROR_INVALID_HANDLE );
  1669. return false;
  1670. }
  1671. mi = GetModuleForPC( pe, Symbol->Address, false );
  1672. if (mi == NULL) {
  1673. SetLastError( ERROR_MOD_NOT_FOUND );
  1674. return false;
  1675. }
  1676. if (!LoadSymbols(hProcess, mi, 0)) {
  1677. SetLastError( ERROR_MOD_NOT_FOUND );
  1678. return false;
  1679. }
  1680. addr = Symbol->Address;
  1681. if (mi->dia) {
  1682. si = diaGetSymNextPrev(mi, addr, Direction);
  1683. vssi = vsGetSymNextPrev(mi, addr, Direction);
  1684. si2lsym(si, Symbol);
  1685. } else {
  1686. se = cvGetSymFromAddr(addr, &disp, mi);
  1687. if (se) {
  1688. if (Direction > 0 && se+1 >= mi->symbolTable+mi->numsyms) {
  1689. se = NULL;
  1690. } else if (Direction < 0 && se-1 < mi->symbolTable) {
  1691. se = NULL;
  1692. }
  1693. se += Direction;
  1694. }
  1695. se2lsym(se, Symbol);
  1696. }
  1697. vssi = vsGetSymNextPrev(mi, addr, Direction);
  1698. if (vssi) {
  1699. if (Symbol->Address) {
  1700. if (Direction > 0) {
  1701. if (vssi->Address < Symbol->Address)
  1702. si2lsym(vssi, Symbol);
  1703. } else if (Symbol->Address < vssi->Address) {
  1704. si2lsym(vssi, Symbol);
  1705. }
  1706. } else {
  1707. si2lsym(vssi, Symbol);
  1708. }
  1709. }
  1710. if (!Symbol->Address) {
  1711. SetLastError(ERROR_INVALID_ADDRESS);
  1712. return false;
  1713. }
  1714. return true;
  1715. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1716. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1717. return false;
  1718. }
  1719. return false;
  1720. }
  1721. BOOL
  1722. IMAGEAPI
  1723. SymGetSourceFile(
  1724. IN HANDLE hProcess,
  1725. IN ULONG64 Base,
  1726. IN LPCSTR FileSpec,
  1727. OUT LPSTR FilePath
  1728. )
  1729. {
  1730. PPROCESS_ENTRY pe;
  1731. PMODULE_ENTRY mi;
  1732. PBYTE stream;
  1733. if (!FileSpec || !*FileSpec || !FilePath)
  1734. return error(ERROR_INVALID_PARAMETER);
  1735. if (!g.fnSrcSrvInit)
  1736. return false;
  1737. pe = FindProcessEntry(hProcess);
  1738. if (!pe)
  1739. return error(ERROR_INVALID_HANDLE);
  1740. mi = GetModuleForPC(pe, Base, false);
  1741. if (!mi)
  1742. return error(ERROR_MOD_NOT_FOUND);
  1743. if (!LoadSymbols(hProcess, mi, 0))
  1744. return error(ERROR_MOD_NOT_FOUND);
  1745. if (mi->cbSrcSrv == -1)
  1746. return error(ERROR_NOT_SUPPORTED);
  1747. if (!mi->cbSrcSrv) {
  1748. diaReadStream(mi, "srcsrv", &stream, &mi->cbSrcSrv);
  1749. if (mi->cbSrcSrv)
  1750. gfnSrcSrvLoadModule(pe->hProcess,
  1751. (*mi->AliasName) ? mi->AliasName : mi->ModuleName,
  1752. mi->BaseOfDll,
  1753. stream,
  1754. mi->cbSrcSrv);
  1755. MemFree(stream);
  1756. }
  1757. if (!mi->cbSrcSrv) {
  1758. mi->cbSrcSrv = -1;
  1759. return error(ERROR_NOT_SUPPORTED);
  1760. }
  1761. return gfnSrcSrvGetFile(pe->hProcess, mi->BaseOfDll, FileSpec, FilePath);
  1762. }
  1763. BOOL
  1764. IMAGEAPI
  1765. SymEnumLines(
  1766. IN HANDLE hProcess,
  1767. IN ULONG64 Base,
  1768. IN PCSTR Obj,
  1769. IN PCSTR File,
  1770. IN PSYM_ENUMLINES_CALLBACK EnumLinesCallback,
  1771. IN PVOID UserContext
  1772. )
  1773. {
  1774. PPROCESS_ENTRY pe;
  1775. PMODULE_ENTRY mi;
  1776. __try {
  1777. pe = FindProcessEntry(hProcess);
  1778. if (!pe)
  1779. return error(ERROR_INVALID_HANDLE);
  1780. mi = GetModuleForPC(pe, Base, false);
  1781. if (!mi)
  1782. return error(ERROR_MOD_NOT_FOUND);
  1783. if (!LoadSymbols(hProcess, mi, 0))
  1784. return error(ERROR_MOD_NOT_FOUND);
  1785. if (!mi->dia)
  1786. return error(ERROR_NOT_SUPPORTED);
  1787. return diaEnumLines(pe, mi, Obj, File, EnumLinesCallback, UserContext);
  1788. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1789. ImagepSetLastErrorFromStatus(GetExceptionCode());
  1790. return false;
  1791. }
  1792. return true;
  1793. }
  1794. BOOL
  1795. IMAGEAPI
  1796. SymGetLineFromAddr64(
  1797. IN HANDLE hProcess,
  1798. IN DWORD64 dwAddr,
  1799. OUT PDWORD pdwDisplacement,
  1800. OUT PIMAGEHLP_LINE64 Line
  1801. )
  1802. /*++
  1803. Routine Description:
  1804. This function finds a source file and line number entry for the
  1805. line closest to the given address.
  1806. Arguments:
  1807. hProcess - Process handle, must have been previously registered
  1808. with SymInitialize.
  1809. dwAddr - Supplies an address for which a line is to be
  1810. located.
  1811. pdwDisplacement - Returns the offset between the given address
  1812. and the first instruction of the line.
  1813. Line - Returns the line and file information.
  1814. Return Value:
  1815. true - A line was located.
  1816. false - The line was not found. Call GetLastError to
  1817. discover the cause of the failure.
  1818. --*/
  1819. {
  1820. PPROCESS_ENTRY pe;
  1821. PMODULE_ENTRY mi;
  1822. SRCCODEINFO sci;
  1823. sciInit(&sci);
  1824. __try {
  1825. if (Line->SizeOfStruct != sizeof(IMAGEHLP_LINE64))
  1826. return error(ERROR_INVALID_PARAMETER);
  1827. pe = FindProcessEntry( hProcess );
  1828. if (!pe)
  1829. return error( ERROR_INVALID_HANDLE );
  1830. mi = GetModuleForPC( pe, dwAddr, false );
  1831. if (!mi)
  1832. return error( ERROR_MOD_NOT_FOUND );
  1833. if (!LoadSymbols(hProcess, mi, 0))
  1834. return error( ERROR_MOD_NOT_FOUND );
  1835. if (!GetLineFromAddr(pe, mi, dwAddr, pdwDisplacement, &sci))
  1836. return error( ERROR_INVALID_ADDRESS );
  1837. sci2lline(mi, &sci, Line);
  1838. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1839. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  1840. return false;
  1841. }
  1842. return true;
  1843. }
  1844. BOOL
  1845. IMAGEAPI
  1846. SymGetLineFromAddr(
  1847. IN HANDLE hProcess,
  1848. IN DWORD dwAddr,
  1849. OUT PDWORD pdwDisplacement,
  1850. OUT PIMAGEHLP_LINE Line32
  1851. )
  1852. {
  1853. IMAGEHLP_LINE64 Line64;
  1854. Line64.SizeOfStruct = sizeof(Line64);
  1855. if (SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &Line64)) {
  1856. lline2line(&Line64, Line32);
  1857. return true;
  1858. } else {
  1859. return false;
  1860. }
  1861. }
  1862. BOOL
  1863. IMAGEAPI
  1864. SymGetLineFromName64(
  1865. IN HANDLE hProcess,
  1866. IN LPSTR ModuleName,
  1867. IN LPSTR FileName,
  1868. IN DWORD dwLineNumber,
  1869. OUT PLONG plDisplacement,
  1870. IN OUT PIMAGEHLP_LINE64 Line64
  1871. )
  1872. /*++
  1873. Routine Description:
  1874. This function finds an entry in the source file and line-number
  1875. information based on a particular filename and line number.
  1876. A module name can be given if the search is to be restricted to
  1877. a specific module.
  1878. The filename can be omitted if a pure line number search is desired,
  1879. in which case Line must be a previously filled out line number
  1880. struct. The module and file that Line->Address lies in is used
  1881. to look up the new line number. This cannot be used when a module
  1882. name is given.
  1883. Arguments:
  1884. hProcess - Process handle, must have been previously registered
  1885. with SymInitialize.
  1886. ModuleName - Module name or NULL.
  1887. FileName - File name or NULL.
  1888. dwLineNumber - Line number of interest.
  1889. plDisplacement - Difference between requested line number and
  1890. returned line number.
  1891. Line - Line information input and return.
  1892. Return Value:
  1893. true - A line was located.
  1894. false - A line was not found. Call GetLastError to
  1895. discover the cause of the failure.
  1896. --*/
  1897. {
  1898. PPROCESS_ENTRY pe;
  1899. PMODULE_ENTRY mi = NULL;
  1900. PLIST_ENTRY Next;
  1901. IMAGEHLP_DEFERRED_SYMBOL_LOAD64 idsl64;
  1902. int i;
  1903. PSOURCE_HINT sh;
  1904. char fname[MAX_PATH + 1];
  1905. SRCCODEINFO sci;
  1906. SRCCODEINFO tsci;
  1907. static DWORD flags[3] = {LS_JUST_TEST, LS_QUALIFIED | LS_LOAD_LINES, LS_QUALIFIED | LS_LOAD_LINES};
  1908. static DWORD method[3] = {mFullPath, mFullPath, mName};
  1909. sciInit(&sci);
  1910. sciInit(&tsci);
  1911. __try {
  1912. if (Line64->SizeOfStruct != sizeof(IMAGEHLP_LINE64))
  1913. return error(ERROR_INVALID_PARAMETER);
  1914. // If no file was given then it's assumed that the file
  1915. // is the same as for the line information passed in.
  1916. if (FileName)
  1917. CopyStrArray(fname, FileName);
  1918. else
  1919. CopyStrArray(fname, Line64->FileName ? Line64->FileName : "");
  1920. // get the process
  1921. pe = FindProcessEntry( hProcess );
  1922. if (!pe)
  1923. return error( ERROR_INVALID_HANDLE );
  1924. if (ModuleName != NULL) {
  1925. //
  1926. // The caller wants to look in a specific module.
  1927. // A filename must be given in this case because it doesn't
  1928. // make sense to do an address-driven search when a module
  1929. // is explicitly specified since the address also specifies
  1930. // a module.
  1931. //
  1932. if (!*fname)
  1933. return error(ERROR_INVALID_PARAMETER);
  1934. mi = FindModule(hProcess, pe, ModuleName, true);
  1935. if (mi) {
  1936. if (GetLineFromName(pe, mi, fname, dwLineNumber, plDisplacement, &sci, mFullPath))
  1937. return sci2lline(mi, &sci, Line64);
  1938. if (GetLineFromName(pe, mi, fname, dwLineNumber, plDisplacement, &sci, mName))
  1939. return sci2lline(mi, &sci, Line64);
  1940. return error(ERROR_NOT_FOUND);
  1941. }
  1942. return error( ERROR_MOD_NOT_FOUND );
  1943. }
  1944. if (!*fname) {
  1945. // Only a line number has been given, implying that
  1946. // it's a line in the same file as the given line is currently in.
  1947. mi = GetModuleForPC( pe, Line64->Address, false );
  1948. if (!mi)
  1949. return error( ERROR_MOD_NOT_FOUND );
  1950. if (!LoadSymbols(hProcess, mi, LS_LOAD_LINES))
  1951. return error( ERROR_MOD_NOT_FOUND );
  1952. if (GetLineFromName(pe, mi, fname, dwLineNumber, plDisplacement, &sci, mFullPath))
  1953. return sci2lline(mi, &sci, Line64);
  1954. if (GetLineFromName(pe, mi, fname, dwLineNumber, plDisplacement, &sci, mName))
  1955. return sci2lline(mi, &sci, Line64);
  1956. return error(ERROR_NOT_FOUND);
  1957. }
  1958. sh = FindSourceFileInHintList(pe, fname);
  1959. if (sh) {
  1960. if (GetLineFromName(pe, sh->mi, fname, dwLineNumber, plDisplacement, &sci, mFullPath))
  1961. return sci2lline(sh->mi, &sci, Line64);
  1962. }
  1963. Next = pe->ModuleList.Flink;
  1964. if (!Next)
  1965. return error( ERROR_MOD_NOT_FOUND );
  1966. ClearModuleFlags(pe);
  1967. ZeroMemory(&sci, sizeof(sci));
  1968. // Search for lines in 3 passes.
  1969. //
  1970. // 0. Look for exact match of full path name. Check only modules with symbols loaded.
  1971. // 1. Look for exact match of full path name. Load all unloaded modules.
  1972. // 2. Look for best match of path name. All modules are already loaded.
  1973. for (i = 0; i < 3; i++) {
  1974. Next = pe->ModuleList.Flink;
  1975. while (Next != &pe->ModuleList) {
  1976. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  1977. Next = mi->ListEntry.Flink;
  1978. #ifdef DEBUG
  1979. if (traceSubName(mi->ModuleName)) // for setting debug breakpoints from DBGHELP_TOKEN
  1980. dtrace("debug(%s)\n", mi->ModuleName);
  1981. #endif
  1982. if (mi->processed && (method[i] == mFullPath))
  1983. continue;
  1984. if (!LoadSymbols(hProcess, mi, flags[i])) {
  1985. if (GetLastError() == ERROR_CANCELLED)
  1986. return false;
  1987. continue;
  1988. }
  1989. mi->processed = true;
  1990. if (GetLineFromName(pe, mi, fname, dwLineNumber, plDisplacement, &tsci, method[i])) {
  1991. if (UpdateBestSrc(fname, sci.FileName, tsci.FileName))
  1992. memcpy(&sci, &tsci, sizeof(SRCCODEINFO));
  1993. }
  1994. }
  1995. if (*sci.FileName)
  1996. return sci2lline(mi, &sci, Line64);
  1997. // Only the 1st pass works with loaded symbols. The next pass will try
  1998. // to load the rest. Might as well quit now if the options don't allow it.
  1999. if (option(SYMOPT_NO_UNQUALIFIED_LOADS))
  2000. return error(ERROR_NOT_FOUND);
  2001. }
  2002. return error(ERROR_NOT_FOUND);
  2003. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2004. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2005. return false;
  2006. }
  2007. return error( ERROR_INVALID_FUNCTION );
  2008. }
  2009. BOOL
  2010. IMAGEAPI
  2011. SymGetLineFromName(
  2012. IN HANDLE hProcess,
  2013. IN LPSTR ModuleName,
  2014. IN LPSTR FileName,
  2015. IN DWORD dwLineNumber,
  2016. OUT PLONG plDisplacement,
  2017. IN OUT PIMAGEHLP_LINE Line32
  2018. )
  2019. {
  2020. IMAGEHLP_LINE64 Line64;
  2021. Line64.SizeOfStruct = sizeof(Line64);
  2022. line2lline(Line32, &Line64);
  2023. if (SymGetLineFromName64(hProcess,
  2024. ModuleName,
  2025. FileName,
  2026. dwLineNumber,
  2027. plDisplacement,
  2028. &Line64)) {
  2029. return lline2line(&Line64, Line32) ? true : false;
  2030. } else {
  2031. return false;
  2032. }
  2033. }
  2034. BOOL
  2035. IMAGEAPI
  2036. SymGetLineNext64(
  2037. IN HANDLE hProcess,
  2038. IN OUT PIMAGEHLP_LINE64 Line
  2039. )
  2040. /*++
  2041. Routine Description:
  2042. This function returns line address information for the line immediately
  2043. following the line given.
  2044. Arguments:
  2045. hProcess - Process handle, must have been previously registered
  2046. with SymInitialize.
  2047. Line - Supplies line number information for the line
  2048. prior to the one being located.
  2049. Return Value:
  2050. true - A line was located. The Key, LineNumber and Address
  2051. of Line are updated.
  2052. false - No such line exists. Call GetLastError to
  2053. discover the cause of the failure.
  2054. --*/
  2055. {
  2056. PPROCESS_ENTRY pe;
  2057. PMODULE_ENTRY mi;
  2058. PSOURCE_LINE SrcLine;
  2059. PSOURCE_ENTRY Src;
  2060. __try {
  2061. if (Line->SizeOfStruct != sizeof(IMAGEHLP_LINE64))
  2062. return error(ERROR_INVALID_PARAMETER);
  2063. pe = FindProcessEntry( hProcess );
  2064. if (!pe)
  2065. return error( ERROR_INVALID_HANDLE );
  2066. mi = GetModuleForPC( pe, Line->Address, false );
  2067. if (!mi)
  2068. return error( ERROR_MOD_NOT_FOUND );
  2069. if (!LoadSymbols(hProcess, mi, 0))
  2070. return error( ERROR_MOD_NOT_FOUND );
  2071. if (mi->dia)
  2072. return diaGetLineNext(mi, Line);
  2073. // Use existing information to look up module and then
  2074. // locate the file information. The key could be extended
  2075. // to make this unnecessary but it's done as a validation step
  2076. // more than as a way to save a DWORD.
  2077. SrcLine = (PSOURCE_LINE)Line->Key;
  2078. for (Src = mi->SourceFiles; Src != NULL; Src = Src->Next) {
  2079. if (SrcLine >= Src->LineInfo &&
  2080. SrcLine < Src->LineInfo+Src->Lines) {
  2081. break;
  2082. }
  2083. }
  2084. if (!Src)
  2085. return error(ERROR_INVALID_PARAMETER);
  2086. if (SrcLine == Src->LineInfo+Src->Lines-1)
  2087. return error(ERROR_NO_MORE_ITEMS);
  2088. SrcLine++;
  2089. Line->Key = SrcLine;
  2090. Line->LineNumber = SrcLine->Line;
  2091. Line->Address = SrcLine->Addr;
  2092. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2093. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2094. return false;
  2095. }
  2096. return true;
  2097. }
  2098. BOOL
  2099. IMAGEAPI
  2100. SymGetLineNext(
  2101. IN HANDLE hProcess,
  2102. IN OUT PIMAGEHLP_LINE Line32
  2103. )
  2104. {
  2105. IMAGEHLP_LINE64 Line64;
  2106. Line64.SizeOfStruct = sizeof(Line64);
  2107. line2lline(Line32, &Line64);
  2108. if (SymGetLineNext64(hProcess, &Line64)) {
  2109. return lline2line(&Line64, Line32) ? true : false;
  2110. } else {
  2111. return false;
  2112. }
  2113. }
  2114. BOOL
  2115. IMAGEAPI
  2116. SymGetLinePrev64(
  2117. IN HANDLE hProcess,
  2118. IN OUT PIMAGEHLP_LINE64 Line
  2119. )
  2120. /*++
  2121. Routine Description:
  2122. This function returns line address information for the line immediately
  2123. before the line given.
  2124. Arguments:
  2125. hProcess - Process handle, must have been previously registered
  2126. with SymInitialize.
  2127. Line - Supplies line number information for the line
  2128. after the one being located.
  2129. Return Value:
  2130. true - A line was located. The Key, LineNumber and Address
  2131. of Line are updated.
  2132. false - No such line exists. Call GetLastError to
  2133. discover the cause of the failure.
  2134. --*/
  2135. {
  2136. PPROCESS_ENTRY pe;
  2137. PMODULE_ENTRY mi;
  2138. PSOURCE_LINE SrcLine;
  2139. PSOURCE_ENTRY Src;
  2140. __try {
  2141. if (Line->SizeOfStruct != sizeof(IMAGEHLP_LINE64))
  2142. return error(ERROR_INVALID_PARAMETER);
  2143. pe = FindProcessEntry( hProcess );
  2144. if (!pe)
  2145. return error( ERROR_INVALID_HANDLE );
  2146. mi = GetModuleForPC( pe, Line->Address, false );
  2147. if (!mi)
  2148. return error( ERROR_MOD_NOT_FOUND );
  2149. if (!LoadSymbols(hProcess, mi, 0))
  2150. return error( ERROR_MOD_NOT_FOUND );
  2151. if (mi->dia)
  2152. return diaGetLinePrev(mi, Line);
  2153. // Use existing information to look up module and then
  2154. // locate the file information. The key could be extended
  2155. // to make this unnecessary but it's done as a validation step
  2156. // more than as a way to save a DWORD.
  2157. SrcLine = (PSOURCE_LINE)Line->Key;
  2158. for (Src = mi->SourceFiles; Src != NULL; Src = Src->Next) {
  2159. if (SrcLine >= Src->LineInfo &&
  2160. SrcLine < Src->LineInfo+Src->Lines) {
  2161. break;
  2162. }
  2163. }
  2164. if (!Src)
  2165. return error(ERROR_INVALID_PARAMETER);
  2166. if (SrcLine == Src->LineInfo)
  2167. return error(ERROR_NO_MORE_ITEMS);
  2168. SrcLine--;
  2169. Line->Key = SrcLine;
  2170. Line->LineNumber = SrcLine->Line;
  2171. Line->Address = SrcLine->Addr;
  2172. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2173. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2174. return false;
  2175. }
  2176. return true;
  2177. }
  2178. BOOL
  2179. IMAGEAPI
  2180. SymGetLinePrev(
  2181. IN HANDLE hProcess,
  2182. IN OUT PIMAGEHLP_LINE Line32
  2183. )
  2184. {
  2185. IMAGEHLP_LINE64 Line64;
  2186. Line64.SizeOfStruct = sizeof(Line64);
  2187. line2lline(Line32, &Line64);
  2188. if (SymGetLinePrev64(hProcess, &Line64)) {
  2189. return lline2line(&Line64, Line32) ? true : false;
  2190. } else {
  2191. return false;
  2192. }
  2193. }
  2194. BOOL
  2195. IMAGEAPI
  2196. SymMatchFileName(
  2197. IN LPSTR FileName,
  2198. IN LPSTR Match,
  2199. OUT LPSTR *FileNameStop,
  2200. OUT LPSTR *MatchStop
  2201. )
  2202. /*++
  2203. Routine Description:
  2204. This function attempts to match a string against a filename and path.
  2205. The match string is allowed to be a suffix of the complete filename,
  2206. so this function is useful for matching a plain filename against
  2207. a fully qualified filename.
  2208. Matching begins from the end of both strings and proceeds backwards.
  2209. Matching is case-insensitive and equates \ with /.
  2210. Arguments:
  2211. FileName - Filename to match against.
  2212. Match - String to match against filename.
  2213. FileNameStop - Returns pointer into FileName where matching stopped.
  2214. May be one before FileName for full matches.
  2215. May be NULL.
  2216. MatchStop - Returns pointer info Match where matching stopped.
  2217. May be one before Match for full matches.
  2218. May be NULL.
  2219. Return Value:
  2220. true - Match is a matching suffix of FileName.
  2221. false - Mismatch.
  2222. --*/
  2223. {
  2224. LPSTR pF, pM;
  2225. pF = FileName+strlen(FileName)-1;
  2226. pM = Match+strlen(Match)-1;
  2227. while (pF >= FileName && pM >= Match) {
  2228. int chF, chM;
  2229. chF = tolower(*pF);
  2230. chF = chF == '\\' ? '/' : chF;
  2231. chM = tolower(*pM);
  2232. chM = chM == '\\' ? '/' : chM;
  2233. if (chF != chM) {
  2234. break;
  2235. }
  2236. pF--;
  2237. pM--;
  2238. }
  2239. if (FileNameStop != NULL) {
  2240. *FileNameStop = pF;
  2241. }
  2242. if (MatchStop != NULL) {
  2243. *MatchStop = pM;
  2244. }
  2245. return pM < Match;
  2246. }
  2247. BOOL
  2248. IMAGEAPI
  2249. SymRegisterFunctionEntryCallback(
  2250. IN HANDLE hProcess,
  2251. IN PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction,
  2252. IN PVOID UserContext
  2253. )
  2254. /*++
  2255. Routine Description:
  2256. Set the address of a callback routine to access extended function
  2257. table entries directly. This function is useful when debugging
  2258. Alpha processes where RUNTIME_FUNCTION_ENTRYs are available from
  2259. sources other than in the image. Two existing examples are:
  2260. 1) Access to dynamic function tables for run-time code
  2261. 2) Access to function tables for ROM images
  2262. Arguments:
  2263. hProcess - Process handle, must have been previously registered
  2264. with SymInitialize.
  2265. DirectFunctionTableRoutine - Address of direct function table callback routine.
  2266. On alpha this routine must return a pointer to the
  2267. RUNTIME_FUNCTION_ENTRY containing the specified address.
  2268. If no such entry is available, it must return NULL.
  2269. Return Value:
  2270. true - The callback was successfully registered
  2271. false - The initialization failed. Most likely failure is that
  2272. the hProcess parameter is invalid. Call GetLastError()
  2273. for specific error codes.
  2274. --*/
  2275. {
  2276. PPROCESS_ENTRY pe = NULL;
  2277. __try {
  2278. if (!CallbackFunction)
  2279. return error(ERROR_INVALID_PARAMETER);
  2280. pe = FindProcessEntry( hProcess );
  2281. if (!pe)
  2282. return error(ERROR_INVALID_PARAMETER);
  2283. pe->pFunctionEntryCallback32 = CallbackFunction;
  2284. pe->pFunctionEntryCallback64 = NULL;
  2285. pe->FunctionEntryUserContext = (ULONG64)UserContext;
  2286. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2287. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2288. return false;
  2289. }
  2290. return true;
  2291. }
  2292. BOOL
  2293. IMAGEAPI
  2294. SymRegisterFunctionEntryCallback64(
  2295. IN HANDLE hProcess,
  2296. IN PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction,
  2297. IN ULONG64 UserContext
  2298. )
  2299. /*++
  2300. Routine Description:
  2301. See SymRegisterFunctionEntryCallback64
  2302. --*/
  2303. {
  2304. PPROCESS_ENTRY pe = NULL;
  2305. __try {
  2306. if (!CallbackFunction)
  2307. return error(ERROR_INVALID_PARAMETER);
  2308. pe = FindProcessEntry( hProcess );
  2309. if (!pe)
  2310. return error(ERROR_INVALID_PARAMETER);
  2311. pe->pFunctionEntryCallback32 = NULL;
  2312. pe->pFunctionEntryCallback64 = CallbackFunction;
  2313. pe->FunctionEntryUserContext = (ULONG64)UserContext;
  2314. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2315. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2316. return false;
  2317. }
  2318. return true;
  2319. }
  2320. LPVOID
  2321. IMAGEAPI
  2322. SymFunctionTableAccess(
  2323. HANDLE hProcess,
  2324. DWORD AddrBase
  2325. )
  2326. {
  2327. return SymFunctionTableAccess64(hProcess, EXTEND64(AddrBase));
  2328. }
  2329. LPVOID
  2330. IMAGEAPI
  2331. SymFunctionTableAccess64(
  2332. HANDLE hProcess,
  2333. DWORD64 AddrBase
  2334. )
  2335. /*++
  2336. Routine Description:
  2337. This function finds a function table entry or FPO record for an address.
  2338. Arguments:
  2339. hProcess - Process handle, must have been previously registered
  2340. with SymInitialize.
  2341. AddrBase - Supplies an address for which a function table entry
  2342. or FPO entry is to be located.
  2343. Return Value:
  2344. Non NULL pointer - The symbol was located.
  2345. NULL pointer - The symbol was not found. Call GetLastError to
  2346. discover the cause of the failure.
  2347. --*/
  2348. {
  2349. PPROCESS_ENTRY pe;
  2350. PMODULE_ENTRY mi;
  2351. PVOID rtf;
  2352. ULONG_PTR rva;
  2353. DWORD bias;
  2354. DWORD MachineType;
  2355. __try {
  2356. pe = FindProcessEntry( hProcess );
  2357. if (!pe) {
  2358. SetLastError(ERROR_INVALID_HANDLE);
  2359. return NULL;
  2360. }
  2361. // Dynamically generated function table entries
  2362. // may not be in a module, so failing to
  2363. // find a module is not a fatal error.
  2364. mi = GetModuleForPC( pe, AddrBase, false );
  2365. if (mi != NULL) {
  2366. if (!LoadSymbols(hProcess, mi, 0)) {
  2367. SetLastError(ERROR_MOD_NOT_FOUND);
  2368. return NULL;
  2369. }
  2370. MachineType = mi->MachineType;
  2371. } else {
  2372. // We need to guess what kind of machine we
  2373. // should be working with. First see if ntdll
  2374. // is loaded and if so use its machine type.
  2375. mi = FindModule(hProcess, pe, "ntdll", true);
  2376. if (mi != NULL) {
  2377. MachineType = mi->MachineType;
  2378. } else if (pe->ModuleList.Flink != NULL) {
  2379. // Try the first module's type.
  2380. mi = CONTAINING_RECORD( pe->ModuleList.Flink,
  2381. MODULE_ENTRY, ListEntry );
  2382. } else {
  2383. // Use the complation machine.
  2384. #if defined(_M_IX86)
  2385. MachineType = IMAGE_FILE_MACHINE_I386;
  2386. #elif defined(_M_IA64)
  2387. MachineType = IMAGE_FILE_MACHINE_IA64;
  2388. #elif defined(_M_AMD64)
  2389. MachineType = IMAGE_FILE_MACHINE_AMD64;
  2390. #else
  2391. #error( "unknown target machine" );
  2392. #endif
  2393. }
  2394. }
  2395. switch (MachineType) {
  2396. default:
  2397. rtf = NULL;
  2398. break;
  2399. case IMAGE_FILE_MACHINE_I386:
  2400. rtf = NULL;
  2401. if (mi == NULL) {
  2402. SetLastError( ERROR_MOD_NOT_FOUND );
  2403. break;
  2404. }
  2405. DWORD64 caddr;
  2406. if (!mi->pFpoData)
  2407. break;
  2408. caddr = ConvertOmapToSrc( mi, AddrBase, &bias, true );
  2409. if (caddr)
  2410. AddrBase = caddr + bias;
  2411. rtf = SwSearchFpoData( (ULONG)(AddrBase - mi->BaseOfDll), mi->pFpoData, mi->dwEntries );
  2412. if (rtf && mi->cOmapFrom && mi->pFpoDataOmap) {
  2413. rva = (ULONG_PTR)rtf - (ULONG_PTR)mi->pFpoData;
  2414. rtf = (PBYTE)mi->pFpoDataOmap + rva;
  2415. }
  2416. break;
  2417. case IMAGE_FILE_MACHINE_IA64:
  2418. rtf = LookupFunctionEntryIa64(hProcess, AddrBase);
  2419. break;
  2420. case IMAGE_FILE_MACHINE_AMD64:
  2421. rtf = LookupFunctionEntryAmd64(hProcess, AddrBase);
  2422. break;
  2423. }
  2424. if (!rtf) {
  2425. SetLastError(ERROR_INVALID_ADDRESS);
  2426. return NULL;
  2427. }
  2428. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2429. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2430. return NULL;
  2431. }
  2432. return rtf;
  2433. }
  2434. BOOL
  2435. IMAGEAPI
  2436. SymGetModuleInfo64(
  2437. IN HANDLE hProcess,
  2438. IN DWORD64 dwAddr,
  2439. OUT PIMAGEHLP_MODULE64 ModuleInfo
  2440. )
  2441. {
  2442. PPROCESS_ENTRY pe;
  2443. PMODULE_ENTRY mi;
  2444. DWORD SizeOfStruct;
  2445. DWORD dw = sizeof(CVDD);
  2446. __try {
  2447. pe = FindProcessEntry( hProcess );
  2448. if (!pe)
  2449. return error( ERROR_INVALID_HANDLE );
  2450. mi = GetModuleForPC( pe, dwAddr, false );
  2451. if (!mi)
  2452. return error( ERROR_MOD_NOT_FOUND );
  2453. SizeOfStruct = ModuleInfo->SizeOfStruct;
  2454. if (SizeOfStruct > sizeof(IMAGEHLP_MODULE64))
  2455. return error( ERROR_INVALID_PARAMETER );
  2456. ZeroMemory( ModuleInfo, SizeOfStruct);
  2457. ModuleInfo->SizeOfStruct = SizeOfStruct;
  2458. ModuleInfo->BaseOfImage = mi->BaseOfDll;
  2459. ModuleInfo->ImageSize = mi->DllSize;
  2460. ModuleInfo->NumSyms = mi->numsyms;
  2461. ModuleInfo->CheckSum = mi->CheckSum;
  2462. ModuleInfo->TimeDateStamp = mi->TimeDateStamp;
  2463. ModuleInfo->SymType = mi->SymType;
  2464. ModuleInfo->ModuleName[0] = 0;
  2465. CatString( ModuleInfo->ModuleName, mi->ModuleName, sizeof(ModuleInfo->ModuleName));
  2466. ModuleInfo->ImageName[0] = 0;
  2467. if (mi->ImageName)
  2468. CopyStrArray(ModuleInfo->ImageName, mi->ImageName);
  2469. ModuleInfo->LoadedImageName[0] = 0;
  2470. if (mi->LoadedImageName)
  2471. CopyStrArray(ModuleInfo->LoadedImageName, mi->LoadedImageName);
  2472. // if (ModuleInfo->SizeofStruct == 0x248) // the original size
  2473. // return true
  2474. // the following code supports the expanded structure
  2475. if (ModuleInfo->SizeOfStruct < sizeof(IMAGEHLP_MODULE64))
  2476. return true;
  2477. ModuleInfo->LoadedPdbName[0] = 0;
  2478. if (mi->LoadedPdbName)
  2479. CopyStrArray(ModuleInfo->LoadedPdbName, mi->LoadedPdbName);
  2480. ModuleInfo->CVSig = mi->cvSig;
  2481. ModuleInfo->PdbSig = mi->pdbdataSig;
  2482. memcpy(&ModuleInfo->PdbSig70, &mi->pdbdataGuid, sizeof(GUID));
  2483. ModuleInfo->PdbAge = mi->pdbdataAge;
  2484. ModuleInfo->PdbUnmatched = mi->fPdbUnmatched;
  2485. ModuleInfo->DbgUnmatched = mi->fDbgUnmatched;
  2486. ModuleInfo->LineNumbers = mi->fLines;
  2487. ModuleInfo->GlobalSymbols = mi->fSymbols;
  2488. ModuleInfo->TypeInfo = mi->fTypes;
  2489. switch (mi->CVRec.dwSig)
  2490. {
  2491. case '01BN':
  2492. CopyString(ModuleInfo->CVData, mi->CVRec.nb10i.szPdb, MAX_PATH * 3);
  2493. break;
  2494. case 'SDSR':
  2495. CopyString(ModuleInfo->CVData, mi->CVRec.rsdsi.szPdb, MAX_PATH * 3);
  2496. break;
  2497. }
  2498. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2499. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2500. return false;
  2501. }
  2502. return true;
  2503. }
  2504. BOOL
  2505. IMAGEAPI
  2506. SymGetModuleInfoW(
  2507. IN HANDLE hProcess,
  2508. IN DWORD dwAddr,
  2509. OUT PIMAGEHLP_MODULEW wModInfo
  2510. )
  2511. {
  2512. IMAGEHLP_MODULE aModInfo;
  2513. if (wModInfo->SizeOfStruct != sizeof(IMAGEHLP_MODULEW))
  2514. return error(ERROR_INVALID_PARAMETER);
  2515. ZeroMemory(wModInfo, sizeof(IMAGEHLP_MODULEW));
  2516. wModInfo->SizeOfStruct = sizeof(IMAGEHLP_MODULEW);
  2517. if (!SympConvertUnicodeModule32ToAnsiModule32(
  2518. wModInfo, &aModInfo))
  2519. {
  2520. return error(ERROR_INVALID_PARAMETER);
  2521. }
  2522. if (!SymGetModuleInfo(hProcess, dwAddr, &aModInfo)) {
  2523. return false;
  2524. }
  2525. if (!SympConvertAnsiModule32ToUnicodeModule32(
  2526. &aModInfo, wModInfo)) {
  2527. return false;
  2528. }
  2529. return true;
  2530. }
  2531. BOOL
  2532. IMAGEAPI
  2533. SymGetModuleInfoW64(
  2534. IN HANDLE hProcess,
  2535. IN DWORD64 dwAddr,
  2536. OUT PIMAGEHLP_MODULEW64 wModInfo
  2537. )
  2538. {
  2539. IMAGEHLP_MODULE64 aModInfo;
  2540. if (!SympConvertUnicodeModule64ToAnsiModule64(
  2541. wModInfo, &aModInfo)) {
  2542. return false;
  2543. }
  2544. if (!SymGetModuleInfo64(hProcess, dwAddr, &aModInfo)) {
  2545. return false;
  2546. }
  2547. if (!SympConvertAnsiModule64ToUnicodeModule64(
  2548. &aModInfo, wModInfo)) {
  2549. return false;
  2550. }
  2551. return true;
  2552. }
  2553. BOOL
  2554. IMAGEAPI
  2555. SymGetModuleInfo(
  2556. IN HANDLE hProcess,
  2557. IN DWORD dwAddr,
  2558. OUT PIMAGEHLP_MODULE ModuleInfo
  2559. )
  2560. {
  2561. PPROCESS_ENTRY pe;
  2562. PMODULE_ENTRY mi;
  2563. DWORD SizeOfStruct;
  2564. __try {
  2565. pe = FindProcessEntry( hProcess );
  2566. if (!pe)
  2567. return error( ERROR_INVALID_HANDLE );
  2568. mi = GetModuleForPC( pe,
  2569. dwAddr == (DWORD)-1 ? (DWORD64)-1 : dwAddr, false );
  2570. if (!mi)
  2571. return error( ERROR_MOD_NOT_FOUND );
  2572. SizeOfStruct = ModuleInfo->SizeOfStruct;
  2573. if (SizeOfStruct > sizeof(IMAGEHLP_MODULE))
  2574. return error( ERROR_INVALID_PARAMETER );
  2575. ZeroMemory( ModuleInfo, SizeOfStruct);
  2576. ModuleInfo->SizeOfStruct = SizeOfStruct;
  2577. ModuleInfo->BaseOfImage = (DWORD)mi->BaseOfDll;
  2578. ModuleInfo->ImageSize = mi->DllSize;
  2579. ModuleInfo->NumSyms = mi->numsyms;
  2580. ModuleInfo->CheckSum = mi->CheckSum;
  2581. ModuleInfo->TimeDateStamp = mi->TimeDateStamp;
  2582. ModuleInfo->SymType = mi->SymType;
  2583. ModuleInfo->ModuleName[0] = 0;
  2584. CatString( ModuleInfo->ModuleName, mi->ModuleName, sizeof(ModuleInfo->ModuleName));
  2585. if (mi->ImageName)
  2586. CopyStrArray(ModuleInfo->ImageName, mi->ImageName);
  2587. if (mi->LoadedImageName)
  2588. CopyStrArray(ModuleInfo->LoadedImageName, mi->LoadedImageName);
  2589. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2590. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2591. return false;
  2592. }
  2593. return true;
  2594. }
  2595. DWORD64
  2596. IMAGEAPI
  2597. SymGetModuleBase64(
  2598. IN HANDLE hProcess,
  2599. IN DWORD64 dwAddr
  2600. )
  2601. {
  2602. PPROCESS_ENTRY pe;
  2603. PMODULE_ENTRY mi;
  2604. __try {
  2605. pe = FindProcessEntry( hProcess );
  2606. if (!pe) {
  2607. return 0;
  2608. }
  2609. mi = GetModuleForPC( pe, dwAddr, false );
  2610. if (mi == NULL) {
  2611. return 0;
  2612. }
  2613. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2614. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2615. return false;
  2616. }
  2617. return mi->BaseOfDll;
  2618. }
  2619. DWORD
  2620. IMAGEAPI
  2621. SymGetModuleBase(
  2622. IN HANDLE hProcess,
  2623. IN DWORD dwAddr
  2624. )
  2625. {
  2626. return (ULONG)SymGetModuleBase64(hProcess, dwAddr);
  2627. }
  2628. BOOL
  2629. IMAGEAPI
  2630. SymUnloadModule64(
  2631. IN HANDLE hProcess,
  2632. IN DWORD64 BaseOfDll
  2633. )
  2634. /*++
  2635. Routine Description:
  2636. Remove the symbols for an image from a process' symbol table.
  2637. Arguments:
  2638. hProcess - Supplies the token which refers to the process
  2639. BaseOfDll - Supplies the offset to the image as supplies by the
  2640. LOAD_DLL_DEBUG_EVENT and UNLOAD_DLL_DEBUG_EVENT.
  2641. Return Value:
  2642. Returns true if the module's symbols were successfully unloaded.
  2643. Returns false if the symbol handler does not recognize hProcess or
  2644. no image was loaded at the given offset.
  2645. --*/
  2646. {
  2647. PPROCESS_ENTRY pe;
  2648. PLIST_ENTRY next;
  2649. PMODULE_ENTRY mi;
  2650. __try {
  2651. pe = FindProcessEntry(hProcess);
  2652. if (!pe) {
  2653. return false;
  2654. }
  2655. next = pe->ModuleList.Flink;
  2656. if (next) {
  2657. while (next != &pe->ModuleList) {
  2658. mi = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
  2659. if (mi->BaseOfDll == BaseOfDll) {
  2660. RemoveEntryList(next);
  2661. gfnSrcSrvUnloadModule(hProcess, mi->BaseOfDll);
  2662. FreeModuleEntry(pe, mi);
  2663. ZeroMemory(pe->DiaCache, sizeof(pe->DiaCache));
  2664. ZeroMemory(pe->DiaLargeData, sizeof(pe->DiaLargeData));
  2665. return true;
  2666. }
  2667. next = mi->ListEntry.Flink;
  2668. }
  2669. }
  2670. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2671. ImagepSetLastErrorFromStatus(GetExceptionCode());
  2672. return false;
  2673. }
  2674. return false;
  2675. }
  2676. BOOL
  2677. IMAGEAPI
  2678. SymUnloadModule(
  2679. IN HANDLE hProcess,
  2680. IN DWORD BaseOfDll
  2681. )
  2682. {
  2683. return SymUnloadModule64(hProcess, BaseOfDll);
  2684. }
  2685. DWORD64
  2686. IMAGEAPI
  2687. SymLoadModuleEx(
  2688. IN HANDLE hProcess,
  2689. IN HANDLE hFile,
  2690. IN PSTR ImageName,
  2691. IN PSTR ModuleName,
  2692. IN DWORD64 BaseOfDll,
  2693. IN DWORD DllSize,
  2694. IN PMODLOAD_DATA Data,
  2695. IN DWORD Flags
  2696. )
  2697. /*++
  2698. Routine Description:
  2699. Loads the symbols for an image for use by the other Sym functions.
  2700. Arguments:
  2701. hProcess - Supplies unique process identifier.
  2702. hFile -
  2703. ImageName - Supplies the name of the image file.
  2704. ModuleName - ???? Supplies the module name that will be returned by
  2705. enumeration functions ????
  2706. BaseOfDll - Supplies loaded base address of image.
  2707. DllSize
  2708. Return Value:
  2709. --*/
  2710. {
  2711. __try {
  2712. return LoadModule( hProcess, ImageName, ModuleName, BaseOfDll, DllSize, hFile, Data, Flags );
  2713. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2714. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2715. return 0;
  2716. }
  2717. }
  2718. DWORD64
  2719. IMAGEAPI
  2720. SymLoadModule64(
  2721. IN HANDLE hProcess,
  2722. IN HANDLE hFile,
  2723. IN PSTR ImageName,
  2724. IN PSTR ModuleName,
  2725. IN DWORD64 BaseOfDll,
  2726. IN DWORD DllSize
  2727. )
  2728. {
  2729. return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, DllSize, NULL, 0);
  2730. }
  2731. DWORD
  2732. IMAGEAPI
  2733. SymLoadModule(
  2734. IN HANDLE hProcess,
  2735. IN HANDLE hFile,
  2736. IN PSTR ImageName,
  2737. IN PSTR ModuleName,
  2738. IN DWORD BaseOfDll,
  2739. IN DWORD DllSize
  2740. )
  2741. {
  2742. return (DWORD)SymLoadModule64( hProcess, hFile, ImageName, ModuleName, BaseOfDll, DllSize );
  2743. }
  2744. BOOL
  2745. IMAGEAPI
  2746. SymUnDName(
  2747. IN PIMAGEHLP_SYMBOL sym,
  2748. OUT LPSTR UnDecName,
  2749. OUT DWORD UnDecNameLength
  2750. )
  2751. {
  2752. __try {
  2753. if (SymUnDNameInternal( UnDecName,
  2754. UnDecNameLength-1,
  2755. sym->Name,
  2756. strlen(sym->Name),
  2757. IMAGE_FILE_MACHINE_UNKNOWN,
  2758. true )) {
  2759. return true;
  2760. } else {
  2761. return false;
  2762. }
  2763. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2764. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2765. return false;
  2766. }
  2767. }
  2768. BOOL
  2769. IMAGEAPI
  2770. SymUnDName64(
  2771. IN PIMAGEHLP_SYMBOL64 sym,
  2772. OUT LPSTR UnDecName,
  2773. OUT DWORD UnDecNameLength
  2774. )
  2775. {
  2776. __try {
  2777. if (SymUnDNameInternal( UnDecName,
  2778. UnDecNameLength-1,
  2779. sym->Name,
  2780. strlen(sym->Name),
  2781. IMAGE_FILE_MACHINE_UNKNOWN,
  2782. true )) {
  2783. return true;
  2784. } else {
  2785. return false;
  2786. }
  2787. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2788. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2789. return false;
  2790. }
  2791. }
  2792. BOOL
  2793. IMAGEAPI
  2794. SymGetSearchPath(
  2795. IN HANDLE hProcess,
  2796. OUT LPSTR SearchPath,
  2797. IN DWORD SearchPathLength
  2798. )
  2799. /*++
  2800. Routine Description:
  2801. This function looks up the symbol search path associated with a process.
  2802. Arguments:
  2803. hProcess - Supplies the token associated with a process.
  2804. Return Value:
  2805. A pointer to the search path. Returns NULL if the process is not
  2806. know to the symbol handler.
  2807. --*/
  2808. {
  2809. PPROCESS_ENTRY pe;
  2810. __try {
  2811. pe = FindProcessEntry( hProcess );
  2812. if (!pe) {
  2813. return false;
  2814. }
  2815. SearchPath[0] = 0;
  2816. CatString( SearchPath, pe->SymbolSearchPath, SearchPathLength );
  2817. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2818. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2819. return false;
  2820. }
  2821. return true;
  2822. }
  2823. BOOL
  2824. IMAGEAPI
  2825. SymSetSearchPath(
  2826. HANDLE hProcess,
  2827. LPSTR UserSearchPath
  2828. )
  2829. /*++
  2830. Routine Description:
  2831. This functions sets the searh path to be used by the symbol loader
  2832. for the given process. If UserSearchPath is not supplied, a default
  2833. path will be used.
  2834. Arguments:
  2835. hProcess - Supplies the process token associated with a symbol table.
  2836. UserSearchPath - Supplies the new search path to associate with the
  2837. process. If this argument is NULL, the following path is generated:
  2838. .;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%
  2839. It is ok if any or all of the environment variables is missing.
  2840. Return Value:
  2841. A pointer to the new search path. The user should not modify this string.
  2842. Returns NULL if the process is not known to the symbol handler.
  2843. --*/
  2844. {
  2845. PPROCESS_ENTRY pe;
  2846. LPSTR p;
  2847. DWORD cbSymPath;
  2848. DWORD cb;
  2849. char ExpandedSearchPath[MAX_PATH];
  2850. __try {
  2851. pe = FindProcessEntry( hProcess );
  2852. if (!pe) {
  2853. return false;
  2854. }
  2855. if (pe->SymbolSearchPath) {
  2856. MemFree(pe->SymbolSearchPath);
  2857. }
  2858. if (UserSearchPath) {
  2859. cbSymPath = ExpandEnvironmentStrings(UserSearchPath,
  2860. ExpandedSearchPath,
  2861. sizeof(ExpandedSearchPath) / sizeof(ExpandedSearchPath[0]));
  2862. if (cbSymPath < sizeof(ExpandedSearchPath)/sizeof(ExpandedSearchPath[0])) {
  2863. pe->SymbolSearchPath = StringDup(ExpandedSearchPath);
  2864. } else {
  2865. pe->SymbolSearchPath = (LPSTR)MemAlloc( cbSymPath );
  2866. ExpandEnvironmentStrings(UserSearchPath,
  2867. pe->SymbolSearchPath,
  2868. cbSymPath );
  2869. }
  2870. } else {
  2871. //
  2872. // ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%
  2873. //
  2874. cbSymPath = 3; // ".;" and ";" between env vars.
  2875. //
  2876. // GetEnvironmentVariable returns the size of the string
  2877. // INCLUDING the '\0' in this case.
  2878. //
  2879. if (!option(SYMOPT_IGNORE_NT_SYMPATH)) {
  2880. cbSymPath += GetEnvironmentVariable( SYMBOL_PATH, NULL, 0 );
  2881. cbSymPath += GetEnvironmentVariable( ALTERNATE_SYMBOL_PATH, NULL, 0 );
  2882. }
  2883. p = pe->SymbolSearchPath = (LPSTR) MemAlloc( cbSymPath );
  2884. if (!p) {
  2885. return false;
  2886. }
  2887. *p++ = '.';
  2888. --cbSymPath;
  2889. if (!option(SYMOPT_IGNORE_NT_SYMPATH)) {
  2890. cb = GetEnvironmentVariable(SYMBOL_PATH, p+1, cbSymPath-1);
  2891. if (cb) {
  2892. *p = ';';
  2893. p += cb+1;
  2894. cbSymPath -= cb+1;
  2895. }
  2896. cb = GetEnvironmentVariable(ALTERNATE_SYMBOL_PATH, p+1, cbSymPath-1);
  2897. if (cb) {
  2898. *p = ';';
  2899. p += cb+1;
  2900. }
  2901. }
  2902. *p = 0;
  2903. }
  2904. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2905. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2906. return false;
  2907. }
  2908. symsrvClose();
  2909. return true;
  2910. }
  2911. BOOL
  2912. IMAGEAPI
  2913. EnumerateLoadedModules(
  2914. IN HANDLE hProcess,
  2915. IN PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
  2916. IN PVOID UserContext
  2917. )
  2918. {
  2919. LOADED_MODULE lm;
  2920. DWORD status = NO_ERROR;
  2921. __try {
  2922. lm.EnumLoadedModulesCallback32 = EnumLoadedModulesCallback;
  2923. lm.EnumLoadedModulesCallback64 = NULL;
  2924. lm.Context = UserContext;
  2925. status = GetProcessModules( hProcess, (PGET_MODULE)LoadedModuleEnumerator, (PVOID)&lm );
  2926. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2927. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2928. return false;
  2929. }
  2930. return (status == NO_ERROR);
  2931. }
  2932. BOOL
  2933. IMAGEAPI
  2934. EnumerateLoadedModules64(
  2935. IN HANDLE hProcess,
  2936. IN PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,
  2937. IN PVOID UserContext
  2938. )
  2939. {
  2940. LOADED_MODULE lm;
  2941. DWORD status = NO_ERROR;
  2942. __try {
  2943. lm.EnumLoadedModulesCallback64 = EnumLoadedModulesCallback;
  2944. lm.EnumLoadedModulesCallback32 = NULL;
  2945. lm.Context = UserContext;
  2946. status = GetProcessModules(hProcess,
  2947. (PGET_MODULE)LoadedModuleEnumerator,
  2948. (PVOID)&lm );
  2949. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2950. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2951. return false;
  2952. }
  2953. return (status == NO_ERROR);
  2954. }
  2955. BOOL
  2956. IMAGEAPI
  2957. SymRegisterCallback(
  2958. IN HANDLE hProcess,
  2959. IN PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
  2960. IN PVOID UserContext
  2961. )
  2962. {
  2963. PPROCESS_ENTRY pe = NULL;
  2964. __try {
  2965. if (!CallbackFunction)
  2966. return error(ERROR_INVALID_PARAMETER);
  2967. pe = FindProcessEntry( hProcess );
  2968. if (!pe)
  2969. return error(ERROR_INVALID_PARAMETER);
  2970. pe->pCallbackFunction32 = CallbackFunction;
  2971. pe->pCallbackFunction64 = NULL;
  2972. pe->CallbackUserContext = (ULONG64)UserContext;
  2973. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2974. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2975. return false;
  2976. }
  2977. return true;
  2978. }
  2979. BOOL
  2980. IMAGEAPI
  2981. SymRegisterCallback64(
  2982. IN HANDLE hProcess,
  2983. IN PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,
  2984. IN ULONG64 UserContext
  2985. )
  2986. {
  2987. PPROCESS_ENTRY pe = NULL;
  2988. __try {
  2989. if (!CallbackFunction)
  2990. return error(ERROR_INVALID_PARAMETER);
  2991. pe = FindProcessEntry( hProcess );
  2992. if (!pe)
  2993. return error(ERROR_INVALID_PARAMETER);
  2994. pe->pCallbackFunction32 = NULL;
  2995. pe->pCallbackFunction64 = CallbackFunction;
  2996. pe->CallbackUserContext = UserContext;
  2997. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2998. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  2999. return false;
  3000. }
  3001. return true;
  3002. }
  3003. void
  3004. InitModuleEntry(
  3005. PMODULE_ENTRY mi
  3006. )
  3007. {
  3008. ZeroMemory(mi, sizeof(MODULE_ENTRY));
  3009. mi->si.MaxNameLen = 2048;
  3010. mi->vssi.MaxNameLen = 2048;
  3011. mi->cGlobals = -1;
  3012. mi->SymType = SymDeferred;
  3013. }
  3014. BOOL
  3015. SympConvertAnsiModule32ToUnicodeModule32(
  3016. PIMAGEHLP_MODULE aMod32,
  3017. PIMAGEHLP_MODULEW wMod32
  3018. )
  3019. {
  3020. ZeroMemory(wMod32, sizeof(*wMod32));
  3021. wMod32->SizeOfStruct = sizeof(*wMod32);
  3022. wMod32->BaseOfImage = aMod32->BaseOfImage;
  3023. wMod32->ImageSize = aMod32->ImageSize;
  3024. wMod32->TimeDateStamp = aMod32->TimeDateStamp;
  3025. wMod32->CheckSum = aMod32->CheckSum;
  3026. wMod32->NumSyms = aMod32->NumSyms;
  3027. wMod32->SymType = aMod32->SymType;
  3028. if (!ansi2wcs(aMod32->ModuleName, wMod32->ModuleName, 256))
  3029. return false;
  3030. if (!ansi2wcs(aMod32->ImageName, wMod32->ImageName, 256))
  3031. return false;
  3032. if (!ansi2wcs(aMod32->LoadedImageName, wMod32->LoadedImageName, 256))
  3033. return false;
  3034. return true;
  3035. }
  3036. BOOL
  3037. SympConvertUnicodeModule32ToAnsiModule32(
  3038. PIMAGEHLP_MODULEW wMod32,
  3039. PIMAGEHLP_MODULE aMod32
  3040. )
  3041. {
  3042. ZeroMemory(aMod32, sizeof(*aMod32));
  3043. aMod32->SizeOfStruct = sizeof(*aMod32);
  3044. aMod32->BaseOfImage = wMod32->BaseOfImage;
  3045. aMod32->ImageSize = wMod32->ImageSize;
  3046. aMod32->TimeDateStamp = wMod32->TimeDateStamp;
  3047. aMod32->CheckSum = wMod32->CheckSum;
  3048. aMod32->NumSyms = wMod32->NumSyms;
  3049. aMod32->SymType = wMod32->SymType;
  3050. if (!wcs2ansi(wMod32->ModuleName, aMod32->ModuleName, DIMA(wMod32->ModuleName)))
  3051. return false;
  3052. if (!wcs2ansi(wMod32->ImageName, aMod32->ImageName, DIMA(wMod32->ImageName)))
  3053. return false;
  3054. if (!wcs2ansi(wMod32->LoadedImageName, aMod32->LoadedImageName, DIMA(wMod32->LoadedImageName)))
  3055. return false;
  3056. return true;
  3057. }
  3058. BOOL
  3059. SympConvertAnsiModule64ToUnicodeModule64(
  3060. PIMAGEHLP_MODULE64 aMod64,
  3061. PIMAGEHLP_MODULEW64 wMod64
  3062. )
  3063. {
  3064. ZeroMemory(wMod64, sizeof(*wMod64));
  3065. wMod64->SizeOfStruct = sizeof(*wMod64);
  3066. wMod64->BaseOfImage = aMod64->BaseOfImage;
  3067. wMod64->ImageSize = aMod64->ImageSize;
  3068. wMod64->TimeDateStamp = aMod64->TimeDateStamp;
  3069. wMod64->CheckSum = aMod64->CheckSum;
  3070. wMod64->NumSyms = aMod64->NumSyms;
  3071. wMod64->SymType = aMod64->SymType;
  3072. if (!ansi2wcs(aMod64->ModuleName, wMod64->ModuleName, 256))
  3073. return false;
  3074. if (!ansi2wcs(aMod64->ImageName, wMod64->ImageName, 256))
  3075. return false;
  3076. if (!ansi2wcs(aMod64->LoadedImageName, wMod64->LoadedImageName, 256))
  3077. return false;
  3078. if (aMod64->SizeOfStruct < sizeof(IMAGEHLP_MODULE64))
  3079. return true;
  3080. if (!ansi2wcs(aMod64->LoadedPdbName, wMod64->LoadedPdbName, 256))
  3081. return false;
  3082. wMod64->CVSig = aMod64->CVSig;
  3083. if (!ansi2wcs(aMod64->CVData, wMod64->CVData, MAX_PATH * 3))
  3084. return false;
  3085. wMod64->PdbSig = aMod64->PdbSig;
  3086. memcpy(&wMod64->PdbSig70, &aMod64->PdbSig70, sizeof(GUID));
  3087. wMod64->PdbAge = aMod64->PdbAge;
  3088. wMod64->PdbUnmatched = aMod64->PdbUnmatched;
  3089. wMod64->DbgUnmatched = aMod64->DbgUnmatched;
  3090. wMod64->LineNumbers = aMod64->LineNumbers;
  3091. wMod64->GlobalSymbols = aMod64->GlobalSymbols;
  3092. wMod64->TypeInfo = aMod64->TypeInfo;
  3093. return true;
  3094. }
  3095. BOOL
  3096. SympConvertUnicodeModule64ToAnsiModule64(
  3097. PIMAGEHLP_MODULEW64 wMod64,
  3098. PIMAGEHLP_MODULE64 aMod64
  3099. )
  3100. {
  3101. ZeroMemory(aMod64, sizeof(*aMod64));
  3102. aMod64->SizeOfStruct = sizeof(*aMod64);
  3103. aMod64->BaseOfImage = wMod64->BaseOfImage;
  3104. aMod64->ImageSize = wMod64->ImageSize;
  3105. aMod64->TimeDateStamp = wMod64->TimeDateStamp;
  3106. aMod64->CheckSum = wMod64->CheckSum;
  3107. aMod64->NumSyms = wMod64->NumSyms;
  3108. aMod64->SymType = wMod64->SymType;
  3109. if (!wcs2ansi(wMod64->ModuleName, aMod64->ModuleName, DIMA(wMod64->ModuleName)))
  3110. return false;
  3111. if (!wcs2ansi(wMod64->ImageName, aMod64->ImageName, DIMA(wMod64->ImageName)))
  3112. return false;
  3113. if (!wcs2ansi(wMod64->LoadedImageName, aMod64->LoadedImageName, DIMA(wMod64->LoadedImageName)))
  3114. return false;
  3115. return true;
  3116. }
  3117. BOOL
  3118. IMAGEAPI
  3119. SymAddSymbol(
  3120. IN HANDLE hProcess,
  3121. IN ULONG64 BaseOfDll,
  3122. IN PCSTR Name,
  3123. IN DWORD64 Address,
  3124. IN DWORD Size,
  3125. IN DWORD Flags
  3126. )
  3127. {
  3128. PPROCESS_ENTRY pe;
  3129. PMODULE_ENTRY mi;
  3130. PSYMBOL_ENTRY psym;
  3131. if (!Name || !*Name || !Address)
  3132. return error(ERROR_INVALID_PARAMETER);
  3133. __try {
  3134. pe = FindProcessEntry(hProcess);
  3135. if (!pe)
  3136. return error(ERROR_INVALID_HANDLE);
  3137. mi = GetModuleForPC(pe, Address, false);
  3138. if (!mi)
  3139. return error(ERROR_MOD_NOT_FOUND);
  3140. if (!LoadSymbols(hProcess, mi, 0))
  3141. return error(ERROR_MOD_NOT_FOUND);
  3142. return vsAddSymbol(mi, Name, Address, Size);
  3143. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3144. ImagepSetLastErrorFromStatus(GetExceptionCode());
  3145. return false;
  3146. }
  3147. return true;
  3148. }
  3149. BOOL
  3150. IMAGEAPI
  3151. SymDeleteSymbol(
  3152. IN HANDLE hProcess,
  3153. IN ULONG64 BaseOfDll,
  3154. IN PCSTR Name,
  3155. IN DWORD64 Address,
  3156. IN DWORD Flags
  3157. )
  3158. {
  3159. PPROCESS_ENTRY pe;
  3160. PMODULE_ENTRY mi;
  3161. PSYMBOL_ENTRY psym;
  3162. __try {
  3163. pe = FindProcessEntry(hProcess);
  3164. if (!pe)
  3165. return error(ERROR_INVALID_HANDLE);
  3166. mi = GetModuleForPC(pe, Address, false);
  3167. if (!mi)
  3168. return error(ERROR_MOD_NOT_FOUND);
  3169. if (!LoadSymbols(hProcess, mi, LS_JUST_TEST))
  3170. return error(ERROR_MOD_NOT_FOUND);
  3171. return vsDeleteSymbol(mi, Name, Address);
  3172. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3173. ImagepSetLastErrorFromStatus(GetExceptionCode());
  3174. return false;
  3175. }
  3176. return true;
  3177. }
  3178. BOOL
  3179. IMAGEAPI
  3180. SymFromAddr(
  3181. IN HANDLE hProcess,
  3182. IN DWORD64 Address,
  3183. OUT PDWORD64 Displacement,
  3184. IN OUT PSYMBOL_INFO Symbol
  3185. )
  3186. {
  3187. PSYMBOL_INFO si;
  3188. si = SympGetSymFromAddr(hProcess, Address, Displacement);
  3189. if (!si)
  3190. return false;
  3191. si2si(Symbol, si);
  3192. return true;
  3193. }
  3194. BOOL
  3195. IMAGEAPI
  3196. SymFromAddrByTag(
  3197. IN HANDLE hProcess,
  3198. IN DWORD64 Address,
  3199. IN DWORD SymTag,
  3200. OUT PDWORD64 Displacement,
  3201. IN OUT PSYMBOL_INFO Symbol
  3202. )
  3203. {
  3204. PPROCESS_ENTRY pe;
  3205. PMODULE_ENTRY mi;
  3206. PSYMBOL_INFO si;
  3207. __try {
  3208. pe = FindProcessEntry(hProcess);
  3209. if (!pe)
  3210. return error(ERROR_INVALID_HANDLE);
  3211. mi = GetModuleForPC(pe, Address, false);
  3212. if (!mi)
  3213. return error(ERROR_MOD_NOT_FOUND);
  3214. if (!LoadSymbols(hProcess, mi, 0))
  3215. return error(ERROR_MOD_NOT_FOUND);
  3216. si = GetSymFromAddrByTag(Address, SymTag, Displacement, mi);
  3217. if (!si)
  3218. return error(ERROR_INVALID_ADDRESS);
  3219. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3220. ImagepSetLastErrorFromStatus(GetExceptionCode());
  3221. return false;
  3222. }
  3223. si2si(Symbol, si);
  3224. return true;
  3225. }
  3226. BOOL
  3227. IMAGEAPI
  3228. SymFromToken(
  3229. IN HANDLE hProcess,
  3230. IN DWORD64 Base,
  3231. IN DWORD Token,
  3232. IN OUT PSYMBOL_INFO Symbol
  3233. )
  3234. {
  3235. PPROCESS_ENTRY pe;
  3236. PMODULE_ENTRY mi;
  3237. PSYMBOL_INFO si;
  3238. __try {
  3239. pe = FindProcessEntry(hProcess);
  3240. if (!pe)
  3241. return error(ERROR_INVALID_HANDLE);
  3242. mi = GetModuleForPC(pe, Base, false);
  3243. if (!mi)
  3244. return error(ERROR_MOD_NOT_FOUND);
  3245. if (!LoadSymbols(hProcess, mi, 0))
  3246. return error(ERROR_MOD_NOT_FOUND);
  3247. si = GetSymFromToken(mi, Token);
  3248. if (!si)
  3249. return error(ERROR_INVALID_ADDRESS);
  3250. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3251. ImagepSetLastErrorFromStatus(GetExceptionCode());
  3252. return false;
  3253. }
  3254. si2si(Symbol, si);
  3255. return true;
  3256. }
  3257. BOOL
  3258. IMAGEAPI
  3259. SymFromName(
  3260. IN HANDLE hProcess,
  3261. IN LPSTR Name,
  3262. OUT PSYMBOL_INFO Symbol
  3263. )
  3264. {
  3265. SYMBOL_ENTRY sym;
  3266. PSYMBOL_INFO si;
  3267. si = SympGetSymFromName(hProcess, Name);
  3268. if (!si)
  3269. return false;
  3270. si2si(Symbol, si);
  3271. return true;
  3272. }
  3273. BOOL
  3274. IMAGEAPI
  3275. SymEnumSymbols(
  3276. IN HANDLE hProcess,
  3277. IN ULONG64 BaseOfDll,
  3278. IN PCSTR Mask,
  3279. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  3280. IN PVOID UserContext
  3281. )
  3282. {
  3283. return SympEnumerateSymbols(hProcess,
  3284. BaseOfDll,
  3285. (LPSTR)Mask,
  3286. (PROC) EnumSymbolsCallback,
  3287. UserContext,
  3288. false,
  3289. false);
  3290. }
  3291. BOOL
  3292. IMAGEAPI
  3293. SymEnumSymbolsByTag(
  3294. IN HANDLE hProcess,
  3295. IN ULONG64 BaseOfDll,
  3296. IN DWORD SymTag,
  3297. IN PCSTR Mask,
  3298. IN DWORD Options,
  3299. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  3300. IN PVOID UserContext
  3301. )
  3302. {
  3303. PPROCESS_ENTRY pe;
  3304. PLIST_ENTRY Next;
  3305. PMODULE_ENTRY mi;
  3306. DWORD i;
  3307. PSYMBOL_ENTRY sym;
  3308. char buf[2500];
  3309. LPSTR p;
  3310. CHAR modmask[200];
  3311. BOOL rc;
  3312. int pass;
  3313. BOOL fCase;
  3314. PSYMBOL_INFO si;
  3315. char match[MAX_SYM_NAME + 100];
  3316. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED | LS_FAIL_IF_LOADED};
  3317. __try {
  3318. pe = FindProcessEntry( hProcess );
  3319. if (!pe) {
  3320. SetLastError( ERROR_INVALID_HANDLE );
  3321. return false;
  3322. }
  3323. p = 0;
  3324. modmask[0] = 0;
  3325. if (Mask)
  3326. p = strchr(Mask, '!');
  3327. if (p > Mask) {
  3328. memcpy(modmask, Mask, (int)(p - Mask));
  3329. modmask[p-Mask] = 0;
  3330. Mask = p + 1;
  3331. } else if (!BaseOfDll) {
  3332. // search is scoped to current scope
  3333. rc = diaGetSymbolsByTag(pe,
  3334. NULL,
  3335. Mask,
  3336. 0,
  3337. SymTag,
  3338. (PROC)EnumSymbolsCallback,
  3339. UserContext,
  3340. false,
  3341. false,
  3342. Options);
  3343. if (!rc && pe->ipmi && pe->ipmi->code == ERROR_CANCELLED) {
  3344. pe->ipmi->code = 0;
  3345. return true;
  3346. }
  3347. return rc;
  3348. }
  3349. if (Mask && *Mask)
  3350. PrepRE4Srch(Mask, match);
  3351. else
  3352. *match = 0;
  3353. for (pass = 0; pass < 2; pass++) {
  3354. Next = pe->ModuleList.Flink;
  3355. if (Next) {
  3356. while (Next != &pe->ModuleList) {
  3357. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  3358. Next = mi->ListEntry.Flink;
  3359. if (BaseOfDll) {
  3360. if (mi->BaseOfDll != BaseOfDll)
  3361. continue;
  3362. } else if (!MatchModuleName(mi, modmask)) {
  3363. continue;
  3364. }
  3365. if (!LoadSymbols(hProcess, mi, flags[pass])) {
  3366. if (GetLastError() == ERROR_CANCELLED)
  3367. return false;
  3368. continue;
  3369. }
  3370. if (mi->dia) {
  3371. rc = diaGetSymbolsByTag(pe,
  3372. mi,
  3373. Mask,
  3374. 0,
  3375. SymTag,
  3376. (PROC)EnumSymbolsCallback,
  3377. UserContext,
  3378. false,
  3379. false,
  3380. Options);
  3381. }
  3382. if (mi->numsyms) {
  3383. fCase = option(SYMOPT_CASE_INSENSITIVE) ? false : true;
  3384. si = (PSYMBOL_INFO)buf;
  3385. ZeroMemory(buf, sizeof(buf));
  3386. si->MaxNameLen = sizeof(buf) - sizeof(SYMBOL_INFO);
  3387. for (i = 0; i < mi->numsyms; i++) {
  3388. sym = &mi->symbolTable[i];
  3389. if (*match && strcmpre(sym->Name, match, fCase))
  3390. continue;
  3391. se2si(sym, si);
  3392. si->ModBase = mi->BaseOfDll;
  3393. if (!DoEnumCallback(
  3394. pe,
  3395. si,
  3396. si->Size,
  3397. (PROC)EnumSymbolsCallback,
  3398. UserContext,
  3399. false,
  3400. false)) {
  3401. break;
  3402. }
  3403. }
  3404. }
  3405. rc = vsEnumSymbols(pe,
  3406. mi,
  3407. Mask,
  3408. (PROC)EnumSymbolsCallback,
  3409. UserContext,
  3410. false,
  3411. false);
  3412. if (!rc) {
  3413. if (mi->code == ERROR_CANCELLED) {
  3414. mi->code = 0;
  3415. return true;
  3416. }
  3417. return rc;
  3418. }
  3419. }
  3420. }
  3421. }
  3422. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3423. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  3424. return false;
  3425. }
  3426. return true;
  3427. }
  3428. BOOL
  3429. IMAGEAPI
  3430. SymEnumObjs(
  3431. IN HANDLE hProcess,
  3432. IN ULONG64 BaseOfDll,
  3433. IN PCSTR Mask,
  3434. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  3435. IN PVOID UserContext
  3436. )
  3437. {
  3438. return SymEnumSymbolsByTag(hProcess, BaseOfDll, SymTagCompiland, Mask, 0, EnumSymbolsCallback, UserContext);
  3439. }
  3440. BOOL
  3441. EnumSymForAddr(
  3442. IN PPROCESS_ENTRY pe,
  3443. IN PMODULE_ENTRY mi,
  3444. IN DWORD64 Address,
  3445. IN PROC EnumSymbolsCallback,
  3446. IN PVOID UserContext,
  3447. IN BOOL Use64,
  3448. IN BOOL CallBackUsesUnicode
  3449. )
  3450. {
  3451. PLIST_ENTRY Next;
  3452. DWORD i;
  3453. PSYMBOL_ENTRY sym;
  3454. LPSTR szSymName;
  3455. SYMBOL_ENTRY SymEntry={0};
  3456. CHAR Buffer[2500];
  3457. LPSTR p;
  3458. CHAR modmask[200];
  3459. BOOL rc;
  3460. int pass;
  3461. BOOL fCase;
  3462. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED | LS_FAIL_IF_LOADED};
  3463. __try {
  3464. if (mi->dia) {
  3465. rc = diaEnumSymForAddr(pe,
  3466. mi,
  3467. Address,
  3468. EnumSymbolsCallback,
  3469. UserContext,
  3470. Use64,
  3471. CallBackUsesUnicode);
  3472. if (rc)
  3473. rc = vsEnumSymbolsForAddr(pe,
  3474. mi,
  3475. Address,
  3476. EnumSymbolsCallback,
  3477. UserContext,
  3478. Use64,
  3479. CallBackUsesUnicode);
  3480. if (!rc) {
  3481. if (mi->code == ERROR_CANCELLED) {
  3482. mi->code = 0;
  3483. return true;
  3484. }
  3485. return rc;
  3486. }
  3487. return rc;
  3488. }
  3489. fCase = option(SYMOPT_CASE_INSENSITIVE) ? false : true;
  3490. for (i = 0; i < mi->numsyms; i++) {
  3491. PSYMBOL_INFO SymInfo = (PSYMBOL_INFO) &Buffer[0];
  3492. sym = &mi->symbolTable[i];
  3493. if (sym->Address != Address)
  3494. continue;
  3495. mi->TmpSym.Name[0] = 0;
  3496. CatString( mi->TmpSym.Name, sym->Name, TMP_SYM_LEN );
  3497. SymEntry = *sym;
  3498. SymEntry.Name = mi->TmpSym.Name;
  3499. SymInfo->MaxNameLen = sizeof(Buffer) - sizeof(SYMBOL_INFO);
  3500. se2si(&SymEntry, SymInfo);
  3501. SymInfo->ModBase = mi->BaseOfDll;
  3502. if (!DoEnumCallback(
  3503. pe,
  3504. SymInfo,
  3505. sym->Size,
  3506. EnumSymbolsCallback,
  3507. UserContext,
  3508. Use64,
  3509. CallBackUsesUnicode)) {
  3510. return true;
  3511. }
  3512. }
  3513. rc = vsEnumSymbolsForAddr(pe,
  3514. mi,
  3515. Address,
  3516. EnumSymbolsCallback,
  3517. UserContext,
  3518. Use64,
  3519. CallBackUsesUnicode);
  3520. if (!rc) {
  3521. if (mi->code == ERROR_CANCELLED) {
  3522. mi->code = 0;
  3523. return true;
  3524. }
  3525. return rc;
  3526. }
  3527. return true;
  3528. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3529. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  3530. return false;
  3531. }
  3532. return true;
  3533. }
  3534. BOOL
  3535. IMAGEAPI
  3536. SymEnumSymbolsForAddr(
  3537. IN HANDLE hProcess,
  3538. IN DWORD64 Address,
  3539. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  3540. IN PVOID UserContext
  3541. )
  3542. {
  3543. PPROCESS_ENTRY pe;
  3544. PMODULE_ENTRY mi;
  3545. __try {
  3546. pe = FindProcessEntry( hProcess );
  3547. if (!pe)
  3548. return error( ERROR_INVALID_HANDLE );
  3549. mi = GetModuleForPC( pe, Address, false );
  3550. if (!mi)
  3551. return error( ERROR_MOD_NOT_FOUND );
  3552. if (!LoadSymbols(hProcess, mi, 0))
  3553. return error( ERROR_MOD_NOT_FOUND );
  3554. return EnumSymForAddr(pe,
  3555. mi,
  3556. Address,
  3557. (PROC) EnumSymbolsCallback,
  3558. UserContext,
  3559. false,
  3560. false);
  3561. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3562. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  3563. return false;
  3564. }
  3565. return true;
  3566. }
  3567. BOOL
  3568. IMAGEAPI
  3569. SymEnumSym(
  3570. IN HANDLE hProcess,
  3571. IN ULONG64 BaseOfDll,
  3572. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  3573. IN PVOID UserContext
  3574. )
  3575. {
  3576. return SymEnumSymbols(hProcess,
  3577. BaseOfDll,
  3578. NULL,
  3579. EnumSymbolsCallback,
  3580. UserContext);
  3581. }
  3582. BOOL
  3583. IMAGEAPI
  3584. SymEnumTypes(
  3585. IN HANDLE hProcess,
  3586. IN ULONG64 BaseOfDll,
  3587. IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
  3588. IN PVOID UserContext
  3589. )
  3590. {
  3591. PPROCESS_ENTRY pe;
  3592. PLIST_ENTRY Next;
  3593. PMODULE_ENTRY mi;
  3594. pe = FindProcessEntry( hProcess );
  3595. if (!pe)
  3596. return error( ERROR_INVALID_HANDLE );
  3597. mi = NULL;
  3598. Next = pe->ModuleList.Flink;
  3599. if (Next) {
  3600. while (Next != &pe->ModuleList) {
  3601. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  3602. if (!mi)
  3603. break;
  3604. Next = mi->ListEntry.Flink;
  3605. if (mi->BaseOfDll == BaseOfDll)
  3606. break;
  3607. }
  3608. }
  3609. if (!mi) {
  3610. return false;
  3611. }
  3612. if (!LoadSymbols(hProcess, mi, 0))
  3613. return error(ERROR_MOD_NOT_FOUND);
  3614. return diaEnumUDT(mi, "", EnumSymbolsCallback, UserContext);
  3615. }
  3616. BOOL
  3617. IMAGEAPI
  3618. SymGetTypeFromName(
  3619. IN HANDLE hProcess,
  3620. IN ULONG64 BaseOfDll,
  3621. IN LPSTR Name,
  3622. OUT PSYMBOL_INFO Symbol
  3623. )
  3624. {
  3625. PPROCESS_ENTRY pe;
  3626. PLIST_ENTRY Next;
  3627. PMODULE_ENTRY mi;
  3628. pe = FindProcessEntry( hProcess );
  3629. if (!pe)
  3630. return error( ERROR_INVALID_HANDLE );
  3631. mi = NULL;
  3632. Next = pe->ModuleList.Flink;
  3633. if (Next) {
  3634. while (Next != &pe->ModuleList) {
  3635. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  3636. if (!mi)
  3637. break;
  3638. Next = mi->ListEntry.Flink;
  3639. if (mi->BaseOfDll == BaseOfDll)
  3640. break;
  3641. }
  3642. }
  3643. if (!mi || mi->BaseOfDll != BaseOfDll) {
  3644. LPSTR p;
  3645. // first check for fully qualified symbol name I.E. mod!sym
  3646. p = strchr( Name, '!' );
  3647. if (p > Name) {
  3648. LPSTR ModName = (LPSTR)MemAlloc(p - Name + 1);
  3649. if (!ModName)
  3650. return error( ERROR_NOT_ENOUGH_MEMORY );
  3651. memcpy(ModName, Name, (int)(p - Name));
  3652. ModName[p-Name] = 0;
  3653. //
  3654. // the caller wants to look in a specific module
  3655. //
  3656. mi = FindModule(hProcess, pe, ModName, true);
  3657. MemFree(ModName);
  3658. if (mi == NULL) {
  3659. return false;
  3660. }
  3661. Name = p+1;
  3662. } else {
  3663. return false;
  3664. }
  3665. }
  3666. if (!LoadSymbols(hProcess, mi, 0))
  3667. return error(ERROR_MOD_NOT_FOUND);
  3668. if (diaGetTiForUDT(mi, Name, Symbol)) {
  3669. return true;
  3670. } else {
  3671. return false;
  3672. }
  3673. return false;
  3674. }
  3675. BOOL
  3676. strcmpre(
  3677. PCSTR pStr,
  3678. PCSTR pRE,
  3679. BOOL fCase
  3680. )
  3681. {
  3682. DWORD rc;
  3683. WCHAR wstr[MAX_SYM_NAME + 2];
  3684. WCHAR wre[MAX_SYM_NAME + 100];
  3685. ansi2wcs(pStr, wstr, MAX_SYM_NAME + 2);
  3686. ansi2wcs(pRE, wre, MAX_SYM_NAME + 100);
  3687. rc = CompareRE(wstr, wre, fCase);
  3688. if (rc == S_OK)
  3689. return false;
  3690. return true;
  3691. }
  3692. BOOL
  3693. IMAGEAPI
  3694. SymMatchString(
  3695. IN LPSTR string,
  3696. IN LPSTR expression,
  3697. IN BOOL fCase
  3698. )
  3699. {
  3700. return !strcmpre(string, expression, fCase);
  3701. }
  3702. BOOL
  3703. SymEnumSourceFiles(
  3704. IN HANDLE hProcess,
  3705. IN ULONG64 ModBase,
  3706. IN LPSTR Mask,
  3707. IN PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,
  3708. IN PVOID UserContext
  3709. )
  3710. {
  3711. PPROCESS_ENTRY pe;
  3712. PLIST_ENTRY Next;
  3713. PMODULE_ENTRY mi;
  3714. DWORD i;
  3715. PSYMBOL_ENTRY sym;
  3716. LPSTR szSymName;
  3717. SYMBOL_ENTRY SymEntry={0};
  3718. CHAR Buffer[2500];
  3719. LPSTR p;
  3720. CHAR modmask[200];
  3721. BOOL rc;
  3722. int pass;
  3723. BOOL fCase;
  3724. static DWORD flags[2] = {LS_JUST_TEST, LS_QUALIFIED | LS_FAIL_IF_LOADED};
  3725. if (!cbSrcFiles)
  3726. return error(ERROR_INVALID_PARAMETER);
  3727. __try {
  3728. pe = FindProcessEntry(hProcess);
  3729. if (!pe)
  3730. return error( ERROR_INVALID_HANDLE );
  3731. p = 0;
  3732. modmask[0] = 0;
  3733. if (Mask)
  3734. p = strchr(Mask, '!');
  3735. if (p > Mask) {
  3736. memcpy(modmask, Mask, (int)(p - Mask));
  3737. modmask[p-Mask] = 0;
  3738. Mask = p + 1;
  3739. }
  3740. for (pass = 0; pass < 2; pass++) {
  3741. Next = pe->ModuleList.Flink;
  3742. if (Next) {
  3743. while (Next != &pe->ModuleList) {
  3744. mi = CONTAINING_RECORD( Next, MODULE_ENTRY, ListEntry );
  3745. Next = mi->ListEntry.Flink;
  3746. if (ModBase) {
  3747. if (mi->BaseOfDll != ModBase)
  3748. continue;
  3749. } else if (!MatchModuleName(mi, modmask)) {
  3750. continue;
  3751. }
  3752. if (!LoadSymbols(hProcess, mi, flags[pass])) {
  3753. if (GetLastError() == ERROR_CANCELLED)
  3754. return false;
  3755. continue;
  3756. }
  3757. if (mi->dia) {
  3758. rc = diaEnumSourceFiles(mi, Mask, cbSrcFiles, UserContext);
  3759. if (!rc) {
  3760. if (mi->code == ERROR_CANCELLED) {
  3761. mi->code = 0;
  3762. return true;
  3763. }
  3764. return rc;
  3765. }
  3766. continue;
  3767. }
  3768. #if 0
  3769. fCase = option(SYMOPT_CASE_INSENSITIVE) ? false : true;
  3770. for (i = 0; i < mi->numsyms; i++) {
  3771. PSYMBOL_INFO SymInfo = (PSYMBOL_INFO) &Buffer[0];
  3772. sym = &mi->symbolTable[i];
  3773. if (Mask && *Mask && strcmpre(sym->Name, Mask, fCase))
  3774. continue;
  3775. }
  3776. #endif
  3777. }
  3778. }
  3779. }
  3780. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3781. ImagepSetLastErrorFromStatus( GetExceptionCode() );
  3782. return false;
  3783. }
  3784. return true;
  3785. }
  3786. PWSTR
  3787. AnsiToUnicode(
  3788. PSTR pszAnsi
  3789. )
  3790. {
  3791. UINT uSizeUnicode;
  3792. PWSTR pwszUnicode;
  3793. if (!pszAnsi) {
  3794. return NULL;
  3795. }
  3796. uSizeUnicode = (strlen(pszAnsi) + 1) * sizeof(wchar_t);
  3797. pwszUnicode = (PWSTR)MemAlloc(uSizeUnicode);
  3798. if (*pszAnsi && pwszUnicode) {
  3799. ZeroMemory(pwszUnicode, uSizeUnicode);
  3800. if (!MultiByteToWideChar(CP_ACP, MB_COMPOSITE,
  3801. pszAnsi, strlen(pszAnsi),
  3802. pwszUnicode, uSizeUnicode)) {
  3803. // Error. Free the string, return NULL.
  3804. MemFree(pwszUnicode);
  3805. pwszUnicode = NULL;
  3806. }
  3807. }
  3808. return pwszUnicode;
  3809. }
  3810. BOOL
  3811. wcs2ansi(
  3812. PWSTR pwsz,
  3813. PSTR psz,
  3814. DWORD pszlen
  3815. )
  3816. {
  3817. BOOL rc;
  3818. int len;
  3819. assert(psz && pwsz);
  3820. len = wcslen(pwsz);
  3821. if (!len) {
  3822. *psz = 0;
  3823. return true;
  3824. }
  3825. rc = WideCharToMultiByte(CP_ACP,
  3826. WC_SEPCHARS | WC_COMPOSITECHECK,
  3827. pwsz,
  3828. len,
  3829. psz,
  3830. pszlen,
  3831. NULL,
  3832. NULL);
  3833. if (!rc)
  3834. return false;
  3835. psz[len] = 0;
  3836. return true;
  3837. }
  3838. BOOL
  3839. ansi2wcs(
  3840. PCSTR psz,
  3841. PWSTR pwsz,
  3842. DWORD pwszlen
  3843. )
  3844. {
  3845. BOOL rc;
  3846. int len;
  3847. assert(psz && pwsz);
  3848. len = strlen(psz);
  3849. if (!len) {
  3850. *pwsz = 0L;
  3851. return true;
  3852. }
  3853. rc = MultiByteToWideChar(CP_ACP,
  3854. MB_COMPOSITE,
  3855. psz,
  3856. len,
  3857. pwsz,
  3858. pwszlen);
  3859. if (!rc)
  3860. return false;
  3861. pwsz[len] = 0;
  3862. return true;
  3863. }
  3864. PSTR
  3865. UnicodeToAnsi(
  3866. PWSTR pwszUnicode
  3867. )
  3868. {
  3869. UINT uSizeAnsi;
  3870. PSTR pszAnsi;
  3871. if (!pwszUnicode) {
  3872. return NULL;
  3873. }
  3874. uSizeAnsi = wcslen(pwszUnicode) + 1;
  3875. pszAnsi = (PSTR)MemAlloc(uSizeAnsi);
  3876. if (*pwszUnicode && pszAnsi) {
  3877. ZeroMemory(pszAnsi, uSizeAnsi);
  3878. if (!WideCharToMultiByte(CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK,
  3879. pwszUnicode, wcslen(pwszUnicode),
  3880. pszAnsi, uSizeAnsi, NULL, NULL)) {
  3881. // Error. Free the string, return NULL.
  3882. free(pszAnsi);
  3883. pszAnsi = NULL;
  3884. }
  3885. }
  3886. return pszAnsi;
  3887. }
  3888. BOOL
  3889. IMAGEAPI
  3890. SymGetTypeInfo(
  3891. IN HANDLE hProcess,
  3892. IN DWORD64 ModBase,
  3893. IN ULONG TypeId,
  3894. IN IMAGEHLP_SYMBOL_TYPE_INFO GetType,
  3895. OUT PVOID pInfo
  3896. )
  3897. {
  3898. HRESULT err;
  3899. err = diaGetSymbolInfo(hProcess, ModBase, TypeId, GetType, pInfo);
  3900. SetLastError((ULONG) err);
  3901. return (err==S_OK);
  3902. }
  3903. //#ifdef _WIN64
  3904. #if 0
  3905. BOOL __cdecl PDBOpenTpi(PDB* ppdb, const char* szMode, TPI** pptpi) {return false;}
  3906. BOOL __cdecl PDBCopyTo(PDB* ppdb, const char* szTargetPdb, DWORD dwCopyFilter, DWORD dwReserved){return false;}
  3907. BOOL __cdecl PDBClose(PDB* ppdb) {return false;}
  3908. BOOL __cdecl ModQueryImod(Mod* pmod, USHORT* pimod) {return false;}
  3909. BOOL __cdecl ModQueryLines(Mod* pmod, BYTE* pbLines, long* pcb) {return false;}
  3910. BOOL __cdecl DBIQueryModFromAddr(DBI* pdbi, USHORT isect, long off, Mod** ppmod, USHORT* pisect, long* poff, long* pcb){return false;}
  3911. BOOL __cdecl ModClose(Mod* pmod){return false;}
  3912. BOOL __cdecl DBIQueryNextMod(DBI* pdbi, Mod* pmod, Mod** ppmodNext) {return false;}
  3913. BYTE* __cdecl GSINextSym (GSI* pgsi, BYTE* pbSym) {return NULL;}
  3914. BOOL __cdecl PDBOpen(char* szPDB,char* szMode,SIG sigInitial,EC* pec,char szError[cbErrMax],PDB** pppdb) {return false;}
  3915. BOOL __cdecl TypesClose(TPI* ptpi){return false;}
  3916. BOOL __cdecl GSIClose(GSI* pgsi){return false;}
  3917. BOOL __cdecl DBIClose(DBI* pdbi){return false;}
  3918. BYTE* __cdecl GSINearestSym (GSI* pgsi, USHORT isect, long off, long* pdisp){return NULL;}
  3919. BOOL __cdecl PDBOpenValidate(char* szPDB,char* szPath,char* szMode,SIG sig,AGE age,EC* pec,char szError[cbErrMax],PDB** pppdb){return false;}
  3920. BOOL __cdecl PDBOpenDBI(PDB* ppdb, const char* szMode, const char* szTarget, DBI** ppdbi){return false;}
  3921. BOOL __cdecl DBIOpenPublics(DBI* pdbi, GSI **ppgsi){return false;}
  3922. BOOL __cdecl DBIQuerySecMap(DBI* pdbi, BYTE* pb, long* pcb){return false;}
  3923. #endif