source: branches/eraser6/6.0/Eraser.Util.Unlocker/Eraser.Util.Unlocker.cpp @ 1677

Revision 1677, 4.4 KB checked in by lowjoel, 5 years ago (diff)

Updated copyright information: since Eraser is still under development we should update our copyright status.

  • 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 "Eraser.Util.Unlocker.h"
24
25namespace Eraser {
26namespace Util {
27    ReadOnlyCollection<OpenHandle^>^ OpenHandle::Items::get()
28    {
29        List<OpenHandle^>^ handles = gcnew List<OpenHandle^>();
30
31        //Get the number of handles on the system then load up the complete list.
32        std::auto_ptr<SYSTEM_HANDLES> handlesList(new SYSTEM_HANDLES);
33        {
34            DWORD bufferSize = 0;
35            NtQuerySystemInformation(static_cast<SYSTEM_INFORMATION_CLASS>(SystemHandleInformation),
36                handlesList.get(), sizeof(SYSTEM_HANDLES), &bufferSize);
37
38            //Then get the whole list
39            handlesList.reset(reinterpret_cast<PSYSTEM_HANDLES>(new char[bufferSize]));
40            NtQuerySystemInformation(static_cast<SYSTEM_INFORMATION_CLASS>(SystemHandleInformation),
41                handlesList.get(), bufferSize, &bufferSize);
42
43            if (bufferSize == 0)
44                throw gcnew InvalidOperationException("The list of open system handles could not be retrieved.");
45        }
46
47        //Iterate over the handles
48        for (ULONG i = 0; i != handlesList->NumberOfHandles; ++i)
49        {
50            //Only consider files
51            SYSTEM_HANDLE_INFORMATION handleInfo = handlesList->Information[i];
52            if (handleInfo.ObjectTypeNumber != 25 && handleInfo.ObjectTypeNumber != 23 &&
53                handleInfo.ObjectTypeNumber != 28)
54            {
55                continue;
56            }
57
58            //Try to resolve the path of the handle, continue if we can't get it
59            String^ handlePath = ResolveHandlePath(IntPtr(handleInfo.Handle),
60                handleInfo.ProcessId);
61            if (String::IsNullOrEmpty(handlePath))
62                continue;
63
64            //Store the entry
65            OpenHandle^ listItem = gcnew OpenHandle(IntPtr(handleInfo.Handle),
66                handleInfo.ProcessId, handlePath);
67            handles->Add(listItem);
68        }
69
70        return handles->AsReadOnly();
71    }
72
73    String^ OpenHandle::ResolveHandlePath(IntPtr handle, int pid)
74    {
75        //Start a name resolution thread (in case one entry hangs)
76        if (NameResolutionThread == NULL)
77        {
78            NameResolutionThread = new HANDLE(0);
79            NameResolutionThreadParam = new NameResolutionThreadParams;
80            CreateNameThread(*NameResolutionThread, *NameResolutionThreadParam);
81        }
82
83        //Create a duplicate handle
84        HANDLE localHandle(NULL);
85        HANDLE processHandle = OpenProcess(PROCESS_DUP_HANDLE, false, pid);
86        DuplicateHandle(processHandle, static_cast<void*>(handle), GetCurrentProcess(),
87            &localHandle, 0, false, DUPLICATE_SAME_ACCESS);
88        CloseHandle(processHandle);
89
90        //We need a handle
91        if (!localHandle)
92            return nullptr;
93
94        //Send the handle to the secondary thread for name resolution
95        NameResult result(localHandle);
96        NameResolutionThreadParam->Input.push_back(&result);
97        ReleaseSemaphore(NameResolutionThreadParam->Semaphore, 1, NULL);
98
99        //Wait for the result
100        if (WaitForSingleObject(result.Event, 50) != WAIT_OBJECT_0)
101        {
102            //The wait failed. Terminate the thread and recreate another.
103            CreateNameThread(*NameResolutionThread, *NameResolutionThreadParam);
104        }
105
106        //Close the handle which we duplicated
107        CloseHandle(localHandle);
108
109        //Return the result
110        if (result.Name.empty())
111            return nullptr;
112        else
113            return gcnew String(result.Name.c_str(), 0,
114                static_cast<int>(result.Name.length()));
115    }
116
117    bool OpenHandle::Close()
118    {
119        //Open a handle to the owning process
120        HANDLE processHandle = OpenProcess(PROCESS_DUP_HANDLE, false, ProcessId);
121
122        //Forcibly close the handle
123        DuplicateHandle(processHandle, static_cast<void*>(Handle), GetCurrentProcess(),
124            NULL, 0, false, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
125
126        //Check if the handle is closed
127        bool result = true;
128        HANDLE duplicateHandle = NULL;
129        if (DuplicateHandle(processHandle, static_cast<void*>(Handle), GetCurrentProcess(),
130            &duplicateHandle, 0, false, DUPLICATE_SAME_ACCESS))
131        {
132            result = false;
133            CloseHandle(duplicateHandle);
134        }
135
136        //Close the process handle
137        CloseHandle(processHandle);
138
139        //Return the result
140        return result;
141    }
142}
143}
Note: See TracBrowser for help on using the repository browser.