:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / lib / kernel32 / file / copy.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/kernel32/file/copy.c
6  * PURPOSE:         Copying files
7  * PROGRAMMER:      Ariadne (ariadne@xs4all.nl)
8  * UPDATE HISTORY:
9  *                  01/11/98 Created
10  *                  07/02/99 Moved to seperate file 
11  */
12
13 /* INCLUDES ****************************************************************/
14
15 #include <ddk/ntddk.h>
16 #include <windows.h>
17
18 #define NDEBUG
19 #include <kernel32/kernel32.h>
20 #include <kernel32/error.h>
21
22
23 #define LPPROGRESS_ROUTINE void*
24
25
26 /* FUNCTIONS ****************************************************************/
27
28 WINBOOL
29 STDCALL
30 CopyFileExW (
31         LPCWSTR                 lpExistingFileName,
32         LPCWSTR                 lpNewFileName,
33         LPPROGRESS_ROUTINE      lpProgressRoutine,
34         LPVOID                  lpData,
35         WINBOOL                 *pbCancel,
36         DWORD                   dwCopyFlags
37         )
38 {
39    NTSTATUS errCode = 0;
40    HANDLE FileHandleSource, FileHandleDest;
41    IO_STATUS_BLOCK IoStatusBlock;
42    FILE_STANDARD_INFORMATION FileStandard;
43    FILE_BASIC_INFORMATION FileBasic;
44    FILE_POSITION_INFORMATION FilePosition;
45    UCHAR *lpBuffer = NULL;
46    ULONG RegionSize = 0x1000000;
47    BOOL bCancel = FALSE;
48
49    FileHandleSource = CreateFileW(lpExistingFileName,
50                                   GENERIC_READ,
51                                   FILE_SHARE_READ,
52                                   NULL,
53                                   OPEN_EXISTING,
54                                   FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING,
55                                   NULL);
56    if (FileHandleSource == NULL)
57      {
58         return(FALSE);
59      }
60
61    errCode = NtQueryInformationFile(FileHandleSource,
62                                     &IoStatusBlock,
63                                     &FileStandard,
64                                     sizeof(FILE_STANDARD_INFORMATION),
65                                     FileStandardInformation);
66    if (!NT_SUCCESS(errCode))
67      {
68         NtClose(FileHandleSource);
69         SetLastErrorByStatus(errCode);
70         return FALSE;
71      }
72
73    errCode = NtQueryInformationFile(FileHandleSource,
74                                     &IoStatusBlock,&FileBasic,
75                                     sizeof(FILE_BASIC_INFORMATION),
76                                     FileBasicInformation);
77    if (!NT_SUCCESS(errCode))
78      {
79         NtClose(FileHandleSource);
80         SetLastErrorByStatus(errCode);
81         return FALSE;
82      }
83
84    FileHandleDest = CreateFileW(lpNewFileName,
85                                 GENERIC_WRITE,
86                                 FILE_SHARE_WRITE,
87                                 NULL,
88                                 dwCopyFlags  ?  CREATE_NEW : CREATE_ALWAYS,
89                                 FileBasic.FileAttributes|FILE_FLAG_NO_BUFFERING,
90                                 NULL);
91    if (FileHandleDest == NULL)
92      {
93         return(FALSE);
94      }
95
96    FilePosition.CurrentByteOffset.QuadPart = 0;
97
98    errCode = NtSetInformationFile(FileHandleSource,
99                                   &IoStatusBlock,
100                                   &FilePosition,
101                                   sizeof(FILE_POSITION_INFORMATION),
102                                   FilePositionInformation);
103    if (!NT_SUCCESS(errCode))
104      {
105         NtClose(FileHandleSource);
106         NtClose(FileHandleDest);
107         SetLastErrorByStatus(errCode);
108         return FALSE;
109      }
110
111    errCode = NtSetInformationFile(FileHandleDest,
112                                   &IoStatusBlock,
113                                   &FilePosition,
114                                   sizeof(FILE_POSITION_INFORMATION),
115                                   FilePositionInformation);
116    if (!NT_SUCCESS(errCode))
117      {
118         NtClose(FileHandleSource);
119         NtClose(FileHandleDest);
120         SetLastErrorByStatus(errCode);
121         return FALSE;
122      }
123
124    errCode = NtAllocateVirtualMemory(NtCurrentProcess(),
125                                      (PVOID *)&lpBuffer,
126                                      2,
127                                      &RegionSize,
128                                      MEM_RESERVE | MEM_COMMIT,
129                                      PAGE_READWRITE);
130
131    if (!NT_SUCCESS(errCode))
132      {
133         NtClose(FileHandleSource);
134         NtClose(FileHandleDest);
135         SetLastErrorByStatus(errCode);
136         return FALSE;
137      }
138
139    do {
140       errCode = NtReadFile(FileHandleSource,
141                            NULL,
142                            NULL,
143                            NULL,
144                            (PIO_STATUS_BLOCK)&IoStatusBlock,
145                            lpBuffer,
146                            RegionSize,
147                            NULL,
148                            NULL);
149       if (pbCancel != NULL)
150         bCancel = *pbCancel;
151
152       if (!NT_SUCCESS(errCode) || bCancel)
153         {
154            NtFreeVirtualMemory(NtCurrentProcess(),
155                                (PVOID *)&lpBuffer, &RegionSize,MEM_RELEASE);
156            NtClose(FileHandleSource);
157            NtClose(FileHandleDest);
158            if ( errCode == STATUS_END_OF_FILE )
159              break;
160            else
161              return FALSE;
162         }
163
164       errCode = NtWriteFile(FileHandleDest,
165                             NULL,
166                             lpProgressRoutine,
167                             lpData,
168                             (PIO_STATUS_BLOCK)&IoStatusBlock,
169                             lpBuffer,
170                             IoStatusBlock.Information,
171                             NULL,
172                             NULL);
173
174       if (!NT_SUCCESS(errCode))
175         {
176            NtFreeVirtualMemory(NtCurrentProcess(),
177                                (PVOID *)&lpBuffer,
178                                &RegionSize,
179                                MEM_RELEASE);
180            NtClose(FileHandleSource);
181            NtClose(FileHandleDest);
182            return FALSE;
183         }
184       
185    } while ( TRUE );
186    return TRUE;
187 }
188
189
190 WINBOOL
191 STDCALL
192 CopyFileExA (
193         LPCSTR                  lpExistingFileName,
194         LPCSTR                  lpNewFileName,
195         LPPROGRESS_ROUTINE      lpProgressRoutine,
196         LPVOID                  lpData,
197         WINBOOL                 *pbCancel,
198         DWORD                   dwCopyFlags
199         )
200 {
201         UNICODE_STRING ExistingFileNameU;
202         UNICODE_STRING NewFileNameU;
203         ANSI_STRING ExistingFileName;
204         ANSI_STRING NewFileName;
205         WINBOOL Result;
206
207         RtlInitAnsiString (&ExistingFileName,
208                            (LPSTR)lpExistingFileName);
209
210         RtlInitAnsiString (&NewFileName,
211                            (LPSTR)lpNewFileName);
212
213         /* convert ansi (or oem) string to unicode */
214         if (bIsFileApiAnsi)
215         {
216                 RtlAnsiStringToUnicodeString (&ExistingFileNameU,
217                                               &ExistingFileName,
218                                               TRUE);
219                 RtlAnsiStringToUnicodeString (&NewFileNameU,
220                                               &NewFileName,
221                                               TRUE);
222         }
223         else
224         {
225                 RtlOemStringToUnicodeString (&ExistingFileNameU,
226                                              &ExistingFileName,
227                                              TRUE);
228                 RtlOemStringToUnicodeString (&NewFileNameU,
229                                              &NewFileName,
230                                              TRUE);
231         }
232
233         Result = CopyFileExW (ExistingFileNameU.Buffer,
234                               NewFileNameU.Buffer,
235                               lpProgressRoutine,
236                               lpData,
237                               pbCancel,
238                               dwCopyFlags);
239
240         RtlFreeHeap (RtlGetProcessHeap (),
241                      0,
242                      ExistingFileNameU.Buffer);
243         RtlFreeHeap (RtlGetProcessHeap (),
244                      0,
245                      NewFileNameU.Buffer);
246
247         return Result;
248 }
249
250
251 WINBOOL
252 STDCALL
253 CopyFileA (
254         LPCSTR  lpExistingFileName,
255         LPCSTR  lpNewFileName,
256         WINBOOL bFailIfExists
257         )
258 {
259         return CopyFileExA (lpExistingFileName,
260                             lpNewFileName,
261                             NULL,
262                             NULL,
263                             NULL,
264                             bFailIfExists);
265 }
266
267
268 WINBOOL
269 STDCALL
270 CopyFileW (
271         LPCWSTR lpExistingFileName,
272         LPCWSTR lpNewFileName,
273         WINBOOL bFailIfExists
274         )
275 {
276         return CopyFileExW (lpExistingFileName,
277                             lpNewFileName,
278                             NULL,
279                             NULL,
280                             NULL,
281                             bFailIfExists);
282 }
283
284 /* EOF */