Click here to Skip to main content
12,300,607 members (22,815 online)
Click here to Skip to main content
Add your own
alternative version

Stats

84.2K views
2.5K downloads
48 bookmarked
Posted

Find and kill a process which uses the specified loaded dynamic library (.dll)

, 29 May 2005
Rate this:
Please Sign up or sign in to vote.
Find and kill all processes which have the given DLL as a module.

Output

Main Features

This article demonstrates a console application that will search and kill all the processes which are holding the given library name (comparison is not case sensitive). It is useful by COM+ registration using gacutil.exe and regsvcs.exe utilities.

Introduction

Often it is necessary to terminate a process which holds the given dynamic library. This case is well-know for COM+ programmers who have to stop before COM+ registration all processes which are holding their DLL. Manual search and termination is very frustrating, onerous and slows-down the programmer. This problem is solved by a utility which searches and terminates all processes which hold the given DLL. This is an occasion to create a batch file and call this utility with the name of the DLL as an input parameter, before the COM+ registration.

The entire source code shows a technique of how to proceed step by step by several processes and owned modules (DLLs). Accessing some processes and modules requires special privileges. This problem is handled in Keith Brown's and Christophe Nasarre's articles (see Credits section). If the access is obtained successfully, there is an opened admission to several modules for the existing process and also a permission to kill the given process.

Code

Well, here is a batch file example for COM+ programmers:

@echo off

freelib.exe sample.dll

echo.
echo Just... paused!
pause > nul

gacutil /nologo /u sample
regsvcs /u /nologo sample.dll

gacutil /nologo /i sample.dll
regsvcs /fc /nologo sample.dll

echo.
echo Press any key to close this console window
pause > nul

And here is the whole source code.

/*
 * FreeLib
 * 
 * Copyright (c) 2005 by eraser
 */

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <aclapi.h>
#include <tchar.h>
#include <stdlib.h>

#if defined (_DEBUG)
    #define TRACE(str)    OutputDebugString(str)
#else
    #define TRACE(str)
#endif

#if !defined (SID_REVISION)
    #define SID_REVISION (1) 
#endif

BOOL enable_privilege(LPCTSTR szPrivilege);
BOOL adjust_dacl(HANDLE h, DWORD dwDesiredAccess); 
BOOL enable_token_privilege(HANDLE htok, 
     LPCTSTR szPrivilege, TOKEN_PRIVILEGES *tpOld);
HANDLE adv_open_process(DWORD pid, DWORD dwAccessRights);
BOOL kill_process(DWORD pid);

BOOL get_process_list(LPCTSTR szLibrary);
BOOL list_process_modules(DWORD dwPID, 
     LPCTSTR szProcessExeFile, LPCTSTR szLibrary);

char HelpText[] = 
"%s - release library utility - (c) 2005 by eraser (eraser@senior.cz)\n\n"
"Syntax: %s.exe [library_name.dll]\n\n";

void __defaultTrapHandler(int code) 
{ 
    abort(); 
} 

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        printf(HelpText, *argv, *argv);

        return 1;
    }

    get_process_list(*(argv + 1));

    return 0;
}

BOOL get_process_list(LPCTSTR szLibrary)
{
    HANDLE hProcessSnap;
    HANDLE hProcess;
    PROCESSENTRY32 pe32;
    DWORD dwPriorityClass;

    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (hProcessSnap == INVALID_HANDLE_VALUE)
    {
        TRACE("CreateToolhelp32Snapshot (of processes)");

        return (FALSE);
    }

    pe32.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hProcessSnap, &pe32))
    {
        TRACE("Process32First");
        CloseHandle(hProcessSnap);

        return (FALSE);
    }

    do
    {
        dwPriorityClass = 0;
        hProcess = adv_open_process(pe32.th32ProcessID, PROCESS_ALL_ACCESS);

        if (hProcess == NULL)
        {
            TRACE("OpenProcess");
        }
        else
        {
            dwPriorityClass = GetPriorityClass(hProcess);

            if (!dwPriorityClass)
            {
                TRACE("GetPriorityClass");
            }

            CloseHandle(hProcess);
        }

        list_process_modules(pe32.th32ProcessID, pe32.szExeFile, szLibrary);

    } while (Process32Next(hProcessSnap, &pe32));

    CloseHandle(hProcessSnap);

    return (TRUE);
}

BOOL list_process_modules(DWORD dwPID, 
     LPCTSTR szProcessExeFile, LPCTSTR szLibrary)
{
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32;

    enable_privilege(SE_DEBUG_NAME);
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);

    if (hModuleSnap == (HANDLE) - 1)
    {
        TRACE("CreateToolhelp32Snapshot() failed!");
        TRACE(szProcessExeFile);

        return (FALSE);
    }

    me32.dwSize = sizeof(MODULEENTRY32);

    if (!Module32First (hModuleSnap, &me32))
    {
        TRACE("Module32First");
        CloseHandle(hModuleSnap);

        return (FALSE);
    }

    do
    {
        if (!lstrcmpi(szLibrary, me32.szModule))
        {
            printf("\nPROCESS: [%d] %s \t MODULE: %s", 
                   dwPID, szProcessExeFile, me32.szModule);
            printf(kill_process(dwPID) ? " terminated!" : 
                                 " termination failed!");
        }

    } while (Module32Next(hModuleSnap, &me32));

    CloseHandle(hModuleSnap);

    return (TRUE);
}

BOOL enable_privilege(LPCTSTR szPrivilege)
{
    BOOL bReturn = FALSE;
    HANDLE hToken;
    TOKEN_PRIVILEGES tpOld;

    if (!OpenProcessToken(GetCurrentProcess(), 
         TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
    {
        TRACE("enable_privilege");

        return(FALSE);
    }

    bReturn = (enable_token_privilege(hToken, szPrivilege, &tpOld));
    CloseHandle(hToken);

    return (bReturn);
}


BOOL adjust_dacl(HANDLE h, DWORD dwDesiredAccess)
{
    SID world = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, 0 };

    EXPLICIT_ACCESS ea =
    {
        0,
            SET_ACCESS,
            NO_INHERITANCE,
        {
            0, NO_MULTIPLE_TRUSTEE,
                TRUSTEE_IS_SID,
                TRUSTEE_IS_USER,
                0
        }
    };

    ACL* pdacl = 0;
    DWORD err = SetEntriesInAcl(1, &ea, 0, &pdacl);

    ea.grfAccessPermissions = dwDesiredAccess;
    ea.Trustee.ptstrName = (LPTSTR)(&world);

    if (err == ERROR_SUCCESS)
    {
        err = SetSecurityInfo(h, SE_KERNEL_OBJECT, 
              DACL_SECURITY_INFORMATION, 0, 0, pdacl, 0);
        LocalFree(pdacl);

        return (err == ERROR_SUCCESS);
    }
    else
    {
        TRACE("adjust_dacl");

        return(FALSE);
    }
}

BOOL enable_token_privilege(HANDLE htok, 
     LPCTSTR szPrivilege, TOKEN_PRIVILEGES *tpOld)
{
    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (LookupPrivilegeValue(0, szPrivilege, &tp.Privileges[0].Luid))
    {
        DWORD cbOld = sizeof (*tpOld);

        if (AdjustTokenPrivileges(htok, FALSE, &tp, cbOld, tpOld, &cbOld))
        {
            return (ERROR_NOT_ALL_ASSIGNED != GetLastError());
        }
        else
        {
            TRACE("enable_token_privilege");

            return (FALSE);
        }
    }
    else
    {
        TRACE("enable_token_privilege");

        return (FALSE);
    }
}


HANDLE adv_open_process(DWORD pid, DWORD dwAccessRights)
{
    HANDLE hProcess = OpenProcess(dwAccessRights, FALSE, pid);

    if (hProcess == NULL)
    {
        HANDLE hpWriteDAC = OpenProcess(WRITE_DAC, FALSE, pid);

        if (hpWriteDAC == NULL)
        {
            HANDLE htok;
            TOKEN_PRIVILEGES tpOld;

            if (!OpenProcessToken(GetCurrentProcess(), 
                 TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &htok))
            {
                return(FALSE);
            }

            if (enable_token_privilege(htok, SE_TAKE_OWNERSHIP_NAME, &tpOld))
            {
                HANDLE hpWriteOwner = OpenProcess(WRITE_OWNER, FALSE, pid);

                if (hpWriteOwner != NULL)
                {
                    BYTE buf[512];
                    DWORD cb = sizeof buf;

                    if (GetTokenInformation(htok, TokenUser, buf, cb, &cb))
                    {
                        DWORD err = SetSecurityInfo(hpWriteOwner, SE_KERNEL_OBJECT, 
                                    OWNER_SECURITY_INFORMATION, 
                                    ((TOKEN_USER *)(buf))->User.Sid, 0, 0, 0);
                        
                        if (err == ERROR_SUCCESS)
                        {
                            if (!DuplicateHandle(GetCurrentProcess(), hpWriteOwner, 
                                 GetCurrentProcess(), &hpWriteDAC, 
                                 WRITE_DAC, FALSE, 0))
                            {
                                hpWriteDAC = NULL;
                            }
                        }
                    }

                    CloseHandle(hpWriteOwner);
                }

                AdjustTokenPrivileges(htok, FALSE, &tpOld, 0, 0, 0);
            }

            CloseHandle(htok);
        }

        if (hpWriteDAC)
        {
            adjust_dacl(hpWriteDAC, dwAccessRights);

            if (!DuplicateHandle(GetCurrentProcess(), hpWriteDAC, 
                GetCurrentProcess(), &hProcess, dwAccessRights, FALSE, 0))
            {
                hProcess = NULL;
            }

            CloseHandle(hpWriteDAC);
        }
    }

    return (hProcess);
}

BOOL kill_process(DWORD pid)
{
    HANDLE hp = adv_open_process(pid, PROCESS_TERMINATE);

    if (hp != NULL)
    {
        BOOL bRet = TerminateProcess(hp, 1);
        CloseHandle(hp);

        return (bRet);
    }

    return (FALSE);
}

Credits

Many thanks to Keith Brown for getting a process handle with high-level rights, and definitely to Christophe Nasarre for his excellent article. I recommend the articles for all interested persons. They can find explanations about this issue and also examine some commented functions which are in my code rewritten from C++ to C language.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Dalibor Drzik
Web Developer
Slovakia Slovakia
Wink | ;-)

You may also be interested in...

Comments and Discussions

 
QuestionTHANNNNNNNNNNNKSSSSSSSSSSSSSSSSSSSSSS Pin
Diel Oliveira12-Feb-14 9:20
memberDiel Oliveira12-Feb-14 9:20 
GeneralThanks a Lot For Your Work Pin
Member 180440310-Jun-09 1:01
memberMember 180440310-Jun-09 1:01 
GeneralThanks Pin
shurzan30-Aug-07 21:02
membershurzan30-Aug-07 21:02 
QuestionIs there 64bit version? Pin
sh40715-Jun-07 10:09
membersh40715-Jun-07 10:09 
GeneralTHANK YOU! Pin
SparkyNZ20-Mar-07 16:22
memberSparkyNZ20-Mar-07 16:22 
AnswerRe: THANK YOU! Pin
Dalibor Drzik22-Mar-07 2:37
memberDalibor Drzik22-Mar-07 2:37 
GeneralThanks Much! Pin
Paul Kissel24-Jul-06 13:46
memberPaul Kissel24-Jul-06 13:46 
AnswerRe: Thanks Much! Pin
Dalibor Drzik27-Jul-06 6:25
memberDalibor Drzik27-Jul-06 6:25 
QuestionCode correct? Pin
Mark A. Johnson25-May-06 11:56
memberMark A. Johnson25-May-06 11:56 
AnswerRe: Code correct? [modified] Pin
Dalibor Drzik26-May-06 1:34
memberDalibor Drzik26-May-06 1:34 
QuestionHow About A GUI Version Pin
easter_200720-Feb-06 17:49
membereaster_200720-Feb-06 17:49 
AnswerRe: How About A GUI Version Pin
Dalibor Drzik20-Feb-06 22:21
memberDalibor Drzik20-Feb-06 22:21 
GeneralRe: How About A GUI Version Pin
easter_200721-Feb-06 12:46
membereaster_200721-Feb-06 12:46 
GeneralVery useful tool Pin
vjairam20-Jan-06 10:21
membervjairam20-Jan-06 10:21 
GeneralRe: Very useful tool Pin
Dalibor Drzik20-Jan-06 12:20
memberDalibor Drzik20-Jan-06 12:20 
GeneralMemory leak in get_process_list() Pin
Corillian29-Oct-05 9:26
memberCorillian29-Oct-05 9:26 
GeneralRe: Memory leak in get_process_list() Pin
Dalibor Drzik29-Oct-05 21:44
memberDalibor Drzik29-Oct-05 21:44 
GeneralRe: Memory leak in get_process_list() Pin
Corillian4-Nov-05 16:48
memberCorillian4-Nov-05 16:48 
QuestionCool but ? Pin
Trance Junkie30-May-05 1:04
memberTrance Junkie30-May-05 1:04 
AnswerRe: Cool but ? Pin
Dalibor Drzik30-May-05 2:59
memberDalibor Drzik30-May-05 2:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    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.160525.2 | Last Updated 30 May 2005
Article Copyright 2005 by Dalibor Drzik
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid