|
|
/****************************************************************************\
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; }
|