mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
845 lines
30 KiB
845 lines
30 KiB
|
|
/****************************************************************************\
|
|
|
|
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;
|
|
}
|