Something went wrong. Try again.
Reactos
Something went wrong. Try again.
11 kB · 394 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395/* * Copyright 2004, 2005 Martin Fuchs * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
// // Explorer clone // // ntobjfs.cpp // // Martin Fuchs, 31.01.2004 //
#include <precomp.h>
#include "ntobjfs.h"//#include "winfs.h"#include "regfs.h"
#define CONSTRUCT_NTDLLFCT(x) x(TEXT("NTDLL"), #x)
typedef DWORD (__stdcall* NTOBJECTOPENFUNCTIONS)(HANDLE*, DWORD, OpenStruct*);
struct NTDLL { NTDLL() : CONSTRUCT_NTDLLFCT(RtlInitAnsiString), CONSTRUCT_NTDLLFCT(RtlInitUnicodeString), CONSTRUCT_NTDLLFCT(RtlFreeAnsiString), CONSTRUCT_NTDLLFCT(RtlFreeUnicodeString), CONSTRUCT_NTDLLFCT(RtlAnsiStringToUnicodeString), CONSTRUCT_NTDLLFCT(RtlUnicodeStringToAnsiString), CONSTRUCT_NTDLLFCT(NtOpenDirectoryObject), CONSTRUCT_NTDLLFCT(NtQueryDirectoryObject), CONSTRUCT_NTDLLFCT(NtOpenFile), CONSTRUCT_NTDLLFCT(NtOpenSymbolicLinkObject), CONSTRUCT_NTDLLFCT(NtQuerySymbolicLinkObject), CONSTRUCT_NTDLLFCT(NtQueryObject), CONSTRUCT_NTDLLFCT(NtOpenMutant), CONSTRUCT_NTDLLFCT(NtOpenSection), CONSTRUCT_NTDLLFCT(NtOpenEvent), CONSTRUCT_NTDLLFCT(NtOpenEventPair), CONSTRUCT_NTDLLFCT(NtOpenIoCompletion), CONSTRUCT_NTDLLFCT(NtOpenSemaphore), CONSTRUCT_NTDLLFCT(NtOpenTimer), CONSTRUCT_NTDLLFCT(NtOpenKey), CONSTRUCT_NTDLLFCT(NtClose), CONSTRUCT_NTDLLFCT(NtOpenProcess), CONSTRUCT_NTDLLFCT(NtOpenThread) { NTOBJECTOPENFUNCTIONS* p = _ObjectOpenFunctions;
*p++ = *NtOpenDirectoryObject; *p++ = *NtOpenSymbolicLinkObject; *p++ = *NtOpenMutant; *p++ = *NtOpenSection; *p++ = *NtOpenEvent; *p++ = *NtOpenSemaphore; *p++ = *NtOpenTimer; *p++ = *NtOpenKey; *p++ = *NtOpenEventPair; *p++ = *NtOpenIoCompletion; *p++ = 0/*Device Object*/; *p++ = 0/*NtOpenFile*/; *p++ = 0/*CONTROLLER_OBJECT*/; *p++ = 0/*PROFILE_OBJECT*/; *p++ = 0/*TYPE_OBJECT*/; *p++ = 0/*DESKTOP_OBJECT*/; *p++ = 0/*WINDOWSTATION_OBJECT*/; *p++ = 0/*DRIVER_OBJECT*/; *p++ = 0/*TOKEN_OBJECT*/; *p++ = 0/*PROCESS_OBJECT*/; *p++ = 0/*THREAD_OBJECT*/; *p++ = 0/*ADAPTER_OBJECT*/; *p++ = 0/*PORT_OBJECT*/; }
NTOBJECTOPENFUNCTIONS _ObjectOpenFunctions[23]; static const LPCWSTR s_ObjectTypes[];
DynamicFct<void (__stdcall*)(RtlAnsiString*, LPCSTR)> RtlInitAnsiString; DynamicFct<void (__stdcall*)(RtlUnicodeString*, LPCWSTR)> RtlInitUnicodeString; DynamicFct<DWORD (__stdcall*)(RtlAnsiString*)> RtlFreeAnsiString; DynamicFct<DWORD (__stdcall*)(RtlUnicodeString*)> RtlFreeUnicodeString; DynamicFct<DWORD (__stdcall*)(RtlUnicodeString*, const RtlAnsiString*, BOOL)> RtlAnsiStringToUnicodeString; DynamicFct<DWORD (__stdcall*)(RtlAnsiString*, const RtlUnicodeString*, BOOL)> RtlUnicodeStringToAnsiString;
DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenDirectoryObject; DynamicFct<DWORD (__stdcall*)(HANDLE, NtObjectInfo*, DWORD size, BOOL, BOOL, void*, void*)> NtQueryDirectoryObject; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, void*, DWORD*, DWORD, OpenStruct*)> NtOpenFile; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSymbolicLinkObject; DynamicFct<DWORD (__stdcall*)(HANDLE, RtlUnicodeString*, DWORD*)> NtQuerySymbolicLinkObject; DynamicFct<DWORD (__stdcall*)(HANDLE, DWORD, NtObject*, DWORD size, DWORD* read)> NtQueryObject; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenMutant; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSection; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenEvent; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenEventPair; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenIoCompletion; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSemaphore; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenTimer; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenKey; DynamicFct<DWORD (__stdcall*)(HANDLE)> NtClose; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenProcess; DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenThread;};
const LPCWSTR NTDLL::s_ObjectTypes[] = { L"Directory", L"SymbolicLink", L"Mutant", L"Section", L"Event", L"Semaphore", L"Timer", L"Key", L"EventPair", L"IoCompletion", L"Device", L"File", L"Controller", L"Profile", L"Type", L"Desktop", L"WindowStatiom", L"Driver", L"Token", L"Process", L"Thread", L"Adapter", L"Port", 0};
NTDLL* g_NTDLL = NULL;
struct UnicodeString : public RtlUnicodeString { UnicodeString(LPCWSTR str) { (*g_NTDLL->RtlInitUnicodeString)(this, str); }
UnicodeString(size_t len, LPWSTR buffer) { alloc_len = (WORD)len; string_ptr = buffer; }
operator LPCWSTR() const {return string_ptr;}};
static DWORD NtOpenObject(OBJECT_TYPE type, HANDLE* phandle, DWORD access, LPCWSTR path/*, BOOL xflag=FALSE*/){ UnicodeString ustr(path); OpenStruct open_struct = {sizeof(OpenStruct), 0x00, &ustr, 0x40};
if (type==DIRECTORY_OBJECT || type==SYMBOLICLINK_OBJECT) access |= FILE_LIST_DIRECTORY;
/* if (xflag) access |= GENERIC_READ; */
DWORD ioStatusBlock[2]; // IO_STATUS_BLOCK
if (type>=DIRECTORY_OBJECT && type<=IOCOMPLETITION_OBJECT) return g_NTDLL->_ObjectOpenFunctions[type](phandle, access|STANDARD_RIGHTS_READ, &open_struct); else if (type == FILE_OBJECT) return (*g_NTDLL->NtOpenFile)(phandle, access, &open_struct, ioStatusBlock, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0/*OpenOptions*/); else return ERROR_INVALID_FUNCTION;}
void NtObjDirectory::read_directory(int scan_flags){ CONTEXT("NtObjDirectory::read_directory()");
if (!g_NTDLL) g_NTDLL = new NTDLL();
Entry* first_entry = NULL; int level = _level + 1;
LPCTSTR path = (LPCTSTR)_path;
TCHAR buffer[MAX_PATH], *p=buffer;#ifndef UNICODE WCHAR wbuffer[MAX_PATH], *w=wbuffer;#endif
do { *p++ = *path;#ifndef UNICODE *w++ = *path;#endif } while(*path++); --p;#ifndef UNICODE --w;#endif
DWORD idx; HANDLE dir_handle;
#ifdef UNICODE if (NtOpenObject(_type, &dir_handle, 0, buffer))#else if (NtOpenObject(_type, &dir_handle, 0, wbuffer))#endif return;
#ifdef UNICODE if (p[-1] != '\\') *p++ = '\\';#else if (w[-1] != '\\') *w++ = '\\';#endif
NtObjectInfo* info = (NtObjectInfo*)alloca(2048);
if (!(*g_NTDLL->NtQueryDirectoryObject)(dir_handle, info, 2048, TRUE, TRUE, &idx, NULL)) { WIN32_FIND_DATA w32fd; Entry* last = NULL; Entry* entry;
do { memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
#ifdef UNICODE if (info->name.string_ptr) { info->name.string_ptr[info->name.string_len / sizeof(WCHAR)] = 0; } else { TCHAR empty_string_ptr[] = _T(""); info->name.string_ptr = empty_string_ptr; } if (info->type.string_ptr) { info->type.string_ptr[info->type.string_len / sizeof(WCHAR)] = 0; } else { TCHAR empty_string_ptr[] = _T(""); info->type.string_ptr = empty_string_ptr; } lstrcpynW(p, info->name.string_ptr, COUNTOF(buffer));#else WideCharToMultiByte(CP_ACP, 0, info->name.string_ptr, info->name.string_len, p, COUNTOF(buffer), 0, 0);#endif
lstrcpyn(w32fd.cFileName, p, sizeof(w32fd.cFileName) / sizeof(0[w32fd.cFileName]));
const LPCWSTR* tname = NTDLL::s_ObjectTypes; OBJECT_TYPE type = UNKNOWN_OBJECT_TYPE;
for(; *tname; tname++) if (!wcsncmp(info->type.string_ptr, *tname, 32)) {type=OBJECT_TYPE(tname-NTDLL::s_ObjectTypes); break;}
if (type == DIRECTORY_OBJECT) { w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
entry = new NtObjDirectory(this, buffer); }
else if (type == SYMBOLICLINK_OBJECT) { w32fd.dwFileAttributes |= ATTRIBUTE_SYMBOLIC_LINK;
entry = NULL;
#ifndef _NO_WIN_FS if (*w32fd.cFileName>='A' &&*w32fd.cFileName<='Z' && w32fd.cFileName[1]==':') if (!_tcsncmp(buffer,TEXT("\\??\\"),4) || // NT4 !_tcsncmp(buffer,TEXT("\\GLOBAL??"),9)) { // XP w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; entry = new WinDirectory(this, w32fd.cFileName); }#endif
if (!entry) entry = new NtObjDirectory(this, buffer); }
else if (type == KEY_OBJECT) { w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
entry = new RegistryRoot(this, buffer); } else entry = new NtObjEntry(this, type);
HANDLE handle;
#ifdef UNICODE lstrcpyW(p, info->name.string_ptr); if (!NtOpenObject(type, &handle, 0, buffer))#else lstrcpyW(w, info->name.string_ptr); if (!NtOpenObject(type, &handle, 0, wbuffer))#endif { NtObject object; DWORD read;
if (!(*g_NTDLL->NtQueryObject)(handle, 0/*ObjectBasicInformation*/, &object, sizeof(NtObject), &read)) { memcpy(&w32fd.ftCreationTime, &object.creation_time, sizeof(FILETIME));
memset(&entry->_bhfi, 0, sizeof(BY_HANDLE_FILE_INFORMATION)); entry->_bhfi.nNumberOfLinks = object.reference_count - 1; entry->_bhfi_valid = true; }
if (type == SYMBOLICLINK_OBJECT) { WCHAR wbuffer[_MAX_PATH]; UnicodeString link(_MAX_PATH, wbuffer);
if (!(*g_NTDLL->NtQuerySymbolicLinkObject)(handle, &link, NULL)) { int len = link.string_len/sizeof(WCHAR); entry->_content = (LPTSTR) malloc((len+1)*sizeof(TCHAR));#ifdef UNICODE wcsncpy_s(entry->_content, len+1, link, len);#else U2nA(link, entry->_content, len);#endif entry->_content[len] = '\0'; } }
(*g_NTDLL->NtClose)(handle); }
memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
#ifdef UNICODE entry->_type_name = _wcsdup(info->type.string_ptr);#else char type_name[32]; WideCharToMultiByte(CP_ACP, 0, info->type.string_ptr, info->type.string_len, type_name, 32, 0, 0); entry->_type_name = _strdup(type_name);#endif
if (!first_entry) first_entry = entry;
if (last) last->_next = entry;
entry->_level = level;
last = entry; } while(!(*g_NTDLL->NtQueryDirectoryObject)(dir_handle, info, 2048, TRUE, FALSE, &idx, NULL));
last->_next = NULL; }
(*g_NTDLL->NtClose)(dir_handle);
_down = first_entry; _scanned = true;}
Entry* NtObjDirectory::find_entry(const void* p){ LPCTSTR name = (LPCTSTR)p;
for(Entry*entry=_down; entry; entry=entry->_next) { LPCTSTR p = name; LPCTSTR q = entry->_data.cFileName;
do { if (!*p || *p==TEXT('\\') || *p==TEXT('/')) return entry; } while(tolower(*p++) == tolower(*q++));
p = name; q = entry->_data.cAlternateFileName;
do { if (!*p || *p==TEXT('\\') || *p==TEXT('/')) return entry; } while(tolower(*p++) == tolower(*q++)); }
return NULL;}
// get full path of specified directory entrybool NtObjEntry::get_path(PTSTR path, size_t path_count) const{ return get_path_base ( path, path_count, ET_NTOBJS );}
BOOL NtObjEntry::launch_entry(HWND hwnd, UINT nCmdShow){ return FALSE;}