This article is written in honour of Matt Pietrek who wrote
the GREAT article on LIB file internals in the "Under The Hood" section of the
April 1998 edition of Microsoft Systems Journal. I urge all readers to read this
excellent article which includes full source codes to a sample
demo program. The following is the link to the article :
LibDump.exe is a small console program this will list out the exported
symbols which are contained in an Import or Static Library file. The library
file must be in COFF format. In Matt's article, he describes how LibDump.exe
works. Inspired by LibDump, I endeavored to write a Visual Studio add-in
that gives LibDump a user interface. The picture displayed above shows a sample
listing of the symbols contained in a library file named c:\libs\netapi32.lib. I also gave
additional facilities like putting the listing report into a Visual Studio
window so that the user is able to do text searches and to save the report into
a text file.
Perhaps the most useful feature of this add-in is its facility to include the
current lib file under view into the library list of the current project so that
the lib file can be linked. I have further plans to expand the add-in in
upcoming versions. I have included full source codes to my add-in in this
article which includes the source files given by Matt Pietrek. I have made sure
that Matt's name remains in his source files.
- Build the zipped LibExplorer.dsw project and copy
LibExplorer.dll into Program Files\Microsoft visual
- Open Tools | Customize | Add-ins and Macro Files and tick
- A new toolbar with two icon buttons shown below will appear.
- Symbol Dump
- Click on the Symbol Dump Add-in Icon and the usual Open Dialog Box will
- Select a static or import library file.
- A modeless dialog box with a list control will be displayed. This list
control will display the all the exported symbols of the library file.
- The Ordinal number of the symbol, the symbol type (exported by Ordinal or by
Name) and the full symbol name are displayed row by row.
- If you click on the "Display Report In Window" button, the report will be
displayed in a Visual Studio window :
- From here, you can opt to save this report in an external text file via
- You can also add the current library that you are viewing into your Project
by clicking on the "Add To Library List" button. The picture below show how
c:\libs\netapi32.lib has been added to the list of libraries in my
- Search Symbol
- Click on the Search Symbol Add-in Icon and the Search Symbol Specifications
Dialog Box will appear.
- This dialog box allows you to specify the symbol to search for, the
directory in which to scan library files, and whether the matching is done for
whole words and whether case sensitivity is enforced.
- After you have specified the conditions for the search, the Search Symbol
Dialog Box will appear :
- Various boxes will show the symbol that you are searching for, the directory
that you have selected for scanning, the conditions for the search and finally,
the search results.
- Via the "Add To Library List" button, you can also select a list entry and
have the add-in add the library file (that is associated with the found symbol)
to be added to the library list of the current Developer Studio Project.
- A "Stop Search" button is also supplied to terminate a search whenever you
- Symbol Dump
- Note that clicking "Display Report In Window" multiple times will cause
multiple reports to be displayed in multiple windows even if one such report has
already been displayed.
- The report is first dumped by the add-in into a temporary file on your
system. The contents of this file (the report) is then displayed in a Visual
Studio window. Therefore the title of the window will be the name of the temp
file and not the name of the library file.
- The same goes for the "Add To Library List" button. Clicking this button
multiple times will cause the same lib file to be included in your project
linker settings multiple times.
- Symbol Search
- The Symbol Search Add-in is currently only able to scan files in one
directory. Sub-directories are not traversed further. I'm currently working on
How Does It Work ?
The entire functionality of the add-in is encapsulated inside the
CDlg_LibraryExplorerSymbolsDump dialog box and in the global
LibInfoForSymbolAnalyse() which are slight modifications of Matt Pietrek's functions. This dialog
box is designed to be a MODELESS dialog box. This dialog box will manage exactly
one lib file and will do so until it is closed. This dialog box will start life
when the add-in icon button is clicked at which time the following code will be
if (m_pDlg_LibraryExplorerSymbolsDump == NULL)
LPTSTR lpszFileName = NULL;
long lRetTemp = 0;
lRetTemp = OpenAFile ((LPTSTR*)&lpszFileName);
if ((lRetTemp == 0) && (lpszFileName))
m_pDlg_LibraryExplorerSymbolsDump -> SetFileToDumpSymbols(
m_pDlg_LibraryExplorerSymbolsDump -> SetCommandsObject (this);
m_pDlg_LibraryExplorerSymbolsDump -> Display();
lpszFileName = NULL;
- A new instance of
CDlg_LibraryExplorerSymbolsDump is created,
the file to view is set by the member
- We also give this dialog box a pointer to the current
CCommands object so that it can communicate with it. It is via the
CCommands pointer that the dialog box instructs
CCommand to display
the Symbols Listing Report.
- We then instruct the dialog box to display itself.
When the dialog box comes alive, the
function will be called. This is where the action starts :
long lRetTemp = 0;
lRetTemp = DoSymbolsCollection ((LPCTSTR)m_szFileToDumpSymbols, this);
if (lRetTemp == 0)
return TRUE; }
- We first call upon
InitSymbolsDumpListControl() to initialize
the List Control. The common APIs to create columns for a list control are used.
- Next, we call on the global function
open up the LIB file and collect all the exported symbols from it.
DoSymbolsCollection() will go through the entire LIB
file and pick up symbols, analyse them and store them into individual
CSymbol objects. These
CSymbol objects will then be
stored inside the dialog class
CDlg_LibraryExplorerSymbolsDump in a
DoSymbolsCollection() is based on the
main() function supplied by Matt Pietrek.
DoSymbolsCollection() also uses the
MEMORY_MAPPED_FILE class supplied by Matt. Note that the file must be a valid COFF file or
this function will reject it. I leave it to the reader to read through the
article by Matt Pietrek to understand the principles of the
DoSymbolsCollection() function. Another function of interest is the
LibInfoForSymbolAnalyse() function which is based on Matt's
LibInfoForSymbolAnalyse() will analyse the current symbol and store the information in a
CSymbol object which is returned. We will transfer the
CSymbol object to the dialog class
CDlg_LibraryExplorerSymbolsDump for long term keeping.
I defined and used a
CSymbol class (derived from
CObject) which is stored in a
CMapWordToOb map in
CDlg_LibraryExplorerSymbolsDump. Usage of such a
CSymbol object makes it much more convenient for reporting and sorting purposes
and also paves the way for future analysis of individual symbols.
CSymbol has also made the member function
DisplaySymbols() much more
clean. It encapsulates one symbol (which can be of several types). We use
CSymbol member functions to obtain the names and types of
2. Symbol Search
With version 2, the
CSymbol class has been extended with several
additional members :
m_cstrSymbol - Stores the symbol string itself.
m_cstrExportedName - Stores the exported name of the symbol.
m_cstrLibFilePath - Stores the full path of the library file
that contains it.
m_dwArchiveMemberOffset - Stores the library file offset of the
archive member that contains this symbol.
Although it may seem extravagant to include a full path to the lib file in
CSymbol object (generating a lot of repeated information in a
CSymbol objects), this member helps in overall
organization. The constructor for
CSymbol has also been extended
with two additional parameters that takes in the lib file name and the archive
member offset. I have also created a new
CSymbolContainerAbstractClass pure abstract base class from which to derive our dialog box class
virtual long AddNewSymbol (CSymbol* pSymbolNewSet) = 0;
This base abstract class defines the public
AddNewSymbol() method which all derived classes must implement. The
CDlg_LibraryExplorerSymbolsDump dialog box class now inherits from
CSymbolContainerAbstractClass as well as
that it will inherit the
AddNewSymbol() method :
class CDlg_LibraryExplorerSymbolsDump : public CDialog,
virtual long AddNewSymbol (CSymbol* pSymbolNewSet);
We have also modified the
DoSymbolsCollection() function so that
it takes a pointer to a
CSymbolContainerAbstractClass class instead
of the former
CDlg_LibraryExplorerSymbolsDump class. This is done
DoSymbolsCollection() can call on any class that contains
AddNewSymbol() serves as a callback into the Symbol
Container to instruct it to add a new symbol object. The
CDlg_LibraryExplorerSymbolsDump dialog class is one of them. And
this new version of LibExplorer will introduce another dialog class that will
also contain symbols. I have avoided the use of interfaces and IDLs. They
unnecessarily complicate things for this project and will be hard for beginners
The Symbol Search Add-in will start life when its associated icon button is
clicked at which time the
CCommands::SymbolSearch() function will
be executed. The
CDlg_SearchSymbolSpecs dialog class encapsulates
the functionality of the Symbol Search Specifications dialog box. This class is
straightforward and the usual methods are used to extract the various search
CDlg_LibraryExplorerSymbolSearch dialog class
encapsulates the functionality of symbol matching. The actual file iteration
through a directory is done via a thread in which the
ThreadFunc_FileScan() function serves as the controlling function.
DoSymbolsCollection() function is used to collect symbols
found in a library file into
Map object that holds pointers to
CSymbol objects that represent
symbols found in a lib file. The
performs the symbol matching operation. The principle of the searching operation
is to scan through the temporary symbols list
CDlg_LibraryExplorerSymbolSearch::m_MapSymbolsTemp and then storing
found symbols in a permanent symbols list
CDlg_LibraryExplorerSymbolSearch::m_MapSymbols. Helper functions
all help in the symbol matching operation.
- I plan on adding more enhancements after this second version of LibExplorer.
- As stated in the "Limitations" section, I'm working on adding a
sub-directory traversing facility to the Symbol Search Add-in.
- I'm also studying the contents of OBJ files and a third version would
probably include listing the RAW contents of exported functions (from static
libs) into a Visual Studio binary view window.
- Hope I've done you proud, Matt.
Interim Enhancements and Bug Fixes
Monday December 17th 2001.
- A reader has kindly alerted me to a Visual Studio crash when a library file
is added to the library list. This crash occurs when Visual Studio currently has
no active workspace or project.
- I tested this case in a Windows 98 machine and noted that the crash does
- The crash occurred in the member function
- When there is no current active project, getting the Active Configuration
Object from the Application Object would raise an exception.
- In WinNT, the exception is caught when
CCommands::GetActiveConfiguration() is able to exit
gracefully and indicate to the user that there is no current active project.
- Apparently, the exception handling routines in MSDEV in Win98 is not as
robust as that in WinNT. Hence the crash.
- To remedy the situation, I made the following code changes in
- I created several more helper functions to obtain the current Projects List
Property from the Application Object. This property will exist even if there is
no current active project.
- Using the returned Projects List Property, I query it for its count of
projects. This will be returned in "
- If "
lProjectsCount" is zero, it means that there is no current
active project and so we can gracefully exit.
- I added in further checks in
CCommands::IncludeLibFileInLibraryList() to ensure no other surprise crashes.
long CCommands::IncludeLibFileInLibraryList(LPCTSTR lpszLibFileName)
LPDISPATCH pProjects = NULL;
LPDISPATCH pProject = NULL;
LPDISPATCH pConfig = NULL;
HRESULT hrRetTemp = S_OK;
long lProjectsCount = 0;
long lRet = 0;
szMessage = '\0';
if (pProjects == NULL)
lRet = -1; wsprintf (szMessage, "ERROR:\r\nUnable to obtain Projects List.");
ProjectsGetCount (pProjects, &lProjectsCount);
if (lProjectsCount <= 0)
lRet = -2; wsprintf (szMessage, "ERROR:\r\nProjects List indicate "
"that there are currently no projects.");
if (pProject == NULL)
lRet = -3; wsprintf (szMessage, "ERROR:\r\nThere is no active project.");
hrRetTemp = ConfigAddToolSettings((LPDISPATCH)pConfig,
if (hrRetTemp == S_OK)
"SUCCESS:\r\nFile <%s> has successfully been "
"included into library list.", lpszLibFileName);
wsprintf (szMessage, "ERROR:\r\nUnable to include file <%s> "
"into library list.", lpszLibFileName);
wsprintf (szMessage, "ERROR:\r\nNo current configuration.\r\nUnable"
" to include file <%s> into library list.", lpszLibFileName);
AfxMessageBox(szMessage, MB_OK | MB_ICONINFORMATION);
pConfig -> Release();
pConfig = NULL;
pProject -> Release();
pProject = NULL;
pProjects -> Release();
pProjects = NULL;
Wednesday December 19th 2001.
- Another reader (Bruno Leclerc) alerted me to a crash on his WinNT 4.0
machine with Visual C++ 6.0. Bruno has used a RELEASE version of the add-in. The
crash occurred after he has selected a lib file in the common File Open dialog
- However, after 2 days of debugging and testing, including enlisting the help
of NuMega's Bounds Checker, I could not reproduce the problem on my machines.
- Hence I sincerely request readers who have faced the same problem, if you
have the time, to perhaps insert trace statements (or use plain old
MessageBoxes) into the supplied source codes to help me pinpoint the exact
source location where the crash occurred.
- If you can reproduce the problem in a DEBUG version of the add-in, and if
you can spare the time to step through the code, all the better
- All these would help me a great deal to narrow down the problem.
- My sincere apologies for this and many thanks to all.
- Monday December 24th 2001. LibExplorer Version 2.
- It's arrived ! I have updated this article with version 2 of the LibExplorer
Developer Studio Add-in.
- This new version includes a new Symbol Search Dialog Box that allows the
user to scan a directory for lib files that contain a particular symbol.
- The user is able to indicate full string search or sub-string search. Case
sensitivity can also be indicated.
- Just like the version 1 symbol dump facility, the user is able to add a
library that contains a found symbol to the library list of a Developer Studio
Project for linking.
- More on these in the "Usage" section below.