916 lines
22 KiB
C
916 lines
22 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
masys32.c
|
|
|
|
Abstract:
|
|
|
|
Functions to migrate a Win9x user's system directory to system32.
|
|
|
|
Author:
|
|
|
|
Mike Condra (mikeco) 25-Feb-1997
|
|
|
|
Revision History:
|
|
|
|
ovidiut 09-Mar-1999 Added support to rename files on Win9x side
|
|
jimschm 23-Sep-1998 Updated for new fileops code
|
|
jimschm 02-Dec-1997 Removed rename of system32 if it already exists
|
|
mikeco 23-Jun-1997 NT-style file- & fn-header comments
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include "pch.h"
|
|
#include "migdbp.h"
|
|
#include "migappp.h"
|
|
|
|
#define DBG_SYS32 "Sys32"
|
|
|
|
|
|
PCTSTR
|
|
pGetNewName (
|
|
PCTSTR FileName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function generates a new name for the file that is going to be renames.
|
|
|
|
Arguments:
|
|
|
|
FileName - Original file name
|
|
|
|
Return Value:
|
|
|
|
the new name for file
|
|
|
|
--*/
|
|
|
|
{
|
|
PCTSTR pattern;
|
|
PTSTR result ;
|
|
UINT count ;
|
|
DWORD attrib ;
|
|
|
|
pattern = JoinText (FileName, TEXT(".%03u"));
|
|
result = JoinText (FileName, TEXT("XXXX"));
|
|
count = 0;
|
|
do {
|
|
if (count == 999) {
|
|
return result;
|
|
}
|
|
_stprintf (result, pattern, count);
|
|
attrib = GetFileAttributes (result);
|
|
count ++;
|
|
}
|
|
while (attrib != 0xFFFFFFFF);
|
|
FreeText (pattern);
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pRenameSystem32File (
|
|
IN PCTSTR NewName,
|
|
IN OUT PGROWBUFFER msgBufRename,
|
|
OUT PBOOL FileDeleted
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
pRenameSystem32File handles the special file %windir%\system32. If it exists and cannot
|
|
be automatically renamed, 2 things may happen:
|
|
- in unattended mode, the file will be deleted (this will be done by textmode setup)
|
|
- otherwise the user is asked to take a decision: either rename the file or cancels
|
|
Setup
|
|
|
|
Arguments:
|
|
|
|
DirName - name of NT dir to check
|
|
|
|
msgBufRename - growbuffer to append a Message when renaming a file.
|
|
|
|
msgBufDelete - growbuffer to append a Message when deleting a file (system32 only).
|
|
|
|
Return Value:
|
|
|
|
TRUE if the operation was successful and Setup can continue, FALSE if user cancelled
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD attrib;
|
|
PCTSTR Message = NULL;
|
|
PCTSTR button1 = NULL;
|
|
PCTSTR button2 = NULL;
|
|
BOOL Quit;
|
|
BOOL b = FALSE;
|
|
|
|
*FileDeleted = FALSE;
|
|
|
|
while (!b && !((attrib = GetFileAttributes (g_System32Dir)) & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
|
|
//
|
|
// rename this file now
|
|
//
|
|
if (SetFileAttributes (g_System32Dir, FILE_ATTRIBUTE_NORMAL)) {
|
|
|
|
if (MoveFile (g_System32Dir, NewName)) {
|
|
|
|
b = TRUE;
|
|
|
|
SetFileAttributes (g_System32Dir, attrib);
|
|
|
|
} else {
|
|
|
|
DEBUGMSG ((
|
|
DBG_SYS32,
|
|
"CheckNtDirs: Unable to set normal attributes on file %s",
|
|
g_System32Dir
|
|
));
|
|
SetFileAttributes (g_System32Dir, attrib);
|
|
|
|
}
|
|
}
|
|
|
|
if (!b) {
|
|
|
|
if (!UNATTENDED()) {
|
|
|
|
//
|
|
// ask user to take a decision about this
|
|
//
|
|
Message = ParseMessageID (MSG_CANNOT_RENAME_FILE, &g_System32Dir);
|
|
button1 = GetStringResource (MSG_RETRY_RENAME);
|
|
button2 = GetStringResource (MSG_QUIT_SETUP);
|
|
|
|
Quit = IDBUTTON1 != TwoButtonBox (g_ParentWnd, Message, button1, button2);
|
|
|
|
FreeStringResource (Message);
|
|
FreeStringResource (button1);
|
|
FreeStringResource (button2);
|
|
|
|
if (Quit) {
|
|
|
|
SetLastError (ERROR_CANCELLED);
|
|
|
|
DEBUGMSG ((
|
|
DBG_SYS32,
|
|
"CheckNtDirs: user cancelled Setup on renaming file %s",
|
|
g_System32Dir
|
|
));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// suppose the admin would delete the file anyway;
|
|
// that's exactly what textmode setup does, so leave it there and
|
|
// return success
|
|
//
|
|
*FileDeleted = TRUE;
|
|
b = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return GetFileAttributes (g_System32Dir) & FILE_ATTRIBUTE_DIRECTORY;
|
|
}
|
|
|
|
|
|
BOOL
|
|
pHandleSingleDir (
|
|
IN PCTSTR DirName,
|
|
IN OUT PGROWBUFFER msgBufRename,
|
|
IN OUT PGROWBUFFER msgBufDelete
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
This function checks if a file is in one of NT5 dirs way. If so, the file is renamed and
|
|
a Message is send to log. If there is a file named %windir%\system32, it is renamed
|
|
at this point (special behaviour) and if this fails, Setup is cancelled.
|
|
|
|
Arguments:
|
|
|
|
DirName - name of NT dir to check
|
|
|
|
msgBufRename - growbuffer to append a Message when renaming a file.
|
|
|
|
msgBufDelete - growbuffer to append a Message when deleting a file (system32 only).
|
|
|
|
Return Value:
|
|
|
|
TRUE if the operation was successful and Setup can continue, FALSE if user cancelled
|
|
|
|
--*/
|
|
|
|
{
|
|
PCTSTR newFileName, FileNamePart;
|
|
DWORD attributes;
|
|
TCHAR msg[MAX_TCHAR_PATH * 2 + 5];
|
|
BOOL FileDeleted;
|
|
|
|
attributes = GetFileAttributes (DirName);
|
|
|
|
if (!(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
|
|
newFileName = pGetNewName (DirName);
|
|
|
|
DEBUGMSG ((DBG_SYS32, "CheckNtDirs: Renaming %s to %s", DirName, newFileName));
|
|
|
|
FileDeleted = FALSE;
|
|
|
|
//
|
|
// special case: if DirName is g_System32Dir, rename the file right now
|
|
// because textmode Setup doesn't have a chance to rename it before
|
|
// it is already deleted and the System32 dir is created
|
|
//
|
|
if (StringIMatch (DirName, g_System32Dir)) {
|
|
|
|
if (!pRenameSystem32File (newFileName, msgBufRename, &FileDeleted)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (!FileDeleted) {
|
|
|
|
FileNamePart = GetFileNameFromPath (newFileName);
|
|
MYASSERT (FileNamePart);
|
|
|
|
//
|
|
// mark this info for undo on cancel
|
|
//
|
|
MemDbSetValueEx (
|
|
MEMDB_CATEGORY_CHG_FILE_PROPS,
|
|
DirName,
|
|
FileNamePart,
|
|
NULL,
|
|
attributes,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
} else {
|
|
|
|
MemDbSetValueEx (MEMDB_CATEGORY_DIRS_COLLISION, DirName, NULL, NULL, 0, NULL);
|
|
}
|
|
|
|
//
|
|
// append to the log
|
|
//
|
|
if (FileDeleted) {
|
|
wsprintf (msg, TEXT("\n\t\t%s"), DirName);
|
|
GrowBufAppendString (msgBufDelete, msg);
|
|
} else {
|
|
wsprintf (msg, TEXT("\n\t\t%s -> %s"), DirName, newFileName);
|
|
GrowBufAppendString (msgBufRename, msg);
|
|
}
|
|
|
|
FreeText (newFileName);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
pCheckProfilesDir (
|
|
IN OUT PGROWBUFFER msgBufRename
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
pCheckProfilesDir makes sure that there is no directory named "g_ProfileDirNt". If
|
|
there is, it is renamed, all files and folders within are marked for external move
|
|
and a message is added to the user report.
|
|
|
|
Arguments:
|
|
|
|
msgBufRename - A grow buffer where the rename message will be appended,
|
|
if this is the case
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR msg[MAX_TCHAR_PATH * 2 + 5];
|
|
DWORD attrib;
|
|
PCTSTR NewName;
|
|
PTSTR p;
|
|
TREE_ENUM TreeEnum;
|
|
TCHAR NewDest[MAX_MBCHAR_PATH];
|
|
PCTSTR Message;
|
|
PCTSTR Group;
|
|
PCTSTR array[2];
|
|
|
|
MYASSERT (g_ProfileDirNt);
|
|
|
|
attrib = GetFileAttributes (g_ProfileDirNt);
|
|
if (attrib != INVALID_ATTRIBUTES) {
|
|
|
|
MemDbSetValueEx (MEMDB_CATEGORY_DIRS_COLLISION, g_ProfileDirNt, NULL, NULL, 0, NULL);
|
|
|
|
NewName = pGetNewName (g_ProfileDirNt);
|
|
|
|
DEBUGMSG ((DBG_SYS32, "CheckNtDirs: Renaming %s to %s", g_ProfileDirNt, NewName));
|
|
MarkFileForMove (g_ProfileDirNt, NewName);
|
|
|
|
wsprintf (msg, TEXT("\n\t\t%s -> %s"), g_ProfileDirNt, NewName);
|
|
GrowBufAppendString (msgBufRename, msg);
|
|
|
|
if (attrib & FILE_ATTRIBUTE_DIRECTORY) {
|
|
//
|
|
// mark all files in the tree for move
|
|
//
|
|
if (EnumFirstFileInTree (&TreeEnum, g_ProfileDirNt, NULL, TRUE)) {
|
|
|
|
StringCopy (NewDest, NewName);
|
|
p = AppendWack (NewDest);
|
|
|
|
do {
|
|
|
|
MYASSERT (*TreeEnum.SubPath != '\\');
|
|
StringCopy (p, TreeEnum.SubPath);
|
|
if (!TreeEnum.Directory) {
|
|
if (CanSetOperation (TreeEnum.FullPath, OPERATION_TEMP_PATH)) {
|
|
//
|
|
// remove old operation and set a new one
|
|
// with the updated final dest
|
|
//
|
|
MarkFileForTemporaryMove (TreeEnum.FullPath, NewDest, g_TempDir);
|
|
} else {
|
|
if (CanSetOperation (TreeEnum.FullPath, OPERATION_FILE_MOVE)) {
|
|
MarkFileForMove (TreeEnum.FullPath, NewDest);
|
|
}
|
|
}
|
|
} else {
|
|
if (CanSetOperation (TreeEnum.FullPath, OPERATION_FILE_MOVE_EXTERNAL)) {
|
|
MarkFileForMoveExternal (TreeEnum.FullPath, NewDest);
|
|
}
|
|
}
|
|
|
|
} while (EnumNextFileInTree (&TreeEnum));
|
|
}
|
|
|
|
array[0] = g_ProfileDirNt;
|
|
array[1] = NewName;
|
|
Message = ParseMessageID (MSG_DIRECTORY_COLLISION_SUBCOMPONENT, array);
|
|
|
|
if (Message) {
|
|
|
|
Group = BuildMessageGroup (
|
|
MSG_INSTALL_NOTES_ROOT,
|
|
MSG_DIRECTORY_COLLISION_SUBGROUP,
|
|
Message
|
|
);
|
|
|
|
if (Group) {
|
|
|
|
MsgMgr_ObjectMsg_Add (TEXT("*RenameFolders"), Group, S_EMPTY);
|
|
|
|
FreeText (Group);
|
|
}
|
|
|
|
FreeStringResource (Message);
|
|
}
|
|
}
|
|
|
|
FreeText (NewName);
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
pCheckNtDirs (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function makes sure that there is no file with the same name as one of
|
|
the NT5 directories.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
TRUE if check was successful; FALSE if Setup was cancelled by the user
|
|
|
|
--*/
|
|
|
|
{
|
|
MEMDB_ENUM enumDirs;
|
|
GROWBUFFER msgBufRename = GROWBUF_INIT;
|
|
GROWBUFFER msgBufDelete = GROWBUF_INIT;
|
|
BOOL Success = TRUE;
|
|
|
|
//
|
|
// check first for g_ProfileDirNt
|
|
//
|
|
pCheckProfilesDir (&msgBufRename);
|
|
|
|
if (MemDbEnumFirstValue (
|
|
&enumDirs,
|
|
TEXT(MEMDB_CATEGORY_NT_DIRSA)TEXT("\\*"),
|
|
MEMDB_ALL_SUBLEVELS,
|
|
MEMDB_ENDPOINTS_ONLY
|
|
)) {
|
|
|
|
do {
|
|
if (!pHandleSingleDir (enumDirs.szName, &msgBufRename, &msgBufDelete)) {
|
|
Success = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
while (MemDbEnumNextValue (&enumDirs));
|
|
}
|
|
|
|
if (Success) {
|
|
|
|
//
|
|
// warn user about what will happen
|
|
//
|
|
if (msgBufDelete.Buf) {
|
|
LOG ((LOG_WARNING, (PCSTR)MSG_DIR_COLLISION_DELETE_LOG, msgBufDelete.Buf));
|
|
}
|
|
|
|
if (msgBufRename.Buf) {
|
|
LOG ((LOG_WARNING, (PCSTR)MSG_DIR_COLLISION_LOG, msgBufRename.Buf));
|
|
}
|
|
}
|
|
|
|
FreeGrowBuffer (&msgBufDelete);
|
|
FreeGrowBuffer (&msgBufRename);
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
DWORD
|
|
CheckNtDirs (
|
|
IN DWORD Request
|
|
)
|
|
{
|
|
switch (Request) {
|
|
case REQUEST_QUERYTICKS:
|
|
return TICKS_CHECK_NT_DIRS;
|
|
case REQUEST_RUN:
|
|
if (!pCheckNtDirs ()) {
|
|
return GetLastError ();
|
|
}
|
|
else {
|
|
return ERROR_SUCCESS;
|
|
}
|
|
default:
|
|
LOG ((LOG_ERROR, "Bad parameter while checking Nt Directories."));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
BOOL
|
|
pReadSystemFixedFiles (
|
|
IN OUT HASHTABLE SystemFixedFiles
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads a section from Win95upg.inf with all modules that must remain in System directory.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
TRUE if successfull, FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
INFCONTEXT context;
|
|
TCHAR fileName[MAX_TCHAR_PATH];
|
|
BOOL result = TRUE;
|
|
|
|
if (g_Win95UpgInf == INVALID_HANDLE_VALUE) {
|
|
LOG ((LOG_ERROR, "Unable to read from WIN95UPG.INF"));
|
|
SetLastError (ERROR_FILE_NOT_FOUND);
|
|
return FALSE;
|
|
}
|
|
|
|
if (SetupFindFirstLine (g_Win95UpgInf, WINDIR_SYSTEM_FIXED_FILES, NULL, &context)) {
|
|
do {
|
|
if (SetupGetStringField (
|
|
&context,
|
|
1,
|
|
fileName,
|
|
MAX_TCHAR_PATH,
|
|
NULL
|
|
)) {
|
|
|
|
HtAddString (SystemFixedFiles, fileName);
|
|
}
|
|
ELSE_DEBUGMSG ((DBG_ERROR, "File name not found in %s", WINDIR_SYSTEM_FIXED_FILES));
|
|
}
|
|
while (SetupFindNextLine (&context, &context));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
pReadSystemForcedMoveFiles (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function reads a section from Win95upg.inf with patterns for all modules that should be moved to System32 directory.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
TRUE if successfull, FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
INFCONTEXT context;
|
|
TCHAR filePattern[MAX_TCHAR_PATH];
|
|
BOOL result = TRUE;
|
|
|
|
if (g_Win95UpgInf == INVALID_HANDLE_VALUE) {
|
|
LOG ((LOG_ERROR, "Unable to read from WIN95UPG.INF"));
|
|
SetLastError (ERROR_FILE_NOT_FOUND);
|
|
return FALSE;
|
|
}
|
|
|
|
if (SetupFindFirstLine (g_Win95UpgInf, SYSTEM32_FORCED_MOVE, NULL, &context)) {
|
|
do {
|
|
if (SetupGetStringField (
|
|
&context,
|
|
1,
|
|
filePattern,
|
|
MAX_TCHAR_PATH,
|
|
NULL
|
|
)) {
|
|
MemDbSetValueEx (
|
|
MEMDB_CATEGORY_SYSTEM32_FORCED_MOVE,
|
|
filePattern,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
NULL
|
|
);
|
|
}
|
|
ELSE_DEBUGMSG ((DBG_ERROR, "File name not found in %s", SYSTEM32_FORCED_MOVE));
|
|
}
|
|
while (SetupFindNextLine (&context, &context));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
pMarkFileForSys32Move (
|
|
IN PCTSTR FileName,
|
|
IN PCTSTR FullFileSpec,
|
|
IN PCTSTR MovedFile,
|
|
IN BOOL CheckExeType
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
pMarkFileForSys32Move marks a file in %windir%\system to be moved to
|
|
%windir%\system32. It takes into account all previous processing, so there
|
|
is no operation collisions.
|
|
|
|
Arguments:
|
|
|
|
FileName - Specifies the src file name or sub-path from %windir%\system.
|
|
FullFileSpec - Specifies the full path to the source file (which is
|
|
supposed to be in the system dir)
|
|
MovedFile - Specifies the destination path (which is supposed to be in
|
|
the system32 dir)
|
|
CheckExeType - Specifies TRUE if only 32-bit binaries should be moved. If TRUE
|
|
and FullFileSpec does not point to a 32-bit binary, then
|
|
memdb is queried for non-32-bit binaries that should be moved.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR key [MEMDB_MAX];
|
|
|
|
//
|
|
// Skip file if we already plan to move or delete it.
|
|
//
|
|
if (!CanSetOperation (FullFileSpec, OPERATION_FILE_MOVE)) {
|
|
DEBUGMSG ((
|
|
DBG_SYS32,
|
|
"File already flagged for change: %s",
|
|
FullFileSpec
|
|
));
|
|
|
|
return;
|
|
}
|
|
|
|
if (!IsFileMarkedForChange (MovedFile)) {
|
|
|
|
if (CheckExeType) {
|
|
//
|
|
// See if Win32 PE
|
|
//
|
|
|
|
if (GetModuleType (FullFileSpec) != W32_MODULE) {
|
|
|
|
MemDbBuildKey (key, MEMDB_CATEGORY_SYSTEM32_FORCED_MOVE, FileName, NULL, NULL);
|
|
if (!MemDbGetPatternValue (key, NULL)) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Move file during text mode because we know it is going to be
|
|
// created. This allows text mode to compare versions before
|
|
// overwriting.
|
|
//
|
|
// NOTE: We can be certain that the creation isn't from a file copy,
|
|
// because we tested the source file above, and there is no
|
|
// other reason why a file in system32 will be copied from
|
|
// any other location than system or the NT sources.
|
|
//
|
|
// Also note that migration DLLs have not been processed yet.
|
|
//
|
|
|
|
RemoveOperationsFromPath (MovedFile, ALL_DEST_CHANGE_OPERATIONS);
|
|
}
|
|
|
|
//
|
|
// All tests passed -- do the move
|
|
//
|
|
|
|
DEBUGMSG ((DBG_SYS32, "Moving %s to %s", FullFileSpec, MovedFile));
|
|
MarkFileForMove (FullFileSpec, MovedFile);
|
|
|
|
}
|
|
|
|
|
|
BOOL
|
|
pMoveSystemDir (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
MoveSystemDir scans the %windir%\system directory for all 32-bit
|
|
executables that are not excluded in win95upg.inf. Any matches are moved
|
|
to system32.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
TRUE if successfull, FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR SystemDirPattern[MAX_TCHAR_PATH];
|
|
TCHAR FullFileSpec[MAX_TCHAR_PATH];
|
|
TCHAR MovedFile[MAX_TCHAR_PATH];
|
|
HANDLE hFind;
|
|
WIN32_FIND_DATA fd;
|
|
TCHAR key [MEMDB_MAX];
|
|
TREE_ENUM e;
|
|
PTSTR p, q;
|
|
PTSTR SubPathEnd;
|
|
HASHTABLE systemFixedFiles;
|
|
DWORD count = 0;
|
|
|
|
DEBUGMSG ((DBG_SYS32, "Begining system to system32 processing"));
|
|
|
|
systemFixedFiles = HtAlloc();
|
|
|
|
if (!pReadSystemFixedFiles (systemFixedFiles)) {
|
|
|
|
HtFree (systemFixedFiles);
|
|
return FALSE;
|
|
}
|
|
|
|
pReadSystemForcedMoveFiles ();
|
|
|
|
//
|
|
// Build the string %sysdir%\\*.*
|
|
//
|
|
StringCopy(SystemDirPattern, g_SystemDir);
|
|
StringCat(SystemDirPattern, TEXT("\\*.*"));
|
|
|
|
hFind = FindFirstFile (SystemDirPattern, &fd);
|
|
|
|
if (INVALID_HANDLE_VALUE != hFind) {
|
|
|
|
StringCopy (FullFileSpec, g_SystemDir);
|
|
p = AppendWack (FullFileSpec);
|
|
|
|
StringCopy (MovedFile, g_System32Dir);
|
|
q = AppendWack (MovedFile);
|
|
|
|
do {
|
|
//
|
|
// Reject "." and ".."
|
|
//
|
|
if (StringMatch(fd.cFileName, _T(".")) ||
|
|
StringMatch(fd.cFileName, _T(".."))) {
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// See if is on list of files that stay in system dir
|
|
//
|
|
if (HtFindString (systemFixedFiles, fd.cFileName)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// If it's a directory, see if we should move it, and if so,
|
|
// move it!
|
|
//
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
|
|
|
MemDbBuildKey (key, MEMDB_CATEGORY_SYSTEM32_FORCED_MOVE, fd.cFileName, NULL, NULL);
|
|
if (!MemDbGetPatternValue (key, NULL)) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// To move a subdir, we enumerate all files in the tree, mark
|
|
// each of them for move, and then follow the normal code path
|
|
// to mark the dir itself to be moved.
|
|
//
|
|
|
|
StringCopy (p, fd.cFileName);
|
|
|
|
StringCopy (q, fd.cFileName);
|
|
SubPathEnd = AppendWack (q);
|
|
|
|
if (EnumFirstFileInTree (&e, FullFileSpec, NULL, FALSE)) {
|
|
|
|
do {
|
|
StringCopy (SubPathEnd, e.SubPath);
|
|
pMarkFileForSys32Move (q, e.FullPath, MovedFile, FALSE);
|
|
|
|
} while (EnumNextFileInTree (&e));
|
|
}
|
|
TickProgressBar ();
|
|
}
|
|
|
|
//
|
|
// Make full file spec
|
|
//
|
|
StringCopy (p, fd.cFileName);
|
|
StringCopy (q, fd.cFileName);
|
|
|
|
pMarkFileForSys32Move (fd.cFileName, FullFileSpec, MovedFile, TRUE);
|
|
|
|
count++;
|
|
if (!(count % 128)) {
|
|
TickProgressBar ();
|
|
}
|
|
} while (FindNextFile (hFind, &fd));
|
|
|
|
FindClose (hFind);
|
|
}
|
|
|
|
HtFree (systemFixedFiles);
|
|
|
|
DEBUGMSG ((DBG_SYS32, "End of system to system32 processing"));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
DWORD
|
|
MoveSystemDir (
|
|
IN DWORD Request
|
|
)
|
|
{
|
|
switch (Request) {
|
|
case REQUEST_QUERYTICKS:
|
|
return TICKS_MOVE_SYSTEM_DIR;
|
|
case REQUEST_RUN:
|
|
if (!pMoveSystemDir ()) {
|
|
return GetLastError ();
|
|
}
|
|
else {
|
|
return ERROR_SUCCESS;
|
|
}
|
|
default:
|
|
LOG ((LOG_ERROR, "Bad parameter found while moving system directory."));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL
|
|
UndoChangedFileProps (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
UndoChangedFileProps enumerates all values in MEMDB_CATEGORY_CHG_FILE_PROPS and
|
|
restore files to their original state (name, attributes). This function should
|
|
be called when the user cancels the upgrade.
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Value:
|
|
|
|
TRUE if all files were successfully set to their original attributes, FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
MEMDB_ENUM e;
|
|
PTSTR FileNamePart, NewName, DirNameEnd;
|
|
BOOL b = TRUE;
|
|
|
|
if (MemDbGetValueEx (
|
|
&e,
|
|
TEXT(MEMDB_CATEGORY_CHG_FILE_PROPS) TEXT("\\*"),
|
|
NULL,
|
|
NULL
|
|
)) {
|
|
|
|
do {
|
|
|
|
FileNamePart = _tcsrchr (e.szName, TEXT('\\'));
|
|
MYASSERT(FileNamePart);
|
|
|
|
*FileNamePart = 0;
|
|
FileNamePart++;
|
|
|
|
DirNameEnd = _tcsrchr (e.szName, TEXT('\\'));
|
|
MYASSERT(DirNameEnd);
|
|
*DirNameEnd = 0;
|
|
|
|
NewName = JoinPaths (e.szName, FileNamePart);
|
|
|
|
*DirNameEnd = TEXT('\\');
|
|
|
|
if (!SetFileAttributes (NewName, FILE_ATTRIBUTE_NORMAL) ||
|
|
!MoveFile (NewName, e.szName) ||
|
|
!SetFileAttributes (e.szName, e.dwValue)) {
|
|
|
|
b = FALSE;
|
|
}
|
|
|
|
FreePathString (NewName);
|
|
|
|
} while (MemDbEnumNextValue (&e));
|
|
}
|
|
|
|
return b;
|
|
}
|