//###########################################################################
// Code for the Browse For Starting Folder
//###########################################################################
// Structure to pass information to browse for folder dialog
typedef struct _bfsf
{
    HWND        hwndOwner;
    LPCITEMIDLIST pidlRoot;      // Root of search.  Typically desktop or my net
    LPSTR        pszDisplayName;// Return display name of item selected.
    int          *piImage;      // where to return the Image index.
    LPCSTR      lpszTitle;      // resource (or text to go in the banner over the tree.
    UINT         ulFlags;       // Flags that control the return stuff
    BFFCALLBACK  lpfn;
    LPARAM      lParam;
    HWND         hwndDlg;       // The window handle to the dialog
    HWND         hwndTree;      // The tree control.
    HTREEITEM    htiCurParent;  // tree item associated with Current shell folder
    IShellFolder * psfParent;    // Cache of the last IShell folder I needed...
    LPITEMIDLIST pidlCurrent;   // IDlist of current folder to select
    BOOL         fShowAllObjects; // Should we Show all ?
} BFSF, *PBFSF;


BOOL CALLBACK _BFSFDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
LPITEMIDLIST _BFSFUpdateISHCache(PBFSF pbfsf, HTREEITEM hti, LPITEMIDLIST pidlItem);


// _BrowseForStartingFolder - Browse for a folder to start the
//         search from.



// BUGBUG, give them a way to turn off the ok button.

LPITEMIDLIST WINAPI SHBrowseForFolder(LPBROWSEINFO lpbi)
{
    LPITEMIDLIST lpRet;
    BFSF bfsf =
        {
          lpbi->hwndOwner,
          lpbi->pidlRoot,
          lpbi->pszDisplayName,
          &lpbi->iImage,
          lpbi->lpszTitle,
          lpbi->ulFlags,
          lpbi->lpfn,
          lpbi->lParam,
        };
    HCURSOR hcOld = SetCursor(LoadCursor(NULL,IDC_WAIT));
    SHELLSTATE ss;

    SHGetSetSettings(&ss, SSF_SHOWALLOBJECTS, FALSE);
    bfsf.fShowAllObjects = ss.fShowAllObjects;

    // Now Create the dialog that will be doing the browsing.
    if (DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_BROWSEFORFOLDER),
                       lpbi->hwndOwner, _BFSFDlgProc, (LPARAM)&bfsf))
        lpRet = bfsf.pidlCurrent;
    else
        lpRet = NULL;

    if (hcOld)
        SetCursor(hcOld);

    return lpRet;
}

void BFSFCallback(PBFSF pbfsf, UINT uMsg, LPARAM lParam)
{
    if (pbfsf->lpfn) {
        pbfsf->lpfn(pbfsf->hwndDlg, uMsg, lParam, pbfsf->lParam);
    }
}


// Some helper functions for processing the dialog

HTREEITEM _AddItemToTree(HWND hwndTree, HTREEITEM htiParent, LPITEMIDLIST pidl, int cChildren)
{
    TV_INSERTSTRUCT tii;

    // Initialize item to add with callback for everything
    tii.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE |
            TVIF_PARAM | TVIF_CHILDREN;
    tii.hParent = htiParent;
    tii.hInsertAfter = TVI_FIRST;
    tii.item.iImage = I_IMAGECALLBACK;
    tii.item.iSelectedImage = I_IMAGECALLBACK;
    tii.item.pszText = LPSTR_TEXTCALLBACK;   //
    tii.item.cChildren = cChildren; //  Assume it has children
    tii.item.lParam = (LPARAM)pidl;

    return TreeView_InsertItem(hwndTree, &tii);
}


LPITEMIDLIST _GetIDListFromTreeItem(HWND hwndTree, HTREEITEM hti)
{
    LPITEMIDLIST pidl;
    LPITEMIDLIST pidlT;
    TV_ITEM tvi;

    // If no hti passed in, get the selected on.
    if (hti == NULL)
    {
        hti = TreeView_GetSelection(hwndTree);
        if (hti == NULL)
            return(NULL);
    }

    // now lets get the information about the item
    tvi.mask = TVIF_PARAM | TVIF_HANDLE;
    tvi.hItem = hti;
    if (!TreeView_GetItem(hwndTree, &tvi))
        return NULL;   // Failed again

    pidl = ILClone((LPITEMIDLIST)tvi.lParam);

    // Now walk up parents.
    while ((tvi.hItem = TreeView_GetParent(hwndTree, tvi.hItem)) && pidl)
    {
        if (!TreeView_GetItem(hwndTree, &tvi))
            return(pidl);   // will assume I messed up...
        pidlT = ILCombine((LPITEMIDLIST)tvi.lParam, pidl);

        ILFree(pidl);

        pidl = pidlT;

    }
    return(pidl);
}


int CALLBACK _BFSFTreeCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    IShellFolder *psfParent = (IShellFolder *)lParamSort;
    HRESULT hres = psfParent->lpVtbl->CompareIDs(psfParent, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2);

    Assert(SUCCEEDED(hres));

    return (short)SCODE_CODE(GetScode(hres));
}

void _BFSFSort(PBFSF pbfsf, HTREEITEM hti, IShellFolder * psf)
{
    TV_SORTCB sSortCB;

    sSortCB.hParent = hti;
    sSortCB.lpfnCompare = _BFSFTreeCompare;

    psf->lpVtbl->AddRef(psf);
    sSortCB.lParam = (LPARAM)psf;
    TreeView_SortChildrenCB(pbfsf->hwndTree, &sSortCB, FALSE);
    psf->lpVtbl->Release(psf);
}


BOOL _BFSFHandleItemExpanding(PBFSF pbfsf, LPNM_TREEVIEW pnmtv)
{
    LPITEMIDLIST pidlToExpand;
    LPITEMIDLIST pidl;
    IShellFolder * psf;
    IShellFolder * psfDesktop = Desktop_GetShellFolder(TRUE);
    BYTE bType;
    DWORD grfFlags;
    BOOL fPrinterTest = FALSE;
    int cAdded = 0;
    TV_ITEM tvi;

    IEnumIDList *   penum;              // Enumerator in use.

    if (pnmtv->action != TVE_EXPAND)
        return FALSE;

    if ((pnmtv->itemNew.state & TVIS_EXPANDEDONCE))
        return FALSE;

    // set this bit now because we might be reentered via the wnet apis
    tvi.mask = TVIF_STATE;
    tvi.hItem = pnmtv->itemNew.hItem;
    tvi.state = TVIS_EXPANDEDONCE;
    tvi.stateMask = TVIS_EXPANDEDONCE;
    TreeView_SetItem(pbfsf->hwndTree, &tvi);


    if (pnmtv->itemNew.hItem == NULL)
    {
        pnmtv->itemNew.hItem = TreeView_GetSelection(pbfsf->hwndTree);
        if (pnmtv->itemNew.hItem == NULL)
            return FALSE;
    }

    pidlToExpand = _GetIDListFromTreeItem(pbfsf->hwndTree, pnmtv->itemNew.hItem);

    if (pidlToExpand == NULL)
        return FALSE;

    // Now lets get the IShellFolder and iterator for this object
    // special case to handle if the Pidl is the desktop
    // This is rather gross, but the desktop appears to be simply a pidl
    // of length 0 and ILIsEqual will not work...
    if (pidlToExpand->mkid.cb == 0)
    {
        psf = psfDesktop;
        psfDesktop->lpVtbl->AddRef(psf);
    }
    else
    {
        if (FAILED(psfDesktop->lpVtbl->BindToObject(psfDesktop,
                pidlToExpand, NULL, &IID_IShellFolder, &psf)))
        {
            ILFree(pidlToExpand);
            return FALSE; // Could not get IShellFolder.
        }
    }

    // Need to do a couple of special cases here to allow us to
    // browse for a network printer.  In this case if we are at server
    // level we then need to change what we search for non folders when
    // we are the level of a server.
    if (pbfsf->ulFlags & BIF_BROWSEFORPRINTER)
    {
        grfFlags = SHCONTF_FOLDERS | SHCONTF_NETPRINTERSRCH;
        pidl = ILFindLastID(pidlToExpand);
        bType = SIL_GetType(pidl);
        fPrinterTest = ((bType & (SHID_NET|SHID_INGROUPMASK))==SHID_NET_SERVER);
        if (fPrinterTest)
            grfFlags |= SHCONTF_NONFOLDERS;
    }
    else
        grfFlags = SHCONTF_FOLDERS;

    if (pbfsf->fShowAllObjects)
        grfFlags |= SHCONTF_INCLUDEHIDDEN;



    if (FAILED(psf->lpVtbl->EnumObjects(psf, pbfsf->hwndDlg, grfFlags, &penum)))
    {
        psf->lpVtbl->Release(psf);
        ILFree(pidlToExpand);
        return FALSE;
    }
    // psf->lpVtbl->AddRef(psf);

    while (pidl = _NextIDL(psf, penum))
    {
        int cChildren = I_CHILDRENCALLBACK;  // Do call back for children
        //
        // We need to special case here in the netcase where we onlyu
        // browse down to workgroups...
        //
        //
        // Here is where I also need to special case to not go below
        // workgroups when the appropriate option is set.
        //
        bType = SIL_GetType(pidl);
        if ((pbfsf->ulFlags & BIF_DONTGOBELOWDOMAIN) && (bType & SHID_NET))
        {
            switch (bType & (SHID_NET | SHID_INGROUPMASK))
            {
            case SHID_NET_SERVER:
                ILFree(pidl);       // Dont want to add this one
                continue;           // Try the next one
            case SHID_NET_DOMAIN:
                cChildren = 0;      // Force to not have children;
            }
        }

        else if ((pbfsf->ulFlags & BIF_BROWSEFORCOMPUTER) && (bType & SHID_NET))
        {
            if ((bType & (SHID_NET | SHID_INGROUPMASK)) == SHID_NET_SERVER)
                cChildren = 0;  // Don't expand below it...
        }
        else if (fPrinterTest)
        {
            // Special case when we are only allowing printers.
            // for now I will simply key on the fact that it is non-FS.
            ULONG ulAttr = SFGAO_FILESYSTEM;

            psf->lpVtbl->GetAttributesOf(psf, 1, &pidl, &ulAttr);

            if ((ulAttr & SFGAO_FILESYSTEM)== 0)
            {
                cChildren = 0;      // Force to not have children;
            }
            else
            {
                ILFree(pidl);       // Dont want to add this one
                continue;           // Try the next one
            }
        }

        _AddItemToTree(pbfsf->hwndTree, pnmtv->itemNew.hItem,
                pidl, cChildren);
        cAdded++;
    }

    // Now Cleanup after ourself
    penum->lpVtbl->Release(penum);

    _BFSFSort(pbfsf, pnmtv->itemNew.hItem, psf);
    psf->lpVtbl->Release(psf);
    ILFree(pidlToExpand);

    // If we did not add anything we should update this item to let
    // the user know something happened.
    //
    if (cAdded == 0)
    {
        TV_ITEM tvi;
        tvi.mask = TVIF_CHILDREN | TVIF_HANDLE;   // only change the number of children
        tvi.hItem = pnmtv->itemNew.hItem;
        tvi.cChildren = 0;

        TreeView_SetItem(pbfsf->hwndTree, &tvi);

    }

    return TRUE;
}



void _BFSFHandleDeleteItem(PBFSF pbfsf, LPNM_TREEVIEW pnmtv)
{
    // We need to free the IDLists that we allocated previously
    if (pnmtv->itemOld.lParam != 0)
        ILFree((LPITEMIDLIST)pnmtv->itemOld.lParam);
}


LPITEMIDLIST _BFSFUpdateISHCache(PBFSF pbfsf, HTREEITEM hti,
        LPITEMIDLIST pidlItem)
{
    HTREEITEM htiParent;
    IShellFolder * psfDesktop = Desktop_GetShellFolder(TRUE);

    if (pidlItem == NULL)
        return(NULL);

    // Need to handle the root case here!
    htiParent = TreeView_GetParent(pbfsf->hwndTree, hti);
    if ((htiParent != pbfsf->htiCurParent) || (pbfsf->psfParent == NULL))
    {
        LPITEMIDLIST pidl;

        if (pbfsf->psfParent)
        {

            if (pbfsf->psfParent != psfDesktop)
                pbfsf->psfParent->lpVtbl->Release(pbfsf->psfParent);
            pbfsf->psfParent = NULL;
        }

        if (htiParent)
        {
            pidl = _GetIDListFromTreeItem(pbfsf->hwndTree, htiParent);
        }
        else
        {
            //
            // If No Parent then the item here is one of our roots which
            // should be fully qualified.  So try to get the parent by
            // decomposing the ID.
            //
            LPITEMIDLIST pidlT = (LPITEMIDLIST)ILFindLastID(pidlItem);
            if (pidlT != pidlItem)
            {
                pidl = ILClone(pidlItem);
                ILRemoveLastID(pidl);
                pidlItem = pidlT;
            }
            else
                pidl = NULL;
        }

        pbfsf->htiCurParent = htiParent;

        // If still NULL then we use root of evil...
        if (pidl == NULL || (pidl->mkid.cb == 0))
        {
            // Still one m
            pbfsf->psfParent = psfDesktop;

            if (pidl)
                ILFree(pidl);
        }

        else
        {
            psfDesktop->lpVtbl->BindToObject(psfDesktop,
                     pidl, NULL, &IID_IShellFolder, &pbfsf->psfParent);
            ILFree(pidl);

            if (pbfsf->psfParent == NULL)
                return NULL;
        }
    }
    return(ILFindLastID(pidlItem));
}



void _BFSFGetDisplayInfo(PBFSF pbfsf, TV_DISPINFO *pnm)
{
    TV_ITEM ti;
    LPITEMIDLIST pidlItem = (LPITEMIDLIST)pnm->item.lParam;

    if ((pnm->item.mask & (TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_CHILDREN)) == 0)
        return; // nothing for us to do here.

    pidlItem = _BFSFUpdateISHCache(pbfsf, pnm->item.hItem, pidlItem);

    ti.mask = 0;
    ti.hItem = (HTREEITEM)pnm->item.hItem;

    // They are asking for IconIndex.  See if we can find it now.
    // Once found update their list, such that they wont call us back for
    // it again.
    if (pnm->item.mask & (TVIF_IMAGE | TVIF_SELECTEDIMAGE))
    {
        // We now need to map the item into the right image index.
        ti.iImage = pnm->item.iImage = SHMapPIDLToSystemImageListIndex(
                pbfsf->psfParent, pidlItem, &ti.iSelectedImage);
        // we should save it back away to
        pnm->item.iSelectedImage = ti.iSelectedImage;
        ti.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
    }
    // Also see if this guy has any child folders
    if (pnm->item.mask & TVIF_CHILDREN)
    {
        ULONG ulAttrs;

        ulAttrs = SFGAO_HASSUBFOLDER;
        pbfsf->psfParent->lpVtbl->GetAttributesOf(pbfsf->psfParent,
                1, &pidlItem, &ulAttrs);

        ti.cChildren = pnm->item.cChildren =
                (ulAttrs & SFGAO_HASSUBFOLDER)? 1 : 0;

        ti.mask |= TVIF_CHILDREN;

    }

    if (pnm->item.mask & TVIF_TEXT)
    {
        STRRET str;
        pbfsf->psfParent->lpVtbl->GetDisplayNameOf(pbfsf->psfParent,
                pidlItem, SHGDN_INFOLDER, &str);

        StrRetToStrN(pnm->item.pszText, pnm->item.cchTextMax, &str, pidlItem);
        ti.mask |= TVIF_TEXT;
        ti.pszText = pnm->item.pszText;
    }

    // Update the item now
    TreeView_SetItem(pbfsf->hwndTree, &ti);
}


void _BFSFHandleSelChanged(PBFSF pbfsf, LPNM_TREEVIEW pnmtv)
{
    LPITEMIDLIST pidl;
    ULONG ulAttrs = SFGAO_FILESYSTEM;
    BYTE bType;

    // We only need to do anything if we only want to return File system
    // level objects.
    if ((pbfsf->ulFlags & (BIF_RETURNONLYFSDIRS|BIF_RETURNFSANCESTORS|BIF_BROWSEFORPRINTER|BIF_BROWSEFORCOMPUTER)) == 0)
        goto NotifySelChange;

    // We need to get the attributes of this object...
    pidl = _BFSFUpdateISHCache(pbfsf, pnmtv->itemNew.hItem,
            (LPITEMIDLIST)pnmtv->itemNew.lParam);

    if (pidl)
    {
        BOOL fEnable;

        bType = SIL_GetType(pidl);
        if ((pbfsf->ulFlags & (BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS)) != 0)
        {
            int i;
            // if this is the root pidl, then do a get attribs on 0
            // so that we'll get the attributes on the root, rather than
            // random returned values returned by FSFolder
            if (ILIsEmpty(pidl)) {
                i = 0;
            } else
                i = 1;

            pbfsf->psfParent->lpVtbl->GetAttributesOf(pbfsf->psfParent,
                                                      i, &pidl, &ulAttrs);

            fEnable = (((ulAttrs & SFGAO_FILESYSTEM) && (pbfsf->ulFlags & BIF_RETURNONLYFSDIRS)) ||
                ((ulAttrs & SFGAO_FILESYSANCESTOR) && (pbfsf->ulFlags & BIF_RETURNFSANCESTORS))) ||
                    ((bType & (SHID_NET | SHID_INGROUPMASK)) == SHID_NET_SERVER);
        }
        else if ((pbfsf->ulFlags & BIF_BROWSEFORCOMPUTER) != 0)
            fEnable = ((bType & (SHID_NET | SHID_INGROUPMASK)) == SHID_NET_SERVER);
        else if ((pbfsf->ulFlags & BIF_BROWSEFORPRINTER) != 0)
        {
            // Printers are of type Share and usage Print...
            fEnable = ((bType & (SHID_NET | SHID_INGROUPMASK)) == SHID_NET_SHARE);
        }

        EnableWindow(GetDlgItem(pbfsf->hwndDlg, IDOK),fEnable);

    }

NotifySelChange:
    if (pbfsf->lpfn) {
        pidl = _GetIDListFromTreeItem(pbfsf->hwndTree, pnmtv->itemNew.hItem);
        BFSFCallback(pbfsf, BFFM_SELCHANGED, (LPARAM)pidl);
        ILFree(pidl);
    }
}

BOOL BrowseSelectPidl(PBFSF pbfsf, LPCITEMIDLIST pidl)
{
    HTREEITEM htiParent;
    LPITEMIDLIST pidlTemp;
    LPITEMIDLIST pidlNext = NULL;
    LPITEMIDLIST pidlParent = NULL;
    BOOL fRet = FALSE;

    htiParent = TreeView_GetChild(pbfsf->hwndTree, NULL);
    if (htiParent) {

        // step through each item of the pidl
        for (;;) {
            TreeView_Expand(pbfsf->hwndTree, htiParent, TVE_EXPAND);
            pidlParent = _GetIDListFromTreeItem(pbfsf->hwndTree, htiParent);
            if (!pidlParent)
                break;

            pidlNext = ILClone(pidl);
            if (!pidlNext)
                break;

            pidlTemp = ILFindChild(pidlParent, pidlNext);
            if (!pidlTemp)
                break;

            if (ILIsEmpty(pidlTemp)) {
                // found it!
                //
                TreeView_SelectItem(pbfsf->hwndTree, htiParent);
                fRet = TRUE;
                break;
            } else {
                // loop to find the next item
                HTREEITEM htiChild;

                pidlTemp = ILGetNext(pidlTemp);
                if (!pidlTemp)
                    break;
                else
                    pidlTemp->mkid.cb = 0;


                htiChild = TreeView_GetChild(pbfsf->hwndTree, htiParent);
                while (htiChild) {
                    BOOL fEqual;
                    pidlTemp = _GetIDListFromTreeItem(pbfsf->hwndTree, htiChild);
                    if (!pidlTemp) {
                        htiChild = NULL;
                        break;
                    }
                    fEqual = ILIsEqual(pidlTemp, pidlNext);

                    ILFree(pidlTemp);
                    if (fEqual) {
                        break;
                    } else {
                        htiChild = TreeView_GetNextSibling(pbfsf->hwndTree, htiChild);
                    }
                }

                if (!htiChild) {
                    // we didn't find the next one... bail
                    break;
                } else {
                    // the found child becomes the next parent
                    htiParent = htiChild;
                    ILFree(pidlParent);
                    ILFree(pidlNext);
                }
            }

        }
    }

    if (pidlParent) ILFree(pidlParent);
    if (pidlNext) ILFree(pidlNext);
    return fRet;
}


// _BFSFOnInitDlg - Process the init dialog

BOOL _BFSFOnInitDlg(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
    HTREEITEM hti;
    PBFSF pbfsf = (PBFSF)lParam;
    HIMAGELIST himl;
    LPSTR lpsz;
    char szTitle[80];    // no title should be bigger than this!
    HWND hwndTree;

    lpsz = ResourceCStrToStr(HINST_THISDLL, pbfsf->lpszTitle);
    SetDlgItemText(hwnd, IDD_BROWSETITLE, lpsz);
    if (lpsz != pbfsf->lpszTitle)
    {
        LocalFree(lpsz);
        lpsz = NULL;
    }


    SetWindowLong(hwnd, DWL_USER, (LONG)lParam);
    pbfsf->hwndDlg = hwnd;
    hwndTree = pbfsf->hwndTree = GetDlgItem(hwnd, IDD_FOLDERLIST);

    if (hwndTree)
    {
        UINT swpFlags = SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER
                | SWP_NOACTIVATE;
        RECT rc;
        POINT pt = {0,0};

        if (!(pbfsf->ulFlags & BIF_STATUSTEXT)) {
            HWND hwndStatus = GetDlgItem(hwnd, IDD_BROWSESTATUS);
            // nuke the status window
            ShowWindow(hwndStatus, SW_HIDE);
            MapWindowPoints(hwndStatus, hwnd, &pt, 1);
            GetClientRect(hwndTree, &rc);
            MapWindowPoints(hwndTree, hwnd, (POINT*)&rc, 2);
            rc.top = pt.y;
            swpFlags =  SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
        }

        Shell_GetImageLists(NULL, &himl);
	TreeView_SetImageList(hwndTree, himl, TVSIL_NORMAL);

        SetWindowLong(hwndTree, GWL_EXSTYLE,
                GetWindowLong(hwndTree, GWL_EXSTYLE) | WS_EX_CLIENTEDGE);

        // Now try to get this window to know to recalc
        SetWindowPos(hwndTree, NULL, rc.left, rc.top,
                     rc.right - rc.left, rc.bottom - rc.top, swpFlags);

    }

    // If they passed in a root, add it, else add the contents of the
    // Root of evil... to the list as ROOT objects.
    if (pbfsf->pidlRoot)
    {
        LPITEMIDLIST pidl;
        if (!HIWORD(pbfsf->pidlRoot)) {
            pidl = SHCloneSpecialIDList(NULL, (UINT)pbfsf->pidlRoot, TRUE);
        } else {
            pidl = ILClone(pbfsf->pidlRoot);
        }
        // Now lets insert the Root object
	hti = _AddItemToTree(hwndTree, TVI_ROOT, pidl, 1);
	// Still need to expand below this point. to the starting location
	// That was passed in. But for now expand the first level.
	TreeView_Expand(hwndTree, hti, TVE_EXPAND);
    }
    else
    {
        LPCITEMIDLIST pidlDrives = GetSpecialFolderIDList(NULL, CSIDL_DRIVES, FALSE);
	LPITEMIDLIST pidlDesktop = SHCloneSpecialIDList(NULL, CSIDL_DESKTOP, FALSE);
	HTREEITEM htiRoot = _AddItemToTree(hwndTree, TVI_ROOT, pidlDesktop, 1);

        // Expand the first level under the desktop
        TreeView_Expand(hwndTree, htiRoot, TVE_EXPAND);

        // Lets Preexpand the Drives portion....
        hti = TreeView_GetChild(hwndTree, htiRoot);
        while (hti)
        {
            LPITEMIDLIST pidl = _GetIDListFromTreeItem(hwndTree, hti);
            if (ILIsEqual(pidl, pidlDrives))
            {

                TreeView_Expand(hwndTree, hti, TVE_EXPAND);

                TreeView_SelectItem(hwndTree, hti);
                ILFree(pidl);
                break;
            }
            ILFree(pidl);
            hti = TreeView_GetNextSibling(hwndTree, hti);
        }
    }

    // go to our internal selection changed code to do any window enabling needed
    {
        NM_TREEVIEW nmtv;
        hti = TreeView_GetSelection(hwndTree);
        if (hti) {
            TV_ITEM ti;
            ti.mask = TVIF_PARAM;
            ti.hItem = hti;
            TreeView_GetItem(hwndTree, &ti);
            nmtv.itemNew.hItem = hti;
            nmtv.itemNew.lParam = ti.lParam;

            _BFSFHandleSelChanged(pbfsf, &nmtv);
        }
    }

    if ((pbfsf->ulFlags & BIF_BROWSEFORCOMPUTER) != 0)
    {
        LoadString(HINST_THISDLL, IDS_FINDSEARCH_COMPUTER, szTitle, sizeof(szTitle));
        SetWindowText(hwnd, szTitle);
    }
    else if ((pbfsf->ulFlags & BIF_BROWSEFORPRINTER) != 0)
    {
        LoadString(HINST_THISDLL, IDS_FINDSEARCH_PRINTER, szTitle, sizeof(szTitle));
        SetWindowText(hwnd, szTitle);
    }

    BFSFCallback(pbfsf, BFFM_INITIALIZED, 0);

    return TRUE;
}

void _BFSFSetStatusText(PBFSF pbfsf, LPCSTR lpszText)
{
    char szText[100];
    if (!HIWORD(lpszText)) {
        LoadString(HINST_THISDLL, LOWORD(lpszText), szText, sizeof(szText));
        lpszText = szText;
    }
    SetDlgItemText(pbfsf->hwndDlg, IDD_BROWSESTATUS, lpszText);
}



// _BFSFOnCommand - Process the WM_COMMAND message

void _BFSFOnCommand(PBFSF pbfsf, int id, HWND hwndCtl, UINT codeNotify)
{
    HTREEITEM hti;
    switch (id)
    {
    case IDOK:
        // We can now update the structure with the idlist of the item selected
        hti = TreeView_GetSelection(pbfsf->hwndTree);
        pbfsf->pidlCurrent = _GetIDListFromTreeItem(pbfsf->hwndTree,
                hti);
        if (pbfsf->pszDisplayName || pbfsf->piImage)
        {
            TV_ITEM tvi;
            tvi.mask = (pbfsf->pszDisplayName)? (TVIF_TEXT | TVIF_IMAGE) :
                    TVIF_IMAGE;
            tvi.hItem = hti;
            tvi.pszText = pbfsf->pszDisplayName;
            tvi.cchTextMax = MAX_PATH;
            TreeView_GetItem(pbfsf->hwndTree, &tvi);

            if (pbfsf->piImage)
                *pbfsf->piImage = tvi.iImage;
        }
        EndDialog(pbfsf->hwndDlg, 1);     // To return TRUE.
        break;
    case IDCANCEL:
        EndDialog(pbfsf->hwndDlg, 0);     // to return FALSE from this.
        break;
    }
}




// _BSFSDlgProc - The dialog procedure for processing the browse
//          for starting folder dialog.

#pragma data_seg(".text", "CODE")
const static DWORD aBrowseHelpIDs[] = {  // Context Help IDs
    IDD_BROWSETITLE,  NO_HELP,
    IDD_BROWSESTATUS, NO_HELP,
    IDD_FOLDERLIST,   IDH_BROWSELIST,

    0, 0
};
#pragma data_seg()

BOOL CALLBACK _BFSFDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
    PBFSF pbfsf = (PBFSF)GetWindowLong(hwndDlg, DWL_USER);

    switch (msg) {
    HANDLE_MSG(pbfsf, WM_COMMAND, _BFSFOnCommand);
    HANDLE_MSG(hwndDlg, WM_INITDIALOG, _BFSFOnInitDlg);

    case WM_DESTROY:
        if (pbfsf->psfParent && (pbfsf->psfParent != Desktop_GetShellFolder(TRUE)))
        {
            pbfsf->psfParent->lpVtbl->Release(pbfsf->psfParent);
            pbfsf->psfParent = NULL;
        }
        break;

    case BFFM_SETSTATUSTEXT:
        _BFSFSetStatusText(pbfsf, (LPCSTR)lParam);
        break;

    case BFFM_SETSELECTION:
    {
        BOOL fRet;

        // wParam TRUE means path, not pidl
        if (wParam) {
            lParam = (LPARAM)SHSimpleIDListFromPath((LPSTR)lParam);
            if (!lParam)
                return FALSE;
        }
        fRet = BrowseSelectPidl(pbfsf, (LPITEMIDLIST)lParam);

        if (wParam)
            ILFree((LPITEMIDLIST)lParam);
        return fRet;
    }

    case BFFM_ENABLEOK:
        EnableWindow(GetDlgItem(hwndDlg, IDOK), lParam);
        break;


    case WM_NOTIFY:
        switch (((NMHDR *)lParam)->code)
        {
        case TVN_GETDISPINFO:
            _BFSFGetDisplayInfo(pbfsf, (TV_DISPINFO *)lParam);
            break;

        case TVN_ITEMEXPANDING:
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            _BFSFHandleItemExpanding(pbfsf, (LPNM_TREEVIEW)lParam);
            break;

        case TVN_ITEMEXPANDED:
            SetCursor(LoadCursor(NULL, IDC_ARROW));
            break;

        case TVN_DELETEITEM:
            _BFSFHandleDeleteItem(pbfsf, (LPNM_TREEVIEW)lParam);
            break;

        case TVN_SELCHANGED:
            _BFSFHandleSelChanged(pbfsf, (LPNM_TREEVIEW)lParam);
            break;
        }
        break;

    case WM_HELP:
        WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, NULL,
            HELP_WM_HELP, (DWORD)(LPSTR) aBrowseHelpIDs);
        break;

    case WM_CONTEXTMENU:
        WinHelp((HWND) wParam, NULL, HELP_CONTEXTMENU,
            (DWORD)(LPVOID) aBrowseHelpIDs);
        break;

    default:
        return FALSE;
    }

    return TRUE;
}