//
// BrowseDir.cpp
//
//              Functionality for the "Browse Directory" dialog.
//              Requires dialog resource IDD_BROWSEDIRECTORY.
//
// History:
//
//              10/04/95        KenSh           Created
//              10/09/95        KenSh           Fixed bugs, removed globals and statics
//

#include "stdafx.h"
#include <dlgs.h>
#include <direct.h>

//*** Custom window messages
//
#define CM_UPDATEEDIT   (WM_USER + 42)  // Update text in the edit (sent to the dialog)

//*** Dialog control IDs
//
#define IDC_FILENAME    edt1                    // Edit box w/ current directory
#define IDC_FILELIST    lst2                    // Listbox with current directory hierarchy
#define IDC_DRIVECOMBO  cmb2                    // Combo-box with current drive
#define IDC_NETWORK             psh14                   // Network button (added at runtime)

//*** Window property names
//
const TCHAR c_szOFNProp[] = _T("OFNStruct");
const TCHAR c_szRedrawProp[] = _T("Redraw");

//*** Globals
//
//              Note: Use of thse globals assumes that any multiple threads using
//              our subclass at the same time always have the same original edit/
//              combo window procs.  I think this is true.
//
WNDPROC                         g_pfnPrevEditProc;      // original edit proc (before subclass)
WNDPROC                         g_pfnPrevComboProc;     // original combo proc (before subclass)

//*** Local function declarations
//
BOOL CALLBACK BrowseDirDlgHook( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam );
BOOL BrowseDir_OnOK( HWND hwnd );

// This struct is used internally and kept as a window property,
// in lieu of using static variables or MFC.
typedef struct _OFNINFO
{
        OPENFILENAME    ofn;                                            // OFN struct passed to GetOpenFileName
        TCHAR                   szLastDirName[_MAX_PATH];       // last known good directory
        BOOL                    fAllowSetText;                          // should we allow WM_SETTEXT for the Edit
//        BOOL                    fNetworking;                            // is Connect Network Drive dialog open
} OFNINFO, *LPOFNINFO;


//----------------------------------------------------------------------------
// Procedure    BrowseForDirectory
//
// Purpose              Displays a dialog that lets the user choose a directory
//                              name, either local or UNC.
//
// Parameters   hwndParent                      Parent window for the dialog
//                              pszInitialDir           Directory to use as the default
//                              pszBuf                          Where to store the answer
//                              cchBuf                          Number of characters in this buffer
//                              pszDialogTitle          Title for the dialog
//
// Returns              nonzero if successful, zero if not.  If successful, pszBuf
//                              will be filled with the full pathname of the chosen directory.
//
// History              10/06/95        KenSh           Created
//                              10/09/95        KenSh           Use lCustData member instead of global
//

CString strSelectDir;

BOOL BrowseForDirectory(
                HWND hwndParent,
                LPCTSTR pszInitialDir,
                LPTSTR pszBuf,
                int cchBuf,
                LPCTSTR pszDialogTitle,
                BOOL bRemoveTrailingBackslash )
{
        TCHAR szInitialDir[MAX_PATH];
        OFNINFO ofnInfo;

        pszBuf[0] = _T('\0');

        // Prepare the initial directory... add a backslash if it's
        // a 2-character path
        _tcscpy( szInitialDir, pszInitialDir );
        if( !szInitialDir[2] )
        {
                szInitialDir[2] = _T('\\');
                szInitialDir[3] = _T('\0');
        }

        if( pszDialogTitle )
        {
                ofnInfo.ofn.lpstrTitle          = pszDialogTitle;
        }
        else
        {
                MyLoadString( IDS_SELECT_DIR, strSelectDir );

                ofnInfo.ofn.lpstrTitle          = (LPCTSTR)strSelectDir;
        }

        ofnInfo.ofn.lStructSize                 = sizeof(OPENFILENAME);
        ofnInfo.ofn.hwndOwner                   = hwndParent;
        ofnInfo.ofn.hInstance                   = (HINSTANCE) g_MyModuleHandle;
        ofnInfo.ofn.lpstrFilter                 = NULL;
        ofnInfo.ofn.lpstrCustomFilter   = NULL;
        ofnInfo.ofn.nMaxCustFilter              = 0;
        ofnInfo.ofn.nFilterIndex                = 0;
        ofnInfo.ofn.lpstrFile                   = pszBuf;
        ofnInfo.ofn.nMaxFile                    = cchBuf;
        ofnInfo.ofn.lpstrFileTitle              = NULL;
        ofnInfo.ofn.nMaxFileTitle               = 0;
        ofnInfo.ofn.lpstrInitialDir     = szInitialDir;
        ofnInfo.ofn.nFileOffset                 = 0;
        ofnInfo.ofn.nFileExtension              = 0;
        ofnInfo.ofn.lpstrDefExt                 = NULL;
        ofnInfo.ofn.lCustData                   = (LPARAM)&ofnInfo;
        ofnInfo.ofn.lpfnHook                    = (LPOFNHOOKPROC)BrowseDirDlgHook;
        ofnInfo.ofn.lpTemplateName              = MAKEINTRESOURCE( IDD_BROWSEDIRECTORY );
        ofnInfo.ofn.Flags                       = OFN_ENABLEHOOK | OFN_PATHMUSTEXIST |
                                                  OFN_NONETWORKBUTTON | OFN_ENABLETEMPLATE |
                                                  OFN_HIDEREADONLY;

        iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("comdlg32:GetOpenFileName().Start.")));
        int nResult = ::GetOpenFileName( &ofnInfo.ofn );
        iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("comdlg32:GetOpenFileName().End.")));

            DWORD dw = 0;
        if (nResult == 0) 
        {
            iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("comdlg32:CommDlgExtendedError().Start.")));
            dw = CommDlgExtendedError();
            iisDebugOut((LOG_TYPE_TRACE_WIN32_API, _T("comdlg32:CommDlgExtendedError().End.")));
        }

        return (BOOL)( IDOK == nResult );
}


//----------------------------------------------------------------------------
// Procedure    pszSkipDriveSpec
//
// Purpose              Returns a pointer to whatever comes after the drive part
//                              of a filename.  For example:
//                  c:\foo\bar.bat         \\server\share\file.txt
//                    ^                                  ^
//
// Returns              Pointer to the appropriate part of the string, or a pointer
//                              to the end of the string if it's not in the right format
//
// History              10/06/95        KenSh           Created
//
LPTSTR pszSkipDriveSpec( LPTSTR pszPathName )
{
        LPTSTR pch = NULL;

        if( pszPathName[0] == _T('\\') && pszPathName[1] == _T('\\') )
        {
                pch = _tcschr(pszPathName+2, _T('\\'));
                if( NULL != pch)
                {
                        LPTSTR pchResult;
                        pchResult = _tcschr( pch, _T('\\') );

                        if( pchResult )
                        {
                                pchResult = _tcschr( pchResult+1, _T('\\') );
                        }

                        if( pchResult )
                        {
                                return pchResult;
                        }
                        else
                        {
                                return _tcschr( pch, _T('\0') );
                        }
                }
                else
                {
                        return _tcschr( pszPathName, _T('\0') );
                }
        }
        else
        {
                pch = _tcschr( pszPathName, _T(':') );

                if( pch )
                {
                        return _tcsinc(pch);
                }
                else
                {
                        return _tcschr( pszPathName, _T('\0') );
                }
        }
}


//----------------------------------------------------------------------------
// Procedure    BrowseDirEditProc
//
// Purpose              Subclassed window proc for the edit control in the Browse
//                              for Directory dialog.  We override the WM_SETTEXT message
//                              to control when the window text can be programatically
//                              changed.
//
// Parameters   standard
//
// Returns              standard
//
// History              10/06/95        KenSh           Created
//                              10/09/95        KenSh           Moved most code into UpdateEditText()
//
LRESULT CALLBACK BrowseDirEditProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
        switch( message )
        {
                // In order to prevent default functionality from setting the Edit's text
                // to strings like "*.*", we capture WM_SETTEXT and only allow it to occur
                // if the fAllowSetText flag is specified in the OFNINFO struct.
                case WM_SETTEXT:
                {
                        LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( GetParent(hwnd), c_szOFNProp );

                        if( lpOFNInfo->fAllowSetText )
                        {
                                break;  // default processing
                        }
                        else
                        {
                                return 0L;      // suppress the urge to change the text
                        }
                }

                default:
                        break;
        }

        return CallWindowProc( g_pfnPrevEditProc, hwnd, message, wParam, lParam );
}


//----------------------------------------------------------------------------
// Procedure    BrowseDirComboProc
//
// Purpose              Subclassed window proc for the combo box in the Browse
//                              Directory dialog.  We need to subclass so we can catch the
//                              change to selection after the Network button is used to
//                              switch drives.
//
// Parameters   standard
//
// Returns              standard
//
// History              10/09/95        KenSh           Created
//
LRESULT CALLBACK BrowseDirComboProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
        switch( message )
        {
                // We catch the WM_SETREDRAW message so that we ignore CB_SETCURSEL
                // messages when the combo is not supposed to be updated.  This is
                // pretty much of a hack due to the ordering of messages after the
                // Network button is clicked.
                case WM_SETREDRAW:
                {
                        if( wParam )
                        {
                                SetProp( hwnd, c_szRedrawProp, (HANDLE)1 );
                        }
                        else
                        {
                                if( GetProp( hwnd, c_szRedrawProp ) )
                                {
                                        RemoveProp( hwnd, c_szRedrawProp );
                                }
                        }
                        break;  // continue with default processing
                }

                // We catch CB_SETCURSEL and use it to update our edit box after the
                // Network button has been pressed.
                case CB_SETCURSEL:
                {
                        LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( GetParent(hwnd), c_szOFNProp );

#ifdef NEVER
                        // If "Network" was pressed and redraw has been re-enabled...
                        if( lpOFNInfo->fNetworking && GetProp( hwnd, c_szRedrawProp ) )
                        {
                                TCHAR szBuf[_MAX_PATH];
                                LRESULT lResult = CallWindowProc( g_pfnPrevComboProc, hwnd, message, wParam, lParam );

                                // Turn off the networking flag
                                lpOFNInfo->fNetworking = FALSE;

                                // Force the selected drive to be the current drive and
                                // get the current directory on that drive
                                GetWindowText( hwnd, szBuf, _MAX_PATH );
                                _chdrive( _totupper(szBuf[0]) - 'A' + 1 );
                                GetCurrentDirectory( _MAX_PATH, szBuf );

                                // Update the edit box with the new text.
                                lpOFNInfo->fAllowSetText = TRUE;
                                SetDlgItemText( GetParent(hwnd), IDC_FILENAME, szBuf );
                                lpOFNInfo->fAllowSetText = FALSE;
                                SendDlgItemMessage( GetParent(hwnd), IDC_FILENAME, EM_SETSEL, 0, (LPARAM)-1 );

                                return lResult;
                        }
#endif
                        break;
                }

                case WM_DESTROY:
                {
                        if( GetProp( hwnd, c_szRedrawProp ) )
                        {
                                RemoveProp( hwnd, c_szRedrawProp );
                        }
                        break;          // continue with default processing
                }

                default:
                        break;
        }

        return CallWindowProc( g_pfnPrevComboProc, hwnd, message, wParam, lParam );
}


//----------------------------------------------------------------------------
// Procedure    UpdateEditText
//
// Purpose              Based on which control has focus and the current state of
//                              the edit control, calculates the new "current directory" and
//                              sets the Edit control's text to match.
//
// Parameters   hwndDlg         handle to the dialog window.  This function will
//                                                      access the lpOFNInfo window property.
//
// Returns              nothing
//
// History              10/09/95        KenSh           Created
//
VOID UpdateEditText( HWND hwndDlg )
{
        HWND hwndLB = GetDlgItem(hwndDlg, IDC_FILELIST);
        int nCurSel = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
        TCHAR szDirName[_MAX_PATH];
        LPTSTR pchStart = NULL;
        LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( hwndDlg, c_szOFNProp );
        int i;

        HWND hwndFocus = GetFocus();
        int idFocus = GetDlgCtrlID( hwndFocus );

        if( idFocus == IDC_FILELIST )
                // Listbox: build name up through current LB selection
        {
                // First get the top entry in the listbox, this will tell us
                // if it's a connected drive or a UNC drive
                SendMessage( hwndLB, LB_GETTEXT, 0, (LPARAM)szDirName );

                // Run down the entries in the listbox appending them
                // and stop when we get to the current selection.
                if( szDirName[0] == _T('\\') && szDirName[1] == _T('\\') )
                        pchStart = _tcschr(szDirName+2, _T('\0'));
                else
                        pchStart = _tcsinc(szDirName) + 1;      // skip 2 chars, first may be MBCS

                if (NULL != pchStart)
                {
                    for( i = 1; i <= nCurSel; i++ )
                    {
                            if( *pchStart != _T('\\') )
                                    *pchStart = _T('\\');
                            pchStart = _tcsinc(pchStart);
                            SendMessage( hwndLB, LB_GETTEXT, i, (LPARAM)pchStart );
                            pchStart = _tcschr(pchStart, _T('\0'));
                    }
                }
        }
        else if( idFocus == IDC_DRIVECOMBO )
                // Combo box: use current working directory
        {
                GetCurrentDirectory( _MAX_PATH, szDirName );
        }
        else if( idFocus == IDC_FILENAME )
                // Edit control: build the new path using the edit contents
        {
                TCHAR szBuf[_MAX_PATH];

                GetDlgItemText( hwndDlg, IDC_FILENAME, szBuf, _MAX_PATH );

                if( szBuf[0] == _T('\\') )
                {
                        if( szBuf[1] == _T('\\') )
                                // full UNC path was specified
                        {
                                _tcscpy( szDirName, szBuf );
                        }
                        else
                                // new directory on the current drive
                        {
                                _tcscpy( szDirName, lpOFNInfo->szLastDirName );
                                LPTSTR pch = pszSkipDriveSpec(szDirName);
                                _tcscpy( pch, szBuf );
                        }
                }
                else if( *_tcsinc(szBuf) == _T(':') )
                {
                        // Change to the requested drive and use the current directory
                        // on that drive.
                        if( 0 == _chdrive( _totupper(szBuf[0]) - 'A' + 1 ) &&
                                szBuf[2] != _T('\\') )
                        {
                                // It's a legal drive and no directory was specified,
                                // so use the current default.
                                GetCurrentDirectory( _MAX_PATH, szDirName );
                        }
                        else
                        {
                                // A directory was specified or the drive does not exist.
                                // Copy the text verbatim to test it and possibly display
                                // an error message.
                                _tcscpy( szDirName, szBuf );
                        }
                }
                else
                        // Subdirectory of the current directory
                {
                        // Start with the current directory
                        _tcscpy( szDirName, lpOFNInfo->szLastDirName );

                        // Append a backslash if there isn't already one there
                        LPTSTR pch = _tcsrchr( szDirName, _T('\\') );
                        if (pch)
                        {
                            if( *_tcsinc(pch) )
                            {
                                    pch = _tcschr( pch, _T('\0') );
                                    if (pch)
                                    {
                                        *pch = _T('\\');
                                    }
                            }
                            pch = _tcsinc(pch);

                            // Append the new directory name
                            _tcscpy( pch, szBuf );
                        }

                        // Attempt to change into the new directory
                        if( SetCurrentDirectory(szDirName) )
                        {
                                // The directory exists, get the official name and use that
                                // instead of whatever we're using now
                                GetCurrentDirectory( _MAX_PATH, szDirName );
                        }
                }
        }
        else
        {
                // Some other control, likely an error message is going on
                _tcscpy( szDirName, lpOFNInfo->szLastDirName );
        }

        lpOFNInfo->fAllowSetText = TRUE;
        SetDlgItemText( hwndDlg, IDC_FILENAME, szDirName );
        lpOFNInfo->fAllowSetText = FALSE;
}


//----------------------------------------------------------------------------
// Procedure    BrowseDirDlgHook
//
// Purpose              Dialog proc for the Browse for Directory subclassed common
//                              dialog.  We spend most of our effort trying to get the right
//                              string into the edit control (IDC_FILENAME).
//
// Parameters   standard
//
// Returns              TRUE to halt further processing, FALSE to do the default.
//
// History              10/06/95        KenSh           Created
//
BOOL CALLBACK BrowseDirDlgHook( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
        switch(message)
        {
                case WM_INITDIALOG:
                {
                        LPOFNINFO lpOFNInfo = (LPOFNINFO)((LPOPENFILENAME)lParam)->lCustData;

                        // Store the OFN struct pointer as a window property
                        SetProp( hwnd, c_szOFNProp, (HANDLE)lpOFNInfo );

                        // Initialize the OFNInfo struct
                        _tcscpy( lpOFNInfo->szLastDirName, lpOFNInfo->ofn.lpstrInitialDir );
                        lpOFNInfo->fAllowSetText = FALSE;
                        //lpOFNInfo->fNetworking = FALSE;

                        // Start our edit off with the initial directory
                        SetDlgItemText( hwnd, IDC_FILENAME, lpOFNInfo->ofn.lpstrInitialDir );

                        // Subclass the edit to let us display only what we want to display
                        g_pfnPrevEditProc = (WNDPROC)SetWindowLongPtr(
                                        GetDlgItem(hwnd, IDC_FILENAME),
                                        GWLP_WNDPROC,
                                        (LONG_PTR)BrowseDirEditProc );

                        // Subclass the combo so we know when the Network button has been used.
                        g_pfnPrevComboProc = (WNDPROC)SetWindowLongPtr(
                                        GetDlgItem(hwnd, IDC_DRIVECOMBO),
                                        GWLP_WNDPROC,
                                        (LONG_PTR)BrowseDirComboProc );

                        return TRUE;    // set default focus
                }

                case WM_DESTROY:
                {
                        // Clean up.
                        RemoveProp( hwnd, c_szOFNProp );
                        return FALSE;   // continue with default processing
                }

                case WM_COMMAND:
                {
                        switch( LOWORD(wParam) )
                        {
                                case IDOK:
                                {
                                        return BrowseDir_OnOK( hwnd );
                                }

                                case IDC_FILELIST:      //directory listbox.
                                {
                                        if( HIWORD(wParam) == LBN_DBLCLK )
                                        {
                                                // Post this message telling us to change the edit box.
                                                PostMessage( hwnd, CM_UPDATEEDIT, 0, 0L );
                                        }
                                        return FALSE;   // continue with default processing.
                                }

                                case IDC_DRIVECOMBO:    // drive combo box:
                                {
                                        if( HIWORD(wParam) == CBN_SELCHANGE )
                                        {
                                                // Post this message telling us to change the edit box.
                                                PostMessage( hwnd, CM_UPDATEEDIT, 0, 0L );
                                        }
                                        return FALSE;   // continue with default processing.
                                }

#ifdef NEVER
                                case IDC_NETWORK:       // "Network..." button
                                {
                                        // Set the fNetworking flag which the combo box looks for when
                                        // processing CB_SETCURSEL.
                                        LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( hwnd, c_szOFNProp );
                                        lpOFNInfo->fNetworking = TRUE;
                                        return FALSE;   // default processing.
                                }
#endif

                                default:
                                        return FALSE;   // default processing.
                        }
                }

                case CM_UPDATEEDIT:     //update edit box with directory
                {
                        LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( hwnd, c_szOFNProp );

                        // Change the text of the edit control.
                        UpdateEditText( hwnd );
                        SendDlgItemMessage( hwnd, IDC_FILENAME, EM_SETSEL, 0, (LPARAM)(INT)-1 );

                        // Store this text as the "last known good" directory
                        GetDlgItemText( hwnd, IDC_FILENAME, lpOFNInfo->szLastDirName, _MAX_PATH );

                        return TRUE;
                }

                default:
                        return FALSE;   //default processing
        }
}


//----------------------------------------------------------------------------
// Procedure    BrowseDir_OnOK
//
// Purpose              Handles a click of the OK button in the Browse Directory
//                              dialog.  We have to do some sneaky stuff here with checking
//                              which control has focus, because we want the dialog to go
//                              away enter when the OK button is clicked directly (i.e. just
//                              hitting Enter doesn't count).
//
// Parameters   hwnd                    The dialog window
//
// Returns              TRUE if processing should halt, FALSE if default processing
//                              should still happen.
//
// History              10/09/95        KenSh           Created
//
BOOL BrowseDir_OnOK( HWND hwnd )
{
        LPOFNINFO lpOFNInfo = (LPOFNINFO)GetProp( hwnd, c_szOFNProp );
        HWND hwndFocus = GetFocus();

        int idFocus = GetDlgCtrlID(hwndFocus);

        if( idFocus != IDC_FILENAME && idFocus != IDC_FILELIST && idFocus != IDC_DRIVECOMBO )
        {
                ASSERT( lpOFNInfo->ofn.lpstrFile != NULL );
                //UpdateEditText( hwnd );
                GetDlgItemText( hwnd, IDC_FILENAME, lpOFNInfo->ofn.lpstrFile, lpOFNInfo->ofn.nMaxFile );

                EndDialog( hwnd, IDOK );

                return TRUE;            // halt processing here.
        }
        else
        {
                // We don't want the dialog to go away at this point.
                // Because the default functionality is expecting
                // a file to be found, not a directory, we must make
                // sure what's been typed in is actually a directory
                // before we hand this message to the default handler.

                TCHAR szBuf[_MAX_PATH];

                // Calculate the new current directory and put it into the Edit
                UpdateEditText( hwnd );

                // Read the newly generated directory name
                GetDlgItemText( hwnd, IDC_FILENAME, szBuf, _MAX_PATH );

                // Update our "last good" directory
                _tcscpy( lpOFNInfo->szLastDirName, szBuf );

                // Post this message to update the edit after the default handler
                // updates the list box
                PostMessage( hwnd, CM_UPDATEEDIT, 0, 0 );

                return FALSE;           // let the original common dialog handle it.
        }
}

BOOL BrowseForFile(
                HWND hwndParent,
                LPCTSTR pszInitialDir,
                LPTSTR pszBuf,
                int cchBuf)
{
        TCHAR szInitialDir[MAX_PATH];
        TCHAR szFileExtension[_MAX_PATH] = _T("");
        LPTSTR p = NULL;
        TCHAR szFileFilter[_MAX_PATH];
        CString csTitle;

        OFNINFO ofnInfo;

        // Prepare the initial directory... add a backslash if it's
        // a 2-character path
        _tcscpy( szInitialDir, pszInitialDir );
        if( !szInitialDir[2] )
        {
                szInitialDir[2] = _T('\\');
                szInitialDir[3] = _T('\0');
        }

        // calculate file extension
        p = _tcsrchr(pszBuf, _T('.'));
        if (p) {
            p = _tcsinc(p);
            if (*p) {
                _tcscpy(szFileExtension, _T("*."));
                _tcscat(szFileExtension, p);
            }
        }

        memset( (PVOID)szFileFilter, 0, sizeof(szFileFilter));
        p = szFileFilter;
        if (*szFileExtension) {
            _tcscpy(p, szFileExtension);
            p = _tcsninc(p, _tcslen(szFileExtension) + 1);
            _tcscpy(p, szFileExtension);
            p = _tcsninc(p, _tcslen(szFileExtension) + 1);
        }
        _tcscpy(p, _T("*.*"));
        p = _tcsninc(p, _tcslen(_T("*.*")) + 1);
        _tcscpy(p, _T("*.*"));

        // dialog title "Locate File"
        MyLoadString(IDS_LOCATE_FILE, csTitle);

        // fill in the OFNINFO struct
        ofnInfo.ofn.lStructSize                 = sizeof(OPENFILENAME);
        ofnInfo.ofn.hwndOwner                   = hwndParent;
        ofnInfo.ofn.hInstance                   = (HINSTANCE) g_MyModuleHandle;
        ofnInfo.ofn.lpstrFilter                 = szFileFilter; // extention of the file we're looking for
        ofnInfo.ofn.lpstrCustomFilter           = NULL;
        ofnInfo.ofn.nMaxCustFilter              = 0;
        ofnInfo.ofn.nFilterIndex                = 1;
        ofnInfo.ofn.lpstrFile                   = pszBuf; // Buffer for file name
        ofnInfo.ofn.nMaxFile                    = cchBuf;
        ofnInfo.ofn.lpstrFileTitle              = NULL;
        ofnInfo.ofn.nMaxFileTitle               = 0;
        ofnInfo.ofn.lpstrInitialDir             = szInitialDir;
        ofnInfo.ofn.lpstrTitle                  = (LPCTSTR)csTitle;
        ofnInfo.ofn.Flags                       = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_EXPLORER |
                                                  OFN_NOCHANGEDIR | OFN_LONGNAMES | OFN_NONETWORKBUTTON;
        ofnInfo.ofn.nFileOffset                 = 0;
        ofnInfo.ofn.nFileExtension              = 0;
        ofnInfo.ofn.lpstrDefExt                 = NULL;
        ofnInfo.ofn.lCustData                   = (LPARAM)&ofnInfo;
        ofnInfo.ofn.lpfnHook                    = NULL;
        ofnInfo.ofn.lpTemplateName              = NULL;

        int nResult = ::GetOpenFileName( &ofnInfo.ofn );

        DWORD dw = 0;
        if (nResult == 0) {
            dw = CommDlgExtendedError();
        }

        if (nResult == IDOK) {
            iisDebugOut((LOG_TYPE_TRACE, _T("pszBuf=%s\n"), pszBuf));
            *(pszBuf + ofnInfo.ofn.nFileOffset - 1) = _T('\0');
        }

        return (BOOL)( IDOK == nResult );
}