| 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 | |
|---|
| 27 | namespace { |
|---|
| 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, ¶ms, 0, NULL); |
|---|
| 99 | } |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | std::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 | } |
|---|