windows-nt/Source/XPSP1/NT/base/ntsetup/opktools/setupmgr/oem/newfiles.c

846 lines
30 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/****************************************************************************\
NEWFILES.C / OPK Wizard (OPKWIZ.EXE)
Microsoft Confidential
Copyright (c) Microsoft Corporation 1998
All rights reserved
3/99 - Jason Cohen (JCOHEN)
Added this new source file for the OPK Wizard as part of the OOBE
update.
09/2000 - Stephen Lodwick (STELO)
Ported OPK Wizard to Whistler
\****************************************************************************/
//
// Include file(s):
//
#include "pch.h"
#include "newfiles.h"
#include "resource.h"
//
// Internal Defined Value(s):
//
#define DIR_CONFIG_OOBE _T("$OEM$")
#define INF_SECT_SOURCEDISK _T("SourcedisksFiles")
#define INF_SECT_DESTDIRS _T("DestinationDirs")
#define INF_SECT_OOBE _T("RegisterOOBE")
#define INF_LINE_COPYFILES _T("CopyFiles")
#define INF_PREFIX _T("X")
#define SOURCENUM_OPTIONS_CAB _T("782")
#define DESTLDID_OOBE _T("11")
#define STR_SEARCH _T("*")
#define STR_PADDING _T("\r\n\r\n")
#define MAX_BUFFER 16384 // 32768
#ifndef CSTR_EQUAL
#define CSTR_EQUAL 2
#endif // CSTR_EQUAL
//
// Internal Structure(s):
//
typedef struct _FILELIST
{
LPTSTR lpFileName;
LPTSTR lpDirectory;
struct _FILELIST * lpNext;
} FILELIST, *PFILELIST, *LPFILELIST;
//
// Internal Function Prototype(s):
//
static void DelFiles(LPTSTR, LPTSTR, DWORD, LPTSTR, LPTSTR);
static LPFILELIST AllocFileList(HWND, LPTSTR, LPTSTR);
static BOOL CompareFiles(LPTSTR, LPTSTR);
//
// External Function(s):
//
//////////////////////////////////////////////////////////////////////////////
// AddFiles - lpSourceDir = location of files to copy to OOBE directory.
// Destination = location of the system directory where installed to
// LDID.
// lpConfigDir = location of oemaudit.inf, and config files.
// lpSourceDir -> OOBE -> lpDestDir
//
void AddFiles(HWND hwndParent, LPTSTR lpSourceDir, LPTSTR lpDestLdid,
LPTSTR lpDestDir, LPTSTR lpDestName, LPTSTR lpConfigDir)
{
LPTSTR lpFilePart,
lpFile,
lpFileName,
lpSectEnd,
lpSearch,
lpTarget,
lpNext;
TCHAR szBuffer[MAX_PATH + 32] = NULLSTR,
szCurDir[MAX_PATH] = NULLSTR,
szSourceDir[MAX_PATH] = NULLSTR,
szCopyDir[MAX_PATH],
szWinbom[MAX_PATH],
szCopyFiles[MAX_PATH + 32];
LPFILELIST lpflHead = NULL,
lpflCur,
lpflBuf;
BOOL bFound;
DWORD dwNum;
int iFilePartLen;
HRESULT hrCat;
HRESULT hrPrintf;
//
// First thing we do is setup the directories and strings
// that we need to do all the work.
//
// We need the path to the config directory. Copydir is where
// the files are going to be copied to from the SourceDir
// so it needs to be cleaned out before we do the CopyFile.
// CopyDir will be created if not exists.
//
lstrcpyn(szCopyDir, lpConfigDir, AS(szCopyDir));
AddPathN(szCopyDir, DIR_CONFIG_OOBE,AS(szCopyDir));
AddPathN(szCopyDir, _T("\\"),AS(szCopyDir));
lpFilePart = szCopyDir + lstrlen(szCopyDir);
iFilePartLen= AS(szCopyDir)-lstrlen(szCopyDir);
// Need a full path to the oemaudit inf.
//
lstrcpyn(szWinbom, lpConfigDir,AS(szWinbom));
AddPathN(szWinbom, FILE_WINBOM_INI,AS(szWinbom));
// We need to construct the prefix to the copy
// files section name.
//
lstrcpyn(szCopyFiles, INF_PREFIX,AS(szCopyFiles));
hrCat=StringCchCat(szCopyFiles, AS(szCopyFiles), lpDestLdid ? lpDestLdid : DESTLDID_OOBE);
if ( lpDestDir && *lpDestDir )
hrCat=StringCchCat(szCopyFiles, AS(szCopyFiles), lpDestDir);
StrRem(szCopyFiles, CHR_BACKSLASH);
lpSectEnd = szCopyFiles + lstrlen(szCopyFiles);
//
// Now that we have that info, we need to get rid of any files that
// may have already been put in the inf and the destination directory.
//
// Cleaned out of the inf and destination directory only if we are
// passed in NULL for the source.
//
if ( !(lpSourceDir && *lpSourceDir) )
DelFiles(szCopyDir, lpFilePart, iFilePartLen, szWinbom, szCopyFiles);
//
// Now we make a list of all the files we are going to add to the
// inf and destination directory.
//
// If the source isn't a valid dir, we must have just wanted to clean up.
//
if ( ( lpSourceDir && *lpSourceDir ) &&
( GetFullPathName(lpSourceDir, sizeof(szSourceDir) / sizeof(TCHAR), szSourceDir, &lpFile) && szSourceDir[0] ) &&
( (dwNum = GetFileAttributes(szSourceDir)) != 0xFFFFFFFF ) )
{
// Check to see if we were passed a file or a directory.
//
if ( ( dwNum & FILE_ATTRIBUTE_DIRECTORY ) ||
( lpFile <= szSourceDir ) )
{
// We are search for all the files in the diretory.
//
lpFile = STR_SEARCH;
}
else
{
// We are only doing one file. We need to separate
// the file from the directory.
//
*(lpFile - 1) = NULLCHR;
}
// Set the staring point for our file search.
//
GetCurrentDirectory(sizeof(szCurDir) / sizeof(TCHAR), szCurDir);
SetCurrentDirectory(szSourceDir);
// Get the file list.
//
lpflHead = AllocFileList(hwndParent, szBuffer, lpFile);
// Make sure the destination dir exits.
//
*lpFilePart = NULLCHR;
CreatePath(szCopyDir);
//
// Now that we have the file list, go through each one processing
// it separately and then free the memory allocated for it.
//
// Loop through all the files in our linked list.
//
for ( lpflCur = lpflHead; lpflCur; lpflCur = lpflBuf )
{
//
// First copy the file into the flat directory.
//
// Setup the relative path from the currect directory
// to the file we want to copy.
//
if ( lpflCur->lpDirectory && *lpflCur->lpDirectory )
lstrcpyn(szBuffer, lpflCur->lpDirectory,AS(szBuffer));
else
szBuffer[0] = NULLCHR;
AddPathN(szBuffer, lpflCur->lpFileName,AS(szBuffer));
// Support for a different file name for the destination.
//
lpFileName = lpDestName ? lpDestName : lpflCur->lpFileName;
// Setup the destination file name.
//
lstrcpyn(lpFilePart, lpFileName, iFilePartLen);
// Copy the file to the Options\Cabs directory and display
// an error if the copy failed. Probably means that this
// is a duplicate file.
//
if ( !CopyFile(szBuffer, szCopyDir, TRUE) )
{
// Save the CopyFile error and then check to see if the file
// is actaully different then the one tried to copy over.
//
dwNum = GetLastError();
if ( ( !CompareFiles(szBuffer, szCopyDir) ) &&
( lpTarget = (LPTSTR) MALLOC(256 * sizeof(TCHAR)) ) )
{
//
// I hate doing UI in backend type code. Because of time I don't have
// much choice, but in the future, this UI code should be replaced
// with a call back mechanism so the caller can do the UI.
//
// This is the first of only two places where UI is used in here.
//
// Allocate another buffer to hold the message with the file name.
//
if ( ( LoadString(NULL, dwNum == ERROR_FILE_EXISTS ? IDS_ERR_DUPFILE : IDS_ERR_COPY, lpTarget, 256 * sizeof(TCHAR)) ) &&
( lpNext = (LPTSTR) MALLOC((lstrlen(lpFileName) + lstrlen(lpTarget) + 1) * sizeof(TCHAR)) ) )
{
// Add the file name to the message, get the title for the message
// box and display the error.
//
hrPrintf=StringCchPrintf(lpNext, (lstrlen(lpFileName) + lstrlen(lpTarget) + 1), lpTarget, lpFileName);
*lpTarget = NULLCHR;
LoadString(NULL, IDS_APPNAME, lpTarget, 256 * sizeof(TCHAR));
MessageBox(hwndParent, lpNext, lpTarget, MB_OK | MB_ICONWARNING | MB_APPLMODAL);
FREE(lpNext);
}
FREE(lpTarget);
}
}
//
// Now add the file to the [SourceDiskFiles] section.
//
// We just use WritePrivateProfileString() to write
// FILENAME=781 to the [SourceDiskFiles] section.
//
WritePrivateProfileString(INF_SECT_SOURCEDISK, lpFileName, SOURCENUM_OPTIONS_CAB, szWinbom);
//
// This code figures out what the copy files section will be
// called. This is based on the path where the files will
// be copied.
//
// Create the name of the copy files section the file will be in.
//
*lpSectEnd = NULLCHR;
if ( lpflCur->lpDirectory && *lpflCur->lpDirectory )
lstrcpyn(lpSectEnd, lpflCur->lpDirectory, AS(szCopyFiles)-(int)(lpSectEnd - szCopyFiles) );
StrRem(lpSectEnd, CHR_BACKSLASH);
//
// Now add the file path to the [DestinationDirs] section.
//
// Create the LDID and dir combo to write to the dest dir section.
//
lstrcpyn(szBuffer, lpDestLdid ? lpDestLdid : DESTLDID_OOBE,AS(szBuffer));
if ( ( lpDestDir && *lpDestDir ) ||
( lpflCur->lpDirectory && *lpflCur->lpDirectory ) )
{
hrCat=StringCchCat(szBuffer,AS(szBuffer), _T(",\""));
if ( lpDestDir && *lpDestDir )
{
hrCat=StringCchCat(szBuffer, AS(szBuffer),lpDestDir);
if ( lpflCur->lpDirectory && *lpflCur->lpDirectory )
AddPathN(szBuffer, lpflCur->lpDirectory,AS(szBuffer));
}
else
hrCat=StringCchCat(szBuffer, AS(szBuffer), lpflCur->lpDirectory);
hrCat=StringCchCat(szBuffer, AS(szBuffer), _T("\""));
}
// We just use WritePrivateProfileString() to write
// COPYFILES=11,"OOBE\\DIR" to the [DestinationDirs] section.
//
WritePrivateProfileString(INF_SECT_DESTDIRS, szCopyFiles, szBuffer, szWinbom);
//
// Now add the copy files section to the CopyFiles line.
//
// First get current CopyFiles line.
//
szBuffer[0] = NULLCHR;
GetPrivateProfileString(INF_SECT_OOBE, INF_LINE_COPYFILES, NULLSTR, szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szWinbom);
// Search each section listed in the CopyFiles line to see
// if we need to add this one. The sections are divided by
// commas.
//
// ISSUE-2002/02/28-stelo- May want to take qutoes into account, but I don't think so.
//
bFound = FALSE;
for ( lpTarget = szBuffer; !bFound && lpTarget && *lpTarget; lpTarget = lpNext )
{
// Get rid of proceeding spaces.
//
while ( *lpTarget == CHR_SPACE )
lpTarget = CharNext(lpTarget);
// NULL terminate at the ',' and setup
// the lpNext pointer.
//
if ( lpNext = StrChr(lpTarget, _T(',')) )
*lpNext = NULLCHR;
// Make sure there are no trailing spaces.
//
if ( lpSearch = StrChr(lpTarget, CHR_SPACE) )
*lpSearch = NULLCHR;
// Check if this section is the same as the one
// we are going to add.
//
if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpTarget, -1, szCopyFiles, -1) == CSTR_EQUAL )
bFound = TRUE;
// Need to restore the characters we may have stomped on.
//
if ( lpNext )
*lpNext++ = _T(',');
if ( lpSearch )
*lpSearch = CHR_SPACE;
}
// Now see if we need to add the line.
//
if ( !bFound )
{
// Append our copy files section.
//
if ( szBuffer[0] )
hrCat=StringCchCat(szBuffer,AS(szBuffer), _T(", "));
hrCat=StringCchCat(szBuffer, AS(szBuffer), szCopyFiles);
// We just use WritePrivateProfileString() to write
// the CopyFiles line back to the [RegisterOOBE] section
// with our added copy files section on it.
//
WritePrivateProfileString(INF_SECT_OOBE, INF_LINE_COPYFILES, szBuffer, szWinbom);
}
//
// Now write the file name to it's copy files section.
//
// First get the entire copy files section.
//
GetPrivateProfileSection(szCopyFiles, szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szWinbom);
// Loop throught the strings to see if the file is already there.
//
bFound = FALSE;
for ( lpTarget = szBuffer; !bFound && *lpTarget; lpTarget += (lstrlen(lpTarget) + 1) )
{
// Get rid of proceeding spaces.
//
while ( *lpTarget == CHR_SPACE )
lpTarget = CharNext(lpTarget);
// Make sure there are no trailing spaces.
//
if ( lpSearch = StrChr(lpTarget, CHR_SPACE) )
*lpSearch = NULLCHR;
// Check if this section is the same as the one
// we are going to add.
//
if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpTarget, -1, lpFileName, -1) == CSTR_EQUAL )
bFound = TRUE;
// Need to restore the character we may have stomped on.
//
if ( lpSearch )
*lpSearch = CHR_SPACE;
}
// Now write back the section if we need to.
//
if ( !bFound )
{
// Need to a pointer to the end of the sub strings.
//
for ( lpSearch = szBuffer; *lpSearch; lpSearch += (lstrlen(lpSearch) + 1) );
// Copy the string to the end and add an extra NULL.
//
lstrcpyn(lpSearch, lpFileName, ((MAX_PATH+32)-(int)(lpSearch-szBuffer)) );
lpSearch += (lstrlen(lpSearch) + 1);
*lpSearch = NULLCHR;
// We need to call WritePrivateProfileSection() with NULL
// to remove the section. We shouldn't have to do this,
// but the Win32 docs are not correct.
//
WritePrivateProfileSection(szCopyFiles, NULL, szWinbom);
// We just use WritePrivateProfileSection() to write the
// copy files section back with our added file in it.
//
WritePrivateProfileSection(szCopyFiles, szBuffer, szWinbom);
}
//
// Now free the structure and the data within it.
//
// Save the next pointer before we free the structure.
//
lpflBuf = lpflCur->lpNext;
// Free the file buffers and the structure.
//
FREE(lpflCur->lpFileName);
FREE(lpflCur->lpDirectory);
FREE(lpflCur);
}
//
// All done, now just clean up.
//
// Put the current directory back to where it should be.
//
if ( szCurDir[0] )
SetCurrentDirectory(szCurDir);
}
// Make sure the changes to the inf are flushed to disk
//
WritePrivateProfileString(NULL, NULL, NULL, szWinbom);
}
//
// Internal Function(s):
//
static void DelFiles(LPTSTR lpszCopyDir, LPTSTR lpszFilePart, DWORD cbFilePart, LPTSTR lpszWinbom, LPTSTR lpszCopyFiles)
{
LPTSTR lpSearch,
lpSection,
lpFileName,
lpTarget,
lpNext;
LPTSTR lpszSections = NULL,
lpszFileNames = NULL,
lpszBuffer = NULL;
BOOL bFound;
//
// Allocate buffers...
//
lpszSections = MALLOC(MAX_BUFFER * sizeof(TCHAR));
lpszFileNames = MALLOC(MAX_BUFFER * sizeof(TCHAR));
lpszBuffer = MALLOC(MAX_BUFFER * sizeof(TCHAR));
if ( !lpszSections || !lpszFileNames || !lpszBuffer )
{
// Free the buffers... Note: FREE macro checks for NULL
//
FREE( lpszSections );
FREE( lpszFileNames );
FREE( lpszBuffer );
return;
}
// We need all the section names.
//
GetPrivateProfileSectionNames(lpszSections, MAX_BUFFER, lpszWinbom);
// Loop throught the section to see if there is any that match our search criteria.
//
for ( lpSection = lpszSections; lpSection && *lpSection; lpSection += (lstrlen(lpSection) + 1) )
{
// Get rid of proceeding spaces.
//
while ( *lpSection == CHR_SPACE )
lpSection = CharNext(lpSection);
// Make sure there are no trailing spaces.
//
if ( lpSearch = StrChr(lpSection, CHR_SPACE) )
*lpSearch = NULLCHR;
// Check if this section is the same as the one
// we are going to add.
//
if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpSection, lstrlen(lpszCopyFiles), lpszCopyFiles, lstrlen(lpszCopyFiles)) == CSTR_EQUAL )
{
// We need all the files in the section.
//
GetPrivateProfileSection(lpSection, lpszFileNames, MAX_BUFFER, lpszWinbom);
// Loop throught the section to see if there is any that match our search criteria.
//
for ( lpFileName = lpszFileNames; *lpFileName; lpFileName += (lstrlen(lpFileName) + 1) )
{
// Get rid of proceeding spaces.
//
while ( *lpFileName == CHR_SPACE )
lpFileName = CharNext(lpFileName);
// Make sure there are no trailing spaces.
//
if ( lpSearch = StrChr(lpFileName, CHR_SPACE) )
*lpSearch = NULLCHR;
// Delete the file from the destination directory.
//
lstrcpyn(lpszFilePart, lpFileName, cbFilePart);
DeleteFile(lpszCopyDir);
// Remove the line from the source disk section.
//
WritePrivateProfileString(INF_SECT_SOURCEDISK, lpFileName, NULL, lpszWinbom);
}
// Search each section listed in the CopyFiles and remove
// this one. The sections are divided by commas.
//
bFound = FALSE;
GetPrivateProfileString(INF_SECT_OOBE, INF_LINE_COPYFILES, NULLSTR, lpszBuffer, MAX_BUFFER, lpszWinbom);
for ( lpTarget = lpszBuffer; !bFound && lpTarget && *lpTarget; lpTarget = lpNext )
{
// Get rid of proceeding spaces.
//
while ( *lpTarget == CHR_SPACE )
lpTarget = CharNext(lpTarget);
// NULL terminate at the ',' and setup
// the lpNext pointer.
//
if ( lpNext = StrChr(lpTarget, _T(',')) )
*lpNext = NULLCHR;
// Make sure there are no trailing spaces.
//
if ( lpSearch = StrChr(lpTarget, CHR_SPACE) )
*lpSearch = NULLCHR;
// Check if this section is the same as the one
// we are going to remove.
//
if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpTarget, -1, lpSection, -1) == CSTR_EQUAL )
bFound = TRUE;
// Need to restore the characters we may have stomped on.
//
if ( lpNext )
*lpNext++ = _T(',');
if ( lpSearch )
*lpSearch = CHR_SPACE;
if ( bFound )
{
// Go back to the ',' or the beginning of the buffer.
//
while ( ( lpTarget > lpszBuffer) && ( *lpTarget != _T(',') ) )
lpTarget = CharPrev(lpszBuffer, lpTarget);
// Now overwrite the string we took out.
//
if ( lpNext )
lstrcpyn(lpTarget, lpNext - 1, (MAX_BUFFER-(int)(lpTarget-lpszBuffer)));
else
*lpTarget = NULLCHR;
}
}
if ( bFound )
{
// We should eat any preceeding spaces and/or commas just
// for good measure.
//
for ( lpTarget = lpszBuffer; ( *lpTarget == CHR_SPACE ) || ( *lpTarget == _T(',') ); lpTarget = CharNext(lpTarget) );
// Now write the buffer back to the inf file.
//
WritePrivateProfileString(INF_SECT_OOBE, INF_LINE_COPYFILES, *lpTarget ? lpTarget : NULL, lpszWinbom);
}
// Remove the line from the destination dirs section.
//
WritePrivateProfileString(INF_SECT_DESTDIRS, lpSection, NULL, lpszWinbom);
// Remove this section entirely.
//
WritePrivateProfileSection(lpSection, NULL, lpszWinbom);
}
}
// Free the buffers... Note: FREE macro checks for NULL
//
FREE( lpszSections );
FREE( lpszFileNames );
FREE( lpszBuffer );
}
static LPFILELIST AllocFileList(HWND hwndParent, LPTSTR lpDirectory, LPTSTR lpSearch)
{
WIN32_FIND_DATA FileFound;
HANDLE hFile;
LPTSTR lpEnd,
lpFileName;
LPFILELIST lpflHead = NULL;
LPFILELIST* lplpflNext = &lpflHead;
HRESULT hrPrintf;
// Process all the files and directories.
//
if ( (hFile = FindFirstFile(lpSearch, &FileFound)) != INVALID_HANDLE_VALUE )
{
do
{
// Display an error if the short and long file names don't match.
// Means that it is a LFN, which INFs don't like.
//
if ( ( FileFound.cAlternateFileName[0] ) &&
( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, FileFound.cAlternateFileName, -1, FileFound.cFileName, -1) != CSTR_EQUAL ) &&
( lpEnd = (LPTSTR) MALLOC(256 * sizeof(TCHAR)) ) )
{
//
// I hate doing UI in backend type code. Because of time I don't have
// much choice, but in the future, this UI code should be replaced
// with a call back mechanism so the caller can do the UI.
//
// This is the second of only two places where UI is used in here.
//
// Allocate another buffer to hold the message with the file name.
//
if ( ( LoadString(NULL, IDS_ERR_LFN, lpEnd, 256) ) &&
( lpFileName = (LPTSTR) MALLOC((lstrlen(FileFound.cFileName) + lstrlen(lpEnd) + 1) * sizeof(TCHAR)) ) )
{
// Add the file name to the message, get the title for the message
// box and display the error.
//
hrPrintf=StringCchPrintf(lpFileName, (lstrlen(FileFound.cFileName) + lstrlen(lpEnd) + 1), lpEnd, FileFound.cFileName);
*lpEnd = NULLCHR;
LoadString(NULL, IDS_APPNAME, lpEnd, 256 * sizeof(TCHAR));
MessageBox(hwndParent, lpFileName, lpEnd, MB_OK | MB_ICONWARNING | MB_APPLMODAL);
FREE(lpFileName);
}
FREE(lpEnd);
}
// Get a pointer to the file name, the short one if possible.
//
if ( FileFound.cAlternateFileName[0] )
lpFileName = FileFound.cAlternateFileName;
else
lpFileName = FileFound.cFileName;
// First check to see if this is a files (not a directory).
//
if ( !( FileFound.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
{
// Allocate the next item in the structure.
//
if ( *lplpflNext = (LPFILELIST) MALLOC(sizeof(FILELIST)) )
{
// Allocate the buffer for the file name and path and
// make sure that none of the allocations fail.
//
if ( ( (*lplpflNext)->lpFileName = (LPTSTR) MALLOC((lstrlen(lpFileName) + 1) * sizeof(TCHAR)) ) &&
( (*lplpflNext)->lpDirectory = (LPTSTR) MALLOC((lstrlen(lpDirectory) + 1) * sizeof(TCHAR)) ) )
{
// Copy the file name and path into the buffers.
//
lstrcpyn((*lplpflNext)->lpFileName, lpFileName, (lstrlen(lpFileName) + 1));
lstrcpyn((*lplpflNext)->lpDirectory, lpDirectory, (lstrlen(lpDirectory) + 1));
// Null the next pointer so we know this is the last item.
//
(*lplpflNext)->lpNext = NULL;
// Set the next pointer to point to the address of
// the next member of this new structure.
//
lplpflNext = &((*lplpflNext)->lpNext);
}
else
{
// Don't worry, the FREE() macro checks for NULL
// before it frees the memory.
//
FREE((*lplpflNext)->lpFileName);
FREE(*lplpflNext);
}
}
}
// Otherwise, make sure the directory is not "." or "..".
//
else if ( ( lstrcmp(lpFileName, _T(".")) ) &&
( lstrcmp(lpFileName, _T("..")) ) )
{
// Tack on this directory name to the current path saving
// the end pointer so that it is easy to get rid of this
// directory name when we return back.
//
lpEnd = lpDirectory + lstrlen(lpDirectory);
AddPath(lpDirectory, lpFileName);
// Go into the next directory, get all the files, and
// the set the current directory back to the original
// directory.
//
SetCurrentDirectory(lpFileName);
*lplpflNext = AllocFileList(hwndParent, lpDirectory, lpSearch);
SetCurrentDirectory(_T(".."));
// Get rid of the directory name off our path buffer.
//
*lpEnd = NULLCHR;
// Need to setup our next pointer to the end of the list
// returned to us.
//
while ( *lplpflNext )
lplpflNext = &((*lplpflNext)->lpNext);
}
}
while ( FindNextFile(hFile, &FileFound) );
FindClose(hFile);
}
return lpflHead;
}
static BOOL CompareFiles(LPTSTR lpFile1, LPTSTR lpFile2)
{
BOOL bCompare,
bRead1,
bRead2;
HANDLE hFile1,
hFile2;
BYTE baBuffer1[4096],
baBuffer2[4096];
DWORD dwBytes1,
dwBytes2,
dwCount;
// Open the files.
//
hFile1 = CreateFile(lpFile1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hFile2 = CreateFile(lpFile2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// Make sure the files were opened.
//
if ( ( hFile1 != INVALID_HANDLE_VALUE ) &&
( hFile2 != INVALID_HANDLE_VALUE ) )
{
// Read all the data from the files.
//
do
{
// Read in the max buffer from each file.
//
bRead1 = ReadFile(hFile1, baBuffer1, sizeof(baBuffer1), &dwBytes1, NULL);
bRead2 = ReadFile(hFile2, baBuffer2, sizeof(baBuffer2), &dwBytes2, NULL);
// Make sure the reads didn't fail.
//
if ( bRead1 && bRead2 )
{
// Check to make sure the sizes are the same.
//
if ( bCompare = ( dwBytes1 == dwBytes2 ) )
{
// Make sure the buffers are identical.
//
for ( dwCount = 0; bCompare && ( dwCount < dwBytes1 ); dwCount++ )
bCompare = ( baBuffer1[dwCount] == baBuffer2[dwCount] );
}
}
else
// If both the reads failed, we will return true.
//
bCompare = ( !bRead1 && !bRead2 );
}
while ( bCompare && bRead1 && bRead2 && dwBytes1 && dwBytes2 );
}
else
// If both the files does not exist, then we will
// return false.
//
bCompare = ( ( hFile1 != INVALID_HANDLE_VALUE ) && ( hFile2 != INVALID_HANDLE_VALUE ) );
// Close the files.
//
if ( hFile1 == INVALID_HANDLE_VALUE )
CloseHandle(hFile1);
if ( hFile2 == INVALID_HANDLE_VALUE )
CloseHandle(hFile2);
return bCompare;
}