Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Tagged as

Dependency Checker

, 21 Oct 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
This is a simple lightweight utility to find which DLL/EXE/OCX in a folder uses a particular DLL.

This is a simple lightweight utility to find which DLL/EXE/OCX in a folder uses a particular DLL.

My development environment usually includes large number of binaries. And I was working in some core library module which is used by many other DLLs. So whenever I change something in the header file of this code library, I have to rebuild all the dependent libraries. Rebuilding the entire environment was not practical all times. So I had to create such an utility so that I can find out who uses this code library and can rebuild those modules only.

How To Use

  1. In the “DLL Name” edit box, enter the name of the DLL for which we have to search.
  2. In the “Path” edit box, enter the folder in which we have to search for DLLs/EXE/OCX that uses DLL entered in the “DLL Name” edit box.
  3. Click “Start” button.

Upon clicking the Start button, the list control starts’ populating the DLL, OCX and EXEs that use the specified DLL. Please note that this application will not list dynamic dependencies and so we cannot enter OCX or COM DLL as “DLL Name”.

How It Works

When the start button is clicked, the application loop through each DLL, OCX and EXEs in the specified folder. It opens each binary, parses the PE (Portable Executable) file format.
For example, consider that user32.dll is specified in the "DLL name" edit box and the path is "c:\windows\system32". When user clicks on the “start” button, the application takes a loop to find EXEs, DLLs and OCXs in the specified folder. Intitally it enumarates all the EXEs. Suppose we get "calc.exe" as file name. The next thing to do is to map the binary file to memory. This is performed with the help of CreateFileMapping() and MapViewOfFile() function.

When we have the binary file in memory, we simply can parse the file. If you are not so faimiliar with the PE (Poratable Executable) file format, I recommond you have a look at the article An In-Depth Look into the Win32 Portable Executable File Format by Matt Pietrek. Our aim here is to find out the import address table. 

CFile fl;
if( !fl.Open( csExeName, CFile::modeRead|CFile::shareDenyNone, 0 ))
{
    CString csMsg;
    csMsg.Format( _T(" Failed to open file %s"), csExeName );
    AfxMessageBox( csMsg );
    continue;
}
HANDLE hSM = CreateFileMapping
	( (HANDLE)fl.m_hFile, 0,PAGE_READONLY,0,0, _T("some_sM"));
LPVOID pBinary = MapViewOfFile( hSM,FILE_MAP_READ,0,0, fl.GetLength());
if( CheckForDependecy( csDllName, pBinary ))
{
    m_List.InsertItem( 0, fl.GetFileName() );
}
UnmapViewOfFile( pBinary );
CloseHandle( hSM );
fl.Close();

As you can see in the above code, after the binary is loaded to memory, the memory address is passed to the CheckForDependecy() function. The function casts the memory address to a IMAGE_DOS_HEADER pointer.

PIMAGE_DOS_HEADER pDOSHeader = (PIMAGE_DOS_HEADER) lpStartAddress;

After this, it will try to get the IMAGE_NT_HEADERS from pDOSHeader. Usually the 16 bit binaries will not be having this header. So we will ignore such binaries at this point.

PIMAGE_NT_HEADERS pNTHeader = 
	MakePtr(PIMAGE_NT_HEADERS, pDOSHeader, pDOSHeader->e_lfanew);
if( IsBadReadPtr( pNTHeader, sizeof( IMAGE_NT_HEADERS)))
{
	return false;
}

Sometimes because of the property of data in the file, it may occur that the pNTHeader points to a valid memory. So we will add one more checking to confirm that we are dealing with PE file (The famous DRWATSON.EXE fails at this checking!!! Ya, it is not a PE file).

The next task is to find the IMAGE_IMPORT_DESCRIPTOR. The IMAGE_NT_HEADERS.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]. VirtualAddress holds the relative address of IMAGE_IMPORT_DESCRIPTOR from the start of the memory. We can use the ImageRvaToVa() API to convert the relative adress to virtual address. There's one IMAGE_IMPORT_DESCRIPTOR for each imported executable. So we will loop through each item and check whether it is for importing the specified DLL (“user32.dll” in our case).

PIMAGE_IMPORT_DESCRIPTOR pImportDesc = 
		(PIMAGE_IMPORT_DESCRIPTOR)ImageRvaToVa( pNTHeader, lpStartAddress, 
		pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
                                                 VirtualAddress, 0 );
    while( pImportDesc && pImportDesc->Name )
    {
        PVOID pName = ImageRvaToVa( pNTHeader, lpStartAddress, pImportDesc->Name , 0 );
        PSTR szCurrMod = (PSTR)pName;
        if( IsBadReadPtr( szCurrMod, 1 ))
        {
            continue;
        }
        CString cs = szCurrMod;
        if( 0 == cs.CollateNoCase( csDllName ))
        {
            return true;
        }
        pImportDesc++;
    }

And for the records, let me say that, there are 1111 files in my system32 folder that have dependency with the user32.dll (Vista SP1).

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Naveen
Software Developer (Senior)
Singapore Singapore
No Biography provided

Comments and Discussions

 
GeneralMy vote of 2 PinmemberAidamin17-Dec-13 4:42 
Questionhow to run??? Pinmemberbleachli9-Nov-11 6:05 
AnswerRe: how to run??? PinmemberNaveen9-Nov-11 15:44 
QuestionWhy.. again? Pinmemberrew´RaZiel19-Aug-10 23:49 
AnswerRe: Why.. again? PinmemberNaveen20-Aug-10 0:25 
QuestionWhy? PinmemberJohnny J.21-Oct-09 22:11 
AnswerRe: Why? PinmvpNaveen21-Oct-09 22:40 
QuestionHow it detects what dlls are loaded with loadlibrary ? Pinmemberarabcoder21-Oct-09 12:02 
AnswerRe: How it detects what dlls are loaded with loadlibrary ? PinmvpNaveen21-Oct-09 19:12 
AnswerRe: How it detects what dlls are loaded with loadlibrary ? Pinmemberrew´RaZiel19-Aug-10 23:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411022.1 | Last Updated 22 Oct 2009
Article Copyright 2009 by Naveen
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid