676 lines
20 KiB
C
676 lines
20 KiB
C
|
|
/****************************************************************************\
|
|
|
|
DISKAPI.C / OPK Wizard (OPKWIZ.EXE)
|
|
|
|
Microsoft Confidential
|
|
Copyright (c) Microsoft Corporation 1999
|
|
All rights reserved
|
|
|
|
Disk API source file for custom disk APIs used in the OPK Wizard.
|
|
|
|
4/99 - Jason Cohen (JCOHEN)
|
|
Added this new source file for the OPK Wizard as part of the
|
|
Millennium rewrite.
|
|
|
|
\****************************************************************************/
|
|
|
|
|
|
//
|
|
// Include file(s)
|
|
//
|
|
|
|
#include <pch.h>
|
|
#include <commdlg.h>
|
|
#include <tchar.h>
|
|
#include <shlobj.h>
|
|
|
|
|
|
//
|
|
// Internal Define(s):
|
|
//
|
|
|
|
#define IDC_BROWSE_EDIT 0x3744 // Common dialogs edit box in the SHBrowseForFolder function.
|
|
|
|
//
|
|
// Internal Function Prototype(s):
|
|
//
|
|
|
|
static DWORD CopyDirectoryEngine(HWND hwnd, HANDLE hEvent, LPCTSTR lpSrc, LPCTSTR lpDst, BOOL fCount);
|
|
static CALLBACK BrowseCallbackProc(HWND, UINT, LPARAM, LPARAM);
|
|
|
|
|
|
//
|
|
// External Function(s):
|
|
//
|
|
|
|
BOOL DirectoryExists(LPCTSTR lpDirectory)
|
|
{
|
|
DWORD dwAttr;
|
|
|
|
return ( ( lpDirectory != NULL ) &&
|
|
( *lpDirectory != NULLCHR ) &&
|
|
( (dwAttr = GetFileAttributes(lpDirectory)) != 0xFFFFFFFF ) &&
|
|
( dwAttr & FILE_ATTRIBUTE_DIRECTORY ) );
|
|
}
|
|
|
|
BOOL FileExists(LPCTSTR lpFile)
|
|
{
|
|
DWORD dwAttr;
|
|
|
|
return ( ( lpFile != NULL ) &&
|
|
( *lpFile != NULLCHR ) &&
|
|
( (dwAttr = GetFileAttributes(lpFile)) != 0xFFFFFFFF ) &&
|
|
( !(dwAttr & FILE_ATTRIBUTE_DIRECTORY) ) );
|
|
}
|
|
|
|
BOOL CopyResetFile(LPCTSTR lpSource, LPCTSTR lpTarget)
|
|
{
|
|
if ( !CopyFile(lpSource, lpTarget, FALSE) )
|
|
return FALSE;
|
|
SetFileAttributes(lpTarget, FILE_ATTRIBUTE_NORMAL);
|
|
return TRUE;
|
|
}
|
|
|
|
DWORD IfGetLongPathName(LPCTSTR lpszShortPath, LPTSTR lpszLongPath, DWORD cchBuffer)
|
|
{
|
|
//
|
|
// See also \nt\base\win32\client\vdm.c.
|
|
//
|
|
DWORD dwReturn = 0;
|
|
#if defined(_WIN64) // _WIN64 postdates the introduction of GetLongPathName.
|
|
typedef (WINAPI* PFNGetLongPathNameA)( PCSTR lpszShortPath, PSTR lpszLongPath, DWORD cchBuffer);
|
|
typedef (WINAPI* PFNGetLongPathNameW)(PCWSTR lpszShortPath, PWSTR lpszLongPath, DWORD cchBuffer);
|
|
#ifdef UNICODE
|
|
typedef PFNGetLongPathNameW PFNGetLongPathName;
|
|
const static char ProcName[] = "GetLongPathNameW";
|
|
#else
|
|
typedef PFNGetLongPathNameA PFNGetLongPathName;
|
|
const static char ProcName[] = "GetLongPathNameA";
|
|
#endif
|
|
static PFNGetLongPathName hGetLongPathName = NULL;
|
|
static BOOL fInited = FALSE;
|
|
|
|
if (!fInited)
|
|
{
|
|
//
|
|
// GetModuleHandle is in kernel32, so as long as this lib code
|
|
// is around, the handle to kernel32 is constant and the result of
|
|
// GetProcAccess is valid.
|
|
//
|
|
// The old code that called LoadLibrary/FreeLibrary would lose the
|
|
// value of GetLastError by calling FreeLibrary.
|
|
//
|
|
HMODULE hKernel32;
|
|
if (hKernel32 = GetModuleHandle(TEXT("Kernel32.dll")))
|
|
hGetLongPathName = (PFNGetLongPathName)(GetProcAddress(hKernel32, ProcName));
|
|
fInited = TRUE;
|
|
}
|
|
|
|
if (hGetLongPathName)
|
|
{
|
|
dwReturn = hGetLongPathName(lpszShortPath, lpszLongPath, cchBuffer);
|
|
}
|
|
#else
|
|
dwReturn = GetLongPathName(lpszShortPath, lpszLongPath, cchBuffer);
|
|
#endif
|
|
return dwReturn;
|
|
}
|
|
|
|
BOOL CreatePath(LPCTSTR lpPath)
|
|
{
|
|
LPTSTR lpFind = (LPTSTR) lpPath;
|
|
|
|
while ( lpFind = _tcschr(lpFind + 1, CHR_BACKSLASH) )
|
|
{
|
|
if ( !((lpFind - lpPath <= 2) && (*(lpFind - 1) == _T(':'))) )
|
|
{
|
|
*lpFind = NULLCHR;
|
|
if ( !DirectoryExists(lpPath) )
|
|
CreateDirectory(lpPath, NULL);
|
|
*lpFind = CHR_BACKSLASH;
|
|
}
|
|
}
|
|
|
|
if ( !DirectoryExists(lpPath) )
|
|
CreateDirectory(lpPath, NULL);
|
|
|
|
return DirectoryExists(lpPath);
|
|
}
|
|
|
|
BOOL DeletePath(LPCTSTR lpDirectory)
|
|
{
|
|
WIN32_FIND_DATA FileFound;
|
|
HANDLE hFile;
|
|
|
|
// Validate the parameters.
|
|
//
|
|
if ( ( lpDirectory == NULL ) ||
|
|
( *lpDirectory == NULLCHR ) ||
|
|
( !SetCurrentDirectory(lpDirectory) ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// Process all the files and directories in the directory passed in.
|
|
//
|
|
SetCurrentDirectory(lpDirectory);
|
|
if ( (hFile = FindFirstFile(_T("*"), &FileFound)) != INVALID_HANDLE_VALUE )
|
|
{
|
|
do
|
|
{
|
|
// First check to see if this is a file (not a directory).
|
|
//
|
|
if ( !( FileFound.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
|
|
{
|
|
// Make sure we clear the readonly flag
|
|
//
|
|
SetFileAttributes(FileFound.cFileName, FILE_ATTRIBUTE_NORMAL);
|
|
DeleteFile(FileFound.cFileName);
|
|
}
|
|
// Otherwise, make sure the directory is not "." or "..".
|
|
//
|
|
else if ( ( lstrcmp(FileFound.cFileName, _T(".")) ) &&
|
|
( lstrcmp(FileFound.cFileName, _T("..")) ) )
|
|
{
|
|
DeletePath(FileFound.cFileName);
|
|
}
|
|
|
|
}
|
|
while ( FindNextFile(hFile, &FileFound) );
|
|
FindClose(hFile);
|
|
}
|
|
|
|
// Go to the parent directory and remove the current one.
|
|
// We have to make sure and reset the readonly attributes
|
|
// on the dir also.
|
|
//
|
|
SetCurrentDirectory(_T(".."));
|
|
SetFileAttributes(lpDirectory, FILE_ATTRIBUTE_NORMAL);
|
|
return RemoveDirectory(lpDirectory);
|
|
}
|
|
|
|
BOOL DeleteFilesEx(LPCTSTR lpDirectory, LPCTSTR lpFileSpec)
|
|
{
|
|
WIN32_FIND_DATA FileFound;
|
|
HANDLE hFile;
|
|
TCHAR szCurDir[MAX_PATH];
|
|
|
|
// Validate the parameters.
|
|
//
|
|
if ( ( lpDirectory == NULL ) ||
|
|
( *lpDirectory == NULLCHR ) ||
|
|
( !SetCurrentDirectory(lpDirectory) ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Get our current directory so we can set ourself back
|
|
//
|
|
GetCurrentDirectory(MAX_PATH, szCurDir);
|
|
|
|
// Process all the files and directories in the directory passed in.
|
|
//
|
|
SetCurrentDirectory(lpDirectory);
|
|
if ( (hFile = FindFirstFile(lpFileSpec, &FileFound)) != INVALID_HANDLE_VALUE )
|
|
{
|
|
do
|
|
{
|
|
// First check to see if this is a file (not a directory).
|
|
//
|
|
if ( !( FileFound.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
|
|
{
|
|
DeleteFile(FileFound.cFileName);
|
|
}
|
|
}
|
|
while ( FindNextFile(hFile, &FileFound) );
|
|
FindClose(hFile);
|
|
}
|
|
|
|
SetCurrentDirectory(szCurDir);
|
|
return TRUE;
|
|
}
|
|
|
|
LPTSTR AddPathN(LPTSTR lpPath, LPCTSTR lpName, DWORD cbPath)
|
|
{
|
|
LPTSTR lpTemp = lpPath;
|
|
|
|
// Validate the parameters passed in.
|
|
//
|
|
if ( ( lpPath == NULL ) ||
|
|
( lpName == NULL ) )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// Find the end of the path.
|
|
//
|
|
while ( *lpTemp )
|
|
{
|
|
lpTemp = CharNext(lpTemp);
|
|
if ( cbPath )
|
|
{
|
|
cbPath--;
|
|
}
|
|
}
|
|
|
|
// If no trailing backslash on the path then add one.
|
|
//
|
|
if ( ( lpTemp > lpPath ) &&
|
|
( *CharPrev(lpPath, lpTemp) != CHR_BACKSLASH ) )
|
|
{
|
|
// Make sure there is room in the path buffer to
|
|
// add the backslash and the null terminator.
|
|
//
|
|
if ( cbPath < 2 )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
*lpTemp = CHR_BACKSLASH;
|
|
lpTemp = CharNext(lpTemp);
|
|
cbPath--;
|
|
}
|
|
else
|
|
{
|
|
// Make sure there is at least room for the null
|
|
// terminator.
|
|
//
|
|
if ( cbPath < 1 )
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// Make sure there is no preceeding spaces or backslashes
|
|
// on the name to add.
|
|
//
|
|
while ( ( *lpName == CHR_SPACE ) ||
|
|
( *lpName == CHR_BACKSLASH ) )
|
|
{
|
|
lpName = CharNext(lpName);
|
|
}
|
|
|
|
// Add the new name to existing path.
|
|
//
|
|
lstrcpyn(lpTemp, lpName, cbPath);
|
|
|
|
// Trim trailing spaces from result.
|
|
//
|
|
while ( ( lpTemp > lpPath ) &&
|
|
( *(lpTemp = CharPrev(lpPath, lpTemp)) == CHR_SPACE ) )
|
|
{
|
|
*lpTemp = NULLCHR;
|
|
}
|
|
|
|
return lpPath;
|
|
}
|
|
|
|
LPTSTR AddPath(LPTSTR lpPath, LPCTSTR lpName)
|
|
{
|
|
return AddPathN(lpPath, lpName, 0xFFFFFFFF);
|
|
}
|
|
|
|
DWORD ExpandFullPath(LPTSTR lpszPath, LPTSTR lpszReturn, DWORD cbReturn)
|
|
{
|
|
LPTSTR lpszExpanded = AllocateExpand(lpszPath ? lpszPath : lpszReturn),
|
|
lpszDontCare;
|
|
DWORD dwRet;
|
|
|
|
*lpszReturn = NULLCHR;
|
|
if ( NULL == lpszExpanded )
|
|
{
|
|
return 0;
|
|
}
|
|
dwRet = GetFullPathName(lpszExpanded, cbReturn, lpszReturn, &lpszDontCare);
|
|
FREE(lpszExpanded);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
BOOL CopyDirectory(LPCTSTR lpSrc, LPCTSTR lpDst)
|
|
{
|
|
return ( CopyDirectoryEngine(NULL, NULL, lpSrc, lpDst, FALSE) != 0 );
|
|
}
|
|
|
|
BOOL CopyDirectoryProgress(HWND hwnd, LPCTSTR lpSrc, LPCTSTR lpDst)
|
|
{
|
|
return ( CopyDirectoryEngine(hwnd, NULL, lpSrc, lpDst, FALSE) != 0 );
|
|
}
|
|
|
|
BOOL CopyDirectoryProgressCancel(HWND hwnd, HANDLE hEvent, LPCTSTR lpSrc, LPCTSTR lpDst)
|
|
{
|
|
return ( CopyDirectoryEngine(hwnd, hEvent, lpSrc, lpDst, FALSE) != 0 );
|
|
}
|
|
|
|
DWORD FileCount(LPCTSTR lpSrc)
|
|
{
|
|
return CopyDirectoryEngine(NULL, NULL, lpSrc, NULL, TRUE);
|
|
}
|
|
|
|
BOOL BrowseForFolder(HWND hwndParent, INT iString, LPTSTR lpDirBuf, DWORD dwFlags)
|
|
{
|
|
BROWSEINFO bi = {0};
|
|
TCHAR szBuffer[MAX_PATH],
|
|
szPath[MAX_PATH],
|
|
szTitle[256] = NULLSTR;
|
|
LPITEMIDLIST lpil;
|
|
|
|
// Copy the current directory into the buffer so
|
|
// we start out from that folder.
|
|
//
|
|
lstrcpyn(szPath, lpDirBuf, AS(szPath));
|
|
|
|
// Load the instructional text for the dialog.
|
|
//
|
|
if ( iString )
|
|
LoadString(NULL, iString, szTitle, sizeof(szTitle) / sizeof(TCHAR));
|
|
|
|
// Setup the BrowseInfo struct.
|
|
//
|
|
bi.hwndOwner = hwndParent;
|
|
bi.pidlRoot = NULL;
|
|
bi.pszDisplayName = szBuffer;
|
|
bi.lpszTitle = szTitle;
|
|
bi.ulFlags = dwFlags ? dwFlags : BIF_RETURNONLYFSDIRS;
|
|
bi.lpfn = (BFFCALLBACK) BrowseCallbackProc;
|
|
bi.lParam = (LPARAM) szPath;
|
|
|
|
// Return the new path if we got one.
|
|
//
|
|
if ( ( (lpil = SHBrowseForFolder(&bi)) != NULL ) &&
|
|
( SHGetPathFromIDList(lpil, szPath) && szPath[0] && DirectoryExists(szPath) ) )
|
|
{
|
|
lstrcpy(lpDirBuf, szPath);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL BrowseForFile(HWND hwnd, INT iTitle, INT iFilter, INT iExtension, LPTSTR lpFileName, DWORD cbFileName, LPTSTR lpDirectory, DWORD dwFlags)
|
|
{
|
|
OPENFILENAME ofn = {sizeof(ofn)};
|
|
TCHAR szTitle[256] = NULLSTR,
|
|
szFilter[256] = NULLSTR,
|
|
szExtension[256] = NULLSTR,
|
|
szFullPath[MAX_PATH] = NULLSTR;
|
|
LPTSTR lpSearch,
|
|
lpNext,
|
|
lpFilePart = NULL;
|
|
|
|
// Load all the strings we need for the open file structure.
|
|
//
|
|
if ( iTitle )
|
|
LoadString(NULL, iTitle, szTitle, sizeof(szTitle) / sizeof(TCHAR));
|
|
if ( iFilter )
|
|
LoadString(NULL, iFilter, szFilter, sizeof(szFilter) / sizeof(TCHAR));
|
|
if ( iExtension )
|
|
LoadString(NULL, iExtension, szExtension, sizeof(szExtension) / sizeof(TCHAR));
|
|
|
|
// Replace all the | in the filter string with \0.
|
|
//
|
|
lpSearch = szFilter;
|
|
while ( *lpSearch )
|
|
{
|
|
lpNext = CharNext(lpSearch);
|
|
if ( *lpSearch == _T('|') )
|
|
*lpSearch = NULLCHR;
|
|
lpSearch = lpNext;
|
|
}
|
|
|
|
// Figure out what the default directory and file will be.
|
|
//
|
|
if ( *lpFileName && GetFullPathName(lpFileName, STRSIZE(szFullPath), szFullPath, &lpFilePart) && szFullPath[0] )
|
|
{
|
|
// If the whole path is a directory, there is no file part.
|
|
//
|
|
if ( DirectoryExists(szFullPath) )
|
|
lpFilePart = NULL;
|
|
|
|
// Copy off the file name part.
|
|
//
|
|
if ( lpFilePart && ( (DWORD) lstrlen(lpFilePart) < cbFileName ) )
|
|
lstrcpy(lpFileName, lpFilePart);
|
|
else
|
|
*lpFileName = NULLCHR;
|
|
|
|
// Now chop off the file name so we are left with the directory.
|
|
//
|
|
if ( lpFilePart )
|
|
*lpFilePart = NULLCHR;
|
|
}
|
|
else
|
|
{
|
|
// No cool default directory or file name to use, so we use the
|
|
// directory passed in and no file name.
|
|
//
|
|
*lpFileName = NULLCHR;
|
|
szFullPath[0] = NULLCHR;
|
|
}
|
|
|
|
// Setup the open file struture.
|
|
//
|
|
ofn.hwndOwner = hwnd;
|
|
ofn.lpstrFilter = szFilter[0] ? szFilter : NULL;
|
|
ofn.nFilterIndex = szFilter[0] ? 1 : 0;
|
|
ofn.lpstrFile = lpFileName;
|
|
ofn.nMaxFile = cbFileName;
|
|
ofn.lpstrInitialDir = ( szFullPath[0] && DirectoryExists(szFullPath) ) ? szFullPath : lpDirectory;
|
|
ofn.lpstrTitle = szTitle[0] ? szTitle : NULL;
|
|
ofn.lpstrDefExt = szExtension[0] ? szExtension : NULL;
|
|
ofn.Flags = dwFlags ? dwFlags : (OFN_HIDEREADONLY | OFN_FILEMUSTEXIST);
|
|
|
|
// Make sure the buffer is zero'ed out if the function failes.
|
|
//
|
|
if ( !GetOpenFileName(&ofn) )
|
|
*lpFileName = NULLCHR;
|
|
|
|
// Return true only if we are passing back a file name.
|
|
//
|
|
return ( *lpFileName != NULLCHR );
|
|
}
|
|
|
|
|
|
//
|
|
// Internal Functions:
|
|
//
|
|
|
|
static DWORD CopyDirectoryEngine(HWND hwnd, HANDLE hEvent, LPCTSTR lpSrc, LPCTSTR lpDst, BOOL fCount)
|
|
{
|
|
WIN32_FIND_DATA FileFound;
|
|
HANDLE hFile;
|
|
BOOL bReturn = TRUE;
|
|
DWORD dwReturn = 0;
|
|
TCHAR szDst[MAX_PATH];
|
|
LPTSTR lpFileName,
|
|
lpSearch = NULL;
|
|
|
|
// If a source directory was passed in, set the current directory
|
|
// to it because that is we we are going to search for files.
|
|
//
|
|
if ( lpSrc )
|
|
{
|
|
// If the source isn't a directory, it is a file or file pattern we are
|
|
// copying.
|
|
//
|
|
if ( DirectoryExists(lpSrc) )
|
|
{
|
|
// Now make sure we set the current directory to the source directory.
|
|
//
|
|
bReturn = SetCurrentDirectory(lpSrc);
|
|
}
|
|
else
|
|
{
|
|
// We have to separate the path from the file or file pattern.
|
|
//
|
|
if ( lpSearch = _tcsrchr(lpSrc, CHR_BACKSLASH) )
|
|
{
|
|
// Set the current directory to the path part of the source buffer.
|
|
//
|
|
TCHAR szPath[MAX_PATH];
|
|
lstrcpyn(szPath, lpSrc, 1 + (int)(lpSearch - lpSrc));
|
|
if ( *(lpSearch = CharNext(lpSearch)) == NULLCHR )
|
|
lpSearch = NULL;
|
|
bReturn = SetCurrentDirectory(szPath);
|
|
}
|
|
else
|
|
lpSearch = (LPTSTR) lpSrc;
|
|
}
|
|
}
|
|
|
|
// Make sure the source directory existed, create the
|
|
// destination directory, and make sure it exists also.
|
|
//
|
|
if ( bReturn && ( fCount || ( bReturn = CreatePath(lpDst) ) ) )
|
|
{
|
|
// Setup the destination buffer with a pointer to the
|
|
// end of the path.
|
|
//
|
|
if ( !fCount )
|
|
{
|
|
lstrcpy(szDst, lpDst);
|
|
AddPath(szDst, NULLSTR);
|
|
lpFileName = szDst + lstrlen(szDst);
|
|
}
|
|
|
|
// Process all the files and directories in the directory passed in.
|
|
//
|
|
if ( (hFile = FindFirstFile(lpSearch ? lpSearch : _T("*"), &FileFound)) != INVALID_HANDLE_VALUE )
|
|
{
|
|
do
|
|
{
|
|
// Create the full path destination name.
|
|
//
|
|
if ( !fCount )
|
|
lstrcpy(lpFileName, FileFound.cFileName);
|
|
|
|
// First check to see if this is a file (not a directory).
|
|
//
|
|
if ( !( FileFound.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
|
|
{
|
|
// Copy the file from the source to the destination.
|
|
//
|
|
fCount ? (dwReturn++) : (bReturn = CopyResetFile(FileFound.cFileName, szDst));
|
|
|
|
// Increase the progress bar. This is the only difference between
|
|
// CopyDirectroy() and CopyDirectoryProgress().
|
|
//
|
|
if ( hwnd )
|
|
SendMessage(hwnd, PBM_STEPIT, 0, 0);
|
|
|
|
}
|
|
// Otherwise, make sure the directory is not "." or "..".
|
|
//
|
|
else if ( lstrcmp(FileFound.cFileName, _T(".")) &&
|
|
lstrcmp(FileFound.cFileName, _T("..")) &&
|
|
SetCurrentDirectory(FileFound.cFileName) )
|
|
{
|
|
// Process all the files there.
|
|
//
|
|
DWORD dwBuffer = CopyDirectoryEngine(hwnd, hEvent, NULL, szDst, fCount);
|
|
fCount ? (dwReturn += dwBuffer) : (bReturn = (dwBuffer != 0));
|
|
SetCurrentDirectory(_T(".."));
|
|
}
|
|
|
|
// Check event to see if the user canceled.
|
|
//
|
|
if ( hEvent && ( WaitForSingleObject(hEvent, 0) != WAIT_TIMEOUT ) )
|
|
bReturn = FALSE;
|
|
|
|
}
|
|
while ( bReturn && FindNextFile(hFile, &FileFound) );
|
|
FindClose(hFile);
|
|
}
|
|
}
|
|
|
|
return bReturn ? (fCount ? dwReturn : 1) : 0;
|
|
}
|
|
|
|
static CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
|
{
|
|
TCHAR szPathName[MAX_PATH];
|
|
LPTSTR lpszData = (LPTSTR) lpData;
|
|
|
|
switch ( uMsg )
|
|
{
|
|
case BFFM_INITIALIZED:
|
|
|
|
// Initialize the dialog with the OK button and current directory.
|
|
//
|
|
if ( lpszData && *lpszData )
|
|
{
|
|
LPTSTR lpEnd;
|
|
|
|
// Make sure there is a trailing backslash so that a drive passed in
|
|
// works (like c:).
|
|
//
|
|
szPathName[0] = NULLCHR;
|
|
if ( GetFullPathName(lpszData, STRSIZE(szPathName), szPathName, NULL) && szPathName[0] )
|
|
lstrcpy(lpszData, szPathName);
|
|
|
|
// For some dumb reason, the BFFM_SETSELECTION doesn't like it when there
|
|
// is a trailing backslash on the path.
|
|
//
|
|
if ( ( lstrlen(lpszData) > 3 ) &&
|
|
( lpEnd = CharPrev(lpszData, lpszData + lstrlen(lpszData)) ) &&
|
|
( *lpEnd == CHR_BACKSLASH ) )
|
|
{
|
|
*lpEnd = NULLCHR;
|
|
}
|
|
|
|
// Update the tree with the default dir and enable/disable the OK button
|
|
// if there is a valid directory.
|
|
//
|
|
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, lpData);
|
|
SendMessage(hwnd, BFFM_ENABLEOK, 0, (DirectoryExists(lpszData) != 0));
|
|
}
|
|
else
|
|
SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);
|
|
break;
|
|
|
|
case BFFM_SELCHANGED:
|
|
|
|
// Turn the id into a folder name.
|
|
//
|
|
szPathName[0] = NULLCHR;
|
|
if ( SHGetPathFromIDList((LPITEMIDLIST) lParam, szPathName) && szPathName[0] && DirectoryExists(szPathName) )
|
|
{
|
|
SetDlgItemText(hwnd, IDC_BROWSE_EDIT, szPathName);
|
|
SendMessage(hwnd, BFFM_ENABLEOK, 0, 1);
|
|
}
|
|
else
|
|
SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);
|
|
break;
|
|
|
|
case BFFM_VALIDATEFAILED:
|
|
SendMessage(hwnd, BFFM_ENABLEOK, 0, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL CreateUnicodeFile(LPCTSTR lpFile)
|
|
{
|
|
HANDLE hFile;
|
|
DWORD dwWritten = 0;
|
|
WCHAR cHeader = 0xFEFF;
|
|
BOOL bReturn = FALSE;
|
|
|
|
// If we have a file name and the file does not exist, attempt to create
|
|
//
|
|
if ( lpFile && *lpFile && !FileExists(lpFile))
|
|
{
|
|
if ( (hFile = CreateFile(lpFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE)
|
|
{
|
|
WriteFile(hFile, &cHeader, sizeof(cHeader), &dwWritten, NULL);
|
|
|
|
CloseHandle(hFile);
|
|
|
|
bReturn = TRUE;
|
|
}
|
|
}
|
|
|
|
return bReturn;
|
|
} |