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