⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 initmv.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
字号:
/* $Id: initmv.c 23684 2006-08-24 11:06:48Z fireball $
 *
 * PROJECT:         ReactOS Operating System
 * LICENSE:         GPL - See COPYING in the top level directory
 * FILE:            base/system/smss/initmv.c
 * PURPOSE:         Process the file rename list.
 * PROGRAMMERS:     Dmitry Philippov (shedon@mail.ru)
 * UPDATE HISTORY:
 *                  Created 13/08/2006
 */

 
/* INCLUDES ******************************************************************/
#include "smss.h"

#define NDEBUG
#include <debug.h>


/* FUNCTIONS *****************************************************************/

/*++
* @name SmpDeleteFile
* 
* The SmpDeleteFile function deletes a specify file.
* 
* @param    lpFileName
*           the name of a file which should be deleted
*
* @return   STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
*           othwerwise.
*
* @remarks 
* This function is called by SmpMoveFilesQueryRoutine().
*
*
*--*/
NTSTATUS
SmpDeleteFile( IN LPCWSTR lpFileName )
{
	FILE_DISPOSITION_INFORMATION FileDispInfo;
	OBJECT_ATTRIBUTES ObjectAttributes;
	IO_STATUS_BLOCK IoStatusBlock;
	UNICODE_STRING FileNameU;
	HANDLE FileHandle;
	NTSTATUS Status;

	DPRINT("SmpDeleteFile ( %S )\n", lpFileName);

	if( !lpFileName )
		return (STATUS_INVALID_PARAMETER);

	RtlInitUnicodeString(&FileNameU, lpFileName);

	InitializeObjectAttributes(&ObjectAttributes,
		&FileNameU,
		OBJ_CASE_INSENSITIVE,
		NULL,
		NULL);

	Status = NtCreateFile (&FileHandle,
		DELETE,
		&ObjectAttributes,
		&IoStatusBlock,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);

	RtlFreeUnicodeString(&FileNameU);

	if( !NT_SUCCESS(Status) ) {
		DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
		return (Status);
	}

	FileDispInfo.DeleteFile = TRUE;

	Status = NtSetInformationFile(
		FileHandle,
		&IoStatusBlock,
		&FileDispInfo,
		sizeof(FILE_DISPOSITION_INFORMATION),
		FileDispositionInformation );

	NtClose(FileHandle);

	return (Status);
}


/*++
* @name SmpMoveFile
* 
* The SmpMoveFile function deletes a specify file.
* 
* @param	lpExistingFileName
*			the name of an existing file which should be removed
*
* @param	lpNewFileName
*			a new name of an existing file.
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
*         othwerwise.
*
* @remarks 
* This function called from the SmpMoveFilesQueryRoutine function.
*
*
*--*/
NTSTATUS
SmpMoveFile( IN LPCWSTR lpExistingFileName,
			 IN LPCWSTR	lpNewFileName
			 )
{
	PFILE_RENAME_INFORMATION FileRenameInfo;
	OBJECT_ATTRIBUTES ObjectAttributes;
	IO_STATUS_BLOCK IoStatusBlock;
	UNICODE_STRING ExistingFileNameU;
	HANDLE FileHandle;
	DWORD FileNameSize;
	BOOLEAN ReplaceIfExists;
	NTSTATUS Status;

	if( !lpExistingFileName || !lpNewFileName )
		return (STATUS_INVALID_PARAMETER);

	DPRINT("SmpMoveFile (%S, %S)\n", lpExistingFileName, lpNewFileName);

	RtlInitUnicodeString(&ExistingFileNameU, lpExistingFileName);

	InitializeObjectAttributes(&ObjectAttributes,
		&ExistingFileNameU,
		OBJ_CASE_INSENSITIVE,
		NULL,
		NULL);

	Status = NtCreateFile (&FileHandle,
		FILE_ALL_ACCESS,
		&ObjectAttributes,
		&IoStatusBlock,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0);

	if( !NT_SUCCESS(Status) ) {
		DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
		return (Status);
	}

	FileNameSize = wcslen(lpNewFileName)*sizeof(*lpNewFileName);
	FileRenameInfo = RtlAllocateHeap(
		RtlGetProcessHeap(),
		HEAP_ZERO_MEMORY,
		sizeof(FILE_RENAME_INFORMATION)+FileNameSize);
	if( !FileRenameInfo ) {
		DPRINT("RtlAllocateHeap failed\n");
		NtClose(FileHandle);
		return (STATUS_NO_MEMORY);
	}

	if( L'!' == *lpNewFileName ) {
		lpNewFileName++;
		FileNameSize -= sizeof(*lpNewFileName);
		ReplaceIfExists = TRUE;
	}
	else {
		ReplaceIfExists = FALSE;
	}

	FileRenameInfo->RootDirectory = NULL;
	FileRenameInfo->ReplaceIfExists = ReplaceIfExists;
	FileRenameInfo->FileNameLength = FileNameSize;
	RtlCopyMemory(FileRenameInfo->FileName, lpNewFileName, FileNameSize);

	Status = NtSetInformationFile(
		FileHandle,
		&IoStatusBlock,
		FileRenameInfo,
		sizeof(FILE_RENAME_INFORMATION)+FileNameSize,
		FileRenameInformation );

	RtlFreeHeap(RtlGetProcessHeap(), 0, FileRenameInfo);

	/* FIXME: After the FileRenameInformation parameter will be implemented into the fs driver
	the following code can be removed */
	if( STATUS_NOT_IMPLEMENTED == Status )
	{
		HANDLE FileHandleNew;
		UNICODE_STRING NewFileNameU;
		FILE_BASIC_INFORMATION FileBasicInfo;
		UCHAR *lpBuffer = NULL;
		SIZE_T RegionSize = 0x10000;
		LARGE_INTEGER BytesCopied;
		BOOL EndOfFileFound;

		Status = NtQueryInformationFile(
			FileHandle,
			&IoStatusBlock,
			&FileBasicInfo,
			sizeof(FILE_BASIC_INFORMATION),
			FileBasicInformation);
		if( !NT_SUCCESS(Status) ) {
			DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
			NtClose(FileHandle);
			return (Status);
		}

		RtlInitUnicodeString(&NewFileNameU, lpNewFileName);

		InitializeObjectAttributes(&ObjectAttributes,
			&NewFileNameU,
			OBJ_CASE_INSENSITIVE,
			NULL,
			NULL);

		Status = NtCreateFile (&FileHandleNew,
			FILE_ALL_ACCESS,
			&ObjectAttributes,
			&IoStatusBlock,
			NULL,
			FILE_ATTRIBUTE_NORMAL,
			FILE_SHARE_READ | FILE_SHARE_WRITE,
			ReplaceIfExists ? FILE_OVERWRITE_IF : FILE_CREATE,
			FILE_SYNCHRONOUS_IO_NONALERT,
			NULL,
			0);

		if( !NT_SUCCESS(Status) ) {
			DPRINT("NtCreateFile() failed (Status %lx)\n", Status);
			NtClose(FileHandle);
			return (Status);
		}

		Status = NtAllocateVirtualMemory(
			NtCurrentProcess(),
			(PVOID *)&lpBuffer,
			2,
			&RegionSize,
			MEM_RESERVE | MEM_COMMIT,
			PAGE_READWRITE);
		if( !NT_SUCCESS(Status) ) {
			DPRINT("NtAllocateVirtualMemory() failed (Status %lx)\n", Status);
			NtClose(FileHandle);
			SmpDeleteFile(lpNewFileName);
			return (Status);
		}
		BytesCopied.QuadPart = 0;
		EndOfFileFound = FALSE;
		while( !EndOfFileFound
			&& NT_SUCCESS(Status) )
		{
			Status = NtReadFile(FileHandle,
				NULL,
				NULL,
				NULL,
				&IoStatusBlock,
				lpBuffer,
				RegionSize,
				NULL,
				NULL);
			if( NT_SUCCESS(Status) ) {
				Status = NtWriteFile(FileHandleNew,
					NULL,
					NULL,
					NULL,
					&IoStatusBlock,
					lpBuffer,
					IoStatusBlock.Information,
					NULL,
					NULL);
				if( NT_SUCCESS(Status) ) {
					BytesCopied.QuadPart += IoStatusBlock.Information;
				}
				else {
					DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
				}
			}
			else {
				if( STATUS_END_OF_FILE == Status ) {
					EndOfFileFound = TRUE;
					Status = STATUS_SUCCESS;
				}
				else {
					DPRINT("NtWriteFile() failed (Status %lx)\n", Status);
				}
			}
		}

		NtFreeVirtualMemory(NtCurrentProcess(),
			(PVOID *)&lpBuffer,
			&RegionSize,
			MEM_RELEASE);

		Status = NtQueryInformationFile(
			FileHandleNew,
			&IoStatusBlock,
			&FileBasicInfo,
			sizeof(FILE_BASIC_INFORMATION),
			FileBasicInformation);
		if( !NT_SUCCESS(Status) ) {
			DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status);
		}

		Status = NtSetInformationFile(FileHandleNew,
			&IoStatusBlock,
			&FileBasicInfo,
			sizeof(FILE_BASIC_INFORMATION),
			FileBasicInformation);
		if( !NT_SUCCESS(Status) ) {
			DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
		}
		NtClose(FileHandleNew);
		NtClose(FileHandle);

		SmpDeleteFile(lpExistingFileName);

		return (Status);
	}

	NtClose(FileHandle);

	return (Status);
}


/*++
* @name SmpMoveFilesQueryRoutine
* 
* The SmpMoveFilesQueryRoutine function processes registry entries.
* 
* @param    ValueName
*           The name of the value.
*
* @param    ValueType
*           The type of the value.
*
* @param    ValueData
*           The null-terminated data for the value.
*
* @param    ValueLength
*           The length of ValueData.
*
* @param    Context
*           NULL
*
* @param    EntryContext
*           NULL
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
*         othwerwise.
*
* @remarks 
*
*
*
*--*/
static NTSTATUS STDCALL
SmpMoveFilesQueryRoutine(IN PWSTR ValueName,
                         IN ULONG ValueType,
                         IN PVOID ValueData,
                         IN ULONG ValueLength,
                         IN PVOID Context,
                         IN PVOID EntryContext)
{
	NTSTATUS Status;
	static LPWSTR FistFileName = NULL;

	DPRINT("SmpMoveFilesQueryRoutine() called \n");
	DPRINT("ValueData = %S \n", ValueData);

	if( !FistFileName )
	{
		/* save a first file name */
		FistFileName = ValueData;
		Status = STATUS_SUCCESS;
	}
	else
	{
		if( 0 == *((LPWSTR)ValueData) ) {
			/* delete if second file name is absent */
			Status = SmpDeleteFile( FistFileName );
		} else {
			/* remove a file */
			Status = SmpMoveFile( FistFileName, (LPCWSTR)ValueData );
		}
		FistFileName = NULL;
	}

	return Status;
}


/*++
* @name SmProcessFileRenameList
* @implemented
* 
* The SmProcessFileRenameList function moves or deletes files thats have been added to the specify registry key for delayed moving.
* 
* @param	VOID
*
* @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
*         othwerwise.
*
* @remarks 
* This function reads the following registry value:
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations
* This registry value is of type REG_MULTI_SZ. The each operation is specifed as two file names.
* A first name is a source file, a second name is a destination file.
* In the case of deleting operation a second file name must be the empty string.
* For exapmle:
* szxSrcFile\0szxDestFile\0\0		<-- the szxSrcFile file will be renamed to the szxDestFile file
* szxSomeFile\0\0\0					<-- the szxSomeFile file will be removed
* After it will be done, the registry value will be deleted.
*
*
*--*/
NTSTATUS
SmProcessFileRenameList( VOID )
{
	RTL_QUERY_REGISTRY_TABLE QueryTable[2];
	NTSTATUS Status;

	DPRINT("SmProcessFileRenameList() called\n");

	RtlZeroMemory( &QueryTable, sizeof(QueryTable) );
	QueryTable[0].Name = L"PendingFileRenameOperations";
	QueryTable[0].Flags = RTL_QUERY_REGISTRY_DELETE;
	QueryTable[0].DefaultType = REG_NONE;
	QueryTable[0].QueryRoutine = SmpMoveFilesQueryRoutine;

	Status = RtlQueryRegistryValues(
		RTL_REGISTRY_CONTROL,
		L"\\Session Manager",
		QueryTable,
		NULL,
		NULL);

	if( !NT_SUCCESS(Status) ) {
		DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
	}

	/* FIXME: RtlQueryRegistryValues can return an error status if the PendingFileRenameOperations value
	does not exist, in this case smss hungs, therefore we always return STATUS_SUCCESS */
	return (STATUS_SUCCESS);
}

/* EOF */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -