Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenentries.cpp
Go to the documentation of this file.
00001 /* 00002 * Copyright 2003, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00017 */ 00018 00019 00020 // 00021 // Explorer clone 00022 // 00023 // entries.cpp 00024 // 00025 // Martin Fuchs, 23.07.2003 00026 // 00027 00028 00029 #include <precomp.h> 00030 00031 //#include "entries.h" 00032 00033 00034 // allocate and initialise a directory entry 00035 Entry::Entry(ENTRY_TYPE etype) 00036 : _etype(etype) 00037 { 00038 _up = NULL; 00039 _next = NULL; 00040 _down = NULL; 00041 _expanded = false; 00042 _scanned = false; 00043 _bhfi_valid = false; 00044 _level = 0; 00045 _icon_id = ICID_UNKNOWN; 00046 _display_name = _data.cFileName; 00047 _type_name = NULL; 00048 _content = NULL; 00049 } 00050 00051 Entry::Entry(Entry* parent, ENTRY_TYPE etype) 00052 : _up(parent), 00053 _etype(etype) 00054 { 00055 _next = NULL; 00056 _down = NULL; 00057 _expanded = false; 00058 _scanned = false; 00059 _bhfi_valid = false; 00060 _level = 0; 00061 _icon_id = ICID_UNKNOWN; 00062 _shell_attribs = 0; 00063 _display_name = _data.cFileName; 00064 _type_name = NULL; 00065 _content = NULL; 00066 } 00067 00068 Entry::Entry(const Entry& other) 00069 { 00070 _next = NULL; 00071 _down = NULL; 00072 _up = NULL; 00073 00074 assert(!other._next); 00075 assert(!other._down); 00076 assert(!other._up); 00077 00078 _expanded = other._expanded; 00079 _scanned = other._scanned; 00080 _level = other._level; 00081 00082 _data = other._data; 00083 00084 _shell_attribs = other._shell_attribs; 00085 _display_name = other._display_name==other._data.cFileName? _data.cFileName: _tcsdup(other._display_name); 00086 _type_name = other._type_name? _tcsdup(other._type_name): NULL; 00087 _content = other._content? _tcsdup(other._content): NULL; 00088 00089 _etype = other._etype; 00090 _icon_id = other._icon_id; 00091 00092 _bhfi = other._bhfi; 00093 _bhfi_valid = other._bhfi_valid; 00094 } 00095 00096 // free a directory entry 00097 Entry::~Entry() 00098 { 00099 free_subentries(); 00100 00101 if (_icon_id > ICID_NONE) 00102 g_Globals._icon_cache.free_icon(_icon_id); 00103 00104 if (_display_name != _data.cFileName) 00105 free(_display_name); 00106 00107 if (_type_name) 00108 free(_type_name); 00109 00110 if (_content) 00111 free(_content); 00112 00113 if (_down) 00114 delete _down; 00115 } 00116 00117 00118 // read directory tree and expand to the given location 00119 Entry* Entry::read_tree(const void* path, SORT_ORDER sortOrder, int scan_flags) 00120 { 00121 CONTEXT("Entry::read_tree()"); 00122 00123 WaitCursor wait; 00124 00125 Entry* entry = this; 00126 00127 for(const void*p=path; p && entry; ) { 00128 entry->smart_scan(sortOrder, scan_flags); 00129 00130 if (entry->_down) 00131 entry->_expanded = true; 00132 00133 Entry* found = entry->find_entry(p); 00134 p = entry->get_next_path_component(p); 00135 00136 entry = found; 00137 } 00138 00139 return entry; 00140 } 00141 00142 00143 void Entry::read_directory_base(SORT_ORDER sortOrder, int scan_flags) 00144 { 00145 CONTEXT("Entry::read_directory_base()"); 00146 00147 // call into subclass 00148 read_directory(scan_flags); 00149 00150 #ifndef ROSSHELL 00151 if (g_Globals._prescan_nodes) { 00152 for(Entry*entry=_down; entry; entry=entry->_next) 00153 if (entry->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 00154 entry->read_directory(scan_flags); 00155 entry->sort_directory(sortOrder); 00156 } 00157 } 00158 #endif 00159 00160 sort_directory(sortOrder); 00161 } 00162 00163 00164 Root::Root() 00165 { 00166 memset(this, 0, sizeof(Root)); 00167 } 00168 00169 Root::~Root() 00170 { 00171 if (_entry) { 00172 _entry->free_subentries(); 00173 delete _entry; 00174 } 00175 } 00176 00177 00178 // sort order for different directory/file types 00179 enum TYPE_ORDER { 00180 TO_DIR, 00181 TO_DOT, 00182 TO_DOTDOT, 00183 TO_OTHER_DIR, 00184 TO_VIRTUAL_FOLDER, 00185 TO_FILE 00186 }; 00187 00188 // distinguish between ".", ".." and any other directory names 00189 static TYPE_ORDER TypeOrderFromDirname(LPCTSTR name) 00190 { 00191 if (name[0] == '.') { 00192 if (name[1] == '\0') 00193 return TO_DOT; // "." 00194 00195 if (name[1]=='.' && name[2]=='\0') 00196 return TO_DOTDOT; // ".." 00197 } 00198 00199 return TO_OTHER_DIR; // any other directory 00200 } 00201 00202 // directories first... 00203 static int compareType(const Entry* entry1, const Entry* entry2) 00204 { 00205 const WIN32_FIND_DATA* fd1 = &entry1->_data; 00206 const WIN32_FIND_DATA* fd2 = &entry2->_data; 00207 00208 TYPE_ORDER order1 = fd1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY? TO_DIR: TO_FILE; 00209 TYPE_ORDER order2 = fd2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY? TO_DIR: TO_FILE; 00210 00211 // Handle "." and ".." as special case and move them at the very first beginning. 00212 if (order1==TO_DIR && order2==TO_DIR) { 00213 order1 = TypeOrderFromDirname(fd1->cFileName); 00214 order2 = TypeOrderFromDirname(fd2->cFileName); 00215 00216 // Move virtual folders after physical folders 00217 if (!(entry1->_shell_attribs & SFGAO_FILESYSTEM)) 00218 order1 = TO_VIRTUAL_FOLDER; 00219 00220 if (!(entry2->_shell_attribs & SFGAO_FILESYSTEM)) 00221 order2 = TO_VIRTUAL_FOLDER; 00222 } 00223 00224 return order2==order1? 0: order1<order2? -1: 1; 00225 } 00226 00227 00228 static int compareNothing(const void* arg1, const void* arg2) 00229 { 00230 return -1; 00231 } 00232 00233 static int compareName(const void* arg1, const void* arg2) 00234 { 00235 const Entry* entry1 = *(const Entry**)arg1; 00236 const Entry* entry2 = *(const Entry**)arg2; 00237 00238 int cmp = compareType(entry1, entry2); 00239 if (cmp) 00240 return cmp; 00241 00242 return lstrcmpi(entry1->_data.cFileName, entry2->_data.cFileName); 00243 } 00244 00245 static int compareExt(const void* arg1, const void* arg2) 00246 { 00247 const Entry* entry1 = *(const Entry**)arg1; 00248 const Entry* entry2 = *(const Entry**)arg2; 00249 const TCHAR *name1, *name2, *ext1, *ext2; 00250 00251 int cmp = compareType(entry1, entry2); 00252 if (cmp) 00253 return cmp; 00254 00255 name1 = entry1->_data.cFileName; 00256 name2 = entry2->_data.cFileName; 00257 00258 ext1 = _tcsrchr(name1, TEXT('.')); 00259 ext2 = _tcsrchr(name2, TEXT('.')); 00260 00261 if (ext1) 00262 ++ext1; 00263 else 00264 ext1 = TEXT(""); 00265 00266 if (ext2) 00267 ++ext2; 00268 else 00269 ext2 = TEXT(""); 00270 00271 cmp = lstrcmpi(ext1, ext2); 00272 if (cmp) 00273 return cmp; 00274 00275 return lstrcmpi(name1, name2); 00276 } 00277 00278 static int compareSize(const void* arg1, const void* arg2) 00279 { 00280 const Entry* entry1 = *(const Entry**)arg1; 00281 const Entry* entry2 = *(const Entry**)arg2; 00282 00283 int cmp = compareType(entry1, entry2); 00284 if (cmp) 00285 return cmp; 00286 00287 cmp = entry2->_data.nFileSizeHigh - entry1->_data.nFileSizeHigh; 00288 00289 if (cmp < 0) 00290 return -1; 00291 else if (cmp > 0) 00292 return 1; 00293 00294 cmp = entry2->_data.nFileSizeLow - entry1->_data.nFileSizeLow; 00295 00296 return cmp<0? -1: cmp>0? 1: 0; 00297 } 00298 00299 static int compareDate(const void* arg1, const void* arg2) 00300 { 00301 const Entry* entry1 = *(const Entry**)arg1; 00302 const Entry* entry2 = *(const Entry**)arg2; 00303 00304 int cmp = compareType(entry1, entry2); 00305 if (cmp) 00306 return cmp; 00307 00308 return CompareFileTime(&entry2->_data.ftLastWriteTime, &entry1->_data.ftLastWriteTime); 00309 } 00310 00311 00312 static int (*sortFunctions[])(const void* arg1, const void* arg2) = { 00313 compareNothing, // SORT_NONE 00314 compareName, // SORT_NAME 00315 compareExt, // SORT_EXT 00316 compareSize, // SORT_SIZE 00317 compareDate // SORT_DATE 00318 }; 00319 00320 00321 void Entry::sort_directory(SORT_ORDER sortOrder) 00322 { 00323 if (sortOrder != SORT_NONE) { 00324 Entry* entry = _down; 00325 Entry** array, **p; 00326 int len; 00327 00328 len = 0; 00329 for(entry=_down; entry; entry=entry->_next) 00330 ++len; 00331 00332 if (len) { 00333 array = (Entry**) alloca(len*sizeof(Entry*)); 00334 00335 p = array; 00336 for(entry=_down; entry; entry=entry->_next) 00337 *p++ = entry; 00338 00339 // call qsort with the appropriate compare function 00340 qsort(array, len, sizeof(array[0]), sortFunctions[sortOrder]); 00341 00342 _down = array[0]; 00343 00344 for(p=array; --len; p++) 00345 (*p)->_next = p[1]; 00346 00347 (*p)->_next = 0; 00348 } 00349 } 00350 } 00351 00352 00353 void Entry::smart_scan(SORT_ORDER sortOrder, int scan_flags) 00354 { 00355 CONTEXT("Entry::smart_scan()"); 00356 00357 if (!_scanned) { 00358 free_subentries(); 00359 read_directory_base(sortOrder, scan_flags); 00360 } 00361 } 00362 00363 00364 00365 int Entry::extract_icon(ICONCACHE_FLAGS flags) 00366 { 00367 TCHAR path[MAX_PATH]; 00368 00369 ICON_ID icon_id = ICID_NONE; 00370 00371 if (_etype!=ET_SHELL && get_path(path, COUNTOF(path))) // not for ET_SHELL to display the correct desktop icon 00372 if (!(flags & ICF_MIDDLE)) // not for ICF_MIDDLE to extract 24x24 icons because SHGetFileInfo() doesn't support this icon size 00373 icon_id = g_Globals._icon_cache.extract(path, flags); 00374 00375 if (icon_id == ICID_NONE) { 00376 if (!(flags & ICF_OVERLAYS)) { 00377 IExtractIcon* pExtract; 00378 if (SUCCEEDED(GetUIObjectOf(0, IID_IExtractIcon, (LPVOID*)&pExtract))) { 00379 unsigned gil_flags = 0; 00380 int idx; 00381 00382 if (flags & ICF_OPEN) 00383 gil_flags |= GIL_OPENICON; 00384 00385 if (SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, COUNTOF(path), &idx, &gil_flags))) { 00386 if (gil_flags & GIL_NOTFILENAME) 00387 icon_id = g_Globals._icon_cache.extract(pExtract, path, idx, flags); 00388 else { 00389 if (idx == -1) 00390 idx = 0; // special case for some control panel applications ("System") 00391 00392 icon_id = g_Globals._icon_cache.extract(path, idx, flags); 00393 } 00394 00395 /* using create_absolute_pidl() [see below] results in more correct icons for some control panel applets (NVidia display driver). 00396 if (icon_id == ICID_NONE) { 00397 SHFILEINFO sfi; 00398 00399 if (SHGetFileInfo(path, 0, &sfi, sizeof(sfi), SHGFI_ICON|SHGFI_SMALLICON)) 00400 icon_id = g_Globals._icon_cache.add(sfi.hIcon)._id; 00401 } */ 00402 /* 00403 if (icon_id == ICID_NONE) { 00404 LPBYTE b = (LPBYTE) alloca(0x10000); 00405 SHFILEINFO sfi; 00406 00407 FILE* file = fopen(path, "rb"); 00408 if (file) { 00409 int l = fread(b, 1, 0x10000, file); 00410 fclose(file); 00411 00412 if (l) 00413 icon_id = g_Globals._icon_cache.add(CreateIconFromResourceEx(b, l, TRUE, 0x00030000, 16, 16, LR_DEFAULTCOLOR)); 00414 } 00415 } */ 00416 } 00417 } 00418 } 00419 00420 if (icon_id == ICID_NONE) { 00421 const ShellPath& pidl_abs = create_absolute_pidl(); 00422 LPCITEMIDLIST pidl = pidl_abs; 00423 00424 icon_id = g_Globals._icon_cache.extract(pidl, flags); 00425 } 00426 } 00427 00428 return icon_id; 00429 } 00430 00431 int Entry::safe_extract_icon(ICONCACHE_FLAGS flags) 00432 { 00433 try { 00434 return extract_icon(flags); 00435 } catch(COMException&) { 00436 // ignore unexpected exceptions while extracting icons 00437 } 00438 00439 return ICID_NONE; 00440 } 00441 00442 00443 BOOL Entry::launch_entry(HWND hwnd, UINT nCmdShow) 00444 { 00445 TCHAR cmd[MAX_PATH]; 00446 00447 if (!get_path(cmd, COUNTOF(cmd))) 00448 return FALSE; 00449 00450 // add path to the recent file list 00451 SHAddToRecentDocs(SHARD_PATH, cmd); 00452 00453 // start program, open document... 00454 return launch_file(hwnd, cmd, nCmdShow); 00455 } 00456 00457 00458 // local replacement implementation for SHBindToParent() 00459 // (derived from http://www.geocities.com/SiliconValley/2060/articles/shell-helpers.html) 00460 static HRESULT my_SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, VOID** ppv, LPCITEMIDLIST* ppidlLast) 00461 { 00462 HRESULT hr; 00463 00464 if (!ppv) 00465 return E_POINTER; 00466 00467 // There must be at least one item ID. 00468 if (!pidl || !pidl->mkid.cb) 00469 return E_INVALIDARG; 00470 00471 // Get the desktop folder as root. 00472 ShellFolder desktop; 00473 /* IShellFolderPtr desktop; 00474 hr = SHGetDesktopFolder(&desktop); 00475 if (FAILED(hr)) 00476 return hr; */ 00477 00478 // Walk to the penultimate item ID. 00479 LPCITEMIDLIST marker = pidl; 00480 for (;;) 00481 { 00482 LPCITEMIDLIST next = reinterpret_cast<LPCITEMIDLIST>( 00483 marker->mkid.abID - sizeof(marker->mkid.cb) + marker->mkid.cb); 00484 if (!next->mkid.cb) 00485 break; 00486 marker = next; 00487 } 00488 00489 if (marker == pidl) 00490 { 00491 // There was only a single item ID, so bind to the root folder. 00492 hr = desktop->QueryInterface(riid, ppv); 00493 } 00494 else 00495 { 00496 // Copy the ID list, truncating the last item. 00497 int length = marker->mkid.abID - pidl->mkid.abID; 00498 if (LPITEMIDLIST parent_id = reinterpret_cast<LPITEMIDLIST>( 00499 malloc(length + sizeof(pidl->mkid.cb)))) 00500 { 00501 LPBYTE raw_data = reinterpret_cast<LPBYTE>(parent_id); 00502 memcpy(raw_data, pidl, length); 00503 memset(raw_data + length, 0, sizeof(pidl->mkid.cb)); 00504 hr = desktop->BindToObject(parent_id, 0, riid, ppv); 00505 free(parent_id); 00506 } 00507 else 00508 return E_OUTOFMEMORY; 00509 } 00510 00511 // Return a pointer to the last item ID. 00512 if (ppidlLast) 00513 *ppidlLast = marker; 00514 00515 return hr; 00516 } 00517 #define USE_MY_SHBINDTOPARENT 00518 00519 HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos, CtxMenuInterfaces& cm_ifs) 00520 { 00521 ShellPath shell_path = create_absolute_pidl(); 00522 LPCITEMIDLIST pidl_abs = shell_path; 00523 00524 if (!pidl_abs) 00525 return S_FALSE; // no action for registry entries, etc. 00526 00527 #ifdef USE_MY_SHBINDTOPARENT 00528 IShellFolder* parentFolder; 00529 LPCITEMIDLIST pidlLast; 00530 00531 // get and use the parent folder to display correct context menu in all cases -> correct "Properties" dialog for directories, ... 00532 HRESULT hr = my_SHBindToParent(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast); 00533 00534 if (SUCCEEDED(hr)) { 00535 hr = ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pos.x, pos.y, cm_ifs); 00536 00537 parentFolder->Release(); 00538 } 00539 00540 return hr; 00541 #else 00542 static DynamicFct<HRESULT(WINAPI*)(LPCITEMIDLIST, REFIID, LPVOID*, LPCITEMIDLIST*)> SHBindToParent(TEXT("SHELL32"), "SHBindToParent"); 00543 00544 if (SHBindToParent) { 00545 IShellFolder* parentFolder; 00546 LPCITEMIDLIST pidlLast; 00547 00548 // get and use the parent folder to display correct context menu in all cases -> correct "Properties" dialog for directories, ... 00549 HRESULT hr = (*SHBindToParent)(pidl_abs, IID_IShellFolder, (LPVOID*)&parentFolder, &pidlLast); 00550 00551 if (SUCCEEDED(hr)) { 00552 hr = ShellFolderContextMenu(parentFolder, hwnd, 1, &pidlLast, pos.x, pos.y, cm_ifs); 00553 00554 parentFolder->Release(); 00555 } 00556 00557 return hr; 00558 } else { 00575 return ShellFolderContextMenu(GetDesktopFolder(), hwnd, 1, &pidl_abs, pos.x, pos.y, cm_ifs); 00576 } 00577 #endif 00578 } 00579 00580 00581 HRESULT Entry::GetUIObjectOf(HWND hWnd, REFIID riid, LPVOID* ppvOut) 00582 { 00583 TCHAR path[MAX_PATH]; 00584 /* 00585 if (!get_path(path, COUNTOF(path))) 00586 return E_FAIL; 00587 00588 ShellPath shell_path(path); 00589 00590 IShellFolder* pFolder; 00591 LPCITEMIDLIST pidl_last = NULL; 00592 00593 static DynamicFct<HRESULT(WINAPI*)(LPCITEMIDLIST, REFIID, LPVOID*, LPCITEMIDLIST*)> SHBindToParent(TEXT("SHELL32"), "SHBindToParent"); 00594 00595 if (!SHBindToParent) 00596 return E_NOTIMPL; 00597 00598 HRESULT hr = (*SHBindToParent)(shell_path, IID_IShellFolder, (LPVOID*)&pFolder, &pidl_last); 00599 if (FAILED(hr)) 00600 return hr; 00601 00602 ShellFolder shell_folder(pFolder); 00603 00604 shell_folder->Release(); 00605 00606 return shell_folder->GetUIObjectOf(hWnd, 1, &pidl_last, riid, NULL, ppvOut); 00607 */ 00608 if (!_up) 00609 return E_INVALIDARG; 00610 00611 if (!_up->get_path(path, COUNTOF(path))) 00612 return E_FAIL; 00613 00614 ShellPath shell_path(path); 00615 ShellFolder shell_folder(shell_path); 00616 00617 #ifdef UNICODE 00618 LPWSTR wname = _data.cFileName; 00619 #else 00620 WCHAR wname[MAX_PATH]; 00621 MultiByteToWideChar(CP_ACP, 0, _data.cFileName, -1, wname, COUNTOF(wname)); 00622 #endif 00623 00624 LPITEMIDLIST pidl_last = NULL; 00625 HRESULT hr = shell_folder->ParseDisplayName(hWnd, NULL, wname, NULL, &pidl_last, NULL); 00626 00627 if (FAILED(hr)) 00628 return hr; 00629 00630 hr = shell_folder->GetUIObjectOf(hWnd, 1, (LPCITEMIDLIST*)&pidl_last, riid, NULL, ppvOut); 00631 00632 ShellMalloc()->Free((void*)pidl_last); 00633 00634 return hr; 00635 } 00636 00637 00638 // get full path of specified directory entry 00639 bool Entry::get_path_base ( PTSTR path, size_t path_count, ENTRY_TYPE etype ) const 00640 { 00641 int level = 0; 00642 size_t len = 0; 00643 size_t l = 0; 00644 LPCTSTR name = NULL; 00645 TCHAR buffer[MAX_PATH]; 00646 00647 if (!path || path_count==0) 00648 return false; 00649 00650 const Entry* entry; 00651 if ( path_count > 1 ) 00652 { 00653 for(entry=this; entry; level++) { 00654 l = 0; 00655 00656 if (entry->_etype == etype) { 00657 name = entry->_data.cFileName; 00658 00659 for(LPCTSTR s=name; *s && *s!=TEXT('/') && *s!=TEXT('\\'); s++) 00660 ++l; 00661 00662 if (!entry->_up) 00663 break; 00664 } else { 00665 if (entry->get_path(buffer, COUNTOF(buffer))) { 00666 l = _tcslen(buffer); 00667 name = buffer; 00668 00669 /* special handling of drive names */ 00670 if (l>0 && buffer[l-1]=='\\' && path[0]=='\\') 00671 --l; 00672 00673 if ( len+l >= path_count ) 00674 { 00675 if ( l + 1 > path_count ) 00676 len = 0; 00677 else 00678 len = path_count - l - 1; 00679 } 00680 memmove(path+l, path, len*sizeof(TCHAR)); 00681 if ( l+1 >= path_count ) 00682 l = path_count - 1; 00683 memcpy(path, name, l*sizeof(TCHAR)); 00684 len += l; 00685 } 00686 00687 entry = NULL; 00688 break; 00689 } 00690 00691 if (l > 0) { 00692 if ( len+l+1 >= path_count ) 00693 { 00694 /* compare to 2 here because of terminator plus the '\\' we prepend */ 00695 if ( l + 2 > path_count ) 00696 len = 0; 00697 else 00698 len = path_count - l - 2; 00699 } 00700 memmove(path+l+1, path, len*sizeof(TCHAR)); 00701 /* compare to 2 here because of terminator plus the '\\' we prepend */ 00702 if ( l+2 >= path_count ) 00703 l = path_count - 2; 00704 memcpy(path+1, name, l*sizeof(TCHAR)); 00705 len += l+1; 00706 00707 #ifndef _NO_WIN_FS 00708 if (etype == ET_WINDOWS && entry->_up && !(entry->_up->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) // a NTFS stream? 00709 path[0] = TEXT(':'); 00710 else 00711 #endif 00712 path[0] = TEXT('\\'); 00713 } 00714 00715 entry = entry->_up; 00716 } 00717 00718 if (entry) { 00719 if ( len+l >= path_count ) 00720 { 00721 if ( l + 1 > path_count ) 00722 len = 0; 00723 else 00724 len = path_count - l - 1; 00725 } 00726 memmove(path+l, path, len*sizeof(TCHAR)); 00727 if ( l+1 >= path_count ) 00728 l = path_count - 1; 00729 memcpy(path, name, l*sizeof(TCHAR)); 00730 len += l; 00731 } 00732 00733 if ( !level && (len+1 < path_count) ) 00734 path[len++] = TEXT('\\'); 00735 } 00736 00737 path[len] = TEXT('\0'); 00738 00739 return true; 00740 } 00741 00742 // recursively free all child entries 00743 void Entry::free_subentries() 00744 { 00745 Entry *entry, *next=_down; 00746 00747 if (next) { 00748 _down = 0; 00749 00750 do { 00751 entry = next; 00752 next = entry->_next; 00753 00754 entry->free_subentries(); 00755 delete entry; 00756 } while(next); 00757 } 00758 } 00759 00760 00761 Entry* Root::read_tree(LPCTSTR path, int scan_flags) 00762 { 00763 Entry* entry; 00764 00765 if (path && *path) 00766 entry = _entry->read_tree(path, _sort_order); 00767 else { 00768 entry = _entry->read_tree(NULL, _sort_order); 00769 00770 _entry->smart_scan(); 00771 00772 if (_entry->_down) 00773 _entry->_expanded = true; 00774 } 00775 00776 return entry; 00777 } 00778 00779 00780 Entry* Root::read_tree(LPCITEMIDLIST pidl, int scan_flags) 00781 { 00782 return _entry->read_tree(pidl, _sort_order); 00783 } Generated on Mon May 28 2012 04:18:17 for ReactOS by
1.7.6.1
|