ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

move.c
Go to the documentation of this file.
00001 /* $Id: move.c 54326 2011-11-07 00:18:13Z ion $
00002  *
00003  * COPYRIGHT:       See COPYING in the top level directory
00004  * PROJECT:         ReactOS system libraries
00005  * FILE:            lib/kernel32/file/file.c
00006  * PURPOSE:         Directory functions
00007  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
00008  *                  Gerhard W. Gruber (sparhawk_at_gmx.at)
00009  *                  Dmitry Philippov (shedon@mail.ru)
00010  * UPDATE HISTORY:
00011  *                  Created 01/11/98
00012  *                  DP (29/07/2006)
00013  *                      Fix some bugs in the add_boot_rename_entry function
00014  */
00015 
00016 /* INCLUDES *****************************************************************/
00017 
00018 #include <k32.h>
00019 #include <malloc.h>
00020 #define NDEBUG
00021 #include <debug.h>
00022 DEBUG_CHANNEL(kernel32file);
00023 
00024 /* GLOBALS *****************************************************************/
00025 
00026 /* FUNCTIONS ****************************************************************/
00027 static BOOL
00028 RemoveReadOnlyAttributeW(IN LPCWSTR lpFileName)
00029 {
00030     DWORD Attributes;
00031     Attributes = GetFileAttributesW(lpFileName);
00032     if (Attributes != INVALID_FILE_ATTRIBUTES)
00033     {   
00034         return SetFileAttributesW(lpFileName,Attributes - 
00035                                   (Attributes & ~FILE_ATTRIBUTE_READONLY));
00036     }
00037  
00038     return FALSE;
00039 }
00040 
00041 
00042 /***********************************************************************
00043  *           add_boot_rename_entry
00044  *
00045  * Adds an entry to the registry that is loaded when windows boots and
00046  * checks if there are some files to be removed or renamed/moved.
00047  * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
00048  * non-NULL then the file is moved, otherwise it is deleted.  The
00049  * entry of the registrykey is always appended with two zero
00050  * terminated strings. If <fn2> is NULL then the second entry is
00051  * simply a single 0-byte. Otherwise the second filename goes
00052  * there. The entries are prepended with \??\ before the path and the
00053  * second filename gets also a '!' as the first character if
00054  * MOVEFILE_REPLACE_EXISTING is set. After the final string another
00055  * 0-byte follows to indicate the end of the strings.
00056  * i.e.:
00057  * \??\D:\test\file1[0]
00058  * !\??\D:\test\file1_renamed[0]
00059  * \??\D:\Test|delete[0]
00060  * [0]                        <- file is to be deleted, second string empty
00061  * \??\D:\test\file2[0]
00062  * !\??\D:\test\file2_renamed[0]
00063  * [0]                        <- indicates end of strings
00064  *
00065  * or:
00066  * \??\D:\test\file1[0]
00067  * !\??\D:\test\file1_renamed[0]
00068  * \??\D:\Test|delete[0]
00069  * [0]                        <- file is to be deleted, second string empty
00070  * [0]                        <- indicates end of strings
00071  *
00072  */
00073 static BOOL add_boot_rename_entry( LPCWSTR source, LPCWSTR dest, DWORD flags )
00074 {
00075     static const WCHAR ValueName[] = {'P','e','n','d','i','n','g',
00076                                       'F','i','l','e','R','e','n','a','m','e',
00077                                       'O','p','e','r','a','t','i','o','n','s',0};
00078 
00079     UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager");
00080 
00081     static const int info_size = FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION, Data );
00082 
00083     OBJECT_ATTRIBUTES ObjectAttributes;
00084     UNICODE_STRING nameW, source_name, dest_name;
00085     KEY_VALUE_PARTIAL_INFORMATION *info;
00086     BOOL rc = FALSE;
00087     HANDLE Reboot = NULL;
00088     DWORD len1, len2;
00089     DWORD DestLen = 0;
00090     DWORD DataSize = 0;
00091     BYTE *Buffer = NULL;
00092     WCHAR *p;
00093     NTSTATUS Status;
00094 
00095     TRACE("add_boot_rename_entry( %S, %S, %d ) \n", source, dest, flags);
00096 
00097     if(dest)
00098         DestLen = wcslen(dest);
00099 
00100     if (!RtlDosPathNameToNtPathName_U( source, &source_name, NULL, NULL ))
00101     {
00102         SetLastError( ERROR_PATH_NOT_FOUND );
00103         return FALSE;
00104     }
00105     dest_name.Buffer = NULL;
00106     if (DestLen && !RtlDosPathNameToNtPathName_U( dest, &dest_name, NULL, NULL ))
00107     {
00108         RtlFreeHeap( RtlGetProcessHeap(), 0, source_name.Buffer );
00109         SetLastError( ERROR_PATH_NOT_FOUND );
00110         return FALSE;
00111     }
00112 
00113     InitializeObjectAttributes(&ObjectAttributes,
00114                                &KeyName,
00115                                OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
00116                                NULL,
00117                                NULL);
00118 
00119      Status = NtCreateKey(&Reboot, 
00120                           KEY_QUERY_VALUE | KEY_SET_VALUE,
00121                           &ObjectAttributes,
00122                           0,
00123                           NULL,
00124                           REG_OPTION_NON_VOLATILE,
00125                           NULL);
00126 
00127      if (Status == STATUS_ACCESS_DENIED)
00128      {
00129          Status = NtCreateKey(
00130              &Reboot, 
00131              KEY_QUERY_VALUE | KEY_SET_VALUE,
00132              &ObjectAttributes,
00133              0,
00134              NULL,
00135              REG_OPTION_BACKUP_RESTORE,
00136              NULL);
00137      }
00138 
00139     if (!NT_SUCCESS(Status))
00140     {
00141         WARN("NtCreateKey() failed (Status 0x%lx)\n", Status);
00142         if (source_name.Buffer)
00143             RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer);
00144         if (dest_name.Buffer)
00145             RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer);
00146         return FALSE;
00147     }
00148 
00149     len1 = source_name.Length + sizeof(WCHAR);
00150     if (DestLen)
00151     {
00152         len2 = dest_name.Length + sizeof(WCHAR);
00153         if (flags & MOVEFILE_REPLACE_EXISTING)
00154             len2 += sizeof(WCHAR); /* Plus 1 because of the leading '!' */
00155     }
00156     else
00157     {
00158         len2 = sizeof(WCHAR); /* minimum is the 0 characters for the empty second string */
00159     }
00160 
00161     RtlInitUnicodeString( &nameW, ValueName );
00162 
00163     /* First we check if the key exists and if so how many bytes it already contains. */
00164     Status = NtQueryValueKey(
00165         Reboot,
00166         &nameW,
00167         KeyValuePartialInformation,
00168         NULL,
00169         0, 
00170         &DataSize );
00171     if ((Status == STATUS_BUFFER_OVERFLOW) ||
00172         (Status == STATUS_BUFFER_TOO_SMALL))
00173     {
00174         if (!(Buffer = HeapAlloc(GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR))))
00175             goto Quit;
00176         Status = NtQueryValueKey(Reboot, &nameW, KeyValuePartialInformation,
00177             Buffer, DataSize, &DataSize);
00178         if(!NT_SUCCESS(Status))
00179             goto Quit;
00180         info = (KEY_VALUE_PARTIAL_INFORMATION *)Buffer;
00181         if (info->Type != REG_MULTI_SZ) goto Quit;
00182         if (DataSize > sizeof(info)) DataSize -= sizeof(WCHAR);  /* remove terminating null (will be added back later) */
00183     }
00184     else
00185     {
00186         DataSize = info_size;
00187         if (!(Buffer = HeapAlloc( GetProcessHeap(), 0, DataSize + len1 + len2 + sizeof(WCHAR) )))
00188             goto Quit;
00189     }
00190 
00191     memcpy( Buffer + DataSize, source_name.Buffer, len1 );
00192     DataSize += len1;
00193     p = (WCHAR *)(Buffer + DataSize);
00194     if (DestLen)
00195     {
00196         if (flags & MOVEFILE_REPLACE_EXISTING)
00197             *p++ = '!';
00198         memcpy( p, dest_name.Buffer, len2 );
00199         DataSize += len2;
00200     }
00201     else
00202     {
00203         *p = 0;
00204         DataSize += sizeof(WCHAR);
00205     }
00206 
00207     /* add final null */
00208     p = (WCHAR *)(Buffer + DataSize);
00209     *p = 0;
00210     DataSize += sizeof(WCHAR);
00211 
00212     rc = NT_SUCCESS(NtSetValueKey(Reboot, &nameW, 0, REG_MULTI_SZ, Buffer + info_size, DataSize - info_size));
00213 
00214  Quit:
00215     RtlFreeHeap(RtlGetProcessHeap(), 0, source_name.Buffer);
00216     if (dest_name.Buffer)
00217         RtlFreeHeap(RtlGetProcessHeap(), 0, dest_name.Buffer);
00218     NtClose(Reboot);
00219     if(Buffer)
00220         HeapFree(GetProcessHeap(), 0, Buffer);
00221     return(rc);
00222 }
00223 
00224 
00225 /*
00226  * @implemented
00227  */
00228 BOOL
00229 WINAPI
00230 MoveFileWithProgressW (
00231     LPCWSTR         lpExistingFileName,
00232     LPCWSTR         lpNewFileName,
00233     LPPROGRESS_ROUTINE  lpProgressRoutine,
00234     LPVOID          lpData,
00235     DWORD           dwFlags
00236     )
00237 {
00238     HANDLE hFile = NULL, hNewFile = NULL;
00239     IO_STATUS_BLOCK IoStatusBlock;
00240     OBJECT_ATTRIBUTES ObjectAttributes;
00241     PFILE_RENAME_INFORMATION FileRename;
00242     NTSTATUS errCode;
00243     BOOL Result;
00244     UNICODE_STRING DstPathU;
00245     BOOL folder = FALSE;
00246 
00247     TRACE("MoveFileWithProgressW()\n");
00248 
00249     if (dwFlags & MOVEFILE_DELAY_UNTIL_REBOOT)
00250         return add_boot_rename_entry( lpExistingFileName, lpNewFileName, dwFlags );
00251 
00252 //    if (dwFlags & MOVEFILE_WRITE_THROUGH)
00253 //        FIXME("MOVEFILE_WRITE_THROUGH unimplemented\n");
00254 
00255     if (!lpNewFileName)
00256         return DeleteFileW(lpExistingFileName);
00257 
00258     /* validate & translate the filename */
00259     if (!RtlDosPathNameToNtPathName_U (lpNewFileName,
00260                            &DstPathU,
00261                            NULL,
00262                            NULL))
00263     {
00264         WARN("Invalid destination path\n");
00265         SetLastError(ERROR_PATH_NOT_FOUND);
00266         return FALSE;
00267     }
00268 
00269     InitializeObjectAttributes(&ObjectAttributes,
00270                                &DstPathU,
00271                                OBJ_CASE_INSENSITIVE,
00272                                NULL,
00273                                NULL);
00274 
00275     errCode = NtOpenFile( &hNewFile,
00276                           GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
00277                           &ObjectAttributes,
00278                           &IoStatusBlock,
00279                           0,
00280                           FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT |
00281                           ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0) );
00282 
00283     if (NT_SUCCESS(errCode)) /* Destination exists */
00284     {
00285         NtClose(hNewFile);
00286 
00287         if (!(dwFlags & MOVEFILE_REPLACE_EXISTING))
00288         {
00289             SetLastError(ERROR_ALREADY_EXISTS);
00290             return FALSE;
00291     }
00292     else if (GetFileAttributesW(lpNewFileName) & FILE_ATTRIBUTE_DIRECTORY)
00293     {
00294         SetLastError(ERROR_ACCESS_DENIED);
00295         return FALSE;
00296     }
00297     }
00298 
00299     hFile = CreateFileW (lpExistingFileName,
00300                          GENERIC_ALL,
00301                          FILE_SHARE_WRITE|FILE_SHARE_READ,
00302                          NULL,
00303                          OPEN_EXISTING,
00304                          FILE_FLAG_BACKUP_SEMANTICS |
00305                          ((dwFlags & MOVEFILE_WRITE_THROUGH) ? FILE_FLAG_WRITE_THROUGH : 0),
00306                          NULL);
00307 
00308     if (hFile == INVALID_HANDLE_VALUE)
00309     {
00310         return FALSE;
00311     }
00312 
00313     FileRename = RtlAllocateHeap(
00314         RtlGetProcessHeap(),
00315         HEAP_ZERO_MEMORY,
00316         sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length);
00317     if( !FileRename ) {
00318         CloseHandle(hFile);
00319         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
00320         return FALSE;
00321     }
00322     if( dwFlags & MOVEFILE_REPLACE_EXISTING ) {
00323         FileRename->ReplaceIfExists = TRUE;
00324     }
00325     else {
00326         FileRename->ReplaceIfExists = FALSE;
00327     }
00328 
00329 
00330     memcpy(FileRename->FileName, DstPathU.Buffer, DstPathU.Length);
00331         RtlFreeHeap (RtlGetProcessHeap (),
00332              0,
00333              DstPathU.Buffer);
00334 
00335     FileRename->FileNameLength = DstPathU.Length;
00336     errCode = NtSetInformationFile (hFile,
00337                                     &IoStatusBlock,
00338                                     FileRename,
00339                                     sizeof(FILE_RENAME_INFORMATION) + DstPathU.Length,
00340                                     FileRenameInformation);
00341     CloseHandle(hFile);
00342     RtlFreeHeap(RtlGetProcessHeap(), 0, FileRename);
00343 
00344     if (GetFileAttributesW(lpExistingFileName) & FILE_ATTRIBUTE_DIRECTORY)
00345     {
00346            folder = TRUE;
00347     }
00348 
00349     
00350     /*
00351      *  FIXME:
00352      *  Fail now move the folder 
00353      *  Before we fail at CreateFileW 
00354      */
00355      
00356      
00357     if (NT_SUCCESS(errCode))
00358     {
00359         Result = TRUE;
00360     }
00361     else 
00362     {
00363             if (folder==FALSE)
00364         {
00365             Result = CopyFileExW (lpExistingFileName,
00366                               lpNewFileName,
00367                               lpProgressRoutine,
00368                               lpData,
00369                               NULL,
00370                               (dwFlags & MOVEFILE_REPLACE_EXISTING) ? 0 : COPY_FILE_FAIL_IF_EXISTS);
00371             if (Result)
00372             {
00373             /* Cleanup the source file */           
00374                     Result = DeleteFileW (lpExistingFileName);
00375             }
00376                   }
00377          else
00378          {
00379            /* move folder code start */
00380            WIN32_FIND_DATAW findBuffer;
00381            LPWSTR lpExistingFileName2 = NULL;
00382            LPWSTR lpNewFileName2 = NULL; 
00383            LPWSTR lpDeleteFile = NULL;
00384            INT size;
00385            INT size2;
00386            BOOL loop = TRUE;
00387            BOOL Result = FALSE;
00388            INT max_size = MAX_PATH;
00389 
00390 
00391                    /* Build the string */
00392            size = wcslen(lpExistingFileName); 
00393            if (size+6> max_size)
00394                max_size = size + 6;
00395 
00396            lpDeleteFile = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
00397            if (lpDeleteFile == NULL)           
00398                return FALSE;                  
00399 
00400            lpNewFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
00401            if (lpNewFileName2 == NULL)
00402            {        
00403              HeapFree(GetProcessHeap(),0,(VOID *)  lpDeleteFile);
00404              return FALSE;
00405            }
00406 
00407            lpExistingFileName2 = (LPWSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,max_size * sizeof(WCHAR));
00408            if (lpExistingFileName2 == NULL)
00409            {        
00410              HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);                             
00411              HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);        
00412              return FALSE;
00413            }                   
00414         
00415            wcscpy( (WCHAR *)lpExistingFileName2,lpExistingFileName);
00416            wcscpy( (WCHAR *)&lpExistingFileName2[size],L"\\*.*\0");
00417       
00418            /* Get the file name */
00419            memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
00420            hFile = FindFirstFileW(lpExistingFileName2,  &findBuffer);
00421            if (hFile == INVALID_HANDLE_VALUE) 
00422                loop=FALSE;
00423 
00424            if (findBuffer.cFileName[0] == L'\0')
00425                loop=FALSE;
00426         
00427 
00428             /* FIXME 
00429              * remove readonly flag from source folder and do not set the readonly flag to dest folder 
00430              */
00431            RemoveReadOnlyAttributeW(lpExistingFileName);
00432            RemoveReadOnlyAttributeW(lpNewFileName);
00433            //CreateDirectoryExW(lpExistingFileName,lpNewFileName,NULL);
00434            CreateDirectoryW(lpNewFileName, NULL);
00435                    
00436            /* search the files/folders and move them */
00437            while (loop==TRUE)
00438            {    
00439              Result = TRUE;
00440 
00441              if ((!wcscmp(findBuffer.cFileName,L"..")) || (!wcscmp(findBuffer.cFileName,L".")))
00442              {        
00443                loop = FindNextFileW(hFile, &findBuffer);          
00444                   
00445                if (!loop)
00446                {                     
00447                  size = wcslen(lpExistingFileName2)-4;
00448                  FindClose(hFile);
00449                  hFile = INVALID_HANDLE_VALUE;
00450 
00451                  wcscpy( &lpExistingFileName2[size],L"\0");
00452 
00453                  if (wcsncmp(lpExistingFileName,lpExistingFileName2,size))
00454                  {  
00455                    DWORD Attributes;
00456 
00457                    /* delete folder */                                   
00458                    TRACE("MoveFileWithProgressW : Delete folder : %S\n",lpDeleteFile);
00459 
00460                    /* remove system folder flag other wise we can not delete the folder */
00461                    Attributes = GetFileAttributesW(lpExistingFileName2);
00462                    if (Attributes != INVALID_FILE_ATTRIBUTES)
00463                    {    
00464                      SetFileAttributesW(lpExistingFileName2,(Attributes & ~FILE_ATTRIBUTE_SYSTEM));
00465                    }
00466                    
00467                    RemoveReadOnlyAttributeW(lpExistingFileName2);
00468                                        
00469                    Result = RemoveDirectoryW(lpExistingFileName2);
00470                    if (Result == FALSE)
00471                        break;
00472                                  
00473                    loop=TRUE;                                
00474                    size = wcslen(lpExistingFileName); 
00475                 
00476                    if (size+6>max_size)
00477                    {                       
00478                       if (lpNewFileName2 != NULL)                       
00479                           HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
00480                    
00481                       if (lpExistingFileName2 != NULL)                    
00482                           HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);        
00483                            
00484                       if (lpDeleteFile != NULL)             
00485                           HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);       
00486                   
00487                       return FALSE;
00488                    }
00489 
00490                    wcscpy( lpExistingFileName2,lpExistingFileName);
00491                    wcscpy( &lpExistingFileName2[size],L"\\*.*\0");
00492 
00493                    /* Get the file name */
00494                    memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
00495                    hFile = FindFirstFileW(lpExistingFileName2, &findBuffer);                     
00496                  }
00497                }          
00498                continue;                  
00499              }
00500               
00501              if (findBuffer.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
00502              {                 
00503 
00504                /* Build the new src string */                         
00505                size = wcslen(findBuffer.cFileName); 
00506                size2= wcslen(lpExistingFileName2);
00507 
00508                if (size2+size+6>max_size)
00509                {
00510                   FindClose(hFile);          
00511 
00512                  if (lpNewFileName2 != NULL)                        
00513                       HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
00514                    
00515                  if (lpExistingFileName2 != NULL)                     
00516                       HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);        
00517                            
00518                  if (lpDeleteFile != NULL)              
00519                       HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);       
00520                   
00521                  return FALSE;                               
00522                }
00523 
00524                 wcscpy( &lpExistingFileName2[size2-3],findBuffer.cFileName);                          
00525                 wcscpy( &lpExistingFileName2[size2+size-3],L"\0");
00526                
00527 
00528                /* Continue */
00529                wcscpy( lpDeleteFile,lpExistingFileName2);
00530                wcscpy( &lpExistingFileName2[size2+size-3],L"\\*.*\0");
00531           
00532           
00533                /* Build the new dst string */
00534                size = wcslen(lpExistingFileName2) + wcslen(lpNewFileName);
00535                size2 = wcslen(lpExistingFileName);
00536           
00537                if (size>max_size)
00538                {
00539                  FindClose(hFile);           
00540 
00541                  if (lpNewFileName2 != NULL)                        
00542                       HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
00543                    
00544                  if (lpExistingFileName2 != NULL)                     
00545                       HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);        
00546                            
00547                  if (lpDeleteFile != NULL)              
00548                       HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);       
00549                   
00550                  return FALSE;               
00551                }
00552 
00553                wcscpy( lpNewFileName2,lpNewFileName);                 
00554                size = wcslen(lpNewFileName);         
00555                wcscpy( &lpNewFileName2[size], &lpExistingFileName2[size2]);
00556                size = wcslen(lpNewFileName2);
00557                wcscpy( &lpNewFileName2[size-4],L"\0");
00558                
00559                /* Create Folder */            
00560 
00561                /* FIXME 
00562                 * remove readonly flag from source folder and do not set the readonly flag to dest folder 
00563                 */
00564                RemoveReadOnlyAttributeW(lpDeleteFile);
00565                RemoveReadOnlyAttributeW(lpNewFileName2);
00566 
00567                CreateDirectoryW(lpNewFileName2,NULL);
00568                //CreateDirectoryExW(lpDeleteFile, lpNewFileName2,NULL);
00569                
00570 
00571                /* set new search path  from src string */
00572                FindClose(hFile);
00573                memset(&findBuffer,0,sizeof(WIN32_FIND_DATAW));
00574                hFile = FindFirstFileW(lpExistingFileName2, &findBuffer);
00575              }
00576              else
00577              {
00578           
00579                /* Build the new string */                                 
00580                size = wcslen(findBuffer.cFileName); 
00581                size2= wcslen(lpExistingFileName2);
00582                wcscpy( lpDeleteFile,lpExistingFileName2);      
00583                wcscpy( &lpDeleteFile[size2-3],findBuffer.cFileName);       
00584           
00585                /* Build dest string */
00586                size = wcslen(lpDeleteFile) + wcslen(lpNewFileName);
00587                size2 = wcslen(lpExistingFileName);
00588 
00589                if (size>max_size)
00590                {                                  
00591                   FindClose(hFile);          
00592 
00593                   if (lpNewFileName2 != NULL)                       
00594                       HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
00595                    
00596                   if (lpExistingFileName2 != NULL)                    
00597                       HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);        
00598                            
00599                   if (lpDeleteFile != NULL)             
00600                       HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);       
00601                   
00602                   return FALSE;
00603                }
00604           
00605                wcscpy( lpNewFileName2,lpNewFileName);                 
00606                size = wcslen(lpNewFileName);         
00607                wcscpy(&lpNewFileName2[size],&lpDeleteFile[size2]);
00608          
00609               
00610                /* overrite existsen file, if the file got the flag have readonly 
00611                 * we need reomve that flag 
00612                 */
00613                
00614                 /* copy file */
00615                
00616                TRACE("MoveFileWithProgressW : Copy file : %S to %S\n",lpDeleteFile, lpNewFileName2);
00617                RemoveReadOnlyAttributeW(lpDeleteFile);
00618                RemoveReadOnlyAttributeW(lpNewFileName2);
00619               
00620                Result = CopyFileExW (lpDeleteFile,
00621                               lpNewFileName2,
00622                               lpProgressRoutine,
00623                               lpData,
00624                               NULL,
00625                               0);
00626 
00627                if (Result == FALSE)                                
00628                    break;
00629               
00630                /* delete file */                                
00631                TRACE("MoveFileWithProgressW : remove readonly flag from file : %S\n",lpNewFileName2);
00632                Result = RemoveReadOnlyAttributeW(lpDeleteFile);
00633                if (Result == FALSE)
00634                    break;
00635 
00636                TRACE("MoveFileWithProgressW : Delete file : %S\n",lpDeleteFile);
00637                Result = DeleteFileW(lpDeleteFile);
00638                if (Result == FALSE)                               
00639                    break;
00640               
00641              }                    
00642              loop = FindNextFileW(hFile, &findBuffer);        
00643            }
00644 
00645            
00646            /* Remove last folder */
00647            if ((loop == FALSE) && (Result != FALSE))
00648            {
00649              DWORD Attributes;
00650 
00651              Attributes = GetFileAttributesW(lpDeleteFile);
00652              if (Attributes != INVALID_FILE_ATTRIBUTES)
00653              {  
00654                 SetFileAttributesW(lpDeleteFile,(Attributes & ~FILE_ATTRIBUTE_SYSTEM));
00655              }
00656                                                      
00657              Result = RemoveDirectoryW(lpExistingFileName);          
00658            }
00659            
00660            /* Cleanup */
00661            FindClose(hFile);    
00662            
00663            if (lpNewFileName2 != NULL)
00664            {        
00665              HeapFree(GetProcessHeap(),0,(VOID *)  lpNewFileName2);
00666              lpNewFileName2 = NULL;
00667            }
00668 
00669            if (lpExistingFileName2 != NULL)
00670            {      
00671              HeapFree(GetProcessHeap(),0,(VOID *) lpExistingFileName2);     
00672              lpExistingFileName2 = NULL;
00673            }
00674 
00675            if (lpDeleteFile != NULL)
00676            {        
00677              HeapFree(GetProcessHeap(),0,(VOID *) lpDeleteFile);        
00678              lpDeleteFile = NULL;
00679            }
00680 
00681            return Result;
00682 
00683            // end move folder code       
00684           }
00685     }
00686     
00687     
00688     return Result;
00689 }
00690 
00691 
00692 /*
00693  * @implemented
00694  */
00695 BOOL
00696 WINAPI
00697 MoveFileWithProgressA (
00698     LPCSTR          lpExistingFileName,
00699     LPCSTR          lpNewFileName,
00700     LPPROGRESS_ROUTINE  lpProgressRoutine,
00701     LPVOID          lpData,
00702     DWORD           dwFlags
00703     )
00704 {
00705     PWCHAR ExistingFileNameW;
00706    PWCHAR NewFileNameW;
00707     BOOL ret;
00708 
00709    if (!(ExistingFileNameW = FilenameA2W(lpExistingFileName, FALSE)))
00710       return FALSE;
00711 
00712    if (!(NewFileNameW= FilenameA2W(lpNewFileName, TRUE)))
00713       return FALSE;
00714 
00715    ret = MoveFileWithProgressW (ExistingFileNameW ,
00716                                    NewFileNameW,
00717                                     lpProgressRoutine,
00718                                     lpData,
00719                                     dwFlags);
00720 
00721    RtlFreeHeap (RtlGetProcessHeap (), 0, NewFileNameW);
00722 
00723     return ret;
00724 }
00725 
00726 
00727 /*
00728  * @implemented
00729  */
00730 BOOL
00731 WINAPI
00732 MoveFileW (
00733     LPCWSTR lpExistingFileName,
00734     LPCWSTR lpNewFileName
00735     )
00736 {
00737     return MoveFileExW (lpExistingFileName,
00738                         lpNewFileName,
00739                         MOVEFILE_COPY_ALLOWED);
00740 }
00741 
00742 
00743 /*
00744  * @implemented
00745  */
00746 BOOL
00747 WINAPI
00748 MoveFileExW (
00749     LPCWSTR lpExistingFileName,
00750     LPCWSTR lpNewFileName,
00751     DWORD   dwFlags
00752     )
00753 {
00754     return MoveFileWithProgressW (lpExistingFileName,
00755                                   lpNewFileName,
00756                                   NULL,
00757                                   NULL,
00758                                   dwFlags);
00759 }
00760 
00761 
00762 /*
00763  * @implemented
00764  */
00765 BOOL
00766 WINAPI
00767 MoveFileA (
00768     LPCSTR  lpExistingFileName,
00769     LPCSTR  lpNewFileName
00770     )
00771 {
00772     return MoveFileExA (lpExistingFileName,
00773                         lpNewFileName,
00774                         MOVEFILE_COPY_ALLOWED);
00775 }
00776 
00777 
00778 /*
00779  * @implemented
00780  */
00781 BOOL
00782 WINAPI
00783 MoveFileExA (
00784     LPCSTR  lpExistingFileName,
00785     LPCSTR  lpNewFileName,
00786     DWORD   dwFlags
00787     )
00788 {
00789     return MoveFileWithProgressA (lpExistingFileName,
00790                                   lpNewFileName,
00791                                   NULL,
00792                                   NULL,
00793                                   dwFlags);
00794 }
00795 
00796 /*
00797  * @implemented
00798  */
00799 BOOL
00800 WINAPI
00801 ReplaceFileA(
00802     LPCSTR  lpReplacedFileName,
00803     LPCSTR  lpReplacementFileName,
00804     LPCSTR  lpBackupFileName,
00805     DWORD   dwReplaceFlags,
00806     LPVOID  lpExclude,
00807     LPVOID  lpReserved
00808     )
00809 {
00810     WCHAR *replacedW, *replacementW, *backupW = NULL;
00811     BOOL ret;
00812 
00813     /* This function only makes sense when the first two parameters are defined */
00814     if (!lpReplacedFileName || !(replacedW = FilenameA2W(lpReplacedFileName, TRUE)))
00815     {
00816         SetLastError(ERROR_INVALID_PARAMETER);
00817         return FALSE;
00818     }
00819 
00820     if (!lpReplacementFileName || !(replacementW = FilenameA2W(lpReplacementFileName, TRUE)))
00821     {
00822         HeapFree(GetProcessHeap(), 0, replacedW);
00823         SetLastError(ERROR_INVALID_PARAMETER);
00824         return FALSE;
00825     }
00826 
00827     /* The backup parameter, however, is optional */
00828     if (lpBackupFileName)
00829     {
00830         if (!(backupW = FilenameA2W(lpBackupFileName, TRUE)))
00831         {
00832             HeapFree(GetProcessHeap(), 0, replacedW);
00833             HeapFree(GetProcessHeap(), 0, replacementW);
00834             SetLastError(ERROR_INVALID_PARAMETER);
00835             return FALSE;
00836         }
00837     }
00838 
00839     ret = ReplaceFileW(replacedW, replacementW, backupW, dwReplaceFlags, lpExclude, lpReserved);
00840     HeapFree(GetProcessHeap(), 0, replacedW);
00841     HeapFree(GetProcessHeap(), 0, replacementW);
00842     HeapFree(GetProcessHeap(), 0, backupW);
00843 
00844     return ret;
00845 }
00846 
00847 /*
00848  * @unimplemented
00849  */
00850 BOOL
00851 WINAPI
00852 ReplaceFileW(
00853     LPCWSTR lpReplacedFileName,
00854     LPCWSTR lpReplacementFileName,
00855     LPCWSTR lpBackupFileName,
00856     DWORD   dwReplaceFlags,
00857     LPVOID  lpExclude,
00858     LPVOID  lpReserved
00859     )
00860 {
00861     HANDLE hReplaced = NULL, hReplacement = NULL;
00862     UNICODE_STRING NtReplacedName = { 0, 0, NULL };
00863     UNICODE_STRING NtReplacementName = { 0, 0, NULL };
00864     DWORD Error = ERROR_SUCCESS;
00865     NTSTATUS Status;
00866     BOOL Ret = FALSE;
00867     IO_STATUS_BLOCK IoStatusBlock;
00868     OBJECT_ATTRIBUTES ObjectAttributes;
00869     PVOID Buffer = NULL ;
00870 
00871     if (dwReplaceFlags)
00872         FIXME("Ignoring flags %x\n", dwReplaceFlags);
00873 
00874     /* First two arguments are mandatory */
00875     if (!lpReplacedFileName || !lpReplacementFileName)
00876     {
00877         SetLastError(ERROR_INVALID_PARAMETER);
00878         return FALSE;
00879     }
00880 
00881     /* Back it up */
00882     if(lpBackupFileName)
00883     {
00884         if(!CopyFileW(lpReplacedFileName, lpBackupFileName, FALSE))
00885         {
00886             Error = GetLastError();
00887             goto Cleanup ;
00888         }
00889     }
00890 
00891     /* Open the "replaced" file for reading and writing */
00892     if (!(RtlDosPathNameToNtPathName_U(lpReplacedFileName, &NtReplacedName, NULL, NULL)))
00893     {
00894         Error = ERROR_PATH_NOT_FOUND;
00895         goto Cleanup;
00896     }
00897 
00898     InitializeObjectAttributes(&ObjectAttributes,
00899                                &NtReplacedName,
00900                                OBJ_CASE_INSENSITIVE,
00901                                NULL,
00902                                NULL);
00903 
00904     Status = NtOpenFile(&hReplaced,
00905                         GENERIC_READ | GENERIC_WRITE | DELETE | SYNCHRONIZE | WRITE_DAC,
00906                         &ObjectAttributes,
00907                         &IoStatusBlock,
00908                         FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
00909                         FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
00910 
00911     if (!NT_SUCCESS(Status))
00912     {
00913         if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
00914             Error = ERROR_FILE_NOT_FOUND;
00915         else
00916             Error = ERROR_UNABLE_TO_REMOVE_REPLACED;
00917         goto Cleanup;
00918     }
00919 
00920     /* Blank it */
00921     SetEndOfFile(hReplaced) ;
00922 
00923     /*
00924      * Open the replacement file for reading, writing, and deleting
00925      * (deleting is needed when finished)
00926      */
00927     if (!(RtlDosPathNameToNtPathName_U(lpReplacementFileName, &NtReplacementName, NULL, NULL)))
00928     {
00929         Error = ERROR_PATH_NOT_FOUND;
00930         goto Cleanup;
00931     }
00932 
00933     InitializeObjectAttributes(&ObjectAttributes,
00934                                &NtReplacementName,
00935                                OBJ_CASE_INSENSITIVE,
00936                                NULL,
00937                                NULL);
00938 
00939     Status = NtOpenFile(&hReplacement,
00940                         GENERIC_READ | DELETE | SYNCHRONIZE,
00941                         &ObjectAttributes,
00942                         &IoStatusBlock,
00943                         0,
00944                         FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE);
00945 
00946     if (!NT_SUCCESS(Status))
00947     {
00948         Error = RtlNtStatusToDosError(Status);
00949         goto Cleanup;
00950     }
00951 
00952     Buffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x10000) ;
00953     if (!Buffer)
00954     {
00955         Error = ERROR_NOT_ENOUGH_MEMORY;
00956         goto Cleanup ;
00957     }
00958     while (Status != STATUS_END_OF_FILE)
00959     {
00960         Status = NtReadFile(hReplacement, NULL, NULL, NULL, &IoStatusBlock, Buffer, 0x10000, NULL, NULL) ;
00961         if (NT_SUCCESS(Status))
00962         {
00963             Status = NtWriteFile(hReplaced, NULL, NULL, NULL, &IoStatusBlock, Buffer,
00964                     IoStatusBlock.Information, NULL, NULL) ;
00965             if (!NT_SUCCESS(Status))
00966             {
00967                 Error = RtlNtStatusToDosError(Status);
00968                 goto Cleanup;
00969             }
00970         }
00971         else if (Status != STATUS_END_OF_FILE)
00972         {
00973             Error = RtlNtStatusToDosError(Status);
00974             goto Cleanup;
00975         }
00976     }
00977 
00978     Ret = TRUE;
00979 
00980     /* Perform resource cleanup */
00981 Cleanup:
00982     if (hReplaced) NtClose(hReplaced);
00983     if (hReplacement) NtClose(hReplacement);
00984     if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
00985 
00986     if (NtReplacementName.Buffer)
00987         RtlFreeHeap(GetProcessHeap(), 0, NtReplacementName.Buffer);
00988     if (NtReplacedName.Buffer)
00989         RtlFreeHeap(GetProcessHeap(), 0, NtReplacedName.Buffer);
00990 
00991     /* If there was an error, set the error code */
00992     if(!Ret)
00993     {
00994         TRACE("ReplaceFileW failed (error=%d)\n", Error);
00995         SetLastError(Error);
00996     }
00997     return Ret;
00998 }
00999 
01000 /*
01001  * @unimplemented
01002  */
01003 BOOL
01004 WINAPI
01005 PrivMoveFileIdentityW(DWORD Unknown1, DWORD Unknown2, DWORD Unknown3)
01006 {
01007     STUB;
01008     return FALSE;
01009 }
01010 
01011 /* EOF */

Generated on Sun May 27 2012 04:18:13 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.