source: trunk/eraser/Eraser.Util.Native/OpenHandle.NameResolver.cpp @ 2515

Revision 2515, 3.7 KB checked in by lowjoel, 3 years ago (diff)

Set svn:keywords and svn:eol-style on all the source files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Rev URL
Line 
1/*
2 * $Id$
3 * Copyright 2008-2010 The Eraser Project
4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22#include "stdafx.h"
23#include "OpenHandle.h"
24
25#pragma unmanaged
26
27namespace {
28    DWORD __stdcall nameResolutionThread(void* data)
29    {
30        //Get the thread parameters
31        NameResolutionThreadParams& param = *static_cast<NameResolutionThreadParams*>(data);
32
33        //Get the list of logical drives
34        wchar_t drives[26 * 3];
35        if (!GetLogicalDriveStrings(sizeof(drives) / sizeof(drives[0]), drives))
36            return 1;
37        for (wchar_t* i = drives; *i; i += 4)
38            *(i + 2) = 0;
39
40        //Get the file path
41        char name[4096];
42        PUNICODE_STRING nameStr = reinterpret_cast<PUNICODE_STRING>(name);
43
44        for ( ; ; )
45        {
46            WaitForSingleObject(param.Semaphore, INFINITE);
47            std::list<NameResult*>::iterator i = param.Input.begin();
48
49            //If the iterator points to a NULL handle terminate us.
50            if (*i == NULL)
51                break;
52
53            //Erase this entry from the queue
54            NameResult& result = **i;
55            param.Input.erase(i);
56
57            //Query the name of the object
58            if (NtQueryObject(result.Handle, static_cast<OBJECT_INFORMATION_CLASS>(ObjectNameInformation),
59                name, sizeof(name), NULL) == STATUS_SUCCESS)
60            {
61                if (nameStr && nameStr->Length)
62                {
63                    std::wstring& name = result.Name;
64
65                    //Resolve the file path into logical drives
66                    wchar_t path[MAX_PATH];
67                    name.assign(nameStr->Buffer);
68                    for (wchar_t* j = drives; *j; j += 4)
69                        if (QueryDosDevice(j, path, MAX_PATH))
70                        {
71                            size_t pathLen = wcslen(path);
72                            if (name.substr(0, pathLen) == path)
73                            {
74                                name.replace(0, pathLen, j);
75                                break;
76                            }
77                        }
78                }
79            }
80
81            //Tell the waiting thread that we're done
82            SetEvent(result.Event);
83        }
84
85        return 0;
86    }
87
88    void CreateNameThread(HANDLE& handle, NameResolutionThreadParams& params)
89    {
90        //If the handle is valid terminate the thread
91        if (handle)
92        {
93            TerminateThread(handle, 1);
94            CloseHandle(handle);
95        }
96
97        //Create the thread
98        handle = CreateThread(NULL, 0, nameResolutionThread, &params, 0, NULL);
99    }
100}
101
102std::wstring ResolveHandleName(HANDLE handle, int pid)
103{
104    static HANDLE thread = NULL;
105    static NameResolutionThreadParams params;
106
107    //Start a name resolution thread (in case one entry hangs)
108    if (thread == NULL)
109        CreateNameThread(thread, params);
110
111    //Create a duplicate handle
112    HANDLE localHandle;
113    HANDLE processHandle = OpenProcess(PROCESS_DUP_HANDLE, false, pid);
114    DuplicateHandle(processHandle, static_cast<void*>(handle), GetCurrentProcess(),
115        &localHandle, 0, false, DUPLICATE_SAME_ACCESS);
116    CloseHandle(processHandle);
117
118    //We need a handle
119    if (!localHandle)
120        return std::wstring();
121
122    //Send the handle to the secondary thread for name resolution
123    NameResult result(localHandle);
124    params.Input.push_back(&result);
125    ReleaseSemaphore(params.Semaphore, 1, NULL);
126
127    //Wait for the result
128    if (WaitForSingleObject(result.Event, 50) != WAIT_OBJECT_0)
129    {
130        //The wait failed. Terminate the thread and recreate another.
131        CreateNameThread(thread, params);
132    }
133
134    //Close the handle which we duplicated
135    CloseHandle(localHandle);
136
137    //Return the result
138    return result.Name;
139}
Note: See TracBrowser for help on using the repository browser.