| 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 | |
|---|
| 25 | namespace Eraser { |
|---|
| 26 | namespace 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 | HANDLE duplicateHandle = NULL; |
|---|
| 124 | DuplicateHandle(processHandle, static_cast<void*>(Handle), GetCurrentProcess(), |
|---|
| 125 | &duplicateHandle, 0, false, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); |
|---|
| 126 | CloseHandle(duplicateHandle); |
|---|
| 127 | |
|---|
| 128 | //Check if the handle is closed |
|---|
| 129 | bool result = true; |
|---|
| 130 | if (DuplicateHandle(processHandle, static_cast<void*>(Handle), GetCurrentProcess(), |
|---|
| 131 | &duplicateHandle, 0, false, DUPLICATE_SAME_ACCESS)) |
|---|
| 132 | { |
|---|
| 133 | result = false; |
|---|
| 134 | CloseHandle(duplicateHandle); |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | //Close the process handle |
|---|
| 138 | CloseHandle(processHandle); |
|---|
| 139 | |
|---|
| 140 | //Return the result |
|---|
| 141 | return result; |
|---|
| 142 | } |
|---|
| 143 | } |
|---|
| 144 | } |
|---|