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

Revision 1812, 3.8 KB checked in by lowjoel, 5 years ago (diff)
  • Move the contents of the OpenHandle::ResolveHandlePath? function to the ResolveHandleName? function in native code (we would have p/invoked quite a bit in that function)
  • Move the global name resolution thread and it's task queue to native code and in a anonymous namespace
  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
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    HANDLE NameResolutionThread;
29    NameResolutionThreadParams NameResolutionThreadParam;
30
31    DWORD __stdcall nameResolutionThread(void* data)
32    {
33        //Get the thread parameters
34        NameResolutionThreadParams& param = *static_cast<NameResolutionThreadParams*>(data);
35
36        //Get the list of logical drives
37        wchar_t drives[26 * 3];
38        if (!GetLogicalDriveStrings(sizeof(drives) / sizeof(drives[0]), drives))
39            return 1;
40        for (wchar_t* i = drives; *i; i += 4)
41            *(i + 2) = 0;
42
43        //Get the file path
44        char name[4096];
45        PUNICODE_STRING nameStr = reinterpret_cast<PUNICODE_STRING>(name);
46
47        for ( ; ; )
48        {
49            WaitForSingleObject(param.Semaphore, INFINITE);
50            std::list<NameResult*>::iterator i = param.Input.begin();
51
52            //If the iterator points to a NULL handle terminate us.
53            if (*i == NULL)
54                break;
55
56            //Erase this entry from the queue
57            NameResult& result = **i;
58            param.Input.erase(i);
59
60            //Query the name of the object
61            if (NtQueryObject(result.Handle, static_cast<OBJECT_INFORMATION_CLASS>(ObjectNameInformation),
62                name, sizeof(name), NULL) == STATUS_SUCCESS)
63            {
64                if (nameStr && nameStr->Length)
65                {
66                    std::wstring& name = result.Name;
67
68                    //Resolve the file path into logical drives
69                    wchar_t path[MAX_PATH];
70                    name.assign(nameStr->Buffer);
71                    for (wchar_t* j = drives; *j; j += 4)
72                        if (QueryDosDevice(j, path, MAX_PATH))
73                        {
74                            size_t pathLen = wcslen(path);
75                            if (name.substr(0, pathLen) == path)
76                            {
77                                name.replace(0, pathLen, j);
78                                break;
79                            }
80                        }
81                }
82            }
83
84            //Tell the waiting thread that we're done
85            SetEvent(result.Event);
86        }
87
88        return 0;
89    }
90
91    void CreateNameThread(HANDLE& handle, NameResolutionThreadParams& params)
92    {
93        //If the handle is valid terminate the thread
94        if (handle)
95        {
96            TerminateThread(handle, 1);
97            CloseHandle(handle);
98        }
99
100        //Create the thread
101        handle = CreateThread(NULL, 0, nameResolutionThread, &params, 0, NULL);
102    }
103
104}
105
106std::wstring ResolveHandleName(HANDLE handle, int pid)
107{
108    //Start a name resolution thread (in case one entry hangs)
109    if (NameResolutionThread == NULL)
110        CreateNameThread(NameResolutionThread, NameResolutionThreadParam);
111
112    //Create a duplicate handle
113    HANDLE localHandle;
114    HANDLE processHandle = OpenProcess(PROCESS_DUP_HANDLE, false, pid);
115    DuplicateHandle(processHandle, static_cast<void*>(handle), GetCurrentProcess(),
116        &localHandle, 0, false, DUPLICATE_SAME_ACCESS);
117    CloseHandle(processHandle);
118
119    //We need a handle
120    if (!localHandle)
121        return std::wstring();
122
123    //Send the handle to the secondary thread for name resolution
124    NameResult result(localHandle);
125    NameResolutionThreadParam.Input.push_back(&result);
126    ReleaseSemaphore(NameResolutionThreadParam.Semaphore, 1, NULL);
127
128    //Wait for the result
129    if (WaitForSingleObject(result.Event, 50) != WAIT_OBJECT_0)
130    {
131        //The wait failed. Terminate the thread and recreate another.
132        CreateNameThread(NameResolutionThread, NameResolutionThreadParam);
133    }
134
135    //Close the handle which we duplicated
136    CloseHandle(localHandle);
137
138    //Return the result
139    return result.Name;
140}
Note: See TracBrowser for help on using the repository browser.