ReactOS  0.4.13-dev-235-g7373cb3
copy.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS system libraries
4  * FILE: dll/win32/kernel32/client/file/copy.c
5  * PURPOSE: Copying files
6  * PROGRAMMER: Ariadne (ariadne@xs4all.nl)
7  * UPDATE HISTORY:
8  * 01/11/98 Created
9  * 07/02/99 Moved to separate file
10  */
11 
12 /* INCLUDES ****************************************************************/
13 
14 #include <k32.h>
15 #define NDEBUG
16 #include <debug.h>
17 
18 #if DBG
20 #endif
21 
22 /* FUNCTIONS ****************************************************************/
23 
24 
25 static NTSTATUS
27  HANDLE FileHandleSource,
28  HANDLE FileHandleDest,
29  LARGE_INTEGER SourceFileSize,
30  LPPROGRESS_ROUTINE lpProgressRoutine,
31  LPVOID lpData,
32  BOOL *pbCancel,
33  BOOL *KeepDest
34 )
35 {
36  NTSTATUS errCode;
38  UCHAR *lpBuffer = NULL;
39  SIZE_T RegionSize = 0x10000;
41  DWORD CallbackReason;
42  DWORD ProgressResult;
43  BOOL EndOfFileFound;
44 
45  *KeepDest = FALSE;
47  (PVOID *)&lpBuffer,
48  0,
49  &RegionSize,
52 
53  if (NT_SUCCESS(errCode))
54  {
55  BytesCopied.QuadPart = 0;
56  EndOfFileFound = FALSE;
57  CallbackReason = CALLBACK_STREAM_SWITCH;
58  while (! EndOfFileFound &&
59  NT_SUCCESS(errCode) &&
60  (NULL == pbCancel || ! *pbCancel))
61  {
62  if (NULL != lpProgressRoutine)
63  {
64  ProgressResult = (*lpProgressRoutine)(SourceFileSize,
66  SourceFileSize,
68  0,
69  CallbackReason,
70  FileHandleSource,
71  FileHandleDest,
72  lpData);
73  switch (ProgressResult)
74  {
75  case PROGRESS_CANCEL:
76  TRACE("Progress callback requested cancel\n");
77  errCode = STATUS_REQUEST_ABORTED;
78  break;
79  case PROGRESS_STOP:
80  TRACE("Progress callback requested stop\n");
81  errCode = STATUS_REQUEST_ABORTED;
82  *KeepDest = TRUE;
83  break;
84  case PROGRESS_QUIET:
85  lpProgressRoutine = NULL;
86  break;
87  case PROGRESS_CONTINUE:
88  default:
89  break;
90  }
91  CallbackReason = CALLBACK_CHUNK_FINISHED;
92  }
93  if (NT_SUCCESS(errCode))
94  {
95  errCode = NtReadFile(FileHandleSource,
96  NULL,
97  NULL,
98  NULL,
100  lpBuffer,
101  RegionSize,
102  NULL,
103  NULL);
104  /* With sync read, 0 length + status success mean EOF:
105  * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx
106  */
107  if (NT_SUCCESS(errCode) && IoStatusBlock.Information == 0)
108  {
109  errCode = STATUS_END_OF_FILE;
110  }
111  if (NT_SUCCESS(errCode) && (NULL == pbCancel || ! *pbCancel))
112  {
113  errCode = NtWriteFile(FileHandleDest,
114  NULL,
115  NULL,
116  NULL,
118  lpBuffer,
120  NULL,
121  NULL);
122  if (NT_SUCCESS(errCode))
123  {
125  }
126  else
127  {
128  WARN("Error 0x%08x reading writing to dest\n", errCode);
129  }
130  }
131  else if (!NT_SUCCESS(errCode))
132  {
133  if (STATUS_END_OF_FILE == errCode)
134  {
135  EndOfFileFound = TRUE;
136  errCode = STATUS_SUCCESS;
137  }
138  else
139  {
140  WARN("Error 0x%08x reading from source\n", errCode);
141  }
142  }
143  }
144  }
145 
146  if (! EndOfFileFound && (NULL != pbCancel && *pbCancel))
147  {
148  TRACE("User requested cancel\n");
149  errCode = STATUS_REQUEST_ABORTED;
150  }
151 
153  (PVOID *)&lpBuffer,
154  &RegionSize,
155  MEM_RELEASE);
156  }
157  else
158  {
159  TRACE("Error 0x%08x allocating buffer of %lu bytes\n", errCode, RegionSize);
160  }
161 
162  return errCode;
163 }
164 
165 static NTSTATUS
168  LARGE_INTEGER LastWriteTime
169 )
170 {
171  NTSTATUS errCode = STATUS_SUCCESS;
173  FILE_BASIC_INFORMATION FileBasic;
174 
176  &IoStatusBlock,
177  &FileBasic,
178  sizeof(FILE_BASIC_INFORMATION),
180  if (!NT_SUCCESS(errCode))
181  {
182  WARN("Error 0x%08x obtaining FileBasicInformation\n", errCode);
183  }
184  else
185  {
186  FileBasic.LastWriteTime.QuadPart = LastWriteTime.QuadPart;
187  errCode = NtSetInformationFile (FileHandle,
188  &IoStatusBlock,
189  &FileBasic,
190  sizeof(FILE_BASIC_INFORMATION),
192  if (!NT_SUCCESS(errCode))
193  {
194  WARN("Error 0x%0x setting LastWriteTime\n", errCode);
195  }
196  }
197 
198  return errCode;
199 }
200 
201 BOOL
202 BasepCopyFileExW(IN LPCWSTR lpExistingFileName,
203  IN LPCWSTR lpNewFileName,
204  IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
205  IN LPVOID lpData OPTIONAL,
206  IN LPBOOL pbCancel OPTIONAL,
207  IN DWORD dwCopyFlags,
208  IN DWORD dwBasepFlags,
209  OUT LPHANDLE lpExistingHandle,
210  OUT LPHANDLE lpNewHandle)
211 {
212  NTSTATUS errCode;
213  HANDLE FileHandleSource, FileHandleDest;
215  FILE_STANDARD_INFORMATION FileStandard;
216  FILE_BASIC_INFORMATION FileBasic;
217  BOOL RC = FALSE;
218  BOOL KeepDestOnError = FALSE;
220 
221  FileHandleSource = CreateFileW(lpExistingFileName,
222  GENERIC_READ,
224  NULL,
227  NULL);
228  if (INVALID_HANDLE_VALUE != FileHandleSource)
229  {
230  errCode = NtQueryInformationFile(FileHandleSource,
231  &IoStatusBlock,
232  &FileStandard,
235  if (!NT_SUCCESS(errCode))
236  {
237  TRACE("Status 0x%08x obtaining FileStandardInformation for source\n", errCode);
238  BaseSetLastNTError(errCode);
239  }
240  else
241  {
242  errCode = NtQueryInformationFile(FileHandleSource,
243  &IoStatusBlock,&FileBasic,
244  sizeof(FILE_BASIC_INFORMATION),
246  if (!NT_SUCCESS(errCode))
247  {
248  TRACE("Status 0x%08x obtaining FileBasicInformation for source\n", errCode);
249  BaseSetLastNTError(errCode);
250  }
251  else
252  {
253  FileHandleDest = CreateFileW(lpNewFileName,
256  NULL,
257  dwCopyFlags ? CREATE_NEW : CREATE_ALWAYS,
258  FileBasic.FileAttributes,
259  NULL);
260  if (INVALID_HANDLE_VALUE != FileHandleDest)
261  {
262  errCode = CopyLoop(FileHandleSource,
263  FileHandleDest,
264  FileStandard.EndOfFile,
265  lpProgressRoutine,
266  lpData,
267  pbCancel,
268  &KeepDestOnError);
269  if (!NT_SUCCESS(errCode))
270  {
271  BaseSetLastNTError(errCode);
272  }
273  else
274  {
276 
277  t.QuadPart = FileBasic.LastWriteTime.QuadPart;
278  errCode = SetLastWriteTime(FileHandleDest, t);
279  if (!NT_SUCCESS(errCode))
280  {
281  BaseSetLastNTError(errCode);
282  }
283  else
284  {
285  RC = TRUE;
286  }
287  }
288  NtClose(FileHandleDest);
289  if (! RC && ! KeepDestOnError)
290  {
293  DeleteFileW(lpNewFileName);
295  }
296  }
297  else
298  {
299  WARN("Error %lu during opening of dest file\n", GetLastError());
300  }
301  }
302  }
303  NtClose(FileHandleSource);
304  }
305  else
306  {
307  WARN("Error %lu during opening of source file\n", GetLastError());
308  }
309 
310  return RC;
311 }
312 
313 /*
314  * @implemented
315  */
316 BOOL
317 WINAPI
318 CopyFileExW(IN LPCWSTR lpExistingFileName,
319  IN LPCWSTR lpNewFileName,
320  IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
321  IN LPVOID lpData OPTIONAL,
322  IN LPBOOL pbCancel OPTIONAL,
323  IN DWORD dwCopyFlags)
324 {
325  BOOL Ret;
326  HANDLE ExistingHandle, NewHandle;
327 
328  ExistingHandle = INVALID_HANDLE_VALUE;
329  NewHandle = INVALID_HANDLE_VALUE;
330 
331  _SEH2_TRY
332  {
333  Ret = BasepCopyFileExW(lpExistingFileName,
334  lpNewFileName,
335  lpProgressRoutine,
336  lpData,
337  pbCancel,
338  dwCopyFlags,
339  0,
340  &ExistingHandle,
341  &NewHandle);
342  }
344  {
345  if (ExistingHandle != INVALID_HANDLE_VALUE)
346  {
347  CloseHandle(ExistingHandle);
348  }
349 
350  if (NewHandle != INVALID_HANDLE_VALUE)
351  {
352  CloseHandle(NewHandle);
353  }
354  }
355  _SEH2_END;
356 
357  return Ret;
358 }
359 
360 
361 /*
362  * @implemented
363  */
364 BOOL
365 WINAPI
366 CopyFileExA(IN LPCSTR lpExistingFileName,
367  IN LPCSTR lpNewFileName,
368  IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL,
369  IN LPVOID lpData OPTIONAL,
370  IN LPBOOL pbCancel OPTIONAL,
371  IN DWORD dwCopyFlags)
372 {
373  BOOL Result = FALSE;
374  UNICODE_STRING lpNewFileNameW;
375  PUNICODE_STRING lpExistingFileNameW;
376 
377  lpExistingFileNameW = Basep8BitStringToStaticUnicodeString(lpExistingFileName);
378  if (!lpExistingFileNameW)
379  {
380  return FALSE;
381  }
382 
383  if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW, lpNewFileName))
384  {
385  Result = CopyFileExW(lpExistingFileNameW->Buffer,
386  lpNewFileNameW.Buffer,
387  lpProgressRoutine,
388  lpData,
389  pbCancel,
390  dwCopyFlags);
391 
392  RtlFreeUnicodeString(&lpNewFileNameW);
393  }
394 
395  return Result;
396 }
397 
398 
399 /*
400  * @implemented
401  */
402 BOOL
403 WINAPI
404 CopyFileA(IN LPCSTR lpExistingFileName,
405  IN LPCSTR lpNewFileName,
406  IN BOOL bFailIfExists)
407 {
408  BOOL Result = FALSE;
409  UNICODE_STRING lpNewFileNameW;
410  PUNICODE_STRING lpExistingFileNameW;
411 
412  lpExistingFileNameW = Basep8BitStringToStaticUnicodeString(lpExistingFileName);
413  if (!lpExistingFileNameW)
414  {
415  return FALSE;
416  }
417 
418  if (Basep8BitStringToDynamicUnicodeString(&lpNewFileNameW, lpNewFileName))
419  {
420  Result = CopyFileExW(lpExistingFileNameW->Buffer,
421  lpNewFileNameW.Buffer,
422  NULL,
423  NULL,
424  NULL,
425  (bFailIfExists ? COPY_FILE_FAIL_IF_EXISTS : 0));
426 
427  RtlFreeUnicodeString(&lpNewFileNameW);
428  }
429 
430  return Result;
431 }
432 
433 
434 /*
435  * @implemented
436  */
437 BOOL
438 WINAPI
439 CopyFileW(IN LPCWSTR lpExistingFileName,
440  IN LPCWSTR lpNewFileName,
441  IN BOOL bFailIfExists)
442 {
443  return CopyFileExW(lpExistingFileName,
444  lpNewFileName,
445  NULL,
446  NULL,
447  NULL,
448  (bFailIfExists ? COPY_FILE_FAIL_IF_EXISTS : 0));
449 }
450 
451 
452 /*
453  * @implemented
454  */
455 BOOL
456 WINAPI
457 PrivCopyFileExW(IN LPCWSTR lpExistingFileName,
458  IN LPCWSTR lpNewFileName,
459  IN LPPROGRESS_ROUTINE lpProgressRoutine,
460  IN LPVOID lpData,
461  IN LPBOOL pbCancel,
462  IN DWORD dwCopyFlags)
463 {
464  BOOL Ret;
465  HANDLE ExistingHandle, NewHandle;
466 
467  ExistingHandle = INVALID_HANDLE_VALUE;
468  NewHandle = INVALID_HANDLE_VALUE;
469 
470  /* Check for incompatible flags */
471  if (dwCopyFlags & COPY_FILE_FAIL_IF_EXISTS && dwCopyFlags & BASEP_COPY_REPLACE)
472  {
474  return FALSE;
475  }
476 
477  _SEH2_TRY
478  {
479  Ret = BasepCopyFileExW(lpExistingFileName,
480  lpNewFileName,
481  lpProgressRoutine,
482  lpData,
483  pbCancel,
484  dwCopyFlags & BASEP_COPY_PUBLIC_MASK,
485  dwCopyFlags & BASEP_COPY_BASEP_MASK,
486  &ExistingHandle,
487  &NewHandle);
488  }
490  {
491  if (ExistingHandle != INVALID_HANDLE_VALUE)
492  {
493  CloseHandle(ExistingHandle);
494  }
495 
496  if (NewHandle != INVALID_HANDLE_VALUE)
497  {
498  CloseHandle(NewHandle);
499  }
500  }
501  _SEH2_END;
502 
503  return Ret;
504 }
505 
506 /* EOF */
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:944
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define IN
Definition: typedefs.h:38
PUNICODE_STRING WINAPI Basep8BitStringToStaticUnicodeString(IN LPCSTR String)
Definition: utils.c:188
#define CALLBACK_CHUNK_FINISHED
Definition: winbase.h:150
#define BASEP_COPY_PUBLIC_MASK
Definition: kernel32.h:129
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define WARN(fmt,...)
Definition: debug.h:111
LONG NTSTATUS
Definition: precomp.h:26
GLdouble GLdouble t
Definition: gl.h:2047
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
#define CALLBACK_STREAM_SWITCH
Definition: winbase.h:151
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
BOOL WINAPI CopyFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:404
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define MEM_COMMIT
Definition: nt_native.h:1313
#define FILE_SHARE_READ
Definition: compat.h:125
_SEH2_TRY
Definition: create.c:4250
#define STATUS_END_OF_FILE
Definition: shellext.h:62
HANDLE FileHandle
Definition: stats.c:38
BOOLEAN WINAPI Basep8BitStringToDynamicUnicodeString(OUT PUNICODE_STRING UnicodeString, IN LPCSTR String)
Definition: utils.c:225
static NTSTATUS CopyLoop(HANDLE FileHandleSource, HANDLE FileHandleDest, LARGE_INTEGER SourceFileSize, LPPROGRESS_ROUTINE lpProgressRoutine, LPVOID lpData, BOOL *pbCancel, BOOL *KeepDest)
Definition: copy.c:26
unsigned int BOOL
Definition: ntddk_ex.h:94
#define kernel32file
Definition: kernel32.h:6
#define COPY_FILE_FAIL_IF_EXISTS
Definition: winbase.h:205
#define GENERIC_WRITE
Definition: nt_native.h:90
#define MEM_RESERVE
Definition: nt_native.h:1314
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:173
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
#define PROGRESS_STOP
Definition: winbase.h:148
#define DEBUG_CHANNEL(args)
Definition: rdesktop.h:159
_In_ UINT _In_ UINT _In_ PNDIS_PACKET _In_ UINT _Out_ PUINT BytesCopied
Definition: ndis.h:3167
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
DWORD BaseSetLastNTError(IN NTSTATUS Status)
Definition: reactos.cpp:166
const char * LPCSTR
Definition: xmlstorage.h:183
#define OPEN_EXISTING
Definition: compat.h:426
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define TRACE(s)
Definition: solgame.cpp:4
LARGE_INTEGER LastWriteTime
Definition: nt_native.h:941
#define PROGRESS_CANCEL
Definition: winbase.h:147
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define PROGRESS_CONTINUE
Definition: winbase.h:146
BOOL WINAPI CopyFileW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN BOOL bFailIfExists)
Definition: copy.c:439
#define FILE_FLAG_NO_BUFFERING
Definition: disk.h:45
BOOL WINAPI PrivCopyFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine, IN LPVOID lpData, IN LPBOOL pbCancel, IN DWORD dwCopyFlags)
Definition: copy.c:457
#define WINAPI
Definition: msvc.h:8
unsigned long DWORD
Definition: ntddk_ex.h:95
static const char * SystemError(DWORD err)
Definition: vfdcmd.c:3368
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define SetLastError(x)
Definition: compat.h:409
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
unsigned char UCHAR
Definition: xmlstorage.h:181
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
BOOL BasepCopyFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN LPBOOL pbCancel OPTIONAL, IN DWORD dwCopyFlags, IN DWORD dwBasepFlags, OUT LPHANDLE lpExistingHandle, OUT LPHANDLE lpNewHandle)
Definition: copy.c:202
NTSYSAPI NTSTATUS NTAPI NtWriteFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID WriteBuffer, IN ULONG WriteBufferLength, IN PLARGE_INTEGER FileOffset OPTIONAL, IN PULONG LockOperationKey OPTIONAL)
DWORD(WINAPI * LPPROGRESS_ROUTINE)(_In_ LARGE_INTEGER, _In_ LARGE_INTEGER, _In_ LARGE_INTEGER, _In_ LARGE_INTEGER, _In_ DWORD, _In_ DWORD, _In_ HANDLE, _In_ HANDLE, _In_opt_ LPVOID)
Definition: winbase.h:1392
BOOL WINAPI CopyFileExW(IN LPCWSTR lpExistingFileName, IN LPCWSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN LPBOOL pbCancel OPTIONAL, IN DWORD dwCopyFlags)
Definition: copy.c:318
#define GENERIC_READ
Definition: compat.h:124
NTSTATUS NTAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass)
#define STATUS_REQUEST_ABORTED
Definition: udferr_usr.h:183
BOOL WINAPI CopyFileExA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName, IN LPPROGRESS_ROUTINE lpProgressRoutine OPTIONAL, IN LPVOID lpData OPTIONAL, IN LPBOOL pbCancel OPTIONAL, IN DWORD dwCopyFlags)
Definition: copy.c:366
#define PROGRESS_QUIET
Definition: winbase.h:149
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define CREATE_ALWAYS
Definition: disk.h:72
#define BASEP_COPY_REPLACE
Definition: kernel32.h:127
_SEH2_END
Definition: create.c:4424
NTSTATUS NTAPI NtAllocateVirtualMemory(IN HANDLE ProcessHandle, IN OUT PVOID *UBaseAddress, IN ULONG_PTR ZeroBits, IN OUT PSIZE_T URegionSize, IN ULONG AllocationType, IN ULONG Protect)
Definition: virtual.c:4367
BOOL * LPBOOL
Definition: windef.h:162
__kernel_entry _Inout_ _Inout_ PSIZE_T RegionSize
Definition: mmfuncs.h:172
#define BASEP_COPY_BASEP_MASK
Definition: kernel32.h:130
_SEH2_FINALLY
Definition: create.c:4395
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define FileStandardInformation
Definition: propsheet.cpp:61
#define CreateFileW
Definition: compat.h:400
#define MEM_RELEASE
Definition: nt_native.h:1316
#define OUT
Definition: typedefs.h:39
static NTSTATUS SetLastWriteTime(HANDLE FileHandle, LARGE_INTEGER LastWriteTime)
Definition: copy.c:166
#define CREATE_NEW
Definition: disk.h:69
return STATUS_SUCCESS
Definition: btrfs.c:2745
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
Definition: iofunc.c:3042
NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
LONGLONG QuadPart
Definition: typedefs.h:112
#define PAGE_READWRITE
Definition: nt_native.h:1304
NTSTATUS NTAPI NtFreeVirtualMemory(IN HANDLE ProcessHandle, IN PVOID *UBaseAddress, IN PSIZE_T URegionSize, IN ULONG FreeType)
Definition: virtual.c:5090
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68