ciderpress/util/ShellTree.cpp

1414 lines
45 KiB
C++
Raw Normal View History

2007-03-27 17:47:10 +00:00
/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
/*
* ShellTree, a TreeCtrl derivative for displaying the Windows shell namespace.
*/
#include "StdAfx.h"
#include "ShellTree.h"
#include "Pidl.h"
#include "PathName.h"
/*
* ==========================================================================
* ShellTree
2007-03-27 17:47:10 +00:00
* ==========================================================================
*/
BEGIN_MESSAGE_MAP(ShellTree, CTreeCtrl)
ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnFolderExpanding)
ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteShellItem)
ON_NOTIFY_REFLECT_EX(TVN_SELCHANGED, OnSelectionChange)
2007-03-27 17:47:10 +00:00
END_MESSAGE_MAP()
BOOL ShellTree::ReplaceDlgCtrl(CDialog* pDialog, int treeID)
2007-03-27 17:47:10 +00:00
{
CWnd* pWnd = pDialog->GetDlgItem(treeID);
2014-11-18 05:13:13 +00:00
if (pWnd == NULL)
return FALSE;
2007-03-27 17:47:10 +00:00
#if 0
DWORD styles = pWnd->GetStyle();
DWORD stylesEx = pWnd->GetExStyle();
CRect rect;
pWnd->GetWindowRect(&rect);
pDialog->ScreenToClient(&rect);
pWnd->DestroyWindow();
CreateEx(stylesEx, WC_TREEVIEW, NULL, styles, rect, pDialog, treeID);
2007-03-27 17:47:10 +00:00
#endif
/* latch on to their window handle */
Attach(pWnd->m_hWnd);
2007-03-27 17:47:10 +00:00
return TRUE;
2007-03-27 17:47:10 +00:00
}
BOOL ShellTree::PopulateTree(int nFolder)
2007-03-27 17:47:10 +00:00
{
2014-11-18 05:13:13 +00:00
LPSHELLFOLDER lpsf = NULL, lpsf2 = NULL;
LPITEMIDLIST lpi = NULL;
TV_SORTCB tvscb;
2014-11-18 05:13:13 +00:00
LPMALLOC lpMalloc = NULL;
HRESULT hr;
BOOL retval = FALSE;
// Grab a malloc handle.
hr = ::SHGetMalloc(&lpMalloc);
if (FAILED(hr))
return FALSE;
// Get a pointer to the desktop folder.
hr = SHGetDesktopFolder(&lpsf);
if (FAILED(hr))
goto bail;
// Initialize the tree view to be empty.
DeleteAllItems();
if (nFolder == CSIDL_DESKTOP) {
// already done
lpsf2 = lpsf;
2014-11-18 05:13:13 +00:00
lpsf = NULL;
ASSERT(lpi == NULL);
} else {
// find the desired special folder
hr = SHGetSpecialFolderLocation(m_hWnd, nFolder, &lpi);
if (FAILED(hr)) {
LOGI("BUG: could not find requested special folder");
goto bail;
}
// bind a ShellFolder to the PIDL.
hr = lpsf->BindToObject(lpi, 0, IID_IShellFolder, (LPVOID *)&lpsf2);
if (FAILED(hr))
goto bail;
}
// fill in the tree starting from this point
FillTreeView(lpsf2, lpi, TVI_ROOT);
// Sort the items in the tree view
tvscb.hParent = TVI_ROOT;
tvscb.lParam = 0;
tvscb.lpfnCompare = TreeViewCompareProc;
SortChildrenCB(&tvscb);
2007-03-27 17:47:10 +00:00
bail:
2014-11-18 05:13:13 +00:00
if (lpsf != NULL)
lpsf->Release();
2014-11-18 05:13:13 +00:00
if (lpsf != NULL)
lpsf2->Release();
lpMalloc->Free(lpi);
2007-03-27 17:47:10 +00:00
return retval;
2007-03-27 17:47:10 +00:00
}
void ShellTree::ExpandMyComputer(void)
2007-03-27 17:47:10 +00:00
{
HTREEITEM hItem;
hItem = FindMyComputer();
2014-11-18 05:13:13 +00:00
if (hItem == NULL)
hItem = GetRootItem();
Expand(hItem, TVE_EXPAND);
Select(hItem, TVGN_CARET);
2007-03-27 17:47:10 +00:00
}
void ShellTree::FillTreeView(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq,
HTREEITEM hParent)
2007-03-27 17:47:10 +00:00
{
CWaitCursor wait;
HTREEITEM hPrev = NULL; // Previous Item Added.
LPENUMIDLIST lpe=NULL;
LPITEMIDLIST lpi=NULL;
LPMALLOC lpMalloc=NULL;
ULONG ulFetched;
HRESULT hr;
HWND hwnd=::GetParent(m_hWnd);
bool gotOne = false;
// Allocate a shell memory object.
hr = ::SHGetMalloc(&lpMalloc);
if (FAILED(hr))
return;
// Get the IEnumIDList object for the given folder.
hr = lpsf->EnumObjects(hwnd,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN,
&lpe);
if (SUCCEEDED(hr))
{
// Enumerate throught the list of folder and non-folder objects.
while (S_OK == lpe->Next(1, &lpi, &ulFetched))
{
//Create a fully qualified path to the current item
//The SH* shell api's take a fully qualified path pidl,
//(see GetIcon above where I call SHGetFileInfo) whereas the
//interface methods take a relative path pidl.
ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER |
SFGAO_FILESYSANCESTOR | SFGAO_DROPTARGET | SFGAO_HIDDEN;
bool goodOne;
// Determine what type of object we have.
lpsf->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lpi, &ulAttrs);
2007-03-27 17:47:10 +00:00
#if 1
{ /* DEBUG */
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
CString name;
if (Pidl::GetName(lpsf, lpi, SHGDN_NORMAL, &name)) {
LOGD(" Checking '%ls' %08lx", (LPCWSTR) name, ulAttrs);
} else {
LOGD(" Checking <no-name> 0x%08lx", ulAttrs);
}
}
2007-03-27 17:47:10 +00:00
#endif
/*
* (This should be converted to a table and automatically
* scanned when assertions are enabled.)
*
* Win2K folders to show:
* 'My Computer' 0xb0000100 [at root]
* 'My Network Places' 0xb0000100 [at root]
* 'My Documents' 0xb0000100 [at root]
* 'WIN (C:)' 0xb0000100
* 'Compact Disc (H:)' 0xb0000100 <-- SFGAO_REMOVABLE not set
* 'Removable Disk (L:)' 0xb0000100
* 'Documents and Settings' 0xf0400177
* 'Entire Network' 0xb0000000
* 'Microsoft Windows Network' 0xb0000000
* 'Computers Near Me' 0xa0000100
* 'ftp.apple.asimov.net' 0xa0000100
* 'QA-C-Recv on QA' 0xa0000100
* 'BACKUP' 0xf0400177
* 'dudley' 0x70400177
*
* Win2K files, folders, etc. to hide:
* 'gVim 6.1' 0x00000100
* 'Internet Explorer' 0x20000000
* 'Recycle Bin' 0x20000100 (folder + droptarget)
* 'Control Panel' 0xa0000000
* 'Scheduled Tasks on Shiny' 0x20000000
* 'Add Network Place' 0x00000000
* 'ColorBars.jpg' 0x40400177
*
* Win98 folders to show:
* 'My Computer' 0xb0000100 [at root]
* 'My Documents' 0xb0000100 [at root]
* 'Network Neighborhood' 0xb0000100 [at root]
* 'WIN98 (C:)' 0xb0000100
* [C:\]'My Documents' 0xf8000177
* 'Entire Network' 0xb0000000
* 'cpt' 0xe0000177
* 'My eBooks' 0x60000177
*
* Win98 folders and stuff to hide:
* 'Control Panel' 0x20000000
* 'Printers' 0x20000100 (folder + droptarget)
* 'Web Folders' 0xa0000000
* 'BOOTLOG.TXT' 0x40080177
*
* Note that Win98 folders on disk don't have FILESYSANCESTOR
* set. If we check FOLDER && FILESYSTEM (0x60000000), we get
* anything starting with 6/7/E/F, which appears safe. We
* need to do additional tests to pick up some of the A/B items
* that we want while hiding the A items we don't want.
*
* FILESYSANCESTOR is 0x10000000, so that plus FOLDER allows
* 3/7/b/f. These appear to be entirely okay.
*
* DROPTARGET is 0x00000100, and HASSUBFOLDER is 0x80000000.
* Combining with FOLDER yields 0xa00000100, allowing A/B/E/F.
* The only at-risk is A, but combined with DROPTARGET we
* seem to screen out all the bad ones.
*/
2014-11-18 05:13:13 +00:00
if (lpifq == NULL) {
/* dealing with stuff at the root level */
goodOne = ( (ulAttrs & SFGAO_FOLDER) &&
(ulAttrs & SFGAO_HASSUBFOLDER) &&
(ulAttrs & SFGAO_FILESYSANCESTOR) );
} else {
/* deeper down, we're picky in different ways */
bool isFolder = (ulAttrs & SFGAO_FOLDER) != 0;
bool fileSys = (ulAttrs & SFGAO_FILESYSTEM) != 0;
bool hasFSAncestor = (ulAttrs & SFGAO_FILESYSANCESTOR) != 0;
bool dropAndSub = (ulAttrs & SFGAO_DROPTARGET) != 0 &&
(ulAttrs & SFGAO_HASSUBFOLDER) != 0;
goodOne = isFolder &&
(fileSys || hasFSAncestor || dropAndSub);
}
if (goodOne) {
gotOne = true;
if (!AddNode(lpsf, lpi, lpifq, ulAttrs, hParent, &hPrev)) {
LOGI("AddNode failed!");
goto Done;
}
}
lpMalloc->Free(lpi); //Free the pidl that the shell gave us.
lpi=0;
}
}
// Sometimes SFGAO_HASSUBFOLDERS lies, notably in Network Neighborhood.
// When we actually scan the directory we can update the parent node
// if it turns out there's nothing underneath.
if (!gotOne) {
TVITEM tvi;
CString name = GetItemText(hParent);
tvi.hItem = hParent;
tvi.mask = TVIF_CHILDREN;
if (!GetItem(&tvi)) {
LOGW("Could not get TV '%ls'", (LPCWSTR) name);
ASSERT(false);
} else if (tvi.cChildren) {
LOGI("Removing child count (%d) from '%ls'",
tvi.cChildren, (LPCWSTR) name);
tvi.cChildren = 0;
if (!SetItem(&tvi)) {
LOGW("Could not set TV '%ls'", (LPCWSTR) name);
ASSERT(false);
}
}
}
2007-03-27 17:47:10 +00:00
Done:
if (lpe)
lpe->Release();
//The following 2 if statements will only be TRUE if we got here on an
//error condition from the "goto" statement. Otherwise, we free this memory
//at the end of the while loop above.
if (lpi && lpMalloc)
lpMalloc->Free(lpi);
if (lpMalloc)
lpMalloc->Release();
//LOGI("FillTreeView DONE");
2007-03-27 17:47:10 +00:00
}
BOOL ShellTree::AddNode(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi, LPITEMIDLIST lpifq,
unsigned long ulAttrs, HTREEITEM hParent, HTREEITEM* phPrev)
2007-03-27 17:47:10 +00:00
{
TVITEM tvi;
TVINSERTSTRUCT tvins;
2014-11-18 05:13:13 +00:00
LPITEMIDLIST lpifqThisItem = NULL;
TVItemData* lptvid = NULL;
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
WCHAR szBuff[MAX_PATH];
CString name;
2014-11-18 05:13:13 +00:00
LPMALLOC lpMalloc = NULL;
HRESULT hr;
BOOL result = FALSE;
hr = ::SHGetMalloc(&lpMalloc);
if (FAILED(hr))
return FALSE;
//Now get the friendly name that we'll put in the treeview.
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
if (!Pidl::GetName(lpsf, lpi, SHGDN_NORMAL, &name)) {
LOGI("HEY: failed getting friendly name");
goto bail; // Error - could not get friendly name.
}
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
wcscpy_s(szBuff, name);
//LOGI("AddNode '%ls' ATTR=0x%08lx", szBuff, ulAttrs);
lptvid = (TVItemData*)lpMalloc->Alloc(sizeof(TVItemData));
if (!lptvid)
goto bail;
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE |
TVIF_PARAM;
if (ulAttrs & SFGAO_HASSUBFOLDER) {
//This item has sub-folders, so let's put the + in the TreeView.
//The first time the user clicks on the item, we'll populate the
//sub-folders.
tvi.mask |= TVIF_CHILDREN;
tvi.cChildren = 1;
}
tvi.pszText = szBuff;
tvi.cchTextMax = MAX_PATH; // (not needed for InsertItem)
// Allocate a fully-qualified PIDL and stuff it in.
lpifqThisItem = Pidl::ConcatPidls(lpifq, lpi);
// Add the icons.
GetNormalAndSelectedIcons(lpifqThisItem, &tvi);
// Done with lipfqThisItem.
lptvid->lpifq = lpifqThisItem;
2014-11-18 05:13:13 +00:00
lpifqThisItem = NULL;
// Put in a copy of the relative PIDL.
lptvid->lpi = Pidl::CopyITEMID(lpMalloc, lpi);
// Stuff the parent folder's lpsf in.
lptvid->lpsfParent = lpsf;
lpsf->AddRef();
// Done with lptvid.
tvi.lParam = (LPARAM)lptvid;
2014-11-18 05:13:13 +00:00
lptvid = NULL;
// Populate the TreeView Insert Struct
// The item is the one filled above.
// Insert it after the last item inserted at this level.
// And indicate this is a root entry.
tvins.item = tvi;
tvins.hInsertAfter = *phPrev;
tvins.hParent = hParent;
// Add the item to the tree
*phPrev = InsertItem(&tvins);
result = TRUE;
2007-03-27 17:47:10 +00:00
bail:
lpMalloc->Release();
return result;
2007-03-27 17:47:10 +00:00
}
void ShellTree::GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTV_ITEM lptvitem)
2007-03-27 17:47:10 +00:00
{
//Note that we don't check the return value here because if GetIcon()
//fails, then we're in big trouble...
lptvitem->iImage = Pidl::GetItemIcon(lpifq,
SHGFI_SYSICONINDEX |
SHGFI_SMALLICON);
2007-03-27 17:47:10 +00:00
lptvitem->iSelectedImage = Pidl::GetItemIcon(lpifq,
SHGFI_SYSICONINDEX |
SHGFI_SMALLICON |
SHGFI_OPENICON);
2007-03-27 17:47:10 +00:00
return;
}
/*static*/ int CALLBACK ShellTree::TreeViewCompareProc(LPARAM lparam1,
LPARAM lparam2, LPARAM)
2007-03-27 17:47:10 +00:00
{
TVItemData* lptvid1 = (TVItemData*)lparam1;
TVItemData* lptvid2 = (TVItemData*)lparam2;
HRESULT hr;
2007-03-27 17:47:10 +00:00
hr = lptvid1->lpsfParent->CompareIDs(0, lptvid1->lpi, lptvid2->lpi);
if (FAILED(hr)) {
ASSERT(false);
return 0;
}
2007-03-27 17:47:10 +00:00
#if 0
if (lptvid1->alphaSort && lptvid2->alphaSort) {
char buf1[MAX_PATH], buf2[MAX_PATH];
if (Pidl::GetName(lptvid1->lpsfParent, lptvid1->lpi, SHGDN_NORMAL, buf1) &&
Pidl::GetName(lptvid2->lpsfParent, lptvid2->lpi, SHGDN_NORMAL, buf2))
{
LOGI("COMPARING '%s' to '%s' (res=%d)", buf1, buf2,
(short) HRESULT_CODE(hr));
return stricmp(buf1, buf2);
} else {
ASSERT(false);
return 0;
}
}
2007-03-27 17:47:10 +00:00
#endif
return (short) HRESULT_CODE(hr);
2007-03-27 17:47:10 +00:00
}
BOOL ShellTree::AddFolderAtSelection(const CString& name)
2007-03-27 17:47:10 +00:00
{
2014-11-18 05:13:13 +00:00
LPSHELLFOLDER lpsf = NULL;
LPITEMIDLIST lpi = NULL;
HTREEITEM hParent;
2014-11-18 05:13:13 +00:00
LPMALLOC lpMalloc = NULL;
LPENUMIDLIST lpe = NULL;
const TVItemData* parentTvid;
2014-11-18 05:13:13 +00:00
TVItemData* newTvid = NULL;
HWND hwnd = ::GetParent(m_hWnd);
2014-11-18 05:13:13 +00:00
HTREEITEM hPrev = NULL;
BOOL result = false;
CString debugName;
HRESULT hr;
LOGI("AddFolderAtSelection '%ls'", (LPCWSTR) name);
// Allocate a shell memory object.
hr = ::SHGetMalloc(&lpMalloc);
if (FAILED(hr))
return FALSE;
hParent = GetSelectedItem();
2014-11-18 05:13:13 +00:00
if (hParent == NULL) {
LOGI("Nothing selected!");
goto bail;
}
/*
* Now we either need to create a new node in an existing tree, or if
* we haven't expanded the current node yet then we can just let the
* usual FillTree mechanism do it for us.
*
* If the current node is marked as having children, but has no
* child structures, then it's a folder with sub-folders that hasn't
* been filled in yet. We don't need to do anything.
*
* If the current node doesn't have children, then this is a leaf
* node that has just become a branch. We update its "#of kids" state
* and again let the usual mechanisms do their work.
*
* If the current node has expanded children, then we need to do the
* work ourselves. (It's that, or invalidate the entire subtree,
* which has some UI consequences.)
*/
TVITEM tvi;
debugName = GetItemText(hParent);
tvi.hItem = hParent;
tvi.mask = TVIF_CHILDREN;
if (!GetItem(&tvi)) {
LOGW("Could not get TV '%ls'", (LPCWSTR) debugName);
ASSERT(false);
} else {
HTREEITEM child = GetChildItem(hParent);
2014-11-18 05:13:13 +00:00
if (child == NULL && tvi.cChildren) {
LOGD(" Found unexpanded node, not adding %ls", (LPCWSTR) name);
result = TRUE;
goto bail;
2014-11-18 05:13:13 +00:00
} else if (child == NULL && !tvi.cChildren) {
LOGD(" Found former leaf node, updating kids in %ls",
(LPCWSTR) debugName);
tvi.cChildren = 1;
if (!SetItem(&tvi)) {
LOGW("Could not set TV '%ls'", (LPCWSTR) debugName);
ASSERT(false);
}
result = TRUE;
goto bail;
} else {
2014-11-18 05:13:13 +00:00
ASSERT(child != NULL && tvi.cChildren != 0);
LOGD(" Found expanded branch node '%ls', adding new '%ls'",
(LPCWSTR) debugName, (LPCWSTR) name);
}
}
parentTvid = (TVItemData*)GetItemData(hParent);
2014-11-18 05:13:13 +00:00
ASSERT(parentTvid != NULL);
// Get a handle to the ShellFolder for the currently selected node.
hr = parentTvid->lpsfParent->BindToObject(parentTvid->lpi,
0, IID_IShellFolder, (LPVOID *)&lpsf);
if (FAILED(hr)) {
LOGW("Glitch: unable to get ShellFolder for selected folder");
goto bail;
}
// Get an enumerator for the selected node.
hr = lpsf->EnumObjects(hwnd, SHCONTF_FOLDERS | SHCONTF_INCLUDEHIDDEN,
&lpe);
if (FAILED(hr)) {
LOGW("Glitch: unable to get enumerator for selected folder");
goto bail;
}
// Enumerate throught the list of folder and non-folder objects.
2014-11-18 05:13:13 +00:00
while (S_OK == lpe->Next(1, &lpi, NULL)) {
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
CString pidlName;
if (Pidl::GetName(lpsf, lpi, SHGDN_NORMAL, &pidlName)) {
if (name.CompareNoCase(pidlName) == 0) {
/* match! */
if (!AddNode(lpsf, lpi, parentTvid->lpifq, 0, hParent, &hPrev)) {
LOGI("AddNode failed!");
goto bail;
}
result = TRUE;
break;
}
}
lpMalloc->Free(lpi); //Free the pidl that the shell gave us.
2014-11-18 05:13:13 +00:00
lpi = NULL;
}
2007-03-27 17:47:10 +00:00
bail:
2014-11-18 05:13:13 +00:00
if (lpi != NULL)
lpMalloc->Free(lpi);
2014-11-18 05:13:13 +00:00
if (lpsf != NULL)
lpsf->Release();
2014-11-18 05:13:13 +00:00
if (lpe != NULL)
lpe->Release();
lpMalloc->Release();
return result;
2007-03-27 17:47:10 +00:00
}
void ShellTree::OnFolderExpanding(NMHDR* pNMHDR, LRESULT* pResult)
{
TVItemData* lptvid; //Long pointer to TreeView item data
HRESULT hr;
LPSHELLFOLDER lpsf2=NULL;
TV_SORTCB tvscb;
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;
if (pnmtv->itemNew.state & TVIS_EXPANDEDONCE) {
LOGI("Already expanded!");
return;
}
lptvid = (TVItemData*)pnmtv->itemNew.lParam;
if (lptvid) {
hr = lptvid->lpsfParent->BindToObject(lptvid->lpi,
0, IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
FillTreeView(lpsf2,
lptvid->lpifq,
pnmtv->itemNew.hItem);
}
tvscb.hParent = pnmtv->itemNew.hItem;
tvscb.lParam = 0;
tvscb.lpfnCompare = TreeViewCompareProc;
SortChildrenCB(&tvscb);
}
*pResult = 0;
2007-03-27 17:47:10 +00:00
}
#if 0
/****************************************************************************
*
* FUNCTION: GetContextMenu(NMHDR* pNMHDR, LRESULT* pResult)
2007-03-27 17:47:10 +00:00
*
* PURPOSE: Diplays a popup menu for the folder selected. Pass the
* parameters from Rclick() to this function.
2007-03-27 17:47:10 +00:00
*
* MESSAGEMAP: NM_RCLICK;
2007-03-27 17:47:10 +00:00
*
****************************************************************************/
void ShellTree::GetContextMenu(NMHDR*, LRESULT* pResult)
{
POINT pt;
TVItemData* lptvid; //Long pointer to TreeView item data
TV_HITTESTINFO tvhti;
TV_ITEM tvi;
::GetCursorPos((LPPOINT)&pt);
ScreenToClient(&pt);
tvhti.pt=pt;
HitTest(&tvhti);
SelectItem(tvhti.hItem);
if (tvhti.flags & (TVHT_ONITEMLABEL|TVHT_ONITEMICON))
{
ClientToScreen(&pt);
tvi.mask=TVIF_PARAM;
tvi.hItem=tvhti.hItem;
if (!GetItem(&tvi)){
return;
}
lptvid = (TVItemData*)tvi.lParam;
Pidl::DoTheMenuThing(::GetParent(m_hWnd),
lptvid->lpsfParent, lptvid->lpi, &pt);
}
*pResult = 0;
2007-03-27 17:47:10 +00:00
}
#endif
BOOL ShellTree::OnSelectionChange(NMHDR* pnmh, LRESULT* pResult)
2007-03-27 17:47:10 +00:00
{
fFolderPathValid = OnFolderSelected(pnmh, pResult, fFolderPath);
*pResult = 0;
return FALSE; // allow window parent to handle notification
2007-03-27 17:47:10 +00:00
}
BOOL ShellTree::OnFolderSelected(NMHDR* pNMHDR, LRESULT* pResult,
CString &szFolderPath)
2007-03-27 17:47:10 +00:00
{
TVItemData* lptvid;
LPSHELLFOLDER lpsf2=NULL;
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
WCHAR szBuff[MAX_PATH];
HRESULT hr;
BOOL bRet=false;
HTREEITEM hItem=NULL;
hItem = GetSelectedItem();
if (hItem) {
lptvid = (TVItemData*)GetItemData(hItem);
if (lptvid && lptvid->lpsfParent && lptvid->lpi)
{
hr = lptvid->lpsfParent->BindToObject(lptvid->lpi,
0, IID_IShellFolder, (LPVOID *)&lpsf2);
if (SUCCEEDED(hr)) {
ULONG ulAttrs = SFGAO_FILESYSTEM;
// Determine what type of object we have.
lptvid->lpsfParent->GetAttributesOf(1,
(const struct _ITEMIDLIST **)&lptvid->lpi, &ulAttrs);
if (ulAttrs & (SFGAO_FILESYSTEM)) {
if (SHGetPathFromIDList(lptvid->lpifq, szBuff)){
szFolderPath = szBuff;
bRet = true;
}
}
if (bRet) {
LOGI("Now selected: '%ls'", szBuff);
} else {
LOGI("Now selected: <no path>");
}
2007-03-27 17:47:10 +00:00
#if 0
// If we're expanding into new territory, load the
// sub-tree. [This makes it expand things that aren't
// necessarily going to be opened, which is very bad for
// empty floppy and CD-ROM drives. Makes little sense.]
TV_SORTCB tvscb;
NM_TREEVIEW* pnmtv = (NM_TREEVIEW*)pNMHDR;
if ((pnmtv->itemNew.cChildren == 1) &&
!(pnmtv->itemNew.state & TVIS_EXPANDEDONCE))
{
FillTreeView(lpsf2, lptvid->lpifq, pnmtv->itemNew.hItem);
tvscb.hParent = pnmtv->itemNew.hItem;
tvscb.lParam = 0;
tvscb.lpfnCompare = TreeViewCompareProc;
SortChildrenCB(&tvscb);
pnmtv->itemNew.state |= TVIS_EXPANDEDONCE;
pnmtv->itemNew.stateMask |= TVIS_EXPANDEDONCE;
pnmtv->itemNew.mask |= TVIF_STATE;
SetItem(&pnmtv->itemNew);
}
2007-03-27 17:47:10 +00:00
#endif
}
}
if(lpsf2)
lpsf2->Release();
}
*pResult = 0;
return bRet;
2007-03-27 17:47:10 +00:00
}
void ShellTree::OnDeleteShellItem(NMHDR* pNMHDR, LRESULT* pResult)
2007-03-27 17:47:10 +00:00
{
TVItemData* lptvid=NULL;
HRESULT hr;
LPMALLOC lpMalloc;
//LOGI("TVN_DELETEITEM");
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
//Let's free the memory for the TreeView item data...
hr = SHGetMalloc(&lpMalloc);
if (FAILED(hr))
return;
lptvid = (TVItemData*)pNMTreeView->itemOld.lParam;
lptvid->lpsfParent->Release();
lpMalloc->Free(lptvid->lpi);
lpMalloc->Free(lptvid->lpifq);
lpMalloc->Free(lptvid);
lpMalloc->Release();
*pResult = 0;
2007-03-27 17:47:10 +00:00
}
void ShellTree::EnableImages()
2007-03-27 17:47:10 +00:00
{
// Get the handle to the system image list, for our icons
HIMAGELIST hImageList;
SHFILEINFO sfi = { 0 };
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
hImageList = (HIMAGELIST)SHGetFileInfo(L"C:\\",
0, &sfi, sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
// Attach ImageList to TreeView
if (hImageList)
::SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM) TVSIL_NORMAL,
(LPARAM)hImageList);
2007-03-27 17:47:10 +00:00
}
BOOL ShellTree::GetSelectedFolderPath(CString &szFolderPath)
{
TVItemData* lptvid; //Long pointer to TreeView item data
LPSHELLFOLDER lpsf2=NULL;
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
WCHAR szBuff[MAX_PATH];
HTREEITEM hItem=NULL;
HRESULT hr;
BOOL bRet=false;
hItem = GetSelectedItem();
if(hItem)
{
lptvid = (TVItemData*)GetItemData(hItem);
if (lptvid && lptvid->lpsfParent && lptvid->lpi)
{
hr = lptvid->lpsfParent->BindToObject(lptvid->lpi,
0, IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
ULONG ulAttrs = SFGAO_FILESYSTEM;
// Determine what type of object we have.
lptvid->lpsfParent->GetAttributesOf(1,
(const struct _ITEMIDLIST **)&lptvid->lpi, &ulAttrs);
if (ulAttrs & (SFGAO_FILESYSTEM))
{
if(SHGetPathFromIDList(lptvid->lpifq, szBuff)){
szFolderPath = szBuff;
bRet = true;
}
}
}
}
if(lpsf2)
lpsf2->Release();
}
return bRet;
2007-03-27 17:47:10 +00:00
}
LPSHELLFOLDER ShellTree::GetParentShellFolder(HTREEITEM folderNode)
{
TVItemData* lptvid; //Long pointer to TreeView item data
2007-03-27 17:47:10 +00:00
lptvid = (TVItemData*)GetItemData(folderNode);
if (lptvid)
return lptvid->lpsfParent;
else
return NULL;
2007-03-27 17:47:10 +00:00
}
LPITEMIDLIST ShellTree::GetRelativeIDLIST(HTREEITEM folderNode)
{
TVItemData* lptvid; //Long pointer to TreeView item data
2007-03-27 17:47:10 +00:00
lptvid = (TVItemData*)GetItemData(folderNode);
if (lptvid)
return lptvid->lpifq;
else
return NULL;
2007-03-27 17:47:10 +00:00
}
LPITEMIDLIST ShellTree::GetFullyQualifiedID(HTREEITEM folderNode)
{
TVItemData* lptvid; //Long pointer to TreeView item data
2007-03-27 17:47:10 +00:00
lptvid = (TVItemData*)GetItemData(folderNode);
if (lptvid)
return lptvid->lpifq;
else
return NULL;
2007-03-27 17:47:10 +00:00
}
void ShellTree::TunnelTree(CString path, CString* pResultStr)
2007-03-27 17:47:10 +00:00
{
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
const WCHAR* str = path;
int len;
if (str[0] == '\\' && str[1] == '\\') {
*pResultStr = L"Can't expand network locations directly.";
return;
}
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
len = path.GetLength();
if (len < 1) {
*pResultStr = L"You must enter a folder name.";
return;
}
/* make sure it ends in \ so splitpath knows it's a directory */
if (path[len-1] != '\\')
path += '\\';
/* if it doesn't exist, there's not much point in searching for it */
PathName pathName(path);
if (!pathName.Exists()) {
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
*pResultStr = L"Folder not found.";
return;
}
/*
* Find the folder that corresponds to "My Computer", and then scan
* it for the drive letter.
*/
HTREEITEM myComputer = FindMyComputer();
2014-11-18 05:13:13 +00:00
if (myComputer == NULL) {
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
*pResultStr = L"Unable to locate My Computer in tree.";
return;
}
CString drive = pathName.GetDriveOnly();
LOGI("Searching for drive='%ls'", (LPCWSTR) drive);
HTREEITEM node = FindDrive(myComputer, drive);
2014-11-18 05:13:13 +00:00
if (node == NULL) {
/* unexpected -- couldn't find the drive */
pResultStr->Format(L"Unable to find drive %ls.", (LPCWSTR) drive);
return;
}
/*
* We've got the node for the drive. Now we just need to walk
* through the tree one level at a time, comparing the name in
* the tree against our pathname component.
*/
node = SearchTree(node, pathName.GetPathOnly());
2014-11-18 05:13:13 +00:00
if (node == NULL) {
/* unexpected -- file doesn't exist */
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
pResultStr->Format(L"Unable to find file '%ls'.",
(LPCWSTR) pathName.GetPathOnly());
} else {
Select(node, TVGN_CARET);
EnsureVisible(node);
}
2007-03-27 17:47:10 +00:00
}
HTREEITEM ShellTree::FindMyComputer(void)
2007-03-27 17:47:10 +00:00
{
/*
* Find the tree entry that corresponds to "My Computer".
*
* This is hampered somewhat by the absence of a way to compare two
* shell folders for equality. The PIDL compare function is meant for
* sorting only (at least as far as it has been documented), and the My
* Computer "folder" has no path to examine.
*
* It helps greatly to assume that My Computer is right under Desktop.
* If it moved, or if we started the tree somewhere other than right at
* the desktop, we'd have to recursively search the tree.
*/
2014-11-18 05:13:13 +00:00
LPSHELLFOLDER desktop = NULL;
LPITEMIDLIST myComputerPidl = NULL;
LPMALLOC lpMalloc = NULL;
HTREEITEM node;
2014-11-18 05:13:13 +00:00
HTREEITEM result = NULL;
HRESULT hr;
hr = ::SHGetMalloc(&lpMalloc);
if (FAILED(hr))
2014-11-18 05:13:13 +00:00
return NULL;
hr = SHGetDesktopFolder(&desktop);
if (FAILED(hr))
goto bail;
2014-11-18 05:13:13 +00:00
hr = SHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &myComputerPidl);
if (FAILED(hr))
goto bail;
node = GetRootItem();
2014-11-18 05:13:13 +00:00
while (node != NULL) {
CString itemText = GetItemText(node);
TVItemData* pData = (TVItemData*) GetItemData(node);
2014-11-18 05:13:13 +00:00
ASSERT(pData != NULL);
hr = desktop->CompareIDs(0, myComputerPidl, pData->lpi);
if (SUCCEEDED(hr) && HRESULT_CODE(hr) == 0) {
LOGD("MATCHED on '%ls'", (LPCWSTR) itemText);
result = node;
break;
}
node = GetNextSiblingItem(node);
}
2014-11-18 05:13:13 +00:00
if (result != NULL && !ItemHasChildren(result)) {
LOGW("Glitch: My Computer has no children");
2014-11-18 05:13:13 +00:00
result = NULL;
}
2007-03-27 17:47:10 +00:00
bail:
2014-11-18 05:13:13 +00:00
if (desktop != NULL)
desktop->Release();
lpMalloc->Free(myComputerPidl);
lpMalloc->Release();
return result;
2007-03-27 17:47:10 +00:00
}
HTREEITEM ShellTree::FindDrive(HTREEITEM myComputer, const CString& drive)
2007-03-27 17:47:10 +00:00
{
CString udrive;
/* expand & scan */
Expand(myComputer, TVE_EXPAND);
HTREEITEM node;
node = GetChildItem(myComputer);
2014-11-18 05:13:13 +00:00
if (node == NULL) {
ASSERT(false); // we verified My Computer has kids earlier
2014-11-18 05:13:13 +00:00
return NULL;
}
/*
* Look for the drive letter. It's buried amongst other fluff, so
* we have to rely on Windows preventing the use of a ":" anywhere
* else in the string to avoid false-positives.
*
* We *might* be able to assume it looks like "(C:)", but that's
* probably unwise.
*/
udrive = drive;
udrive.MakeUpper();
2014-11-18 05:13:13 +00:00
while (node != NULL) {
CString itemText = GetItemText(node);
itemText.MakeUpper();
//LOGI("COMPARING '%ls' vs '%ls'", (LPCWSTR) udrive, (LPCWSTR) itemText);
if (itemText.Find(udrive) != -1) {
LOGI("MATCHED '%ls' in '%ls'", (LPCWSTR) udrive, (LPCWSTR) itemText);
break;
}
node = GetNextSiblingItem(node);
}
return node;
2007-03-27 17:47:10 +00:00
}
HTREEITEM ShellTree::SearchTree(HTREEITEM treeNode, const CString& path)
2007-03-27 17:47:10 +00:00
{
LOGD("SearchTree node=0x%p path='%ls'", treeNode, (LPCWSTR) path);
HTREEITEM node;
CString mangle(path);
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
WCHAR* start;
WCHAR* end;
/* make a copy of "path" that we can mess with */
start = mangle.GetBuffer(0);
2014-11-18 05:13:13 +00:00
if (start == NULL || *start != '\\' || *(start + wcslen(start)-1) != '\\')
return NULL;
start++;
node = treeNode;
while (*start != '\0') {
/* grab first node in next level down */
Expand(node, TVE_EXPAND); // need to fill in the tree
node = GetChildItem(node);
Large set of changes to restore CiderPress build. CiderPress and MDC now compile, and execute far enough to open their respective "about" boxes, but I doubt they'll do much more than that. * Switch from MBCS to UNICODE APIs Microsoft switched to UTF-16 (by way of UCS-2) a long time ago, and the support for MBCS seems to be getting phased out. So it's time to switch to wide strings. This is a bit awkward for CiderPress because it works with disk and file archives with 8-bit filenames, and I want NufxLib and DiskImgLib to continue to work on Linux (which has largely taken the UTF-8 approach to Unicode). The libraries will continue to work with 8-bit filenames, with CiderPress/MDC doing the conversion at the appropriate point. There were a couple of places where strings from a structure handed back by one of the libraries were used directly in the UI, or vice-versa, which is a problem because we have nowhere to store the result of the conversion. These currently have fixed place-holder "xyzzy" strings. All UI strings are now wide. Various format strings now use "%ls" and "%hs" to explicitly specify wide and narrow. This doesn't play well with gcc, so only the Windows-specific parts use those. * Various updates to vcxproj files The project-file conversion had some cruft that is now largely gone. The build now has a common output directory for the EXEs and libraries, avoiding the old post-build copy steps. * Added zlib 1.2.8 and nufxlib 2.2.2 source snapshots The old "prebuilts" directory is now gone. The libraries are now built as part of building the apps. I added a minimal set of files for zlib, and a full set for nufxlib. The Linux-specific nufxlib goodies are included for the benefit of the Linux utilities, which are currently broken (don't build). * Replace symbols used for include guards Symbols with a leading "__" are reserved.
2014-11-10 23:32:55 +00:00
end = wcschr(start, '\\');
2014-11-18 05:13:13 +00:00
if (end == NULL) {
ASSERT(false);
2014-11-18 05:13:13 +00:00
return NULL;
}
*end = '\0';
2014-11-18 05:13:13 +00:00
while (node != NULL) {
CString itemText = GetItemText(node);
//LOGI("COMPARE '%s' '%s'", start, itemText);
if (itemText.CompareNoCase(start) == 0) {
//LOGI("MATCHED '%s' '%s'", itemText, start);
break;
}
node = GetNextSiblingItem(node);
}
2014-11-18 05:13:13 +00:00
if (node == NULL) {
LOGI("NOT FOUND '%ls' '%ls'", (LPCTSTR) path, start);
break;
}
start = end+1;
}
return node;
2007-03-27 17:47:10 +00:00
}
#ifdef USE_OLD
/****************************************************************************
*
* FUNCTION: SearchTree( HTREEITEM treeNode,
* CString szSearchName )
2007-03-27 17:47:10 +00:00
*
* PURPOSE: Too crude to explain, just use it
2007-03-27 17:47:10 +00:00
*
* WARNING: Only works if you use the default PopulateTree()
* Not guaranteed to work on any future or existing
* version of windows. Use with caution. Pretty much
* ok if you're using on local drives
2007-03-27 17:47:10 +00:00
*
****************************************************************************/
bool ShellTree::SearchTree(HTREEITEM treeNode,
CString szSearchName,
FindAttribs attr)
2007-03-27 17:47:10 +00:00
{
TVItemData* lptvid; //Long pointer to TreeView item data
LPSHELLFOLDER lpsf2=NULL;
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
bool bRet=false;
HRESULT hr;
CString szCompare;
szSearchName.MakeUpper();
while(treeNode && bRet==false)
{
lptvid=(TVItemData*)GetItemData(treeNode);
if (lptvid && lptvid->lpsfParent && lptvid->lpi)
{
hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
0,IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
ULONG ulAttrs = SFGAO_FILESYSTEM;
lptvid->lpsfParent->GetAttributesOf(1,
(const struct _ITEMIDLIST **)&lptvid->lpi, &ulAttrs);
if (ulAttrs & (SFGAO_FILESYSTEM))
{
if(SHGetPathFromIDList(lptvid->lpifq,
szCompare.GetBuffer(MAX_PATH)))
{
switch(attr)
{
case type_drive:
_splitpath(szCompare,drive,dir,fname,ext);
szCompare=drive;
break;
case type_folder:
szCompare = GetItemText(treeNode);
break;
}
szCompare.MakeUpper();
if(szCompare == szSearchName)
{
EnsureVisible(treeNode);
SelectItem(treeNode);
bRet=true;
}
}
}
lpsf2->Release();
}
}
treeNode = GetNextSiblingItem(treeNode);
}
return bRet;
2007-03-27 17:47:10 +00:00
}
/****************************************************************************
*
* FUNCTION: TunnelTree(CString szFindPath)
2007-03-27 17:47:10 +00:00
*
* PURPOSE: Too crude to explain, just use it
2007-03-27 17:47:10 +00:00
*
* WARNING: Only works if you use the default PopulateTree()
* Not guaranteed to work on any future or existing
* version of windows. Use with caution. Pretty much
* ok if you're using on local drives
2007-03-27 17:47:10 +00:00
*
****************************************************************************/
void ShellTree::TunnelTree(CString szFindPath)
{
HTREEITEM subNode = GetRootItem();
CString szPathHop;
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
char delimiter[]="\\";
PathName checkPath(szFindPath);
if(!checkPath.Exists())
{
MessageBox(szFindPath,"Folder not found",MB_ICONERROR);
return;
}
if(szFindPath.ReverseFind('\\') != szFindPath.GetLength()-1)
{
szFindPath += "\\";
}
_splitpath(szFindPath,drive,dir,fname,ext);
//search the drive first
szPathHop=drive;
subNode=GetChildItem(subNode);
if(subNode)
{
if(SearchTree(subNode,szPathHop, ShellTree::type_drive))
{
//break down subfolders and search
char *p=strtok(dir,delimiter);
while(p)
{
subNode = GetSelectedItem();
subNode = GetChildItem(subNode);
if(SearchTree(subNode,p,ShellTree::type_folder))
p=strtok(NULL,delimiter);
else
p=NULL;
}
}
}
2007-03-27 17:47:10 +00:00
}
#endif
#ifdef USE_NEW
// new version for Win2K
/****************************************************************************
*
* FUNCTION: SearchTree( HTREEITEM treeNode,
* CString szSearchName )
2007-03-27 17:47:10 +00:00
*
* PURPOSE: Too crude to explain, just use it
2007-03-27 17:47:10 +00:00
*
* WARNING: Only works if you use the default PopulateTree()
* Not guaranteed to work on any future or existing
* version of windows. Use with caution. Pretty much
* ok if you're using on local drives
2007-03-27 17:47:10 +00:00
*
****************************************************************************/
bool ShellTree::SearchTree(HTREEITEM treeNode,
CString szSearchName,
FindAttribs attr)
2007-03-27 17:47:10 +00:00
{
TVItemData* lptvid; //Long pointer to TreeView item data
LPSHELLFOLDER lpsf2=NULL;
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
bool bRet=false;
HRESULT hr;
CString szCompare;
szSearchName.MakeUpper();
while(treeNode && bRet==false)
{
lptvid=(TVItemData*)GetItemData(treeNode);
if (lptvid && lptvid->lpsfParent && lptvid->lpi)
{
hr=lptvid->lpsfParent->BindToObject(lptvid->lpi,
0,IID_IShellFolder,(LPVOID *)&lpsf2);
if (SUCCEEDED(hr))
{
ULONG ulAttrs = SFGAO_FILESYSTEM;
lptvid->lpsfParent->GetAttributesOf(1, (const struct _ITEMIDLIST **)&lptvid->lpi, &ulAttrs);
if (ulAttrs & (SFGAO_FILESYSTEM))
{
if(SHGetPathFromIDList(lptvid->lpifq,
szCompare.GetBuffer(MAX_PATH)))
{
CString folder;
SHGetSpecialFolderPath(NULL,
folder.GetBuffer(MAX_PATH),
CSIDL_COMMON_DESKTOPDIRECTORY, FALSE);
if( szCompare.Find( folder ) != -1 )
if( szSearchName.Find( szCompare ) == -1 ) {
LOGI("Magic match on '%s'", szCompare);
return false;
}
SHGetSpecialFolderPath(NULL,
folder.GetBuffer(MAX_PATH),
CSIDL_DESKTOPDIRECTORY, FALSE );
if( szCompare.Find( folder ) != -1 )
if( szSearchName.Find( szCompare ) == -1 ) {
LOGI("MAGIC '%s'='%s' and '%s'='%s'",
szCompare, folder, szSearchName, szCompare);
return false;
}
SHGetSpecialFolderPath(NULL,
folder.GetBuffer(MAX_PATH),
CSIDL_PERSONAL, FALSE );
if( szCompare.Find( folder ) != -1 )
if( szSearchName.Find( szCompare ) == -1 ) {
LOGI("Magic match on '%s'", szCompare);
return false;
}
switch(attr) {
case type_drive:
_splitpath(szCompare,drive,dir,fname,ext);
szCompare = drive;
break;
case type_folder:
szCompare = GetItemText(treeNode);
break;
}
szCompare.MakeUpper();
if(szCompare == szSearchName)
{
EnsureVisible(treeNode);
SelectItem(treeNode);
bRet=true;
}
}
}
lpsf2->Release();
}
}
treeNode = GetNextSiblingItem(treeNode);
}
return bRet;
2007-03-27 17:47:10 +00:00
}
/****************************************************************************
*
* FUNCTION: TunnelTree(CString szFindPath)
2007-03-27 17:47:10 +00:00
*
* PURPOSE: Too crude to explain, just use it
2007-03-27 17:47:10 +00:00
*
* WARNING: Only works if you use the default PopulateTree()
* Not guaranteed to work on any future or existing
* version of windows. Use with caution. Pretty much
* ok if you're using on local drives
2007-03-27 17:47:10 +00:00
*
****************************************************************************/
void ShellTree::TunnelTree(CString szFindPath)
{
HTREEITEM subNode = GetRootItem();
CString szPathHop;
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
char delimiter[]="\\";
PathName checkPath(szFindPath);
if(!checkPath.Exists()) {
MessageBox(szFindPath,"Folder not found",MB_ICONERROR);
return;
}
if(szFindPath.ReverseFind('\\') != szFindPath.GetLength()-1) {
szFindPath += "\\";
}
_splitpath(szFindPath, drive, dir, fname, ext);
HTREEITEM root = subNode;
//search the drive first
szPathHop=drive;
do {
CString currItem = GetItemText( root );
LOGI("Scanning '%s' for drive '%s'", currItem, szPathHop);
if (ItemHasChildren(root))
{
Expand(root, TVE_EXPAND);
subNode = GetChildItem(root);
if(subNode)
{
if(SearchTree(subNode, szPathHop, ShellTree::type_drive))
{
// we have a match on the drive; SearchTree will have
// left it as the selected item
LOGI("Tunnel match '%s' in subnode", szPathHop);
// break down subfolders and search
char* p = strtok(dir, delimiter);
while (p) {
subNode = GetSelectedItem();
subNode = GetChildItem(subNode);
if(SearchTree(subNode, p, ShellTree::type_folder))
p=strtok(NULL,delimiter);
else
p=NULL;
}
return;
}
}
Expand(root, TVE_COLLAPSE);
}
root = GetNextSiblingItem( root );
} while( root );
2007-03-27 17:47:10 +00:00
}
#endif
#if 0 // quick test
2014-11-18 05:13:13 +00:00
LPMALLOC g_pMalloc = NULL;
2007-03-27 17:47:10 +00:00
// Main_OnBrowse - browses for a program folder.
// hwnd - handle to the application's main window.
//
// Uses the global variable g_pMalloc, which is assumed to point
// to the shell's IMalloc interface.
void Main_OnBrowse(HWND hwnd)
{
BROWSEINFO bi;
LPSTR lpBuffer;
LPITEMIDLIST pidlPrograms; // PIDL for Programs folder
LPITEMIDLIST pidlBrowse; // PIDL selected by user
2014-11-18 05:13:13 +00:00
if (g_pMalloc == NULL)
::SHGetMalloc(&g_pMalloc);
2007-03-27 17:47:10 +00:00
// Allocate a buffer to receive browse information.
if ((lpBuffer = (LPSTR) g_pMalloc->Alloc(
MAX_PATH)) == NULL)
return;
// Get the PIDL for the Programs folder.
if (!SUCCEEDED(SHGetSpecialFolderLocation(
hwnd, CSIDL_PROGRAMS, &pidlPrograms))) {
g_pMalloc->Free(lpBuffer);
return;
}
// Fill in the BROWSEINFO structure.
bi.hwndOwner = hwnd;
bi.pidlRoot = pidlPrograms;
bi.pszDisplayName = lpBuffer;
bi.lpszTitle = "Choose a Program Group";
bi.ulFlags = 0;
bi.lpfn = NULL;
bi.lParam = 0;
// Browse for a folder and return its PIDL.
pidlBrowse = SHBrowseForFolder(&bi);
if (pidlBrowse != NULL) {
// Show the display name, title, and file system path.
MessageBox(hwnd, lpBuffer, "Display name", MB_OK);
if (SHGetPathFromIDList(pidlBrowse, lpBuffer))
SetWindowText(hwnd, lpBuffer);
// Free the PIDL returned by SHBrowseForFolder.
g_pMalloc->Free(pidlBrowse);
}
// Clean up.
g_pMalloc->Free(pidlPrograms);
g_pMalloc->Free(lpBuffer);
}
#endif