ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

entries.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.