dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10

Thread: Enum HANDLEs for current process

  1. #1
    Join Date
    Aug 2001
    Location
    Stockholm, Sweden
    Posts
    1,664

    Enum HANDLEs for current process

    Hi all,

    Does anyone know how to enumerate open handles for the current process (or other processes)? I need to enum all opened handles for my process and get the type (like handle to reg, handle to file, etc...). I then need to close the handle. Don't ask why:-)

    Source code or any hits/suggestions would be great.


    Thanks,
    Jonas

    PS. The "Process Explorer" from www.sysinternals.com does this, but there's no source code or hits...

    PS2. It's for Windows 2000...


    ***
    I like feedback, so please rate my answer.

  2. #2
    Join Date
    Jan 2002
    Location
    Pakistan
    Posts
    28

    Re: Enum HANDLEs for current process

    #include <windows.h>
    #include <iostream.h>
    #include <tlhelp32.h>
    #include <conio.h>
    #include <stdio.h>

    BOOL GetProcessList (DWORD buff)
    {
    HANDLE hProcessSnap = NULL;
    BOOL bRet = FALSE;
    PROCESSENTRY32 pe32 = {0};

    // Take a snapshot of all processes in the system.

    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);

    if (hProcessSnap == INVALID_HANDLE_VALUE)
    return (FALSE);

    // Fill in the size of the structure before using it.

    pe32.dwSize = sizeof(PROCESSENTRY32);

    // Walk the snapshot of the processes, and for each process,
    // display information.

    if (Process32First(hProcessSnap, &pe32))
    {
    do
    {
    if(buff==pe32.th32ProcessID)
    printf( "Full Path\t\t%s\n\n", pe32.szExeFile );
    else
    ;
    /*printf( "\nPriority Class Base\t%d\n",
    pe32.pcPriClassBase);
    printf( "PID\t\t\t%d\n", pe32.th32ProcessID);
    printf( "Thread Count\t\t%d\n", pe32.cntThreads);
    printf( "Full Path\t\t%s\n\n", pe32.szExeFile );*/

    }
    while (Process32Next(hProcessSnap, &pe32) );
    bRet = TRUE;
    }
    else
    bRet = FALSE; // could not walk the list of processes

    // Do not forget to clean up the snapshot object.

    CloseHandle (hProcessSnap);
    return (bRet);
    }

    void main() {

    DWORD buff;
    HWND hwndMedia = FindWindowEx(NULL, NULL, NULL, "Windows Media Player");
    GetWindowThreadProcessId(hwndMedia,&buff );
    GetProcessList (buff) ;
    getche();
    //cout<<buff;
    }

    4rukh

  3. #3
    Join Date
    Aug 2001
    Location
    Stockholm, Sweden
    Posts
    1,664

    Re: Enum HANDLEs for current process

    Isnīt this code W9x specific? I need it for w2k... Does it work for w2k?

    Thank you,
    Jonas

    ***
    I like feedback, so please rate my answer.

  4. #4
    Join Date
    Apr 2002
    Posts
    17
    I am looking for a very similar solution. This sample code does not seem to be a solution to this question at all. It only gets a list of process id's... not a list of usable handles, or a way to query the handle type.

    have you found a solution to this.... if so please post.
    Thanks,
    Chris

  5. #5
    Join Date
    Mar 2002
    Posts
    350
    here it is .. you need the DDK for that , Gary Nebbett is the author:
    Code:
    #include "ntdll.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include "ntddk.h"
    
    #define DUPLICATE_SAME_ATTRIBUTES   0x00000004
    
    #pragma comment(lib,"ntdll.lib")
    
    BOOL EnablePrivilege(PCSTR name)
    {
        TOKEN_PRIVILEGES priv = {1, {0, 0, SE_PRIVILEGE_ENABLED}};
        LookupPrivilegeValue(0, name, &priv.Privileges[0].Luid);
    
        HANDLE hToken;
        OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
    
        AdjustTokenPrivileges(hToken, FALSE, &priv, sizeof priv, 0, 0);
        BOOL rv = GetLastError() == ERROR_SUCCESS;
    
        CloseHandle(hToken);
        return rv;
    }
    
    int main(int argc, char *argv[])
    {
        if (argc == 1) return 0;
    
        ULONG pid = strtoul(argv[1], 0, 0);
    
        EnablePrivilege(SE_DEBUG_NAME);
    
        HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid);
    
        ULONG n = 0x1000;
        PULONG p = new ULONG[n];
    
        while (NT::ZwQuerySystemInformation(NT::SystemHandleInformation, p, n * sizeof *p, 0)
               == STATUS_INFO_LENGTH_MISMATCH)
    
            delete [] p, p = new ULONG[n *= 2];
    
        NT::PSYSTEM_HANDLE_INFORMATION h = NT::PSYSTEM_HANDLE_INFORMATION(p + 1);
    
        for (ULONG i = 0; i < *p; i++) {
    
            if (h[i].ProcessId == pid) {
                HANDLE hObject;
    
                if (NT::ZwDuplicateObject(hProcess, HANDLE(h[i].Handle), NtCurrentProcess(), &hObject,
                                          0, 0, DUPLICATE_SAME_ATTRIBUTES)
                    != STATUS_SUCCESS) continue;
    
                NT::OBJECT_BASIC_INFORMATION obi;
    
                NT::ZwQueryObject(hObject, NT::ObjectBasicInformation, &obi, sizeof obi, &n);
    
                printf("%p %04hx %6lx %2x %3lx %3ld %4ld ", 
                       h[i].Object, h[i].Handle, h[i].GrantedAccess,
                       int(h[i].Flags), obi.Attributes,
                       obi.HandleCount - 1, obi.PointerCount - 2);
    
                n = obi.TypeInformationLength + 2;
    
                NT::POBJECT_TYPE_INFORMATION oti = NT::POBJECT_TYPE_INFORMATION(new CHAR[n]);
    
                NT::ZwQueryObject(hObject, NT::ObjectTypeInformation, oti, n, &n);
    
                printf("%-14.*ws ", oti[0].Name.Length / 2, oti[0].Name.Buffer);
    
                n = obi.NameInformationLength == 0 
                    ? MAX_PATH * sizeof (WCHAR) : obi.NameInformationLength;
    
                NT::POBJECT_NAME_INFORMATION oni = NT::POBJECT_NAME_INFORMATION(new CHAR[n]);
    
                NTSTATUS rv = NT::ZwQueryObject(hObject, NT::ObjectNameInformation, oni, n, &n);
                if (NT_SUCCESS(rv))
                    printf("%.*ws", oni[0].Name.Length / 2, oni[0].Name.Buffer);
    
                printf("\n");
    
                CloseHandle(hObject);
            }
        }
        delete [] p;
    
        CloseHandle(hProcess);
    
        return 0;
    }
    Last edited by AdaraCD; October 3rd, 2002 at 02:18 AM.

  6. #6
    Join Date
    Apr 2002
    Posts
    17
    I have used this code and it works great. Thank you very much for the post.

    But, my program also needs to work under Win98 and will not have access to ntdll in this case.

    The application ProcessExplorer from sysinternals.com is able to do this under winXP and win98. I have run the same exe under both, and the app can also open its own handles..... so i can see that under XP it has opened ntdll and under win98 it has not opened ntdll... but the same list of handles for other apps is shown.

    Does anyone know how to enumerate the handles under win98?

    Thanks very much,
    Chris

  7. #7
    Join Date
    Sep 2002
    Posts
    1,747

    Quick point to snowman

    Both versions were included above. Just do a check for which version you are running on and you can include both examples in one app. Then take out all direct calls to functions in ntdll above and instead get the handle of the ntdll module and use it in a GetProcAddress for each ntdlll function you need. You will probably want to use a standard typedef to cast the result of GetProcAddress. You need to do this because you want to be able to call the functions in ntdll without specifically linking to them in your import address table (which would make your app not work on 9x). You won't need to specifically LoadLibrary to get ntdll hmodule, because it is always loaded as the first module in a process (everything else, especiall kernel32, depends on it). You may need to modify the includes as well, but the rest is straightforward.

  8. #8
    Join Date
    Sep 2002
    Posts
    1,747

    Whoops!

    Sorry, I just looked through the above and noticed that the first item DIDN'T solve the problem for 9x, which is what Snowman wanted. I can't think of a simple answer right now for consumer Windows, even through something like toolhelp. The only thing I can think of right now is to go down to the kernel and check out the object tables, but I doubt that is the answer you want. **** Russinovich and co... always solving the really difficult probs with seeming ease and style. What's up with that?

  9. #9
    Join Date
    Apr 2002
    Posts
    17
    I found a solution and I am going to add it here for others to find.
    This is a very CRUDE method I think, but the only one I have been able to come up with for win98. So far it works fine for me.

    I made this routine to attempt to duplicate all handles from 1 to 1000 and then look to see which are socket handles....
    The passed variable processId is the application you want handles for.

    Code:
    BOOL MyAppDlg::EnumPorts(DWORD processId )
    {
    	DWORD lpdwFlags = 0;
    	char temp[10] = "";
    	int t=0,i=0;
    	HANDLE handle;
    	HANDLE hRemoteProcess = NULL;
    	sockaddr sock_address;
    	int sock_add_size = sizeof(sock_address);
    	BOOL remote = processId != GetCurrentProcessId();
    
    	if ( remote )
    	{
    		// Open the remote process
    		hRemoteProcess = OpenProcess(PROCESS_DUP_HANDLE,FALSE, processId );
    		
    		if ( hRemoteProcess == NULL )
    			return 0;
    
    		for(t=1;t<1000;t++){
    
    		// Duplicate the handle
    			if( ::DuplicateHandle(hRemoteProcess,
    								 (HANDLE)t,
    								 GetCurrentProcess(),
    								 &handle,
    								 0,
    								 FALSE,
    								 DUPLICATE_SAME_ACCESS)){
    
    				if(!getsockname((SOCKET) handle,	&sock_address, &sock_add_size)){
    
    					//you found a socket handle do with it as you like.....
    				}
    			}
    		}
    	}
    	else
    		return 0;
    
    	return 1;
    }
    Like I said a little crude, but if you find a better way please post. This solution does not need ntdll.dll and so far works fine under win98.
    Chris

  10. #10
    Join Date
    May 1999
    Location
    Southern California
    Posts
    12,266
    I think this is something that has been discussed by experts and Microsoft has acknowledged that it is a limitation of Windows. Of course that was before Windows 2000 so there might be something new for 2000 but I doubt it. Perhaps XP has something new.

    I think the reason the source for the sysinternals utility is not provided is that it uses undocumented and unsupported stuff and sysinternals wants to protect their investment in it.
    "Signature":
    My web site is Simple Samples.
    C# Corner Editor

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)