237 lines
5.3 KiB
C
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;
|
||
|
}
|
||
|
|
||
|
|