windows-nt/Source/XPSP1/NT/base/ntsetup/oemtools/oemapply/usermod/main.cpp
2020-09-26 16:20:57 +08:00

364 lines
8.5 KiB
C++

#include <stdio.h>
#include <direct.h>
#include <windows.h>
#include "patchapi.h"
#include "const.h"
BOOL IsUnicodeFile(IN HANDLE hFile);
BOOL ReadLine(IN HANDLE hFile, IN WCHAR* strLine);
BOOL CopyThisFile(IN WCHAR* strFrom, IN WCHAR* strTo);
BOOL MoveThisFile(IN WCHAR* strFrom, IN WCHAR* strTo);
BOOL PatchFile(IN WCHAR* strOldFile, IN WCHAR* strPatchFile, IN WCHAR* strNewFile);
BOOL CreateZeroFile(IN WCHAR* strFile);
BOOL CreateThisDirectory(IN WCHAR* strDirectory, IN WCHAR* strAttrib);
BOOL DeleteThisDirectory(IN WCHAR* strDirectory);
extern "C" VOID __cdecl wmain(VOID)
{
HANDLE hScriptFile = CreateFileW(APPLY_PATCH_SCRIPT,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hScriptFile != INVALID_HANDLE_VALUE)
{
if(IsUnicodeFile(hScriptFile))
{
// local varibles
BOOL blnReturn = TRUE;
WCHAR strThisLine[SUPER_LENGTH / 2];
WCHAR* strAction = NULL;
WCHAR strParam1[STRING_LENGTH];
WCHAR strParam2[STRING_LENGTH];
WCHAR strParam3[STRING_LENGTH];
DWORD iError = 0;
// get drive letter
INT iDrive = _getdrive() - 1;
if(iDrive >= 0)
{
strParam1[0] = strParam2[0] = strParam3[0] = (WCHAR)(L'A' + iDrive);
strParam1[1] = strParam2[1] = strParam3[1] = L':';
while(ReadLine(hScriptFile, strThisLine))
{
blnReturn = TRUE;
strParam1[2] = strParam2[2] = strParam3[2] = 0;
strAction = wcstok(strThisLine, SEPARATOR);
if(strAction)
{
switch(strAction[0])
{
case ACTION_C_NEW_DIRECTORY:
wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
blnReturn = CreateThisDirectory(strParam1, wcstok(NULL, SEPARATOR));
break;
case ACTION_C_PATCH_FILE:
wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
wcscpy(strParam2 + 2, wcstok(NULL, SEPARATOR));
wcscpy(strParam3 + 2, wcstok(NULL, SEPARATOR));
blnReturn = PatchFile(strParam1, strParam2, strParam3);
break;
case ACTION_C_MOVE_FILE:
case ACTION_C_EXCEPT_FILE:
case ACTION_C_RENAME_FILE:
case ACTION_C_NOT_PATCH_FILE:
case ACTION_C_SAVED_FILE:
wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
wcscpy(strParam2 + 2, wcstok(NULL, SEPARATOR));
blnReturn = MoveThisFile(strParam1, strParam2);
break;
case ACTION_C_COPY_FILE:
wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
wcscpy(strParam2 + 2, wcstok(NULL, SEPARATOR));
blnReturn = CopyThisFile(strParam1, strParam2);
break;
case ACTION_C_NEW_ZERO_FILE:
wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
blnReturn = CreateZeroFile(strParam1);
break;
case ACTION_C_DELETE_DIRECTORY:
wcscpy(strParam1 + 2, wcstok(NULL, SEPARATOR));
blnReturn = DeleteThisDirectory(strParam1);
break;
default:
blnReturn = FALSE;
break;
}
}
if(!blnReturn)
{
iError = GetLastError();
switch(iError)
{
case ERROR_PATCH_NOT_NECESSARY:
CopyThisFile(strParam1, strParam3);
break;
default:
// some thing went wrong
printf("warning, A=%ls, 1=%ls, 2=%ls, 3=%ls, C=%d\n", strAction, strParam1, strParam2, strParam3, iError);
break;
}
}
}
}
}
CloseHandle(hScriptFile);
}
}
BOOL IsUnicodeFile(IN HANDLE hFile)
{
WCHAR cFirstChar = 0;
ULONG iRead = 0;
if(hFile != INVALID_HANDLE_VALUE &&
ReadFile(hFile, &cFirstChar, sizeof(WCHAR), &iRead, NULL) &&
iRead != 0 &&
cFirstChar == UNICODE_HEAD)
{
return(TRUE);
}
return(FALSE);
}
BOOL ReadLine(IN HANDLE hFile, IN WCHAR* strLine)
{
static WCHAR strBuffer[SUPER_LENGTH + 1];
static LONG iLength = 0;
static LONG iReadChar = 0;
static ULONG iRead = 0;
static LONG iOffset = 0;
static LONG iThisLineLength = 0;
static WCHAR* strThisLine = NULL;
if(iLength > 0)
{
// char 0xA is set to 0
strThisLine = wcstok(strBuffer + iReadChar - iLength, CRETURN);
iThisLineLength = wcslen(strThisLine);
if(iThisLineLength + 1 <= iLength)
{
// char 0xD is set to 0
strThisLine[iThisLineLength - 1] = 0;
wcscpy(strLine, strThisLine);
iLength = iLength - iThisLineLength - 1;
}
else
{
wcsncpy(strLine, strThisLine, iLength);
// set the last char + 1 to 0 for cat
strLine[iLength] = 0;
if(iLength <= 0 || strLine[iLength - 1] != ENDOFLINE[0])
{
ReadFile(hFile, strBuffer, SUPER_LENGTH * sizeof(WCHAR), &iRead, NULL);
iReadChar = iRead / sizeof(WCHAR);
// char 0xA is set to 0
strThisLine = wcstok(strBuffer, CRETURN);
iThisLineLength = wcslen(strThisLine);
iLength = iReadChar - iThisLineLength - 1;
// char 0xD is set to 0
strThisLine[iThisLineLength - 1] = 0;
wcscat(strLine, strThisLine);
if(strBuffer[0] == CRETURN[0])
{
iLength -= 1;
}
}
else
{
strLine[iLength - 1] = 0;
iLength = 0;
}
}
}
else
{
if(ReadFile(hFile, strBuffer, SUPER_LENGTH * sizeof(WCHAR), &iRead, NULL) && iRead != 0)
{
iReadChar = iRead / sizeof(WCHAR);
// char 0xA is set to 0
strThisLine = wcstok(strBuffer, CRETURN);
iThisLineLength = wcslen(strThisLine);
iLength = iReadChar - iThisLineLength - 1;
// char 0xD is set to 0
strThisLine[iThisLineLength - 1] = 0;
wcscpy(strLine, strThisLine);
if(strBuffer[0] == CRETURN[0])
{
iLength -= 1;
}
}
else
{
return(FALSE);
}
}
return(TRUE);
}
BOOL CopyThisFile(IN WCHAR* strFrom, IN WCHAR* strTo)
{
BOOL blnReturn = TRUE;
blnReturn = CopyFileW(strFrom, strTo, TRUE);
return(blnReturn);
}
BOOL MoveThisFile(IN WCHAR* strFrom, IN WCHAR* strTo)
{
BOOL blnReturn = FALSE;
DWORD iAttrib = GetFileAttributesW(strFrom);
if(iAttrib != 0xFFFFFFFF)
{
blnReturn = SetFileAttributesW(strFrom, FILE_ATTRIBUTE_ARCHIVE);
blnReturn &= MoveFileW(strFrom, strTo);
blnReturn &= SetFileAttributesW(strTo, iAttrib);
}
return(blnReturn);
}
BOOL CreateZeroFile(IN WCHAR* strFile)
{
BOOL blnReturn = TRUE;
HANDLE hFile = CreateFileW(strFile,
GENERIC_READ | GENERIC_WRITE,
0, NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if((blnReturn = (hFile != INVALID_HANDLE_VALUE)) == TRUE)
{
CloseHandle(hFile);
}
return(blnReturn);
}
BOOL PatchFile(IN WCHAR* strOldFile, IN WCHAR* strPatchFile, IN WCHAR* strNewFile)
{
BOOL blnReturn = TRUE;
blnReturn = ApplyPatchToFileW(strPatchFile,
strOldFile,
strNewFile,
0);
return(blnReturn);
}
BOOL CreateThisDirectory(IN WCHAR* strDirectory, IN WCHAR* strAttrib)
{
BOOL blnReturn = TRUE;
blnReturn = (_wmkdir(strDirectory) == 0 || errno == 17 /*EEXIST*/);
if(blnReturn && strAttrib)
{
DWORD iAttrib = 0;
for(UINT i = 0; i < wcslen(strAttrib); i++)
{
switch(strAttrib[i])
{
case DIR_C_READONLY:
iAttrib |= FILE_ATTRIBUTE_READONLY;
break;
case DIR_C_SYSTEM:
iAttrib |= FILE_ATTRIBUTE_SYSTEM;
break;
case DIR_C_HIDDEN:
iAttrib |= FILE_ATTRIBUTE_HIDDEN;
break;
case DIR_C_COMPRESSED:
iAttrib |= FILE_ATTRIBUTE_COMPRESSED;
break;
case DIR_C_ENCRYPTED:
iAttrib |= FILE_ATTRIBUTE_ENCRYPTED;
break;
default:
break;
}
}
SetFileAttributesW(strDirectory, iAttrib);
}
return(blnReturn);
}
BOOL DeleteThisDirectory(IN WCHAR* strDirectory)
{
INT length = 0;
BOOL result = TRUE;
HANDLE findHandle = INVALID_HANDLE_VALUE;
WIN32_FIND_DATAW file;
WCHAR path[MAXPATH + 7];
if((length = wcslen(strDirectory)) > MAXPATH)
{
result = FALSE;
goto done;
}
wcscpy(path, strDirectory);
if(length)
{
if((path[length - 1] != '\\') AND (path[length - 1] != ':'))
{
wcscpy(path + length, L"\\");
length++;
}
}
wcscpy(path + length, L"*.*");
findHandle = FindFirstFileW(path, &file);
if(findHandle == INVALID_HANDLE_VALUE)
{
result = FALSE;
}
path[length] = L'\0';
while(result)
{
if((file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY &&
wcscmp(file.cFileName, L".") != 0 &&
wcscmp(file.cFileName, L"..") != 0)
{
/* recursively going into this directory */
wcscpy(path + length, file.cFileName);
DeleteThisDirectory(path);
}
else
{
wcscpy(path + length, file.cFileName);
if(!DeleteFileW(path))
{
SetFileAttributesW(path, FILE_ATTRIBUTE_ARCHIVE);
DeleteFileW(path);
}
}
path[length] = 0;
if(!FindNextFileW(findHandle, &file))
{
result = FALSE;
}
}
/* All files are examed, close the findhandle */
if(findHandle != INVALID_HANDLE_VALUE)
{
FindClose(findHandle);
findHandle = INVALID_HANDLE_VALUE;
}
done:
/* finally remove the directory */
return(RemoveDirectoryW(path));
}