Windows NT 4.0 source code leak
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.

1610 lines
33 KiB

4 years ago
  1. #include <malloc.h>
  2. #include <limits.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "ntsdp.h"
  6. #include "types.h"
  7. #include "cvtypes.h"
  8. #include "shapi.h"
  9. #include "cvproto.h"
  10. #include "cvinfo.h"
  11. #include "sapi.h"
  12. #include "shiproto.h"
  13. #include "ntempd.h"
  14. #include "ntimage.h"
  15. #include "ntsapi.h"
  16. #ifndef NT_HOST
  17. #define LOADDS _loadds
  18. #define PASCAL _pascal
  19. typedef unsigned long HATOMTBL;
  20. typedef unsigned short ATOM;
  21. // Liberated from pmwin.h and mangled to fit into OS2/NT environment
  22. HATOMTBL PASCAL WinCreateAtomTable(USHORT cbInitial,USHORT cBuckets);
  23. ATOM PASCAL WinFindAtom(HATOMTBL hAtomTbl,unsigned char *Name);
  24. ATOM PASCAL WinAddAtom(HATOMTBL hAtomTbl, unsigned char *Name);
  25. ATOM PASCAL WinDeleteAtom(HATOMTBL hAtomTbl,ATOM atom);
  26. // end of liberation
  27. #define SH_AddAtom(sz) WinAddAtom(hAtmTable, sz)
  28. #define SH_FindAtom(sz) WinFindAtom(hAtmTable, sz)
  29. #define SH_DeleteAtom(atm) WinDeleteAtom(hAtmTable, atm)
  30. HATOMTBL hAtmTable;
  31. void ExitProcess(DWORD error)
  32. {
  33. exit((int)error);
  34. }
  35. #else
  36. #define SH_AddAtom(sz) AddAtom(sz)
  37. #define SH_FindAtom(sz) FindAtom(sz)
  38. #define SH_DeleteAtom(atm) DeleteAtom(atm)
  39. #endif
  40. /*
  41. * Function Prototypes
  42. */
  43. VOID DeferSymbolLoad (PIMAGE_INFO); // NTSYM.C
  44. VOID InitSymContext(PPROCESS_INFO); // NTSYM.C
  45. VOID LoadSymbols(PIMAGE_INFO); // NTSYM.C
  46. PNODE NextNode(PSYMCONTEXT, PNODE); // NTSYM.C
  47. PIMAGE_INFO pImageFromIndex( UCHAR); // NTSYM.C
  48. void UnloadSymbols(PIMAGE_INFO); // NTSYM.C
  49. int CV_CLOSE( int handle);
  50. int CV_OPEN( char *name, int ignore1, int ignore2);
  51. int CV_READ( int handle, void * buffer, unsigned count);
  52. int CV_SEEK( int handle, long offset, int origin);
  53. long CV_TELL( int handle);
  54. /*
  55. * Global Memory (Program)
  56. */
  57. extern PPROCESS_INFO pProcessHead = NULL;
  58. extern PPROCESS_INFO pProcessCurrent = NULL;
  59. extern ULONG ObjectTableOffset;
  60. extern UINT ObjectTableCount;
  61. extern SHE SHerror = 0; // SH specific error (from ntsym.c)
  62. BOOLEAN KdVerbose = FALSE; // if TRUE, output verbose info
  63. BOOLEAN fLazyLoad = TRUE; // if TRUE, defer symbol loads
  64. UCHAR chSymbolSuffix = 'a'; // suffix to add to symbol if search
  65. BOOLEAN fPointerExpression;
  66. int fControlC = 0;
  67. /*
  68. * Global Memory (File)
  69. */
  70. static LSZ lszDLLexclude = NULL;
  71. /***********************************************************************/
  72. int SHModelFromAddr(PADDR paddr, LPW lpw, LPB lpb, UOFFSET FAR * lpuoff)
  73. {
  74. Unreferenced( paddr );
  75. Unreferenced( lpb );
  76. Unreferenced( lpuoff );
  77. *lpw = CEXM_MDL_native;
  78. return(0);
  79. }
  80. BOOL SHFIsAddrNonVirtual(PADDR paddr)
  81. {
  82. Unreferenced( paddr );
  83. return TRUE;
  84. }
  85. LSZ SHLszGetErrorText( SHE she )
  86. {
  87. static char * szNone = "symbols loaded";
  88. static char * szOther = "no symbols loaded";
  89. if (she == sheNone) return szNone;
  90. else return szOther;
  91. }
  92. /**********************************************************************/
  93. /*** SH_AddImage
  94. **
  95. ** Synopsis:
  96. ** PIMAGE_INFO SH_AddImage( ATOM aname, LSZ lszName);
  97. **
  98. ** Entry:
  99. ** aname - Atomized image name
  100. ** lszName - The Name of the module being added.
  101. **
  102. ** Returns:
  103. ** Pointer to a NT Image Info structure that was created.
  104. ** NULL if there was an error.
  105. **
  106. ** Property:
  107. ** Local to SHD
  108. **
  109. ** Description:
  110. ** Adds a new image to the current process and returns a pointer
  111. ** to it. The image->aFile will contain the atom.
  112. **
  113. */
  114. PIMAGE_INFO SH_AddImage( ATOM aname, LSZ lszName )
  115. {
  116. PIMAGE_INFO pImageCurrent;
  117. PIMAGE_INFO pImageAfter;
  118. PIMAGE_INFO pImageNew;
  119. UCHAR index = 0;
  120. CHAR Base[_MAX_CVFNAME];
  121. pImageNew = LocalAlloc(LMEM_FIXED, sizeof(IMAGE_INFO));
  122. if ( pImageNew != NULL) {
  123. pImageNew->aFile = aname;
  124. pImageNew->lpBaseOfImage = (void *)-1;
  125. pImageNew->offsetLow = 0;
  126. pImageNew->offsetHigh = 0;
  127. pImageNew->fSymbolsLoaded = FALSE;
  128. pImageNew->pImageNext = NULL;
  129. pImageNew->pGSN = NULL;
  130. pImageNew->pRVA = NULL;
  131. pImageNew->hQCFile = 0;
  132. pImageNew->QCOpened = FALSE;
  133. pImageNew->IgnoreSymbols = FALSE;
  134. pImageNew->TypeCount = 0;
  135. pImageNew->rgTypeInfo = NULL;
  136. if ( lszDLLexclude ) {
  137. _splitpath( lszName, NULL, NULL, Base, NULL);
  138. if ( strstr( lszDLLexclude, Base ) != NULL )
  139. pImageNew->IgnoreSymbols = TRUE;
  140. }
  141. pImageNew->pszName = LocalAlloc(LMEM_FIXED, strlen(lszName) + 1);
  142. assert( pImageNew->pszName);
  143. strcpy(pImageNew->pszName,lszName);
  144. pImageCurrent = pProcessCurrent->pImageHead;
  145. if ( pImageCurrent != NULL ) {
  146. if (pImageCurrent->index > index) {
  147. pImageNew->pImageNext = pImageCurrent;
  148. pProcessCurrent->pImageHead = pImageNew;
  149. }
  150. else {
  151. index++;
  152. while ((pImageAfter = pImageCurrent->pImageNext)
  153. && pImageAfter->index == index) {
  154. index++;
  155. pImageCurrent = pImageAfter;
  156. }
  157. pImageNew->pImageNext = pImageAfter;
  158. pImageCurrent->pImageNext = pImageNew;
  159. }
  160. pImageNew->index = index;
  161. }
  162. else {
  163. pImageNew->index = 0;
  164. pProcessCurrent->pImageHead = pImageNew;
  165. }
  166. }
  167. return pImageNew;
  168. }
  169. /*** SH_FindImage
  170. **
  171. ** Synopsis:
  172. ** PIMAGE_INFO SH_FindImage( ATOM aname);
  173. **
  174. ** Entry:
  175. ** aname - Atomized image name
  176. **
  177. ** Returns:
  178. ** Pointer to a NT Image Info structure for the given atom or
  179. ** NULL if not found.
  180. **
  181. ** Property:
  182. ** Local to SHD
  183. **
  184. ** Description:
  185. ** Finds the image in the current process that has the atom passed
  186. ** to us. returns NULL if not found.
  187. **
  188. */
  189. PIMAGE_INFO SH_FindImage( ATOM aname )
  190. {
  191. PIMAGE_INFO pImageNew = pProcessCurrent->pImageHead;
  192. while (pImageNew) {
  193. if (pImageNew->aFile == aname) break;
  194. pImageNew = pImageNew->pImageNext;
  195. }
  196. return pImageNew;
  197. }
  198. /*** SH_HexeFromHSym
  199. **
  200. ** Synopsis:
  201. ** HEXE SH_HexeFromHSym( HSYM hsym );
  202. **
  203. ** Entry:
  204. ** hsym - Handle to a symbol.
  205. **
  206. ** Returns:
  207. ** Return a Handle to an EXE or NULL if not found.
  208. **
  209. ** Description:
  210. **
  211. **
  212. **
  213. */
  214. HEXE SH_HexeFromHSym(HSYM hsym)
  215. {
  216. PSYMBOL pSymbol = (PSYMBOL)hsym;
  217. PIMAGE_INFO pImage = NULL;
  218. if ( pSymbol->cvkind == K_PUBLIC ||
  219. pSymbol->cvkind == K_PROC )
  220. pImage = pImageFromIndex( pSymbol->modIndex );
  221. return (HEXE)pImage;
  222. }
  223. /*** SH_InitAtom
  224. **
  225. ** Synopsis:
  226. ** void SH_InitAtom(void)
  227. **
  228. ** Entry:
  229. **
  230. ** Returns:
  231. **
  232. ** Description:
  233. ** Initialize the atom table. Only here because WINDOWS and OS/2
  234. ** do things differently.
  235. **
  236. */
  237. void SH_InitAtom(void)
  238. {
  239. #define ATOM_SIZE 63
  240. #ifdef NT_HOST
  241. /* InitAtomTable(ATOM_SIZE); */
  242. #else
  243. hAtmTable = WinCreateAtomTable(0,ATOM_SIZE);
  244. #endif
  245. }
  246. /*** SH_OffsetFromAddr
  247. **
  248. ** Synopsis:
  249. ** ULONG SH_OffsetFromAddr( LPADDR paddr );
  250. **
  251. ** Entry:
  252. ** paddr - Pointer to a address structure
  253. **
  254. ** Returns:
  255. ** Returns the real address the corrisponds to the addr
  256. **
  257. ** Description:
  258. ** Given an addr structure return the read address of the
  259. ** object.
  260. **
  261. */
  262. ULONG SH_OffsetFromAddr( LPADDR paddr )
  263. {
  264. PIMAGE_INFO pImage;
  265. ULONG offset;
  266. int i;
  267. SYUnFixupAddr(paddr);
  268. pImage = (PIMAGE_INFO)paddr->emi;
  269. i = paddr->addr.seg;
  270. assert( pImage );
  271. if ( pProcessCurrent->hpid == (ULONG)pImage )
  272. offset = paddr->addr.off;
  273. else {
  274. assert( pImage->pRVA );
  275. assert( paddr->addr.seg <= (SEGMENT) pImage->ObjectCount);
  276. offset = paddr->addr.off
  277. + pImage->pRVA[i]
  278. + (ULONG) pImage->lpBaseOfImage;
  279. }
  280. return offset;
  281. }
  282. /*** SH_OpenImage
  283. **
  284. ** Synopsis:
  285. ** PIMAGE_INFO SH_OpenImage( LSZ lszName);
  286. **
  287. ** Entry:
  288. ** lszName - Pointer to the name of the image to find in
  289. ** the current process.
  290. **
  291. ** Returns:
  292. ** Pointer to a NT Image Info structure. NULL if there was
  293. ** an error.
  294. **
  295. ** Property:
  296. ** Local to SHD
  297. **
  298. ** Description:
  299. ** Open the image in the current process given its full pathname.
  300. ** If the image doesn't exist, attempt to create an atom entry and
  301. ** add the image to the process.
  302. **
  303. **
  304. */
  305. PIMAGE_INFO SH_OpenImage( LSZ lszNam )
  306. {
  307. ATOM aFile;
  308. PIMAGE_INFO pImage = NULL;
  309. LSZ lszName;
  310. LSZ lszModule;
  311. LSZ lszHandle;
  312. LSZ lszBase;
  313. LSZ lszNext;
  314. ULONG lhandle;
  315. ULONG lBase;
  316. BOOLEAN opened;
  317. /*
  318. * Make a local copy of the string
  319. */
  320. if ( !(lszName = _strdup(lszNam)) ) {
  321. dprintf("SH_OpenImage() can't strdup lszNam\n");
  322. return pImage;
  323. }
  324. /*
  325. * Check for "handlized" filename and convert
  326. */
  327. if ( *lszName == '|') {
  328. lszModule = strtok(lszName+1,"|");
  329. lszHandle = strtok(NULL,"|");
  330. lszBase = strtok(NULL,"|");
  331. lhandle = strtoul(lszHandle,&lszNext, 0);
  332. lBase = strtoul(lszBase,&lszNext, 0);
  333. if ( lhandle == ULONG_MAX) {
  334. free(lszName);
  335. return pImage;
  336. }
  337. opened = TRUE;
  338. }
  339. /*
  340. * Its a real file just open it
  341. */
  342. else {
  343. lszModule = lszName;
  344. lhandle = (ULONG)SYOpen(lszModule);
  345. if ( lhandle == 0l) {
  346. SHerror = sheFileOpen;
  347. free(lszName);
  348. return pImage;
  349. }
  350. opened = FALSE;
  351. }
  352. /*
  353. * Check if Image name has been atomized. If not do so.
  354. */
  355. if ( !(aFile = SH_FindAtom(lszModule)) )
  356. aFile = SH_AddAtom(lszModule);
  357. /*
  358. * Check to see if the Image is already known, if not add
  359. * one to the process.
  360. */
  361. if ( !(pImage = SH_FindImage(aFile)) )
  362. pImage = SH_AddImage(aFile, lszModule);
  363. /*
  364. * If we have a image then insert its handle
  365. */
  366. if ( pImage ) {
  367. pImage->hQCFile = (int)lhandle;
  368. pImage->QCOpened = opened;
  369. pImage->lpBaseOfImage = (LPVOID) lBase;
  370. }
  371. free(lszName);
  372. return pImage;
  373. }
  374. /*** SH_SetAddr
  375. **
  376. ** Synopsis:
  377. ** VOID SH_SetAddr( LPADDR paddr, ULONG offset, HEXE hexe)
  378. **
  379. ** Entry:
  380. ** paddr - Pointer to the address packet.
  381. ** offset - 32 Bit offset for the address
  382. ** hexe - Handle to its EXE (EMI), Must be present
  383. **
  384. ** Returns:
  385. **
  386. ** Description:
  387. ** Creates a CV compatable ADDR from NT information.
  388. **
  389. */
  390. VOID SH_SetAddr( LPADDR paddr, ULONG offset, HEXE hexe)
  391. {
  392. PIMAGE_INFO pImage = (PIMAGE_INFO)hexe;
  393. int i;
  394. assert( hexe != 0);
  395. assert( pImage->pRVA != 0);
  396. MEMSET( &paddr->addr, 0, sizeof(ADDR) );
  397. paddr->emi = (HEMI)hexe;
  398. offset -= (ULONG)pImage->lpBaseOfImage;
  399. for ( i=1; i < pImage->ObjectCount; i++)
  400. if ( pImage->pRVA[i] <= offset && offset <=
  401. pImage->pRVA[i+1] ) break;
  402. paddr->addr.off = offset - pImage->pRVA[i];
  403. paddr->addr.seg = (SEGMENT) i;
  404. paddr->mode.flat32 = 1;
  405. paddr->mode.isLI = 1;
  406. }
  407. /*** SH_SetupGSN
  408. **
  409. ** Synopsis:
  410. ** void SH_SetupGSN( PIMAGE_INFO pImage);
  411. **
  412. ** Entry:
  413. ** pImage - Pointer to current Image
  414. **
  415. ** Returns:
  416. **
  417. ** Description:
  418. ** Used to setup the GSN and RVA tables during Image loading
  419. ** (LoadSymbol() in ntsym.c).
  420. **
  421. */
  422. VOID SH_SetupGSN( PIMAGE_INFO pImage )
  423. {
  424. IMAGE_SECTION_HEADER o32Obj;
  425. LPGSI pGSI;
  426. LPL pRVA;
  427. INT handle = pImage->hQCFile;
  428. UINT iobj;
  429. assert( pImage );
  430. pImage->pRVA = (LPL)MHAlloc( sizeof(ULONG) * (ObjectTableCount+1) );
  431. assert( pImage->pRVA);
  432. pImage->ObjectCount = ObjectTableCount;
  433. assert( ObjectTableCount < 32 );
  434. /*
  435. * Allocate GSN big enought for each of the objects in the image
  436. */
  437. pImage->pGSN = (LPGSI)MHAlloc(
  438. sizeof(GSI) + ObjectTableCount * sizeof(SGI) );
  439. assert( pImage->pGSN );
  440. memset(pImage->pGSN,0,sizeof(GSI));
  441. pGSI = (LPGSI)pImage->pGSN;
  442. pRVA = (LPL)pImage->pRVA;
  443. pGSI->csgMax = (USHORT)ObjectTableCount;
  444. pGSI->csgLogical = (USHORT)ObjectTableCount;
  445. CV_SEEK(handle, ObjectTableOffset, SEEK_SET);
  446. for( iobj=0; iobj<ObjectTableCount; iobj++ ) {
  447. if ( CV_READ(handle, &o32Obj, sizeof(o32Obj) ) != sizeof(o32Obj) )
  448. assert( FALSE );
  449. pGSI->rgsgi[iobj].sgf.u.u2.segAttr = 0xD;
  450. pGSI->rgsgi[iobj].sgf.u.u2.saAttr = 1;
  451. pGSI->rgsgi[iobj].isgPhy = (USHORT)(iobj+1);
  452. pGSI->rgsgi[iobj].doffseg = 0;
  453. pGSI->rgsgi[iobj].cbSeg = o32Obj.SizeOfRawData;
  454. pRVA[iobj+1] = o32Obj.VirtualAddress;
  455. }
  456. }
  457. /*** SHAddDll
  458. **
  459. ** Synopsis:
  460. ** flag = SHAddDll( lsz Name, BOOL DLL );
  461. **
  462. ** Entry:
  463. ** Name - A pointer to a zero-terminated string containing the fully
  464. ** qualified path/file specification.
  465. **
  466. ** DLL - Not Referenced
  467. **
  468. ** Returns:
  469. ** she error code.
  470. **
  471. ** Description:
  472. **
  473. ** Notify the SH about an EXE/DLL for which symbolic information
  474. ** will need to be loaded later.
  475. **
  476. ** During the startup of a debuggee application, this function
  477. ** will be called once for the EXE, and once for each DLL that is
  478. ** used by the EXE. Note: Symbols are not loaded until SHLoadDll()
  479. **
  480. */
  481. SHE LOADDS PASCAL SHAddDll ( LSZ lszName, BOOL fDll )
  482. {
  483. PIMAGE_INFO pImage;
  484. Unreferenced(fDll);
  485. pImage = SH_OpenImage( lszName );
  486. if ( pImage != NULL) {
  487. DeferSymbolLoad (pImage);
  488. if ( !pImage->QCOpened ) {
  489. CV_CLOSE(pImage->hQCFile);
  490. pImage->hQCFile = 0;
  491. }
  492. }
  493. return SHerror;
  494. }
  495. /*** SHAddDllsToProcess
  496. **
  497. ** Synopsis:
  498. ** SHE SHAddDllsToProcess( void );
  499. **
  500. ** Entry:
  501. **
  502. ** Returns:
  503. ** SHE - Enumerated error code.
  504. **
  505. ** Description:
  506. **
  507. ** NT SAPI IGNORES THIS AT PRESENT TIME AND RETURNS sheNone (No Error)
  508. **
  509. ** Associate all DLLs that have been loaded with the current EXE.
  510. ** the debugger, at init time, will call SHAddDll on one EXE
  511. ** and zero or more DLLs. Then it should call this function
  512. ** to indicate that those DLLs are associated with (used by)
  513. ** that EXE; thus, a user request for a symbol from the EXE
  514. ** will also search the symbolic information from those DLLs.
  515. **
  516. */
  517. SHE LOADDS LOADDS PASCAL SHAddDllsToProcess ( VOID )
  518. {
  519. return sheNone;
  520. }
  521. /*** SHAddrFromHsym
  522. **
  523. ** Synopsis:
  524. ** VOID SHAddrFromHsym( LPADDR pAddr, HSYM hSym);
  525. **
  526. ** Entry:
  527. ** pAddr - Pointer to the ADDR block to be filled out.
  528. ** hSym - Symbol Handle for which infomation is needed.
  529. **
  530. ** Returns:
  531. **
  532. ** Description:
  533. ** Given a handle to a symbol, fill out the ADDR block
  534. **
  535. */
  536. VOID PASCAL LOADDS SHAddrFromHsym( LPADDR paddr, HSYM hsym)
  537. {
  538. PSYMBOL pSymbol = (PSYMBOL)hsym;
  539. SH_SetAddr(paddr, pSymbol->offset, SH_HexeFromHSym(hsym) );
  540. }
  541. /*** SHChangeProcess
  542. **
  543. ** Synopsis:
  544. ** void SHChangeProcess(HPDS hpds);
  545. **
  546. ** Entry:
  547. ** hpds - The handle for the process to change to.
  548. **
  549. ** Returns:
  550. **
  551. ** Description:
  552. ** Change the current debuggee process handle (HPDS). SAPI can
  553. ** maintain symbols for multiple processes; This set which one
  554. ** is current for symbol table lookup.
  555. **
  556. */
  557. VOID LOADDS PASCAL SHChangeProcess ( HPDS hpds )
  558. {
  559. pProcessCurrent = (PPROCESS_INFO)hpds;
  560. }
  561. /*** SHCreateProcess
  562. **
  563. ** Synopsis:
  564. ** HPDS SHCreateProcess( void );
  565. **
  566. ** Entry:
  567. **
  568. ** Returns:
  569. ** HPDS - A handle to the process information.
  570. **
  571. ** Description:
  572. ** Allocates the storage needed for the process information. Returns
  573. ** a handle to the PDS or NULL if on failure.
  574. **
  575. ** Notes:
  576. ** Based on the function CreateProcess found in ntsd.c and changed to
  577. ** not initialize the fields from Debug event.
  578. **
  579. */
  580. HPDS LOADDS PASCAL SHCreateProcess ( void )
  581. {
  582. PPROCESS_INFO pProcessNew;
  583. PPROCESS_INFO pProcess;
  584. PPROCESS_INFO pProcessAfter;
  585. UCHAR index = 0;
  586. pProcessNew = LocalAlloc(LMEM_FIXED, sizeof(PROCESS_INFO));
  587. if (!pProcessNew) return (HPDS)NULL;
  588. if (pProcessHead == NULL || pProcessHead->index > index) {
  589. pProcessNew->pProcessNext = pProcessHead;
  590. pProcessHead = pProcessNew;
  591. }
  592. else {
  593. index++;
  594. pProcess = pProcessHead;
  595. while ((pProcessAfter = pProcess->pProcessNext)
  596. && pProcessAfter->index == index) {
  597. index++;
  598. pProcess = pProcessAfter;
  599. }
  600. pProcessNew->pProcessNext = pProcessAfter;
  601. pProcess->pProcessNext = pProcessNew;
  602. }
  603. pProcessNew->index = index;
  604. pProcessNew->pImageHead = NULL;
  605. InitSymContext(pProcessNew);
  606. pProcessCurrent = pProcessNew;
  607. return (HPDS)pProcessCurrent;
  608. }
  609. /*** SHFindNameInContext
  610. **
  611. ** Synopsis:
  612. ** HSYM SHFindNameInContext( HSYM hSym, PCXT pcxt, LPSSTR lpsstr,
  613. ** SHFLAG fCase, PFNCMP pfnCmp, SHFLAG fChild, PCXT pcxtOut)
  614. **
  615. ** Entry:
  616. ** hsym - Handle to the current hsym
  617. ** pcxt - pointer to the current context
  618. ** lpsstr - Pointer to a length prefixed string containing the name
  619. ** fCase - Argument to comparsion routine
  620. ** pFnCmp - Pointer to the Comparsion routine to use
  621. ** fChild - Not Referenced.
  622. ** pcxtOut - pointer to the output context
  623. **
  624. ** Returns:
  625. ** Returns HSYM for the Symbol found or NULL if not found.
  626. **
  627. ** Description:
  628. ** Scans through the locals for the current function (hproc) and sends
  629. ** each to the comparison routine. If symbol found returns its hsym.
  630. **
  631. */
  632. HSYM LOADDS PASCAL SHFindNameInContext( HSYM hSym, PCXT pcxt, LPSSTR lpsstr,
  633. SHFLAG fCase, PFNCMP pfnCmp, SHFLAG fChild, PCXT pcxtOut)
  634. {
  635. PLOCAL pLocal = (PLOCAL)hSym;
  636. PSYMBOL pSymbol;
  637. LPV CVbuff;
  638. LSZ CVname;
  639. Unreferenced(fChild);
  640. // If we didn't get a hsym, try to get one from the pcxt
  641. if ( !pLocal ) {
  642. assert( pcxt );
  643. if ( pcxt->hProc ) {
  644. pSymbol = (PSYMBOL)pcxt->hProc;
  645. pLocal = pSymbol->pLocal;
  646. }
  647. }
  648. // While we have a Local
  649. while ( pLocal ) {
  650. // Lock down the pLocal (HSYM) and Isolate its name
  651. CVbuff = (SYMPTR)MHOmfLock((HDEP)pLocal);
  652. CVname = ((BPRELPTR32)CVbuff)->name;
  653. if ( !(*pfnCmp)( lpsstr, CVbuff, CVname, fCase) ) {
  654. *pcxtOut = *pcxt;
  655. MHOmfUnLock((HDEP)CVbuff);
  656. break;
  657. }
  658. pLocal = pLocal->next;
  659. MHOmfUnLock((HDEP)CVbuff);
  660. }
  661. return (HSYM)pLocal;
  662. }
  663. /*** SHFindNameInGlobal
  664. **
  665. ** Synopsis:
  666. ** HSYM SHFindNameInGlobal( HSYM hSym, PCXT pCxt, LPSSTR lpsstr,
  667. ** SHFLAG fCaseSensitive, PFNCMP pfnCmp,
  668. ** SHFLAG fChild, PCXT pCxtOut)
  669. **
  670. ** Entry:
  671. ** None of the Arguments are referenced
  672. **
  673. ** Returns:
  674. ** Returns NULL
  675. **
  676. ** Description:
  677. ** Just a stub for now.
  678. **
  679. */
  680. HSYM LOADDS PASCAL SHFindNameInGlobal( HSYM hSym, PCXT pCxt, LPSSTR lpsstr,
  681. SHFLAG fCaseSensitive, PFNCMP pfnCmp,
  682. SHFLAG fChild, PCXT pCxtOut)
  683. {
  684. Unreferenced(hSym);
  685. Unreferenced(pCxt);
  686. Unreferenced(lpsstr);
  687. Unreferenced(fCaseSensitive);
  688. Unreferenced(pfnCmp);
  689. Unreferenced(fChild);
  690. Unreferenced(pCxtOut);
  691. return (HSYM)NULL;
  692. }
  693. /*** SHGetCxtFromHmod
  694. **
  695. ** Synopsis:
  696. ** PCXT SHGetCxtFromHmod( HMOD hmod, PCXT pcxt);
  697. **
  698. ** Entry:
  699. ** hmod - handle to module
  700. ** pcxt - Handle to the context to be updated
  701. **
  702. ** Returns:
  703. ** Returns a pointer to the context, or NULL if we had
  704. ** a problem.
  705. **
  706. ** Description:
  707. ** Given a handle to a module, return a context block
  708. ** for it.
  709. **
  710. */
  711. PCXT LOADDS PASCAL SHGetCxtFromHmod( HMOD hmod, PCXT pcxt)
  712. {
  713. PSYMFILE pSymfile = (PSYMFILE)hmod;
  714. if ( hmod) {
  715. HEXE hexe = SHHexeFromHmod( hmod);
  716. MEMSET( pcxt, 0, sizeof(CXT));
  717. pcxt->hGrp = pcxt->hMod = hmod;
  718. SH_SetAddr( &pcxt->addr, pSymfile->startOffset, hexe);
  719. }
  720. else
  721. return (PCXT)NULL;
  722. }
  723. /*** SHGetExeName
  724. **
  725. ** Synopsis:
  726. ** LSZ SHGetExeName( HEXE hexe);
  727. **
  728. ** Entry:
  729. ** hexe - The Handle to the EXE
  730. **
  731. ** Returns:
  732. ** pointer to exe's full path-name file.
  733. **
  734. ** Description:
  735. ** Given an HEXE return a pointer to the full path-name file.
  736. ** returns NULL if not available.
  737. **
  738. */
  739. LSZ LOADDS PASCAL SHGetExeName ( HEXE hexe )
  740. {
  741. PIMAGE_INFO pInfo = (PIMAGE_INFO)hexe;
  742. if ( pInfo )
  743. return (LSZ)pInfo->pszName;
  744. else
  745. return (LSZ)NULL;
  746. }
  747. /*** SHGethExeFromName
  748. **
  749. ** Synopsis:
  750. ** HEXE SHGethExeFromName( LSZ Name);
  751. **
  752. ** Entry:
  753. ** Name - The filename of the exe
  754. **
  755. ** Returns:
  756. ** A handle to the HEXE, or NULL if not found.
  757. **
  758. ** Description:
  759. ** To get an EXE handle given its name.
  760. **
  761. */
  762. HEXE PASCAL LOADDS SHGethExeFromName( LSZ lszNam)
  763. {
  764. PIMAGE_INFO pImageNew = pProcessCurrent->pImageHead;
  765. LSZ lszModule;
  766. LSZ lszName;
  767. CHAR Base[_MAX_CVFNAME];
  768. /*
  769. * Make a local copy of the name so we can mangle it
  770. */
  771. if ( !(lszName = _strdup(lszNam)) ) {
  772. dprintf("SHGethExeFromName() can't strdup lszNam\n");
  773. return (HEXE)0;
  774. }
  775. /*
  776. * Check for "handlized" filename and convert
  777. */
  778. if ( *lszName == '|')
  779. lszModule = strtok(lszName+1,"|");
  780. else
  781. lszModule = lszName;
  782. _splitpath( lszModule, NULL, NULL, Base, NULL);
  783. /*
  784. * Now Search for the sanitized version of the base name
  785. */
  786. while (pImageNew) {
  787. if ( _stricmp(pImageNew->pszName, Base) == 0 ||
  788. _stricmp(pImageNew->pszName, lszModule) == 0) break;
  789. pImageNew = pImageNew->pImageNext;
  790. }
  791. free(lszName);
  792. return (HEXE)pImageNew;
  793. }
  794. /*** SHGetNearestHsym
  795. **
  796. ** Synopsis:
  797. ** UOFF32 SHGetNearestHsym ( LPADDR paddr, HMOD hmod,
  798. ** int mDataCode, PHSYM phsym )
  799. **
  800. ** Entry:
  801. ** paddr - The Address we looking for
  802. ** hmod - Module adddress is located in
  803. ** mDataCode - Not Referenced
  804. ** phsym - Pointer to the HSYM to fill out
  805. **
  806. ** Returns:
  807. ** The offset between the symbol and the address, or CV_MAXOFFSET
  808. ** if no symbol found.
  809. **
  810. ** Description:
  811. ** Finds the closest symbol to an address. <phsym> is updated to
  812. ** the handle to the symbol or NULL if not found.
  813. **
  814. ** Since we don't know how to handle labels yet, just a call to
  815. ** PHGetNearestHsym().
  816. **
  817. */
  818. UOFF32 LOADDS PASCAL SHGetNearestHsym ( LPADDR paddr, HMOD hmod,
  819. int mDataCode, PHSYM phsym )
  820. {
  821. HEXE hexe = SHHexeFromHmod(hmod);
  822. Unreferenced(mDataCode);
  823. // Hummm we don't know how to handle labels yet, so just find
  824. // the closest proc, and since the [other sh] always zero symbol,
  825. // we will too.
  826. *phsym = (HSYM) NULL;
  827. return (PHGetNearestHsym(paddr,hexe,phsym) );
  828. }
  829. /*** SHGetNextExe
  830. **
  831. ** Synopsis:
  832. ** HEXE SHGetNextExe( HEXE hexe);
  833. **
  834. ** Entry:
  835. ** hexe - handle to the current exe, or NULL to get the
  836. ** first one in the list
  837. **
  838. ** Returns:
  839. ** The hexe of the next executable or NULL if the last one
  840. ** in the list.
  841. **
  842. ** Description:
  843. ** Gets the handle to the next entry in the exe list for the
  844. ** current process. If the input is NULL returns the first
  845. ** entry in the list.
  846. **
  847. */
  848. HEXE LOADDS PASCAL SHGetNextExe ( HEXE hexe )
  849. {
  850. PPROCESS_INFO Next = (PPROCESS_INFO)hexe;
  851. if ( !Next ) {
  852. assert(pProcessCurrent);
  853. return (HEXE)pProcessHead->pImageHead;
  854. }
  855. else
  856. return (HEXE)Next->pProcessNext;
  857. }
  858. /*** SHGetNextMod
  859. **
  860. ** Synopsis:
  861. ** HMOD SHGetNextMod( HEXE hexe, HMOD hmod);
  862. **
  863. ** Entry:
  864. ** hexe - The executable to find the module in, If NULL
  865. ** select the first exe in the list.
  866. **
  867. ** hmod - The current module in the list, If null returns
  868. ** the first module in the exe.
  869. **
  870. ** Returns:
  871. ** The handle to the next module or NULL if no more modules
  872. ** in the executable.
  873. **
  874. ** Description:
  875. ** Returns the next module in the current executable for the
  876. ** current process. Returns NULL if no more modules.
  877. **
  878. */
  879. HMOD LOADDS PASCAL SHGetNextMod ( HEXE hexe, HMOD hmod )
  880. {
  881. PIMAGE_INFO pImage = (PIMAGE_INFO)hexe;
  882. PSYMFILE pSymfile = (PSYMFILE)hmod;
  883. PNODE pNode = 0;
  884. /*
  885. * If we don't have an image (hexe) get the first one
  886. */
  887. if ( !pImage )
  888. pImage = (PIMAGE_INFO)SHGetNextExe((HEXE)NULL);
  889. /*
  890. * If we have a symfile (hmod) then convert to the node and get the
  891. * next one. If not just get the first one for the process to start
  892. * the scan.
  893. */
  894. if ( pSymfile ) {
  895. pNode = PSYMBOL_TO_PNODE(pSymfile,
  896. &(pProcessCurrent->symcontextSymfileString));
  897. pNode = NextNode(&(pProcessCurrent->symcontextSymfileString), pNode);
  898. }
  899. else
  900. pNode = NextNode(&(pProcessCurrent->symcontextSymfileString), NULL);
  901. /*
  902. * if we have a node, then check to see that it is in the pimage (hexe),
  903. * Keep scanning until we get one in the pimage or run out of nodes.
  904. */
  905. if (pNode) {
  906. do {
  907. pSymfile = PNODE_TO_PSYMFILE(pNode,
  908. &(pProcessCurrent->symcontextSymfileString));
  909. if (pSymfile->modIndex == (CHAR)pImage->index) break;
  910. pNode = NextNode(
  911. &(pProcessCurrent->symcontextSymfileString),pNode);
  912. } while (pNode);
  913. }
  914. /*
  915. * If we have a node return the symfile (hmod) otherwise they lose
  916. */
  917. if ( pNode )
  918. return (HMOD)pSymfile;
  919. else
  920. return (HMOD)0;
  921. }
  922. /*** SHGetModName
  923. **
  924. ** Synopsis:
  925. ** LSZ SHGetModName( HMOD hmod);
  926. **
  927. ** Entry:
  928. ** hmod - The handle to the module
  929. **
  930. ** Returns:
  931. ** pointer to the module name or NULL if not available.
  932. **
  933. ** Description:
  934. ** Given a handle to a module, return a pointer to the name
  935. ** of the module. Returns NULL if not availble.
  936. **
  937. */
  938. LSZ LOADDS PASCAL SHGetModName ( HMOD hmod )
  939. {
  940. PSYMFILE pSymfile = (PSYMFILE)hmod;
  941. return (LSZ)(pSymfile->pchName);
  942. }
  943. /*** SHGetSymbol
  944. **
  945. ** Synopsis:
  946. ** LSZ SHGetSymbol( LPADDR op, SOP sop, LPADDR loc, LSZ pName, LPL pOff);
  947. **
  948. ** Entry:
  949. ** op - Address to base search on
  950. ** sop - Not Referenced
  951. ** loc - Not Referenced
  952. ** pName - Pointer to Buffer for Name
  953. ** pOff - Pointer to Offset
  954. **
  955. ** Returns:
  956. ** Pointer to the Symbol Name or NULL.
  957. **
  958. ** Description:
  959. ** Find a symbol nearest to the address. Update the Offset, and puts
  960. ** the symbol name in the buffer supplied.
  961. **
  962. */
  963. LSZ PASCAL LOADDS SHGetSymbol(LPADDR op,SOP sop,LPADDR loc,LSZ pName,LPL pOff)
  964. {
  965. HSYM sym = 0;
  966. Unreferenced(sop);
  967. Unreferenced(loc);
  968. *pOff = PHGetNearestHsym(op, 0, &sym);
  969. if ( !sym )
  970. return( NULL);
  971. else
  972. return( SHGetSymName( sym, pName) );
  973. }
  974. /*** SHGetSymName
  975. **
  976. ** Synopsis:
  977. ** LSZ SHGetSymName( HSYM hsym, LSZ Name);
  978. **
  979. ** Entry:
  980. ** hsym - A handle to a symbol
  981. ** Name - A pointer to the string that receives the name
  982. **
  983. ** Returns:
  984. ** Returns the pointer to the Name or NULL on failure.
  985. **
  986. ** Description:
  987. ** Returns the name associated with the handle to the symbol passed.
  988. ** returns NULL if it can't, otherwise the pointer to the buffer (the
  989. ** one passed in).
  990. **
  991. */
  992. LSZ PASCAL LOADDS SHGetSymName ( HSYM hsym, LSZ lsz )
  993. {
  994. PSYMBOL pSymbol = (PSYMBOL)hsym;
  995. PLOCAL pLocal = (PLOCAL)hsym;
  996. LSZ ptr = lsz;
  997. CHAR Count;
  998. switch ( pSymbol->cvkind) {
  999. case K_PUBLIC:
  1000. case K_PROC:
  1001. Count = pSymbol->underscores;
  1002. while (Count--) *ptr++ = '_';
  1003. strcpy(ptr, pSymbol->string);
  1004. break;
  1005. case K_LOCAL:
  1006. strcpy(ptr, pLocal->pszLocalName);
  1007. break;
  1008. default:
  1009. lsz = NULL;
  1010. }
  1011. return lsz;
  1012. }
  1013. /*** SHGotoParent
  1014. **
  1015. ** Synopsis:
  1016. ** HSYM SHGotoParent( PCXT pcxt, PCXT pcxtout);
  1017. **
  1018. ** Entry:
  1019. ** pcxt - The current context
  1020. ** pcxtout - The New context
  1021. **
  1022. ** Returns:
  1023. ** Returns the HSYM for the parent context, or NULL
  1024. ** if we can't.
  1025. **
  1026. ** Description:
  1027. ** Given a context, return the hsym for the parent context, and
  1028. ** update <pcxtout> to the parents context.
  1029. **
  1030. **
  1031. */
  1032. HSYM LOADDS PASCAL SHGoToParent ( PCXT pcxt, PCXT pcxtOut )
  1033. {
  1034. HSYM hsym;
  1035. if( !pcxt->hMod ) return (HSYM) NULL;
  1036. *pcxtOut = *pcxt;
  1037. if( pcxt->hBlk != (HSYM) NULL ) {
  1038. pcxtOut->hBlk = (HBLK) NULL;
  1039. hsym = (HSYM)pcxt->hProc;
  1040. }
  1041. else if ( pcxt->hProc != (HPROC) NULL ) {
  1042. pcxtOut->hProc = (HPROC) NULL;
  1043. hsym = (HSYM)pcxt->hMod;
  1044. }
  1045. else
  1046. return (HSYM) NULL;
  1047. }
  1048. /*** SHHexeFromHmod
  1049. **
  1050. ** Synopsis:
  1051. ** HEXE SHHexeFromHmod( HMOD hmod);
  1052. **
  1053. ** Entry:
  1054. ** hmod - Handle to the module
  1055. **
  1056. ** Returns:
  1057. ** Handle to the exe the module is in, or NULL if not found.
  1058. **
  1059. ** Description:
  1060. ** Given a HMOD return the associated HEXE.
  1061. **
  1062. */
  1063. HEXE PASCAL LOADDS SHHexeFromHmod( HMOD hmod )
  1064. {
  1065. PSYMFILE pSymfile = (PSYMFILE)hmod;
  1066. PIMAGE_INFO pImage;
  1067. pImage = pImageFromIndex( pSymfile->modIndex );
  1068. return (HEXE)pImage;
  1069. }
  1070. /*** SHIsInProlog
  1071. **
  1072. ** Synopsis:
  1073. ** SHFLAG SHIsInProlog( PCXT pCxt);
  1074. **
  1075. ** Entry:
  1076. ** pCxt - Not Referenced
  1077. **
  1078. ** Returns:
  1079. ** Returns FALSE
  1080. **
  1081. ** Description:
  1082. ** Just a stub for now
  1083. **
  1084. */
  1085. SHFLAG SHIsInProlog(PCXT pCxt)
  1086. {
  1087. Unreferenced(pCxt);
  1088. return FALSE;
  1089. }
  1090. /*** SHIsFarProc
  1091. **
  1092. ** Synopsis:
  1093. ** BOOL SHIsFarProc( HSYM hsym);
  1094. **
  1095. ** Entry:
  1096. ** hsym - Not Referenced
  1097. **
  1098. ** Returns:
  1099. ** Returns FALSE
  1100. **
  1101. ** Description:
  1102. ** Always returns FALSE because NT only has near procs.
  1103. **
  1104. */
  1105. BOOL LOADDS PASCAL SHIsFarProc ( HSYM hsym )
  1106. {
  1107. Unreferenced(hsym);
  1108. return FALSE;
  1109. }
  1110. /*** SHLoadDll
  1111. **
  1112. ** Synopsis:
  1113. ** SHE SHLoadDll ( LSZ lszName, BOOL fLoading );
  1114. **
  1115. ** Entry:
  1116. ** lszName - Name of the DLL or EXE to load
  1117. **
  1118. ** fLoading - TRUE if the EXE/DLL is acually in memory.
  1119. **
  1120. ** Returns:
  1121. ** SHE error code. sheNone indicates no problem.
  1122. **
  1123. ** Description:
  1124. ** Loads the symbolic information for an EXE/DLL into memory so
  1125. ** that its symbols are available to the user. It also is used
  1126. ** to indicate whether the EXE/DLL is actually loaded in memory.
  1127. **
  1128. ** It is possible and legal to call this function multiple times
  1129. ** with the exact same information.
  1130. **
  1131. */
  1132. SHE LOADDS PASCAL SHLoadDll( LSZ lszName, BOOL fLoading )
  1133. {
  1134. PIMAGE_INFO pImage;
  1135. Unreferenced(fLoading);
  1136. pImage = SH_OpenImage( lszName );
  1137. if ( pImage != NULL) {
  1138. LoadSymbols(pImage);
  1139. SH_SetupGSN(pImage);
  1140. if ( SHerror == sheNone )
  1141. pImage->fSymbolsLoaded = TRUE;
  1142. if ( !pImage->QCOpened ) {
  1143. CV_CLOSE(pImage->hQCFile);
  1144. pImage->hQCFile = 0;
  1145. } else {
  1146. CloseHandle( (HANDLE)pImage->hQCFile );
  1147. }
  1148. }
  1149. return SHerror;
  1150. }
  1151. /*** SHLpGSNGetTable
  1152. **
  1153. ** Synopsis:
  1154. ** LPV SHLpGSNGetTable( HEXE hexe);
  1155. **
  1156. ** Entry:
  1157. ** hexe - Handle to a exe (PIMAGE).
  1158. **
  1159. ** Returns:
  1160. ** Pointer to the GSN
  1161. **
  1162. ** Description:
  1163. ** Returns a pointer to the GSN for the given hexe (pimage).
  1164. **
  1165. */
  1166. LPV PASCAL LOADDS SHLpGSNGetTable( HEXE hexe)
  1167. {
  1168. PIMAGE_INFO pImage = (PIMAGE_INFO)hexe;
  1169. return (LPV)pImage->pGSN;
  1170. }
  1171. /*** SHNextHsym
  1172. **
  1173. ** Synopsis:
  1174. ** HSYM SHNextHsym( HMOD hmod, HSYM hsym);
  1175. **
  1176. ** Entry:
  1177. ** hmod - Handle to the module the hsym is in.
  1178. ** hsym - Current hsym.
  1179. **
  1180. ** Returns:
  1181. ** Returns the next logical hsym or NULL if none.
  1182. **
  1183. ** Description:
  1184. ** Returns the next logical HSYM. Only useful really
  1185. ** for locals. If you pass it a PROC or PUBLIC will
  1186. ** return the first local associated. If you pass a
  1187. ** local you'll get the next local.
  1188. **
  1189. */
  1190. HSYM LOADDS PASCAL SHNextHsym ( HMOD hmod, HSYM hsym)
  1191. {
  1192. PLOCAL pLocal;
  1193. PSYMBOL pSymbol;
  1194. Unreferenced(hmod);
  1195. assert(hsym);
  1196. pLocal =(PLOCAL)hsym;
  1197. pSymbol=(PSYMBOL)hsym;
  1198. switch ( pLocal->cvkind) {
  1199. case K_LOCAL:
  1200. return ( (HSYM)pLocal->next );
  1201. break;
  1202. case K_PROC:
  1203. case K_PUBLIC:
  1204. return ( (HSYM)pSymbol->pLocal);
  1205. break;
  1206. default:
  1207. return( (HSYM)0 );
  1208. }
  1209. }
  1210. /*** SHSetHpid
  1211. **
  1212. ** Synopsis:
  1213. ** void SHSetHpid( HPID hpid );
  1214. **
  1215. ** Entry:
  1216. ** hpid -
  1217. **
  1218. ** Returns:
  1219. **
  1220. ** Description:
  1221. ** Sets the HPID for the current process.
  1222. **
  1223. */
  1224. VOID LOADDS PASCAL SHSetHpid ( HPID hpid )
  1225. {
  1226. pProcessCurrent->hpid = hpid;
  1227. }
  1228. /*** SHSetCxt
  1229. **
  1230. ** Synopsis:
  1231. ** PCXT SHSetCxt( LPADDR paddr, PCXT pcxt);
  1232. **
  1233. ** Entry:
  1234. ** paddr - pointer to Address
  1235. ** pcxt - pointer to Context
  1236. **
  1237. ** Returns:
  1238. ** Returns the pcxt;
  1239. **
  1240. ** Description:
  1241. ** Given an address structure fill out an context. Since NT
  1242. ** doesn't grok blocks yet, just call SHSetCxtMod().
  1243. **
  1244. */
  1245. PCXT PASCAL LOADDS SHSetCxt( LPADDR paddr, PCXT pcxt)
  1246. {
  1247. return( SHSetCxtMod(paddr,pcxt));
  1248. }
  1249. /*** SHSetCxtMod
  1250. **
  1251. ** Synopsis:
  1252. ** PCXT SHSetCxtMod( LPADDR paddr, PCXT pcxt);
  1253. **
  1254. ** Entry:
  1255. ** paddr - pointer to Address
  1256. ** pcxt - pointer to Context
  1257. **
  1258. ** Returns:
  1259. ** Returns the pcxt;
  1260. **
  1261. ** Description:
  1262. ** Given an address structure fill out an context. All fields
  1263. ** are filled except hBlk which we zero.
  1264. **
  1265. */
  1266. PCXT PASCAL LOADDS SHSetCxtMod( LPADDR paddr, PCXT pcxt)
  1267. {
  1268. HSF hsf;
  1269. PSYMFILE pSymfile;
  1270. memcpy( &pcxt->addr, paddr, sizeof(ADDR));
  1271. hsf = SLHsfFromPcxt(pcxt);
  1272. pcxt->hMod = (HMOD)hsf;
  1273. pcxt->hGrp = (HGRP)hsf;
  1274. pcxt->hProc = (HPROC)GetFunctionFromOffset(&pSymfile,
  1275. SH_OffsetFromAddr(paddr) );
  1276. pcxt->hBlk = 0; // we no do'em stink'em blocks!
  1277. return(pcxt);
  1278. }
  1279. /*** SHSetupExclude
  1280. **
  1281. ** Synopsis:
  1282. ** SHE SHSetupExclude( LSZ exclude );
  1283. **
  1284. ** Entry:
  1285. ** exclude - Pointer to a string of filenames seperated by
  1286. ** semicolons. Either BASE name only, or FULL path.
  1287. **
  1288. ** Returns:
  1289. ** SHE error code
  1290. **
  1291. ** Description:
  1292. ** Sets the exclude file list for DLL loads. If a DLL is contained
  1293. ** in the list, the symbols for that DLL will NEVER be loaded.
  1294. **
  1295. */
  1296. SHE LOADDS PASCAL SHSetupExclude(LSZ exclude)
  1297. {
  1298. lszDLLexclude = _strdup(exclude);
  1299. if ( lszDLLexclude )
  1300. return sheNone;
  1301. else
  1302. return sheOutOfMemory;
  1303. }
  1304. /*** SHUnloadDLL
  1305. **
  1306. ** Synopsis:
  1307. ** void SHUnloadDLL( HEXE hexe);
  1308. **
  1309. ** Entry:
  1310. ** hexe - Handle to the exe that was unloaded
  1311. **
  1312. ** Returns:
  1313. **
  1314. ** Description:
  1315. ** Unloads the symbol information for given hexe (pImage).
  1316. **
  1317. */
  1318. VOID PASCAL LOADDS SHUnloadDll ( HEXE hexe )
  1319. {
  1320. PIMAGE_INFO pImage = (PIMAGE_INFO)hexe;
  1321. unsigned int i = 0;
  1322. assert( pImage);
  1323. // Unload the GSN and RVA tables
  1324. if ( pImage->pGSN) free(pImage->pGSN);
  1325. if ( pImage->pRVA) free(pImage->pRVA);
  1326. // Unload the Type Records
  1327. if ( pImage->TypeCount ) {
  1328. while(i < pImage->TypeCount) {
  1329. free(pImage->rgTypeInfo[i]);
  1330. i++;
  1331. }
  1332. free( pImage->rgTypeInfo );
  1333. }
  1334. // Now let coff unload its info
  1335. UnloadSymbols( pImage );
  1336. }