| 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 | namespace Eraser { |
|---|
| 26 | namespace Util { |
|---|
| 27 | IList<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(S::_(L"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 | List<OpenHandle^>^ OpenHandle::Close(String^ path) |
|---|
| 74 | { |
|---|
| 75 | List<OpenHandle^>^ result = gcnew List<OpenHandle^>(); |
|---|
| 76 | for each (OpenHandle^ handle in Items) |
|---|
| 77 | { |
|---|
| 78 | if (handle->Path == path) |
|---|
| 79 | if (!handle->Close()) |
|---|
| 80 | result->Add(handle); |
|---|
| 81 | } |
|---|
| 82 | |
|---|
| 83 | return result; |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | String^ OpenHandle::ResolveHandlePath(IntPtr handle, int pid) |
|---|
| 87 | { |
|---|
| 88 | std::wstring result(ResolveHandleName(static_cast<void*>(handle), pid)); |
|---|
| 89 | return result.empty() ? nullptr : |
|---|
| 90 | gcnew String(result.c_str(), 0, static_cast<int>(result.length())); |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | bool OpenHandle::Close() |
|---|
| 94 | { |
|---|
| 95 | //Open a handle to the owning process |
|---|
| 96 | HANDLE processHandle = OpenProcess(PROCESS_DUP_HANDLE, false, processId); |
|---|
| 97 | |
|---|
| 98 | //Forcibly close the handle |
|---|
| 99 | HANDLE duplicateHandle = NULL; |
|---|
| 100 | DuplicateHandle(processHandle, static_cast<void*>(Handle), GetCurrentProcess(), |
|---|
| 101 | &duplicateHandle, 0, false, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); |
|---|
| 102 | CloseHandle(duplicateHandle); |
|---|
| 103 | |
|---|
| 104 | //Check if the handle is closed |
|---|
| 105 | bool result = true; |
|---|
| 106 | if (DuplicateHandle(processHandle, static_cast<void*>(Handle), GetCurrentProcess(), |
|---|
| 107 | &duplicateHandle, 0, false, DUPLICATE_SAME_ACCESS)) |
|---|
| 108 | { |
|---|
| 109 | result = false; |
|---|
| 110 | CloseHandle(duplicateHandle); |
|---|
| 111 | } |
|---|
| 112 | |
|---|
| 113 | //Close the process handle |
|---|
| 114 | CloseHandle(processHandle); |
|---|
| 115 | |
|---|
| 116 | //Return the result |
|---|
| 117 | return result; |
|---|
| 118 | } |
|---|
| 119 | } |
|---|
| 120 | } |
|---|