windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/w95upgnt/commonnt/file.c
2020-09-26 16:20:57 +08:00

237 lines
5.3 KiB
C

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
file.c
Abstract:
General file-related functions.
Author:
Souren Aghajanyan 12-Jul-2001
Revision History:
sourenag 12-Jul-2001 RenameOperation supports function
--*/
#include "pch.h"
#define UNDO_FILE_NAME L"UNDO_GUIMODE.TXT"
BOOL
pRenameOnRestartOfGuiMode (
IN OUT HANDLE *UndoHandlePtr, OPTIONAL
IN PCWSTR PathName,
IN PCWSTR PathNameNew OPTIONAL
)
{
DWORD dontCare;
BOOL result;
static WCHAR undoFilePath[MAX_PATH];
BYTE signUnicode[] = {0xff, 0xfe};
DWORD filePos;
HANDLE undoHandle;
if (!PathName) {
MYASSERT (FALSE);
return FALSE;
}
if (!UndoHandlePtr || !(*UndoHandlePtr)) {
if (!undoFilePath[0]) {
//
// Create the path to the journal file
//
wsprintfW (undoFilePath, L"%s\\" UNDO_FILE_NAME, g_System32Dir);
}
//
// Open the journal file
//
undoHandle = CreateFileW (
undoFilePath,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (undoHandle == INVALID_HANDLE_VALUE) {
LOG ((LOG_ERROR, "Failed to open journal file %s", undoFilePath));
return FALSE;
}
MYASSERT (undoHandle); // never NULL
} else {
undoHandle = *UndoHandlePtr;
}
//
// Move to the end of the journal, and if the journal is empty, write the UNICODE header
//
filePos = SetFilePointer (undoHandle, 0, NULL, FILE_END);
if (!filePos) {
result = WriteFile (undoHandle, signUnicode, sizeof(signUnicode), &dontCare, NULL);
} else {
result = TRUE;
}
//
// Output the move or delete operation
//
result = result && WriteFile (
undoHandle,
L"\\??\\",
8,
&dontCare,
NULL
);
result = result && WriteFile (
undoHandle,
PathName,
ByteCountW (PathName),
&dontCare,
NULL
);
result = result && WriteFile (
undoHandle,
L"\r\n",
4,
&dontCare,
NULL
);
if (PathNameNew) {
result = result && WriteFile (
undoHandle,
L"\\??\\",
8,
&dontCare,
NULL
);
result = result && WriteFile (
undoHandle,
PathNameNew,
ByteCountW (PathNameNew),
&dontCare,
NULL
);
}
result = result && WriteFile (
undoHandle,
L"\r\n",
4,
&dontCare,
NULL
);
if (!result) {
//
// On failure, log an error and truncate the file
//
LOGW ((
LOG_ERROR,
"Failed to record move in restart journal: %s to %s",
PathName,
PathNameNew
));
SetFilePointer (undoHandle, filePos, NULL, FILE_BEGIN);
SetEndOfFile (undoHandle);
}
if (UndoHandlePtr) {
if (!(*UndoHandlePtr)) {
//
// If caller did not pass in handle, then we opened it.
//
if (result) {
*UndoHandlePtr = undoHandle; // give ownership to caller
} else {
FlushFileBuffers (undoHandle);
CloseHandle (undoHandle); // fail; don't leak handle
}
}
} else {
//
// Caller wants to record just one move
//
FlushFileBuffers (undoHandle);
CloseHandle (undoHandle);
}
return result;
}
BOOL
RenameOnRestartOfGuiMode (
IN PCWSTR PathName,
IN PCWSTR PathNameNew OPTIONAL
)
{
return pRenameOnRestartOfGuiMode (NULL, PathName, PathNameNew);
}
BOOL
RenameListOnRestartOfGuiMode (
IN PGROWLIST SourceList,
IN PGROWLIST DestList
)
{
UINT u;
UINT count;
PCWSTR source;
PCWSTR dest;
HANDLE journal = NULL;
count = GrowListGetSize (SourceList);
for (u = 0 ; u < count ; u++) {
source = GrowListGetString (SourceList, u);
if (!source) {
continue;
}
dest = GrowListGetString (DestList, u);
if (!pRenameOnRestartOfGuiMode (&journal, source, dest)) {
break;
}
}
if (journal) {
FlushFileBuffers (journal);
CloseHandle (journal);
}
return u == count;
}