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

📄 move.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: move.c 28083 2007-08-01 22:04:04Z cwittich $
 *
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS system libraries
 * FILE:            lib/kernel32/file/file.c
 * PURPOSE:         Directory functions
 * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
 *                  Gerhard W. Gruber (sparhawk_at_gmx.at)
 *                  Dmitry Philippov (shedon@mail.ru)
 * UPDATE HISTORY:
 *                  Created 01/11/98
 *                  DP (29/07/2006)
 *                      Fix some bugs in the add_boot_rename_entry function
 */

/* INCLUDES *****************************************************************/

#include <k32.h>
#include <malloc.h>

#define NDEBUG
#include "../include/debug.h"

/* GLOBALS *****************************************************************/

/* FUNCTIONS ****************************************************************/
static BOOL
RemoveReadOnlyAttributeW(IN LPCWSTR lpFileName)
{
    DWORD Attributes;
    Attributes = GetFileAttributesW(lpFileName);
    if (Attributes != INVALID_FILE_ATTRIBUTES)
    {	
        return SetFileAttributesW(lpFileName,Attributes - 
			                      (Attributes & ~FILE_ATTRIBUTE_READONLY));
    }
 
    return FALSE;
}


/***********************************************************************
 *           add_boot_rename_entry
 *
 * Adds an entry to the registry that is loaded when windows boots and
 * checks if there are some files to be removed or renamed/moved.
 * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
 * non-NULL then the file is moved, otherwise it is deleted.  The
 * entry of the registrykey is always appended with two zero
 * terminated strings. If <fn2> is NULL then the second entry is
 * simply a single 0-byte. Otherwise the second filename goes
 * there. The entries are prepended with \??\ before the path and the
 * second filename gets also a '!' as the first character if
 * MOVEFILE_REPLACE_EXISTING is set. After the final string another
 * 0-byte follows to indicate the end of the strings.
 * i.e.:
 * \??\D:\test\file1[0]
 * !\??\D:\test\file1_renamed[0]
 * \??\D:\Test|delete[0]
 * [0]                        <- file is to be deleted, second string empty
 * \??\D:\test\file2[0]
 * !\??\D:\test\file2_renamed[0]
 * [0]                        <- indicates end of strings
 *
 * or:
 * \??\D:\test\file1[0]
 * !\??\D:\test\file1_renamed[0]
 * \??\D:\Test|delete[0]
 * [0]                        <- file is to be deleted, second string empty
 * [0]                        <- indicates end of strings
 *
 */
static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags )
{
    static const WCHAR ValueName[] = {'P','e','n','d','i','n','g',
                                      'F','i','l','e','R','e','n','a','m','e',
                                      'O','p','e','r','a','t','i','o','n','s',0};

    UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager");

    static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data );

    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING nameW, source_name, dest_name;
    KEY_VALUE_PARTIAL_INFORMATION *info;
    BOOL rc = FALSE;
    HANDLE Reboot = NULL;
    DWORD len1, len2;
    DWORD DestLen = 0;
    DWORD DataSize = 0;
    BYTE *Buffer = NULL;
    WCHAR *p;
    NTSTATUS Status;

    DPRINT("add_boot_rename_entry( %S, %S, %d ) \n", source, dest, flags);

    if(dest)
        DestLen = wcslen(dest);

    if (!RtlDosPathNameToNtPathName_U( source, &source_name, NULL, NULL ))
    {
        SetLastError( ERROR_PATH_NOT_FOUND );
        return FALSE;
    }
    dest_name.Buffer = NULL;
    if (DestLen && !RtlDosPathNameToNtPathName_U( dest, &dest_name, NULL, NULL ))
    {
        RtlFreeHeap( RtlGetProcessHeap(), 0, source_name.Buffer );
        SetLastError( ERROR_PATH_NOT_FOUND );
        return FALSE;
    }

    InitializeObjectAttributes(&ObjectAttributes,
                               &KeyName,
                               OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);

     Status = NtCreateKey(&Reboot, 
                          KEY_QUERY_VALUE | KEY_SET_VALUE,
                          &ObjectAttributes,
                          0,
                          NULL,
                          REG_OPTION_NON_VOLATILE,
                          NULL);

     if (Status == STATUS_ACCESS_DENIED)
     {
         Status = NtCreateKey(
             &Reboot, 
             KEY_QUERY_VALUE | KEY_SET_VALUE,
             &ObjectAttributes,
             0,
             NULL,
             REG_OPTION_BACKUP_RESTORE,
             NULL);
     }

    if (!NT_SUCCESS(Status))
    {
        DPRINT("NtCreateKey() failed (Status 0x%lx)\n", Status);
        if (source_name.Buffer)
            RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer);
        if (dest_name.Buffer)
            RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer);
        return FALSE;
    }

    len1 = source_name.Length + sizeof(WCHAR);
    if (DestLen)
    {
        len2 = dest_name.Length + sizeof(WCHAR);
        if (flags & MOVEFILE_REPLACE_EXISTING)
            len2 += sizeof(WCHAR); /* Plus 1 because of the leading '!' */
    }
    else
    {
        len2 = sizeof(WCHAR); /* minimum is the 0 characters for the empty second string */
    }

    RtlInitUnicodeString( &nameW, ValueName );

    /* First we check if the key exists and if so how many bytes it already contains. */
    Status = NtQueryValueKey(
        Reboot,
        &nameW,
        KeyValuePartialInformation,
        NULL,
        0, 
        &DataSize );
    if ((Status == STATUS_BUFFER_OVERFLOW) ||
        (Status == STATUS_BUFFER_TOO_SMALL))
    {
        if (!(Buffer = HeapAlloc(GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR))))
            goto Quit;
        Status = NtQueryValueKey(Reboot, &nameW, KeyValuePartialInformation,
            Buffer, DataSize, &DataSize);
        if(!NT_SUCCESS(Status))
            goto Quit;
        info = (KEY_VALUE_PARTIAL_INFORMATION *)Buffer;
        if (info->Type != REG_MULTI_SZ) goto Quit;
        if (DataSize > sizeof(info)) DataSize -= sizeof(WCHAR);  /* remove terminating null (will be added back later) */
    }
    else
    {
        DataSize = info_size;
        if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
            goto Quit;
    }

    memcpy( Buffer + DataSize, source_name.Buffer, len1 );
    DataSize += len1;
    p = (WCHAR *)(Buffer + DataSize);
    if (DestLen)
    {
        if (flags & MOVEFILE_REPLACE_EXISTING)
            *p++ = '!';
        memcpy( p, dest_name.Buffer, len2 );
        DataSize += len2;
    }
    else
    {
        *p = 0;
        DataSize += sizeof(WCHAR);
    }

    /* add final null */
    p = (WCHAR *)(Buffer + DataSize);
    *p = 0;
    DataSize += sizeof(WCHAR);

    rc = NT_SUCCESS(NtSetValueKey(Reboot, &nameW, 0, REG_MULTI_SZ, Buffer + info_size, DataSize - info_size));

 Quit:
    RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer);
    if (dest_name.Buffer)
        RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer);
    NtClose(Reboot);
    if(Buffer)
        HeapFree(GetProcessHeap(), 0, Buffer);
    return(rc);
}


/*
 * @implemented
 */
BOOL
STDCALL
MoveFileWithProgressW (
	LPCWSTR			lpExistingFileName,
	LPCWSTR			lpNewFileName,
	LPPROGRESS_ROUTINE	lpProgressRoutine,
	LPVOID			lpData,
	DWORD			dwFlags
	)
{
	HANDLE hFile = NULL;
	IO_STATUS_BLOCK IoStatusBlock;
	PFILE_RENAME_INFORMATION FileRename;
	NTSTATUS errCode;
	BOOL Result;
	UNICODE_STRING DstPathU;
	BOOL folder = FALSE;

	DPRINT("MoveFileWithProgressW()\n");

	if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT)
		return add_boot_rename_entry( lpExistingFileName, lpNewFileName, dwFlags );

	hFile = CreateFileW (lpExistingFileName,
	                     GENERIC_ALL,
	                     FILE_SHARE_WRITE|FILE_SHARE_READ,
	                     NULL,
	                     OPEN_EXISTING,
	                     FILE_FLAG_BACKUP_SEMANTICS,
	                     NULL);

	if (hFile == INVALID_HANDLE_VALUE)
	{
	   return FALSE;
	}

	
        /* validate & translate the filename */
        if (!RtlDosPathNameToNtPathName_U (lpNewFileName,
				           &DstPathU,
				           NULL,
				           NULL))
        {
           DPRINT("Invalid destination path\n");
	   CloseHandle(hFile);
           SetLastError(ERROR_PATH_NOT_FOUND);
           return FALSE;
        }

	FileRename = RtlAllocateHeap(
		RtlGetProcessHeap(),
		HEAP_ZERO_MEMORY,
		sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length);
	if( !FileRename ) {
		CloseHandle(hFile);
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}
	if( dwFlags & MOVEFILE_REPLACE_EXISTING ) {
		FileRename->ReplaceIfExists = TRUE;
	}
	else {
		FileRename->ReplaceIfExists = FALSE;
	}


	memcpy(FileRename->FileName, DstPathU.Buffer, DstPathU.Length);
        RtlFreeHeap (RtlGetProcessHeap (),
		     0,
		     DstPathU.Buffer);

	FileRename->FileNameLength = DstPathU.Length;
	errCode = NtSetInformationFile (hFile,
	                                &IoStatusBlock,
	                                FileRename,
	                                sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length,
	                                FileRenameInformation);
	CloseHandle(hFile);
	RtlFreeHeap(RtlGetProcessHeap(), 0, FileRename);

	if (GetFileAttributesW(lpExistingFileName) & FILE_ATTRIBUTE_DIRECTORY)
	{
           folder = TRUE;
	}

	
	/*
	 *  FIXME:
	 *  Fail now move the folder 
	 *  Before we fail at CreateFileW 
	 */
	 
	 
	if (NT_SUCCESS(errCode))
	{
		Result = TRUE;
	}
	else 
	{
 	        if (folder==FALSE)
		{
		    Result = CopyFileExW (lpExistingFileName,
		                      lpNewFileName,
		                      lpProgressRoutine,
		                      lpData,
		                      NULL,
		                      (dwFlags & MOVEFILE_REPLACE_EXISTING) ? 0 : COPY_FILE_FAIL_IF_EXISTS);
 		    if (Result)
		    {
			/* Cleanup the source file */			
	                Result = DeleteFileW (lpExistingFileName);
		    }
                  }
		 else
		 {
		   /* move folder code start */
		   WIN32_FIND_DATAW findBuffer;
		   LPWSTR lpExistingFileName2 = NULL;
		   LPWSTR lpNewFileName2 = NULL; 
		   LPWSTR lpDeleteFile = NULL;
		   INT size;
		   INT size2;
		   BOOL loop = TRUE;
		   BOOL Result = FALSE;
		   INT max_size = MAX_PATH;


		   		   /* Build the string */
		   size = wcslen(lpExistingFileName); 
		   if (size+6> max_size)
			   max_size = size + 6;

		   lpDeleteFile = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
		   if (lpDeleteFile == NULL)		   
		       return FALSE;		  		  

		   lpNewFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
		   if (lpNewFileName2 == NULL)
		   {		
		     HeapFree(GetProcessHeap(),0,(VOID *)  lpDeleteFile);
			 return FALSE;
		   }

		   lpExistingFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
		   if (lpNewFileName2 == NULL)
		   {		
		     HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);		  	  		    		
		     HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);		
		     return FALSE;
		   }		   		   
		
		   wcscpy( (WCHAR *)lpExistingFileName2,lpExistingFileName);
		   wcscpy( (WCHAR *)&lpExistingFileName2[size],L"\\*.*\0");
	  

⌨️ 快捷键说明

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