ntobjfs.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2004, 2005 Martin Fuchs
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 
00020  //
00021  // Explorer clone
00022  //
00023  // ntobjfs.cpp
00024  //
00025  // Martin Fuchs, 31.01.2004
00026  //
00027 
00028 
00029 #include <precomp.h>
00030 
00031 #include "ntobjfs.h"
00032 //#include "winfs.h"
00033 #include "regfs.h"
00034 
00035 
00036 #define CONSTRUCT_NTDLLFCT(x) x(TEXT("NTDLL"), #x)
00037 
00038 typedef DWORD (__stdcall* NTOBJECTOPENFUNCTIONS)(HANDLE*, DWORD, OpenStruct*);
00039 
00040 struct NTDLL {
00041     NTDLL()
00042      :  CONSTRUCT_NTDLLFCT(RtlInitAnsiString),
00043         CONSTRUCT_NTDLLFCT(RtlInitUnicodeString),
00044         CONSTRUCT_NTDLLFCT(RtlFreeAnsiString),
00045         CONSTRUCT_NTDLLFCT(RtlFreeUnicodeString),
00046         CONSTRUCT_NTDLLFCT(RtlAnsiStringToUnicodeString),
00047         CONSTRUCT_NTDLLFCT(RtlUnicodeStringToAnsiString),
00048         CONSTRUCT_NTDLLFCT(NtOpenDirectoryObject),
00049         CONSTRUCT_NTDLLFCT(NtQueryDirectoryObject),
00050         CONSTRUCT_NTDLLFCT(NtOpenFile),
00051         CONSTRUCT_NTDLLFCT(NtOpenSymbolicLinkObject),
00052         CONSTRUCT_NTDLLFCT(NtQuerySymbolicLinkObject),
00053         CONSTRUCT_NTDLLFCT(NtQueryObject),
00054         CONSTRUCT_NTDLLFCT(NtOpenMutant),
00055         CONSTRUCT_NTDLLFCT(NtOpenSection),
00056         CONSTRUCT_NTDLLFCT(NtOpenEvent),
00057         CONSTRUCT_NTDLLFCT(NtOpenEventPair),
00058         CONSTRUCT_NTDLLFCT(NtOpenIoCompletion),
00059         CONSTRUCT_NTDLLFCT(NtOpenSemaphore),
00060         CONSTRUCT_NTDLLFCT(NtOpenTimer),
00061         CONSTRUCT_NTDLLFCT(NtOpenKey),
00062         CONSTRUCT_NTDLLFCT(NtClose),
00063         CONSTRUCT_NTDLLFCT(NtOpenProcess),
00064         CONSTRUCT_NTDLLFCT(NtOpenThread)
00065     {
00066         NTOBJECTOPENFUNCTIONS* p = _ObjectOpenFunctions;
00067 
00068         *p++ = *NtOpenDirectoryObject;
00069         *p++ = *NtOpenSymbolicLinkObject;
00070         *p++ = *NtOpenMutant;
00071         *p++ = *NtOpenSection;
00072         *p++ = *NtOpenEvent;
00073         *p++ = *NtOpenSemaphore;
00074         *p++ = *NtOpenTimer;
00075         *p++ = *NtOpenKey;
00076         *p++ = *NtOpenEventPair;
00077         *p++ = *NtOpenIoCompletion;
00078         *p++ = 0/*Device Object*/;
00079         *p++ = 0/*NtOpenFile*/;
00080         *p++ = 0/*CONTROLLER_OBJECT*/;
00081         *p++ = 0/*PROFILE_OBJECT*/;
00082         *p++ = 0/*TYPE_OBJECT*/;
00083         *p++ = 0/*DESKTOP_OBJECT*/;
00084         *p++ = 0/*WINDOWSTATION_OBJECT*/;
00085         *p++ = 0/*DRIVER_OBJECT*/;
00086         *p++ = 0/*TOKEN_OBJECT*/;
00087         *p++ = 0/*PROCESS_OBJECT*/;
00088         *p++ = 0/*THREAD_OBJECT*/;
00089         *p++ = 0/*ADAPTER_OBJECT*/;
00090         *p++ = 0/*PORT_OBJECT*/;
00091     }
00092 
00093     NTOBJECTOPENFUNCTIONS _ObjectOpenFunctions[23];
00094     static const LPCWSTR s_ObjectTypes[];
00095 
00096     DynamicFct<void (__stdcall*)(RtlAnsiString*, LPCSTR)> RtlInitAnsiString;
00097     DynamicFct<void (__stdcall*)(RtlUnicodeString*, LPCWSTR)> RtlInitUnicodeString;
00098     DynamicFct<DWORD (__stdcall*)(RtlAnsiString*)> RtlFreeAnsiString;
00099     DynamicFct<DWORD (__stdcall*)(RtlUnicodeString*)> RtlFreeUnicodeString;
00100     DynamicFct<DWORD (__stdcall*)(RtlUnicodeString*, const RtlAnsiString*, BOOL)> RtlAnsiStringToUnicodeString;
00101     DynamicFct<DWORD (__stdcall*)(RtlAnsiString*, const RtlUnicodeString*, BOOL)> RtlUnicodeStringToAnsiString;
00102 
00103     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenDirectoryObject;
00104     DynamicFct<DWORD (__stdcall*)(HANDLE, NtObjectInfo*, DWORD size, BOOL, BOOL, void*, void*)> NtQueryDirectoryObject;
00105     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, void*, DWORD*, DWORD, OpenStruct*)> NtOpenFile;
00106     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSymbolicLinkObject;
00107     DynamicFct<DWORD (__stdcall*)(HANDLE, RtlUnicodeString*, DWORD*)> NtQuerySymbolicLinkObject;
00108     DynamicFct<DWORD (__stdcall*)(HANDLE, DWORD, NtObject*, DWORD size, DWORD* read)> NtQueryObject;
00109     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenMutant;
00110     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSection;
00111     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenEvent;
00112     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenEventPair;
00113     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenIoCompletion;
00114     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSemaphore;
00115     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenTimer;
00116     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenKey;
00117     DynamicFct<DWORD (__stdcall*)(HANDLE)> NtClose;
00118     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenProcess;
00119     DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenThread;
00120 };
00121 
00122 const LPCWSTR NTDLL::s_ObjectTypes[] = {
00123     L"Directory", L"SymbolicLink",
00124     L"Mutant", L"Section", L"Event", L"Semaphore",
00125     L"Timer", L"Key", L"EventPair", L"IoCompletion",
00126     L"Device", L"File", L"Controller", L"Profile",
00127     L"Type", L"Desktop", L"WindowStatiom", L"Driver",
00128     L"Token", L"Process", L"Thread", L"Adapter", L"Port",
00129     0
00130 };
00131 
00132 NTDLL* g_NTDLL = NULL;
00133 
00134 
00135 struct UnicodeString : public RtlUnicodeString {
00136     UnicodeString(LPCWSTR str)
00137     {
00138         (*g_NTDLL->RtlInitUnicodeString)(this, str);
00139     }
00140 
00141     UnicodeString(size_t len, LPWSTR buffer)
00142     {
00143         alloc_len = len;
00144         string_ptr = buffer;
00145     }
00146 
00147     operator LPCWSTR() const {return string_ptr;}
00148 };
00149 
00150 
00151 static DWORD NtOpenObject(OBJECT_TYPE type, HANDLE* phandle, DWORD access, LPCWSTR path/*, BOOL xflag=FALSE*/)
00152 {
00153     UnicodeString ustr(path);
00154     OpenStruct open_struct = {sizeof(OpenStruct), 0x00, &ustr, 0x40};
00155 
00156     if (type==DIRECTORY_OBJECT || type==SYMBOLICLINK_OBJECT)
00157         access |= FILE_LIST_DIRECTORY;
00158 
00159     /* if (xflag)
00160         access |= GENERIC_READ; */
00161 
00162     DWORD ioStatusBlock[2]; // IO_STATUS_BLOCK
00163 
00164     if (type>=DIRECTORY_OBJECT && type<=IOCOMPLETITION_OBJECT)
00165         return g_NTDLL->_ObjectOpenFunctions[type](phandle, access|STANDARD_RIGHTS_READ, &open_struct);
00166     else if (type == FILE_OBJECT)
00167         return (*g_NTDLL->NtOpenFile)(phandle, access, &open_struct, ioStatusBlock, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0/*OpenOptions*/);
00168     else
00169         return ERROR_INVALID_FUNCTION;
00170 }
00171 
00172 
00173 void NtObjDirectory::read_directory(int scan_flags)
00174 {
00175     CONTEXT("NtObjDirectory::read_directory()");
00176 
00177     if (!g_NTDLL)
00178         g_NTDLL = new NTDLL();
00179 
00180     Entry* first_entry = NULL;
00181     int level = _level + 1;
00182 
00183     LPCTSTR path = (LPCTSTR)_path;
00184 
00185     TCHAR buffer[MAX_PATH], *p=buffer;
00186 #ifndef UNICODE
00187     WCHAR wbuffer[MAX_PATH], *w=wbuffer;
00188 #endif
00189 
00190     do {
00191         *p++ = *path;
00192 #ifndef UNICODE
00193         *w++ = *path;
00194 #endif
00195     } while(*path++);
00196     --p;
00197 #ifndef UNICODE
00198     --w;
00199 #endif
00200 
00201     DWORD idx;
00202     HANDLE dir_handle;
00203 
00204 #ifdef UNICODE
00205     if (NtOpenObject(_type, &dir_handle, 0, buffer))
00206 #else
00207     if (NtOpenObject(_type, &dir_handle, 0, wbuffer))
00208 #endif
00209         return;
00210 
00211 #ifdef UNICODE
00212     if (p[-1] != '\\')
00213         *p++ = '\\';
00214 #else
00215     if (w[-1] != '\\')
00216         *w++ = '\\';
00217 #endif
00218 
00219     NtObjectInfo* info = (NtObjectInfo*)alloca(2048);
00220 
00221     if (!(*g_NTDLL->NtQueryDirectoryObject)(dir_handle, info, 2048, TRUE, TRUE, &idx, NULL)) {
00222         WIN32_FIND_DATA w32fd;
00223         Entry* last = NULL;
00224         Entry* entry;
00225 
00226         do {
00227             memset(&w32fd, 0, sizeof(WIN32_FIND_DATA));
00228 
00229 #ifdef UNICODE
00230             if (info->name.string_ptr) {
00231                 info->name.string_ptr[info->name.string_len / sizeof(WCHAR)] = 0;
00232             } else {
00233                 TCHAR empty_string_ptr[] = _T("");
00234                 info->name.string_ptr = empty_string_ptr;
00235             }
00236             if (info->type.string_ptr) {
00237                 info->type.string_ptr[info->type.string_len / sizeof(WCHAR)] = 0;
00238             } else {
00239                 TCHAR empty_string_ptr[] = _T("");
00240                 info->type.string_ptr = empty_string_ptr;
00241             }
00242             lstrcpynW(p, info->name.string_ptr, COUNTOF(buffer));
00243 #else
00244             WideCharToMultiByte(CP_ACP, 0, info->name.string_ptr, info->name.string_len, p, COUNTOF(buffer), 0, 0);
00245 #endif
00246 
00247             lstrcpyn(w32fd.cFileName, p, sizeof(w32fd.cFileName) / sizeof(0[w32fd.cFileName]));
00248 
00249             const LPCWSTR* tname = NTDLL::s_ObjectTypes;
00250             OBJECT_TYPE type = UNKNOWN_OBJECT_TYPE;
00251 
00252             for(; *tname; tname++)
00253                 if (!wcsncmp(info->type.string_ptr, *tname, 32))
00254                     {type=OBJECT_TYPE(tname-NTDLL::s_ObjectTypes); break;}
00255 
00256             if (type == DIRECTORY_OBJECT) {
00257                 w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
00258 
00259                 entry = new NtObjDirectory(this, buffer);
00260             }
00261 
00262             else if (type == SYMBOLICLINK_OBJECT) {
00263                 w32fd.dwFileAttributes |= ATTRIBUTE_SYMBOLIC_LINK;
00264 
00265                 entry = NULL;
00266 
00267 #ifndef _NO_WIN_FS
00268                 if (*w32fd.cFileName>='A' &&*w32fd.cFileName<='Z' && w32fd.cFileName[1]==':')
00269                     if (!_tcsncmp(buffer,TEXT("\\??\\"),4) ||       // NT4
00270                         !_tcsncmp(buffer,TEXT("\\GLOBAL??"),9)) {   // XP
00271                         w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
00272                         entry = new WinDirectory(this, w32fd.cFileName);
00273                     }
00274 #endif
00275 
00276                 if (!entry)
00277                     entry = new NtObjDirectory(this, buffer);
00278             }
00279 
00280             else if (type == KEY_OBJECT) {
00281                 w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
00282 
00283                 entry = new RegistryRoot(this, buffer);
00284             }
00285             else
00286                 entry = new NtObjEntry(this, type);
00287 
00288             HANDLE handle;
00289 
00290 #ifdef UNICODE
00291             lstrcpyW(p, info->name.string_ptr);
00292             if (!NtOpenObject(type, &handle, 0, buffer))
00293 #else
00294             lstrcpyW(w, info->name.string_ptr);
00295             if (!NtOpenObject(type, &handle, 0, wbuffer))
00296 #endif
00297             {
00298                 NtObject object;
00299                 DWORD read;
00300 
00301                 if (!(*g_NTDLL->NtQueryObject)(handle, 0/*ObjectBasicInformation*/, &object, sizeof(NtObject), &read)) {
00302                     memcpy(&w32fd.ftCreationTime, &object.creation_time, sizeof(FILETIME));
00303 
00304                     memset(&entry->_bhfi, 0, sizeof(BY_HANDLE_FILE_INFORMATION));
00305                     entry->_bhfi.nNumberOfLinks = object.reference_count - 1;
00306                     entry->_bhfi_valid = true;
00307                 }
00308 
00309                 if (type == SYMBOLICLINK_OBJECT) {
00310                     WCHAR wbuffer[_MAX_PATH];
00311                     UnicodeString link(_MAX_PATH, wbuffer);
00312 
00313                     if (!(*g_NTDLL->NtQuerySymbolicLinkObject)(handle, &link, NULL)) {
00314                         int len = link.string_len/sizeof(WCHAR);
00315                         entry->_content = (LPTSTR) malloc((len+1)*sizeof(TCHAR));
00316 #ifdef UNICODE
00317                         wcsncpy_s(entry->_content, len+1, link, len);
00318 #else
00319                         U2nA(link, entry->_content, len);
00320 #endif
00321                         entry->_content[len] = '\0';
00322                     }
00323                 }
00324 
00325                 (*g_NTDLL->NtClose)(handle);
00326             }
00327 
00328             memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA));
00329 
00330 #ifdef UNICODE
00331             entry->_type_name = _wcsdup(info->type.string_ptr);
00332 #else
00333             char type_name[32];
00334             WideCharToMultiByte(CP_ACP, 0, info->type.string_ptr, info->type.string_len, type_name, 32, 0, 0);
00335             entry->_type_name = _strdup(type_name);
00336 #endif
00337 
00338             if (!first_entry)
00339                 first_entry = entry;
00340 
00341             if (last)
00342                 last->_next = entry;
00343 
00344             entry->_level = level;
00345 
00346             last = entry;
00347         } while(!(*g_NTDLL->NtQueryDirectoryObject)(dir_handle, info, 2048, TRUE, FALSE, &idx, NULL));
00348 
00349         last->_next = NULL;
00350     }
00351 
00352     (*g_NTDLL->NtClose)(dir_handle);
00353 
00354     _down = first_entry;
00355     _scanned = true;
00356 }
00357 
00358 
00359 Entry* NtObjDirectory::find_entry(const void* p)
00360 {
00361     LPCTSTR name = (LPCTSTR)p;
00362 
00363     for(Entry*entry=_down; entry; entry=entry->_next) {
00364         LPCTSTR p = name;
00365         LPCTSTR q = entry->_data.cFileName;
00366 
00367         do {
00368             if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
00369                 return entry;
00370         } while(tolower(*p++) == tolower(*q++));
00371 
00372         p = name;
00373         q = entry->_data.cAlternateFileName;
00374 
00375         do {
00376             if (!*p || *p==TEXT('\\') || *p==TEXT('/'))
00377                 return entry;
00378         } while(tolower(*p++) == tolower(*q++));
00379     }
00380 
00381     return NULL;
00382 }
00383 
00384 
00385  // get full path of specified directory entry
00386 bool NtObjEntry::get_path(PTSTR path, size_t path_count) const
00387 {
00388     return get_path_base ( path, path_count, ET_NTOBJS );
00389 }
00390 
00391 BOOL NtObjEntry::launch_entry(HWND hwnd, UINT nCmdShow)
00392 {
00393     return FALSE;
00394 }

ROS Explorer Source Code Documentation
generated on 02.01.2013 by doxygen

ROS Explorer Homepage