1 /* 2 * Copyright 2004, 2005 Martin Fuchs 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 20 // 21 // Explorer clone 22 // 23 // ntobjfs.cpp 24 // 25 // Martin Fuchs, 31.01.2004 26 // 27 28 29 #include <precomp.h> 30 31 #include "ntobjfs.h" 32 //#include "winfs.h" 33 #include "regfs.h" 34 35 36 #define CONSTRUCT_NTDLLFCT(x) x(TEXT("NTDLL"), #x) 37 38 typedef DWORD (__stdcall* NTOBJECTOPENFUNCTIONS)(HANDLE*, DWORD, OpenStruct*); 39 40 struct NTDLL { 41 NTDLL() 42 : CONSTRUCT_NTDLLFCT(RtlInitAnsiString), 43 CONSTRUCT_NTDLLFCT(RtlInitUnicodeString), 44 CONSTRUCT_NTDLLFCT(RtlFreeAnsiString), 45 CONSTRUCT_NTDLLFCT(RtlFreeUnicodeString), 46 CONSTRUCT_NTDLLFCT(RtlAnsiStringToUnicodeString), 47 CONSTRUCT_NTDLLFCT(RtlUnicodeStringToAnsiString), 48 CONSTRUCT_NTDLLFCT(NtOpenDirectoryObject), 49 CONSTRUCT_NTDLLFCT(NtQueryDirectoryObject), 50 CONSTRUCT_NTDLLFCT(NtOpenFile), 51 CONSTRUCT_NTDLLFCT(NtOpenSymbolicLinkObject), 52 CONSTRUCT_NTDLLFCT(NtQuerySymbolicLinkObject), 53 CONSTRUCT_NTDLLFCT(NtQueryObject), 54 CONSTRUCT_NTDLLFCT(NtOpenMutant), 55 CONSTRUCT_NTDLLFCT(NtOpenSection), 56 CONSTRUCT_NTDLLFCT(NtOpenEvent), 57 CONSTRUCT_NTDLLFCT(NtOpenEventPair), 58 CONSTRUCT_NTDLLFCT(NtOpenIoCompletion), 59 CONSTRUCT_NTDLLFCT(NtOpenSemaphore), 60 CONSTRUCT_NTDLLFCT(NtOpenTimer), 61 CONSTRUCT_NTDLLFCT(NtOpenKey), 62 CONSTRUCT_NTDLLFCT(NtClose), 63 CONSTRUCT_NTDLLFCT(NtOpenProcess), 64 CONSTRUCT_NTDLLFCT(NtOpenThread) 65 { 66 NTOBJECTOPENFUNCTIONS* p = _ObjectOpenFunctions; 67 68 *p++ = *NtOpenDirectoryObject; 69 *p++ = *NtOpenSymbolicLinkObject; 70 *p++ = *NtOpenMutant; 71 *p++ = *NtOpenSection; 72 *p++ = *NtOpenEvent; 73 *p++ = *NtOpenSemaphore; 74 *p++ = *NtOpenTimer; 75 *p++ = *NtOpenKey; 76 *p++ = *NtOpenEventPair; 77 *p++ = *NtOpenIoCompletion; 78 *p++ = 0/*Device Object*/; 79 *p++ = 0/*NtOpenFile*/; 80 *p++ = 0/*CONTROLLER_OBJECT*/; 81 *p++ = 0/*PROFILE_OBJECT*/; 82 *p++ = 0/*TYPE_OBJECT*/; 83 *p++ = 0/*DESKTOP_OBJECT*/; 84 *p++ = 0/*WINDOWSTATION_OBJECT*/; 85 *p++ = 0/*DRIVER_OBJECT*/; 86 *p++ = 0/*TOKEN_OBJECT*/; 87 *p++ = 0/*PROCESS_OBJECT*/; 88 *p++ = 0/*THREAD_OBJECT*/; 89 *p++ = 0/*ADAPTER_OBJECT*/; 90 *p++ = 0/*PORT_OBJECT*/; 91 } 92 93 NTOBJECTOPENFUNCTIONS _ObjectOpenFunctions[23]; 94 static const LPCWSTR s_ObjectTypes[]; 95 96 DynamicFct<void (__stdcall*)(RtlAnsiString*, LPCSTR)> RtlInitAnsiString; 97 DynamicFct<void (__stdcall*)(RtlUnicodeString*, LPCWSTR)> RtlInitUnicodeString; 98 DynamicFct<DWORD (__stdcall*)(RtlAnsiString*)> RtlFreeAnsiString; 99 DynamicFct<DWORD (__stdcall*)(RtlUnicodeString*)> RtlFreeUnicodeString; 100 DynamicFct<DWORD (__stdcall*)(RtlUnicodeString*, const RtlAnsiString*, BOOL)> RtlAnsiStringToUnicodeString; 101 DynamicFct<DWORD (__stdcall*)(RtlAnsiString*, const RtlUnicodeString*, BOOL)> RtlUnicodeStringToAnsiString; 102 103 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenDirectoryObject; 104 DynamicFct<DWORD (__stdcall*)(HANDLE, NtObjectInfo*, DWORD size, BOOL, BOOL, void*, void*)> NtQueryDirectoryObject; 105 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, void*, DWORD*, DWORD, OpenStruct*)> NtOpenFile; 106 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSymbolicLinkObject; 107 DynamicFct<DWORD (__stdcall*)(HANDLE, RtlUnicodeString*, DWORD*)> NtQuerySymbolicLinkObject; 108 DynamicFct<DWORD (__stdcall*)(HANDLE, DWORD, NtObject*, DWORD size, DWORD* read)> NtQueryObject; 109 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenMutant; 110 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSection; 111 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenEvent; 112 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenEventPair; 113 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenIoCompletion; 114 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenSemaphore; 115 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenTimer; 116 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenKey; 117 DynamicFct<DWORD (__stdcall*)(HANDLE)> NtClose; 118 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenProcess; 119 DynamicFct<DWORD (__stdcall*)(HANDLE*, DWORD, OpenStruct*)> NtOpenThread; 120 }; 121 122 const LPCWSTR NTDLL::s_ObjectTypes[] = { 123 L"Directory", L"SymbolicLink", 124 L"Mutant", L"Section", L"Event", L"Semaphore", 125 L"Timer", L"Key", L"EventPair", L"IoCompletion", 126 L"Device", L"File", L"Controller", L"Profile", 127 L"Type", L"Desktop", L"WindowStatiom", L"Driver", 128 L"Token", L"Process", L"Thread", L"Adapter", L"Port", 129 0 130 }; 131 132 NTDLL* g_NTDLL = NULL; 133 134 135 struct UnicodeString : public RtlUnicodeString { 136 UnicodeString(LPCWSTR str) 137 { 138 (*g_NTDLL->RtlInitUnicodeString)(this, str); 139 } 140 141 UnicodeString(size_t len, LPWSTR buffer) 142 { 143 alloc_len = (WORD)len; 144 string_ptr = buffer; 145 } 146 147 operator LPCWSTR() const {return string_ptr;} 148 }; 149 150 151 static DWORD NtOpenObject(OBJECT_TYPE type, HANDLE* phandle, DWORD access, LPCWSTR path/*, BOOL xflag=FALSE*/) 152 { 153 UnicodeString ustr(path); 154 OpenStruct open_struct = {sizeof(OpenStruct), 0x00, &ustr, 0x40}; 155 156 if (type==DIRECTORY_OBJECT || type==SYMBOLICLINK_OBJECT) 157 access |= FILE_LIST_DIRECTORY; 158 159 /* if (xflag) 160 access |= GENERIC_READ; */ 161 162 DWORD ioStatusBlock[2]; // IO_STATUS_BLOCK 163 164 if (type>=DIRECTORY_OBJECT && type<=IOCOMPLETITION_OBJECT) 165 return g_NTDLL->_ObjectOpenFunctions[type](phandle, access|STANDARD_RIGHTS_READ, &open_struct); 166 else if (type == FILE_OBJECT) 167 return (*g_NTDLL->NtOpenFile)(phandle, access, &open_struct, ioStatusBlock, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, 0/*OpenOptions*/); 168 else 169 return ERROR_INVALID_FUNCTION; 170 } 171 172 173 void NtObjDirectory::read_directory(int scan_flags) 174 { 175 CONTEXT("NtObjDirectory::read_directory()"); 176 177 if (!g_NTDLL) 178 g_NTDLL = new NTDLL(); 179 180 Entry* first_entry = NULL; 181 int level = _level + 1; 182 183 LPCTSTR path = (LPCTSTR)_path; 184 185 TCHAR buffer[MAX_PATH], *p=buffer; 186 #ifndef UNICODE 187 WCHAR wbuffer[MAX_PATH], *w=wbuffer; 188 #endif 189 190 do { 191 *p++ = *path; 192 #ifndef UNICODE 193 *w++ = *path; 194 #endif 195 } while(*path++); 196 --p; 197 #ifndef UNICODE 198 --w; 199 #endif 200 201 DWORD idx; 202 HANDLE dir_handle; 203 204 #ifdef UNICODE 205 if (NtOpenObject(_type, &dir_handle, 0, buffer)) 206 #else 207 if (NtOpenObject(_type, &dir_handle, 0, wbuffer)) 208 #endif 209 return; 210 211 #ifdef UNICODE 212 if (p[-1] != '\\') 213 *p++ = '\\'; 214 #else 215 if (w[-1] != '\\') 216 *w++ = '\\'; 217 #endif 218 219 NtObjectInfo* info = (NtObjectInfo*)alloca(2048); 220 221 if (!(*g_NTDLL->NtQueryDirectoryObject)(dir_handle, info, 2048, TRUE, TRUE, &idx, NULL)) { 222 WIN32_FIND_DATA w32fd; 223 Entry* last = NULL; 224 Entry* entry; 225 226 do { 227 memset(&w32fd, 0, sizeof(WIN32_FIND_DATA)); 228 229 #ifdef UNICODE 230 if (info->name.string_ptr) { 231 info->name.string_ptr[info->name.string_len / sizeof(WCHAR)] = 0; 232 } else { 233 TCHAR empty_string_ptr[] = _T(""); 234 info->name.string_ptr = empty_string_ptr; 235 } 236 if (info->type.string_ptr) { 237 info->type.string_ptr[info->type.string_len / sizeof(WCHAR)] = 0; 238 } else { 239 TCHAR empty_string_ptr[] = _T(""); 240 info->type.string_ptr = empty_string_ptr; 241 } 242 lstrcpynW(p, info->name.string_ptr, COUNTOF(buffer)); 243 #else 244 WideCharToMultiByte(CP_ACP, 0, info->name.string_ptr, info->name.string_len, p, COUNTOF(buffer), 0, 0); 245 #endif 246 247 lstrcpyn(w32fd.cFileName, p, sizeof(w32fd.cFileName) / sizeof(0[w32fd.cFileName])); 248 249 const LPCWSTR* tname = NTDLL::s_ObjectTypes; 250 OBJECT_TYPE type = UNKNOWN_OBJECT_TYPE; 251 252 for(; *tname; tname++) 253 if (!wcsncmp(info->type.string_ptr, *tname, 32)) 254 {type=OBJECT_TYPE(tname-NTDLL::s_ObjectTypes); break;} 255 256 if (type == DIRECTORY_OBJECT) { 257 w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; 258 259 entry = new NtObjDirectory(this, buffer); 260 } 261 262 else if (type == SYMBOLICLINK_OBJECT) { 263 w32fd.dwFileAttributes |= ATTRIBUTE_SYMBOLIC_LINK; 264 265 entry = NULL; 266 267 #ifndef _NO_WIN_FS 268 if (*w32fd.cFileName>='A' &&*w32fd.cFileName<='Z' && w32fd.cFileName[1]==':') 269 if (!_tcsncmp(buffer,TEXT("\\??\\"),4) || // NT4 270 !_tcsncmp(buffer,TEXT("\\GLOBAL??"),9)) { // XP 271 w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; 272 entry = new WinDirectory(this, w32fd.cFileName); 273 } 274 #endif 275 276 if (!entry) 277 entry = new NtObjDirectory(this, buffer); 278 } 279 280 else if (type == KEY_OBJECT) { 281 w32fd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; 282 283 entry = new RegistryRoot(this, buffer); 284 } 285 else 286 entry = new NtObjEntry(this, type); 287 288 HANDLE handle; 289 290 #ifdef UNICODE 291 lstrcpyW(p, info->name.string_ptr); 292 if (!NtOpenObject(type, &handle, 0, buffer)) 293 #else 294 lstrcpyW(w, info->name.string_ptr); 295 if (!NtOpenObject(type, &handle, 0, wbuffer)) 296 #endif 297 { 298 NtObject object; 299 DWORD read; 300 301 if (!(*g_NTDLL->NtQueryObject)(handle, 0/*ObjectBasicInformation*/, &object, sizeof(NtObject), &read)) { 302 memcpy(&w32fd.ftCreationTime, &object.creation_time, sizeof(FILETIME)); 303 304 memset(&entry->_bhfi, 0, sizeof(BY_HANDLE_FILE_INFORMATION)); 305 entry->_bhfi.nNumberOfLinks = object.reference_count - 1; 306 entry->_bhfi_valid = true; 307 } 308 309 if (type == SYMBOLICLINK_OBJECT) { 310 WCHAR wbuffer[_MAX_PATH]; 311 UnicodeString link(_MAX_PATH, wbuffer); 312 313 if (!(*g_NTDLL->NtQuerySymbolicLinkObject)(handle, &link, NULL)) { 314 int len = link.string_len/sizeof(WCHAR); 315 entry->_content = (LPTSTR) malloc((len+1)*sizeof(TCHAR)); 316 #ifdef UNICODE 317 wcsncpy_s(entry->_content, len+1, link, len); 318 #else 319 U2nA(link, entry->_content, len); 320 #endif 321 entry->_content[len] = '\0'; 322 } 323 } 324 325 (*g_NTDLL->NtClose)(handle); 326 } 327 328 memcpy(&entry->_data, &w32fd, sizeof(WIN32_FIND_DATA)); 329 330 #ifdef UNICODE 331 entry->_type_name = _wcsdup(info->type.string_ptr); 332 #else 333 char type_name[32]; 334 WideCharToMultiByte(CP_ACP, 0, info->type.string_ptr, info->type.string_len, type_name, 32, 0, 0); 335 entry->_type_name = _strdup(type_name); 336 #endif 337 338 if (!first_entry) 339 first_entry = entry; 340 341 if (last) 342 last->_next = entry; 343 344 entry->_level = level; 345 346 last = entry; 347 } while(!(*g_NTDLL->NtQueryDirectoryObject)(dir_handle, info, 2048, TRUE, FALSE, &idx, NULL)); 348 349 last->_next = NULL; 350 } 351 352 (*g_NTDLL->NtClose)(dir_handle); 353 354 _down = first_entry; 355 _scanned = true; 356 } 357 358 359 Entry* NtObjDirectory::find_entry(const void* p) 360 { 361 LPCTSTR name = (LPCTSTR)p; 362 363 for(Entry*entry=_down; entry; entry=entry->_next) { 364 LPCTSTR p = name; 365 LPCTSTR q = entry->_data.cFileName; 366 367 do { 368 if (!*p || *p==TEXT('\\') || *p==TEXT('/')) 369 return entry; 370 } while(tolower(*p++) == tolower(*q++)); 371 372 p = name; 373 q = entry->_data.cAlternateFileName; 374 375 do { 376 if (!*p || *p==TEXT('\\') || *p==TEXT('/')) 377 return entry; 378 } while(tolower(*p++) == tolower(*q++)); 379 } 380 381 return NULL; 382 } 383 384 385 // get full path of specified directory entry 386 bool NtObjEntry::get_path(PTSTR path, size_t path_count) const 387 { 388 return get_path_base ( path, path_count, ET_NTOBJS ); 389 } 390 391 BOOL NtObjEntry::launch_entry(HWND hwnd, UINT nCmdShow) 392 { 393 return FALSE; 394 } 395