Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
b6c94018
Commit
b6c94018
authored
May 05, 2020
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel32: Move some file functions to kernelbase.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
e36a9c45
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
721 additions
and
796 deletions
+721
-796
file.c
dlls/kernel32/file.c
+0
-326
kernel32.spec
dlls/kernel32/kernel32.spec
+11
-11
path.c
dlls/kernel32/path.c
+0
-449
file.c
dlls/kernelbase/file.c
+700
-0
kernelbase.spec
dlls/kernelbase/kernelbase.spec
+10
-10
No files found.
dlls/kernel32/file.c
View file @
b6c94018
...
@@ -416,121 +416,6 @@ BOOL WINAPI KERNEL32_FlushFileBuffers( HANDLE file )
...
@@ -416,121 +416,6 @@ BOOL WINAPI KERNEL32_FlushFileBuffers( HANDLE file )
/**************************************************************************
/**************************************************************************
* ReplaceFileW (KERNEL32.@)
* ReplaceFile (KERNEL32.@)
*/
BOOL
WINAPI
ReplaceFileW
(
LPCWSTR
lpReplacedFileName
,
LPCWSTR
lpReplacementFileName
,
LPCWSTR
lpBackupFileName
,
DWORD
dwReplaceFlags
,
LPVOID
lpExclude
,
LPVOID
lpReserved
)
{
UNICODE_STRING
nt_replaced_name
,
nt_replacement_name
;
HANDLE
hReplacement
=
NULL
;
NTSTATUS
status
;
IO_STATUS_BLOCK
io
;
OBJECT_ATTRIBUTES
attr
;
FILE_BASIC_INFORMATION
info
;
TRACE
(
"%s %s %s 0x%08x %p %p
\n
"
,
debugstr_w
(
lpReplacedFileName
),
debugstr_w
(
lpReplacementFileName
),
debugstr_w
(
lpBackupFileName
),
dwReplaceFlags
,
lpExclude
,
lpReserved
);
if
(
dwReplaceFlags
)
FIXME
(
"Ignoring flags %x
\n
"
,
dwReplaceFlags
);
/* First two arguments are mandatory */
if
(
!
lpReplacedFileName
||
!
lpReplacementFileName
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
Attributes
=
OBJ_CASE_INSENSITIVE
;
attr
.
ObjectName
=
NULL
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
/* Open the "replaced" file for reading */
if
(
!
(
RtlDosPathNameToNtPathName_U
(
lpReplacedFileName
,
&
nt_replaced_name
,
NULL
,
NULL
)))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
attr
.
ObjectName
=
&
nt_replaced_name
;
/* Replacement should fail if replaced is READ_ONLY */
status
=
NtQueryAttributesFile
(
&
attr
,
&
info
);
RtlFreeUnicodeString
(
&
nt_replaced_name
);
if
(
status
!=
STATUS_SUCCESS
)
return
set_ntstatus
(
status
);
if
(
info
.
FileAttributes
&
FILE_ATTRIBUTE_READONLY
)
{
SetLastError
(
ERROR_ACCESS_DENIED
);
return
FALSE
;
}
/*
* Open the replacement file for reading, writing, and deleting
* (writing and deleting are needed when finished)
*/
if
(
!
(
RtlDosPathNameToNtPathName_U
(
lpReplacementFileName
,
&
nt_replacement_name
,
NULL
,
NULL
)))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
attr
.
ObjectName
=
&
nt_replacement_name
;
status
=
NtOpenFile
(
&
hReplacement
,
GENERIC_READ
|
GENERIC_WRITE
|
DELETE
|
WRITE_DAC
|
SYNCHRONIZE
,
&
attr
,
&
io
,
0
,
FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_NON_DIRECTORY_FILE
);
RtlFreeUnicodeString
(
&
nt_replacement_name
);
if
(
status
!=
STATUS_SUCCESS
)
return
set_ntstatus
(
status
);
NtClose
(
hReplacement
);
/* If the user wants a backup then that needs to be performed first */
if
(
lpBackupFileName
)
{
if
(
!
MoveFileExW
(
lpReplacedFileName
,
lpBackupFileName
,
MOVEFILE_REPLACE_EXISTING
))
return
FALSE
;
}
else
{
/* ReplaceFile() can replace an open target. To do this, we need to move
* it out of the way first. */
static
const
WCHAR
prefixW
[]
=
{
'r'
,
'f'
,
0
};
WCHAR
temp_path
[
MAX_PATH
],
temp_file
[
MAX_PATH
];
lstrcpynW
(
temp_path
,
lpReplacedFileName
,
ARRAY_SIZE
(
temp_path
)
);
PathRemoveFileSpecW
(
temp_path
);
if
(
!
GetTempFileNameW
(
temp_path
,
prefixW
,
0
,
temp_file
)
||
!
MoveFileExW
(
lpReplacedFileName
,
temp_file
,
MOVEFILE_REPLACE_EXISTING
))
return
FALSE
;
DeleteFileW
(
temp_file
);
}
/*
* Now that the backup has been performed (if requested), copy the replacement
* into place
*/
if
(
!
MoveFileExW
(
lpReplacementFileName
,
lpReplacedFileName
,
0
))
{
/* on failure we need to indicate whether a backup was made */
if
(
!
lpBackupFileName
)
SetLastError
(
ERROR_UNABLE_TO_MOVE_REPLACEMENT
);
else
SetLastError
(
ERROR_UNABLE_TO_MOVE_REPLACEMENT_2
);
return
FALSE
;
}
return
TRUE
;
}
/**************************************************************************
* ReplaceFileA (KERNEL32.@)
* ReplaceFileA (KERNEL32.@)
*/
*/
BOOL
WINAPI
ReplaceFileA
(
LPCSTR
lpReplacedFileName
,
LPCSTR
lpReplacementFileName
,
BOOL
WINAPI
ReplaceFileA
(
LPCSTR
lpReplacedFileName
,
LPCSTR
lpReplacementFileName
,
...
@@ -865,214 +750,3 @@ DWORD WINAPI K32GetDeviceDriverFileNameW(void *image_base, LPWSTR file_name, DWO
...
@@ -865,214 +750,3 @@ DWORD WINAPI K32GetDeviceDriverFileNameW(void *image_base, LPWSTR file_name, DWO
return
0
;
return
0
;
}
}
/***********************************************************************
* GetFinalPathNameByHandleW (KERNEL32.@)
*/
DWORD
WINAPI
GetFinalPathNameByHandleW
(
HANDLE
file
,
LPWSTR
path
,
DWORD
charcount
,
DWORD
flags
)
{
WCHAR
buffer
[
sizeof
(
OBJECT_NAME_INFORMATION
)
+
MAX_PATH
+
1
];
OBJECT_NAME_INFORMATION
*
info
=
(
OBJECT_NAME_INFORMATION
*
)
&
buffer
;
WCHAR
drive_part
[
MAX_PATH
];
DWORD
drive_part_len
=
0
;
NTSTATUS
status
;
DWORD
result
=
0
;
ULONG
dummy
;
WCHAR
*
ptr
;
TRACE
(
"(%p,%p,%d,%x)
\n
"
,
file
,
path
,
charcount
,
flags
);
if
(
flags
&
~
(
FILE_NAME_OPENED
|
VOLUME_NAME_GUID
|
VOLUME_NAME_NONE
|
VOLUME_NAME_NT
))
{
WARN
(
"Unknown flags: %x
\n
"
,
flags
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
/* get object name */
status
=
NtQueryObject
(
file
,
ObjectNameInformation
,
&
buffer
,
sizeof
(
buffer
)
-
sizeof
(
WCHAR
),
&
dummy
);
if
(
status
!=
STATUS_SUCCESS
)
{
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
return
0
;
}
if
(
!
info
->
Name
.
Buffer
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
0
;
}
if
(
info
->
Name
.
Length
<
4
*
sizeof
(
WCHAR
)
||
info
->
Name
.
Buffer
[
0
]
!=
'\\'
||
info
->
Name
.
Buffer
[
1
]
!=
'?'
||
info
->
Name
.
Buffer
[
2
]
!=
'?'
||
info
->
Name
.
Buffer
[
3
]
!=
'\\'
)
{
FIXME
(
"Unexpected object name: %s
\n
"
,
debugstr_wn
(
info
->
Name
.
Buffer
,
info
->
Name
.
Length
/
sizeof
(
WCHAR
)));
SetLastError
(
ERROR_GEN_FAILURE
);
return
0
;
}
/* add terminating null character, remove "\\??\\" */
info
->
Name
.
Buffer
[
info
->
Name
.
Length
/
sizeof
(
WCHAR
)]
=
0
;
info
->
Name
.
Length
-=
4
*
sizeof
(
WCHAR
);
info
->
Name
.
Buffer
+=
4
;
/* FILE_NAME_OPENED is not supported yet, and would require Wineserver changes */
if
(
flags
&
FILE_NAME_OPENED
)
{
FIXME
(
"FILE_NAME_OPENED not supported
\n
"
);
flags
&=
~
FILE_NAME_OPENED
;
}
/* Get information required for VOLUME_NAME_NONE, VOLUME_NAME_GUID and VOLUME_NAME_NT */
if
(
flags
==
VOLUME_NAME_NONE
||
flags
==
VOLUME_NAME_GUID
||
flags
==
VOLUME_NAME_NT
)
{
if
(
!
GetVolumePathNameW
(
info
->
Name
.
Buffer
,
drive_part
,
MAX_PATH
))
return
0
;
drive_part_len
=
strlenW
(
drive_part
);
if
(
!
drive_part_len
||
drive_part_len
>
strlenW
(
info
->
Name
.
Buffer
)
||
drive_part
[
drive_part_len
-
1
]
!=
'\\'
||
strncmpiW
(
info
->
Name
.
Buffer
,
drive_part
,
drive_part_len
))
{
FIXME
(
"Path %s returned by GetVolumePathNameW does not match file path %s
\n
"
,
debugstr_w
(
drive_part
),
debugstr_w
(
info
->
Name
.
Buffer
));
SetLastError
(
ERROR_GEN_FAILURE
);
return
0
;
}
}
if
(
flags
==
VOLUME_NAME_NONE
)
{
ptr
=
info
->
Name
.
Buffer
+
drive_part_len
-
1
;
result
=
strlenW
(
ptr
);
if
(
result
<
charcount
)
memcpy
(
path
,
ptr
,
(
result
+
1
)
*
sizeof
(
WCHAR
));
else
result
++
;
}
else
if
(
flags
==
VOLUME_NAME_GUID
)
{
WCHAR
volume_prefix
[
51
];
/* GetVolumeNameForVolumeMountPointW sets error code on failure */
if
(
!
GetVolumeNameForVolumeMountPointW
(
drive_part
,
volume_prefix
,
50
))
return
0
;
ptr
=
info
->
Name
.
Buffer
+
drive_part_len
;
result
=
strlenW
(
volume_prefix
)
+
strlenW
(
ptr
);
if
(
result
<
charcount
)
{
path
[
0
]
=
0
;
strcatW
(
path
,
volume_prefix
);
strcatW
(
path
,
ptr
);
}
else
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
result
++
;
}
}
else
if
(
flags
==
VOLUME_NAME_NT
)
{
WCHAR
nt_prefix
[
MAX_PATH
];
/* QueryDosDeviceW sets error code on failure */
drive_part
[
drive_part_len
-
1
]
=
0
;
if
(
!
QueryDosDeviceW
(
drive_part
,
nt_prefix
,
MAX_PATH
))
return
0
;
ptr
=
info
->
Name
.
Buffer
+
drive_part_len
-
1
;
result
=
strlenW
(
nt_prefix
)
+
strlenW
(
ptr
);
if
(
result
<
charcount
)
{
path
[
0
]
=
0
;
strcatW
(
path
,
nt_prefix
);
strcatW
(
path
,
ptr
);
}
else
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
result
++
;
}
}
else
if
(
flags
==
VOLUME_NAME_DOS
)
{
static
const
WCHAR
dos_prefix
[]
=
{
'\\'
,
'\\'
,
'?'
,
'\\'
,
'\0'
};
result
=
strlenW
(
dos_prefix
)
+
strlenW
(
info
->
Name
.
Buffer
);
if
(
result
<
charcount
)
{
path
[
0
]
=
0
;
strcatW
(
path
,
dos_prefix
);
strcatW
(
path
,
info
->
Name
.
Buffer
);
}
else
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
result
++
;
}
}
else
{
/* Windows crashes here, but we prefer returning ERROR_INVALID_PARAMETER */
WARN
(
"Invalid combination of flags: %x
\n
"
,
flags
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
}
return
result
;
}
/***********************************************************************
* GetFinalPathNameByHandleA (KERNEL32.@)
*/
DWORD
WINAPI
GetFinalPathNameByHandleA
(
HANDLE
file
,
LPSTR
path
,
DWORD
charcount
,
DWORD
flags
)
{
WCHAR
*
str
;
DWORD
result
,
len
,
cp
;
TRACE
(
"(%p,%p,%d,%x)
\n
"
,
file
,
path
,
charcount
,
flags
);
len
=
GetFinalPathNameByHandleW
(
file
,
NULL
,
0
,
flags
);
if
(
len
==
0
)
return
0
;
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
if
(
!
str
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
result
=
GetFinalPathNameByHandleW
(
file
,
str
,
len
,
flags
);
if
(
result
!=
len
-
1
)
{
HeapFree
(
GetProcessHeap
(),
0
,
str
);
WARN
(
"GetFinalPathNameByHandleW failed unexpectedly: %u
\n
"
,
result
);
return
0
;
}
cp
=
AreFileApisANSI
()
?
CP_ACP
:
CP_OEMCP
;
len
=
WideCharToMultiByte
(
cp
,
0
,
str
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
!
len
)
{
HeapFree
(
GetProcessHeap
(),
0
,
str
);
WARN
(
"Failed to get multibyte length
\n
"
);
return
0
;
}
if
(
charcount
<
len
)
{
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
len
-
1
;
}
len
=
WideCharToMultiByte
(
cp
,
0
,
str
,
-
1
,
path
,
charcount
,
NULL
,
NULL
);
if
(
!
len
)
{
HeapFree
(
GetProcessHeap
(),
0
,
str
);
WARN
(
"WideCharToMultiByte failed
\n
"
);
return
0
;
}
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
len
-
1
;
}
dlls/kernel32/kernel32.spec
View file @
b6c94018
...
@@ -258,10 +258,10 @@
...
@@ -258,10 +258,10 @@
# @ stub CopyContext
# @ stub CopyContext
@ stdcall CopyFileA(str str long)
@ stdcall CopyFileA(str str long)
@ stdcall CopyFileExA (str str ptr ptr ptr long)
@ stdcall CopyFileExA (str str ptr ptr ptr long)
@ stdcall
CopyFileExW
(wstr wstr ptr ptr ptr long)
@ stdcall
-import CopyFileExW
(wstr wstr ptr ptr ptr long)
# @ stub CopyFileTransactedA
# @ stub CopyFileTransactedA
# @ stub CopyFileTransactedW
# @ stub CopyFileTransactedW
@ stdcall CopyFileW(wstr wstr long)
@ stdcall
-import
CopyFileW(wstr wstr long)
@ stdcall CopyLZFile(long long) LZCopy
@ stdcall CopyLZFile(long long) LZCopy
@ stdcall CreateActCtxA(ptr)
@ stdcall CreateActCtxA(ptr)
@ stdcall -import CreateActCtxW(ptr)
@ stdcall -import CreateActCtxW(ptr)
...
@@ -287,10 +287,10 @@
...
@@ -287,10 +287,10 @@
@ stdcall -import CreateFileMappingNumaW(long ptr long long long wstr long)
@ stdcall -import CreateFileMappingNumaW(long ptr long long long wstr long)
@ stdcall -import CreateFileMappingW(long ptr long long long wstr)
@ stdcall -import CreateFileMappingW(long ptr long long long wstr)
@ stdcall -import CreateFileW(wstr long long ptr long long long)
@ stdcall -import CreateFileW(wstr long long ptr long long long)
@ stdcall CreateHardLinkA(str str ptr)
@ stdcall
-import
CreateHardLinkA(str str ptr)
@ stdcall CreateHardLinkTransactedA(str str ptr ptr)
@ stdcall CreateHardLinkTransactedA(str str ptr ptr)
@ stdcall CreateHardLinkTransactedW(wstr wstr ptr ptr)
@ stdcall CreateHardLinkTransactedW(wstr wstr ptr ptr)
@ stdcall CreateHardLinkW(wstr wstr ptr)
@ stdcall
-import
CreateHardLinkW(wstr wstr ptr)
@ stdcall -import CreateIoCompletionPort(long long long long)
@ stdcall -import CreateIoCompletionPort(long long long long)
@ stdcall CreateJobObjectA(ptr str)
@ stdcall CreateJobObjectA(ptr str)
@ stdcall CreateJobObjectW(ptr wstr)
@ stdcall CreateJobObjectW(ptr wstr)
...
@@ -326,7 +326,7 @@
...
@@ -326,7 +326,7 @@
@ stdcall CreateSymbolicLinkA(str str long)
@ stdcall CreateSymbolicLinkA(str str long)
# @ stub CreateSymbolicLinkTransactedA
# @ stub CreateSymbolicLinkTransactedA
# @ stub CreateSymbolicLinkTransactedW
# @ stub CreateSymbolicLinkTransactedW
@ stdcall CreateSymbolicLinkW(wstr wstr long)
@ stdcall
-import
CreateSymbolicLinkW(wstr wstr long)
@ stdcall CreateTapePartition(long long long long)
@ stdcall CreateTapePartition(long long long long)
@ stdcall -import CreateThread(ptr long ptr long long ptr)
@ stdcall -import CreateThread(ptr long ptr long long ptr)
@ stdcall -import CreateThreadpool(ptr)
@ stdcall -import CreateThreadpool(ptr)
...
@@ -684,8 +684,8 @@
...
@@ -684,8 +684,8 @@
@ stdcall -import GetFileSizeEx(long ptr)
@ stdcall -import GetFileSizeEx(long ptr)
@ stdcall -import GetFileTime(long ptr ptr ptr)
@ stdcall -import GetFileTime(long ptr ptr ptr)
@ stdcall -import GetFileType(long)
@ stdcall -import GetFileType(long)
@ stdcall GetFinalPathNameByHandleA(long ptr long long)
@ stdcall
-import
GetFinalPathNameByHandleA(long ptr long long)
@ stdcall GetFinalPathNameByHandleW(long ptr long long)
@ stdcall
-import
GetFinalPathNameByHandleW(long ptr long long)
@ stdcall GetFirmwareEnvironmentVariableA(str str ptr long)
@ stdcall GetFirmwareEnvironmentVariableA(str str ptr long)
@ stdcall GetFirmwareEnvironmentVariableW(wstr wstr ptr long)
@ stdcall GetFirmwareEnvironmentVariableW(wstr wstr ptr long)
@ stdcall -import GetFullPathNameA(str long ptr ptr)
@ stdcall -import GetFullPathNameA(str long ptr ptr)
...
@@ -1091,12 +1091,12 @@
...
@@ -1091,12 +1091,12 @@
@ stdcall Module32NextW(long ptr)
@ stdcall Module32NextW(long ptr)
@ stdcall MoveFileA(str str)
@ stdcall MoveFileA(str str)
@ stdcall MoveFileExA(str str long)
@ stdcall MoveFileExA(str str long)
@ stdcall MoveFileExW(wstr wstr long)
@ stdcall
-import
MoveFileExW(wstr wstr long)
@ stdcall MoveFileTransactedA(str str ptr ptr long ptr)
@ stdcall MoveFileTransactedA(str str ptr ptr long ptr)
@ stdcall MoveFileTransactedW(wstr wstr ptr ptr long ptr)
@ stdcall MoveFileTransactedW(wstr wstr ptr ptr long ptr)
@ stdcall MoveFileW(wstr wstr)
@ stdcall MoveFileW(wstr wstr)
@ stdcall MoveFileWithProgressA(str str ptr ptr long)
@ stdcall MoveFileWithProgressA(str str ptr ptr long)
@ stdcall MoveFileWithProgressW(wstr wstr ptr ptr long)
@ stdcall
-import
MoveFileWithProgressW(wstr wstr ptr ptr long)
@ stdcall MulDiv(long long long)
@ stdcall MulDiv(long long long)
@ stdcall -import MultiByteToWideChar(long long str long ptr long)
@ stdcall -import MultiByteToWideChar(long long str long ptr long)
@ stdcall -import NeedCurrentDirectoryForExePathA(str)
@ stdcall -import NeedCurrentDirectoryForExePathA(str)
...
@@ -1273,9 +1273,9 @@
...
@@ -1273,9 +1273,9 @@
@ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler
@ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler
@ stdcall RemoveVectoredExceptionHandler(ptr) ntdll.RtlRemoveVectoredExceptionHandler
@ stdcall RemoveVectoredExceptionHandler(ptr) ntdll.RtlRemoveVectoredExceptionHandler
@ stdcall -import ReOpenFile(ptr long long long) ReOpenFile
@ stdcall -import ReOpenFile(ptr long long long) ReOpenFile
@ stdcall ReplaceFile(wstr wstr wstr long ptr ptr) ReplaceFileW
@ stdcall
-import
ReplaceFile(wstr wstr wstr long ptr ptr) ReplaceFileW
@ stdcall ReplaceFileA(str str str long ptr ptr)
@ stdcall ReplaceFileA(str str str long ptr ptr)
@ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr)
@ stdcall
-import
ReplaceFileW(wstr wstr wstr long ptr ptr)
# @ stub RemoveDirectoryTransactedA
# @ stub RemoveDirectoryTransactedA
# @ stub RemoveDirectoryTransactedW
# @ stub RemoveDirectoryTransactedW
@ stdcall -import RemoveDllDirectory(ptr)
@ stdcall -import RemoveDllDirectory(ptr)
...
...
dlls/kernel32/path.c
View file @
b6c94018
...
@@ -73,153 +73,6 @@ static DWORD copy_filename_WtoA( LPCWSTR nameW, LPSTR buffer, DWORD len )
...
@@ -73,153 +73,6 @@ static DWORD copy_filename_WtoA( LPCWSTR nameW, LPSTR buffer, DWORD len )
}
}
/***********************************************************************
/***********************************************************************
* 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 registry key 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
};
static
const
WCHAR
SessionW
[]
=
{
'\\'
,
'R'
,
'e'
,
'g'
,
'i'
,
's'
,
't'
,
'r'
,
'y'
,
'\\'
,
'M'
,
'a'
,
'c'
,
'h'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'S'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
'\\'
,
'C'
,
'u'
,
'r'
,
'r'
,
'e'
,
'n'
,
't'
,
'C'
,
'o'
,
'n'
,
't'
,
'r'
,
'o'
,
'l'
,
'S'
,
'e'
,
't'
,
'\\'
,
'C'
,
'o'
,
'n'
,
't'
,
'r'
,
'o'
,
'l'
,
'\\'
,
'S'
,
'e'
,
's'
,
's'
,
'i'
,
'o'
,
'n'
,
' '
,
'M'
,
'a'
,
'n'
,
'a'
,
'g'
,
'e'
,
'r'
,
0
};
static
const
int
info_size
=
FIELD_OFFSET
(
KEY_VALUE_PARTIAL_INFORMATION
,
Data
);
OBJECT_ATTRIBUTES
attr
;
UNICODE_STRING
nameW
,
source_name
,
dest_name
;
KEY_VALUE_PARTIAL_INFORMATION
*
info
;
BOOL
rc
=
FALSE
;
HANDLE
Reboot
=
0
;
DWORD
len1
,
len2
;
DWORD
DataSize
=
0
;
BYTE
*
Buffer
=
NULL
;
WCHAR
*
p
;
if
(
!
RtlDosPathNameToNtPathName_U
(
source
,
&
source_name
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
dest_name
.
Buffer
=
NULL
;
if
(
dest
&&
!
RtlDosPathNameToNtPathName_U
(
dest
,
&
dest_name
,
NULL
,
NULL
))
{
RtlFreeUnicodeString
(
&
source_name
);
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
ObjectName
=
&
nameW
;
attr
.
Attributes
=
0
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
RtlInitUnicodeString
(
&
nameW
,
SessionW
);
if
(
NtCreateKey
(
&
Reboot
,
KEY_ALL_ACCESS
,
&
attr
,
0
,
NULL
,
0
,
NULL
)
!=
STATUS_SUCCESS
)
{
WARN
(
"Error creating key for reboot management [%s]
\n
"
,
"SYSTEM
\\
CurrentControlSet
\\
Control
\\
Session Manager"
);
RtlFreeUnicodeString
(
&
source_name
);
RtlFreeUnicodeString
(
&
dest_name
);
return
FALSE
;
}
len1
=
source_name
.
Length
+
sizeof
(
WCHAR
);
if
(
dest
)
{
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. */
if
(
NtQueryValueKey
(
Reboot
,
&
nameW
,
KeyValuePartialInformation
,
NULL
,
0
,
&
DataSize
)
==
STATUS_BUFFER_TOO_SMALL
)
{
if
(
!
(
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
DataSize
+
len1
+
len2
+
sizeof
(
WCHAR
)
)))
goto
Quit
;
if
(
NtQueryValueKey
(
Reboot
,
&
nameW
,
KeyValuePartialInformation
,
Buffer
,
DataSize
,
&
DataSize
))
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
(
dest
)
{
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
=
!
NtSetValueKey
(
Reboot
,
&
nameW
,
0
,
REG_MULTI_SZ
,
Buffer
+
info_size
,
DataSize
-
info_size
);
Quit:
RtlFreeUnicodeString
(
&
source_name
);
RtlFreeUnicodeString
(
&
dest_name
);
if
(
Reboot
)
NtClose
(
Reboot
);
HeapFree
(
GetProcessHeap
(),
0
,
Buffer
);
return
(
rc
);
}
/***********************************************************************
* GetShortPathNameA (KERNEL32.@)
* GetShortPathNameA (KERNEL32.@)
*/
*/
DWORD
WINAPI
GetShortPathNameA
(
LPCSTR
longpath
,
LPSTR
shortpath
,
DWORD
shortlen
)
DWORD
WINAPI
GetShortPathNameA
(
LPCSTR
longpath
,
LPSTR
shortpath
,
DWORD
shortlen
)
...
@@ -244,26 +97,6 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen
...
@@ -244,26 +97,6 @@ DWORD WINAPI GetShortPathNameA( LPCSTR longpath, LPSTR shortpath, DWORD shortlen
}
}
static
BOOL
is_same_file
(
HANDLE
h1
,
HANDLE
h2
)
{
FILE_ID_INFORMATION
id1
,
id2
;
IO_STATUS_BLOCK
io
;
return
!
NtQueryInformationFile
(
h1
,
&
io
,
&
id1
,
sizeof
(
id1
),
FileIdInformation
)
&&
!
NtQueryInformationFile
(
h2
,
&
io
,
&
id2
,
sizeof
(
id2
),
FileIdInformation
)
&&
!
memcmp
(
&
id1
,
&
id2
,
sizeof
(
FILE_ID_INFORMATION
)
);
}
/**************************************************************************
* CopyFileW (KERNEL32.@)
*/
BOOL
WINAPI
CopyFileW
(
LPCWSTR
source
,
LPCWSTR
dest
,
BOOL
fail_if_exists
)
{
return
CopyFileExW
(
source
,
dest
,
NULL
,
NULL
,
NULL
,
fail_if_exists
?
COPY_FILE_FAIL_IF_EXISTS
:
0
);
}
/**************************************************************************
/**************************************************************************
* CopyFileA (KERNEL32.@)
* CopyFileA (KERNEL32.@)
*/
*/
...
@@ -283,101 +116,6 @@ BOOL WINAPI CopyFileA( LPCSTR source, LPCSTR dest, BOOL fail_if_exists)
...
@@ -283,101 +116,6 @@ BOOL WINAPI CopyFileA( LPCSTR source, LPCSTR dest, BOOL fail_if_exists)
/**************************************************************************
/**************************************************************************
* CopyFileExW (KERNEL32.@)
*/
BOOL
WINAPI
CopyFileExW
(
LPCWSTR
source
,
LPCWSTR
dest
,
LPPROGRESS_ROUTINE
progress
,
LPVOID
param
,
LPBOOL
cancel_ptr
,
DWORD
flags
)
{
static
const
int
buffer_size
=
65536
;
HANDLE
h1
,
h2
;
BY_HANDLE_FILE_INFORMATION
info
;
DWORD
count
;
BOOL
ret
=
FALSE
;
char
*
buffer
;
if
(
!
source
||
!
dest
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
!
(
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
buffer_size
)))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
TRACE
(
"%s -> %s, %x
\n
"
,
debugstr_w
(
source
),
debugstr_w
(
dest
),
flags
);
if
((
h1
=
CreateFileW
(
source
,
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
|
FILE_SHARE_DELETE
,
NULL
,
OPEN_EXISTING
,
0
,
0
))
==
INVALID_HANDLE_VALUE
)
{
WARN
(
"Unable to open source %s
\n
"
,
debugstr_w
(
source
));
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
return
FALSE
;
}
if
(
!
GetFileInformationByHandle
(
h1
,
&
info
))
{
WARN
(
"GetFileInformationByHandle returned error for %s
\n
"
,
debugstr_w
(
source
));
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
CloseHandle
(
h1
);
return
FALSE
;
}
if
(
!
(
flags
&
COPY_FILE_FAIL_IF_EXISTS
))
{
BOOL
same_file
=
FALSE
;
h2
=
CreateFileW
(
dest
,
0
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
if
(
h2
!=
INVALID_HANDLE_VALUE
)
{
same_file
=
is_same_file
(
h1
,
h2
);
CloseHandle
(
h2
);
}
if
(
same_file
)
{
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
CloseHandle
(
h1
);
SetLastError
(
ERROR_SHARING_VIOLATION
);
return
FALSE
;
}
}
if
((
h2
=
CreateFileW
(
dest
,
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
(
flags
&
COPY_FILE_FAIL_IF_EXISTS
)
?
CREATE_NEW
:
CREATE_ALWAYS
,
info
.
dwFileAttributes
,
h1
))
==
INVALID_HANDLE_VALUE
)
{
WARN
(
"Unable to open dest %s
\n
"
,
debugstr_w
(
dest
));
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
CloseHandle
(
h1
);
return
FALSE
;
}
while
(
ReadFile
(
h1
,
buffer
,
buffer_size
,
&
count
,
NULL
)
&&
count
)
{
char
*
p
=
buffer
;
while
(
count
!=
0
)
{
DWORD
res
;
if
(
!
WriteFile
(
h2
,
p
,
count
,
&
res
,
NULL
)
||
!
res
)
goto
done
;
p
+=
res
;
count
-=
res
;
}
}
ret
=
TRUE
;
done:
/* Maintain the timestamp of source file to destination file */
SetFileTime
(
h2
,
NULL
,
NULL
,
&
info
.
ftLastWriteTime
);
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
CloseHandle
(
h1
);
CloseHandle
(
h2
);
return
ret
;
}
/**************************************************************************
* CopyFileExA (KERNEL32.@)
* CopyFileExA (KERNEL32.@)
*/
*/
BOOL
WINAPI
CopyFileExA
(
LPCSTR
sourceFilename
,
LPCSTR
destFilename
,
BOOL
WINAPI
CopyFileExA
(
LPCSTR
sourceFilename
,
LPCSTR
destFilename
,
...
@@ -422,95 +160,6 @@ BOOL WINAPI MoveFileTransactedW(const WCHAR *source, const WCHAR *dest, LPPROGRE
...
@@ -422,95 +160,6 @@ BOOL WINAPI MoveFileTransactedW(const WCHAR *source, const WCHAR *dest, LPPROGRE
}
}
/**************************************************************************
/**************************************************************************
* MoveFileWithProgressW (KERNEL32.@)
*/
BOOL
WINAPI
MoveFileWithProgressW
(
LPCWSTR
source
,
LPCWSTR
dest
,
LPPROGRESS_ROUTINE
fnProgress
,
LPVOID
param
,
DWORD
flag
)
{
FILE_RENAME_INFORMATION
*
rename_info
;
FILE_BASIC_INFORMATION
info
;
UNICODE_STRING
nt_name
;
OBJECT_ATTRIBUTES
attr
;
IO_STATUS_BLOCK
io
;
NTSTATUS
status
;
HANDLE
source_handle
=
0
;
ULONG
size
;
TRACE
(
"(%s,%s,%p,%p,%04x)
\n
"
,
debugstr_w
(
source
),
debugstr_w
(
dest
),
fnProgress
,
param
,
flag
);
if
(
flag
&
MOVEFILE_DELAY_UNTIL_REBOOT
)
return
add_boot_rename_entry
(
source
,
dest
,
flag
);
if
(
!
dest
)
return
DeleteFileW
(
source
);
/* check if we are allowed to rename the source */
if
(
!
RtlDosPathNameToNtPathName_U
(
source
,
&
nt_name
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
Attributes
=
OBJ_CASE_INSENSITIVE
;
attr
.
ObjectName
=
&
nt_name
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
status
=
NtOpenFile
(
&
source_handle
,
DELETE
|
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
|
FILE_SHARE_DELETE
,
FILE_SYNCHRONOUS_IO_NONALERT
);
RtlFreeUnicodeString
(
&
nt_name
);
if
(
status
!=
STATUS_SUCCESS
)
{
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
goto
error
;
}
status
=
NtQueryInformationFile
(
source_handle
,
&
io
,
&
info
,
sizeof
(
info
),
FileBasicInformation
);
if
(
status
!=
STATUS_SUCCESS
)
{
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
goto
error
;
}
if
(
!
RtlDosPathNameToNtPathName_U
(
dest
,
&
nt_name
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
goto
error
;
}
size
=
offsetof
(
FILE_RENAME_INFORMATION
,
FileName
)
+
nt_name
.
Length
;
if
(
!
(
rename_info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
)))
goto
error
;
rename_info
->
ReplaceIfExists
=
!!
(
flag
&
MOVEFILE_REPLACE_EXISTING
);
rename_info
->
RootDirectory
=
NULL
;
rename_info
->
FileNameLength
=
nt_name
.
Length
;
memcpy
(
rename_info
->
FileName
,
nt_name
.
Buffer
,
nt_name
.
Length
);
RtlFreeUnicodeString
(
&
nt_name
);
status
=
NtSetInformationFile
(
source_handle
,
&
io
,
rename_info
,
size
,
FileRenameInformation
);
HeapFree
(
GetProcessHeap
(),
0
,
rename_info
);
if
(
status
==
STATUS_NOT_SAME_DEVICE
&&
(
flag
&
MOVEFILE_COPY_ALLOWED
))
{
NtClose
(
source_handle
);
if
(
!
CopyFileExW
(
source
,
dest
,
fnProgress
,
param
,
NULL
,
flag
&
MOVEFILE_REPLACE_EXISTING
?
0
:
COPY_FILE_FAIL_IF_EXISTS
))
return
FALSE
;
return
DeleteFileW
(
source
);
}
NtClose
(
source_handle
);
return
set_ntstatus
(
status
);
error:
if
(
source_handle
)
NtClose
(
source_handle
);
return
FALSE
;
}
/**************************************************************************
* MoveFileWithProgressA (KERNEL32.@)
* MoveFileWithProgressA (KERNEL32.@)
*/
*/
BOOL
WINAPI
MoveFileWithProgressA
(
LPCSTR
source
,
LPCSTR
dest
,
BOOL
WINAPI
MoveFileWithProgressA
(
LPCSTR
source
,
LPCSTR
dest
,
...
@@ -534,14 +183,6 @@ BOOL WINAPI MoveFileWithProgressA( LPCSTR source, LPCSTR dest,
...
@@ -534,14 +183,6 @@ BOOL WINAPI MoveFileWithProgressA( LPCSTR source, LPCSTR dest,
}
}
/**************************************************************************
/**************************************************************************
* MoveFileExW (KERNEL32.@)
*/
BOOL
WINAPI
MoveFileExW
(
LPCWSTR
source
,
LPCWSTR
dest
,
DWORD
flag
)
{
return
MoveFileWithProgressW
(
source
,
dest
,
NULL
,
NULL
,
flag
);
}
/**************************************************************************
* MoveFileExA (KERNEL32.@)
* MoveFileExA (KERNEL32.@)
*/
*/
BOOL
WINAPI
MoveFileExA
(
LPCSTR
source
,
LPCSTR
dest
,
DWORD
flag
)
BOOL
WINAPI
MoveFileExA
(
LPCSTR
source
,
LPCSTR
dest
,
DWORD
flag
)
...
@@ -570,87 +211,6 @@ BOOL WINAPI MoveFileA( LPCSTR source, LPCSTR dest )
...
@@ -570,87 +211,6 @@ BOOL WINAPI MoveFileA( LPCSTR source, LPCSTR dest )
}
}
/*************************************************************************
* CreateHardLinkW (KERNEL32.@)
*/
BOOL
WINAPI
CreateHardLinkW
(
LPCWSTR
lpFileName
,
LPCWSTR
lpExistingFileName
,
LPSECURITY_ATTRIBUTES
lpSecurityAttributes
)
{
UNICODE_STRING
ntDest
,
ntSource
;
FILE_LINK_INFORMATION
*
info
=
NULL
;
OBJECT_ATTRIBUTES
attr
;
IO_STATUS_BLOCK
io
;
BOOL
ret
=
FALSE
;
HANDLE
file
;
ULONG
size
;
TRACE
(
"(%s, %s, %p)
\n
"
,
debugstr_w
(
lpFileName
),
debugstr_w
(
lpExistingFileName
),
lpSecurityAttributes
);
ntDest
.
Buffer
=
ntSource
.
Buffer
=
NULL
;
if
(
!
RtlDosPathNameToNtPathName_U
(
lpFileName
,
&
ntDest
,
NULL
,
NULL
)
||
!
RtlDosPathNameToNtPathName_U
(
lpExistingFileName
,
&
ntSource
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
goto
err
;
}
size
=
offsetof
(
FILE_LINK_INFORMATION
,
FileName
)
+
ntDest
.
Length
;
if
(
!
(
info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
)))
{
SetLastError
(
ERROR_OUTOFMEMORY
);
goto
err
;
}
InitializeObjectAttributes
(
&
attr
,
&
ntSource
,
OBJ_CASE_INSENSITIVE
,
0
,
NULL
);
if
(
!
(
ret
=
set_ntstatus
(
NtOpenFile
(
&
file
,
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
FILE_SYNCHRONOUS_IO_NONALERT
)
)))
goto
err
;
info
->
ReplaceIfExists
=
FALSE
;
info
->
RootDirectory
=
NULL
;
info
->
FileNameLength
=
ntDest
.
Length
;
memcpy
(
info
->
FileName
,
ntDest
.
Buffer
,
ntDest
.
Length
);
ret
=
set_ntstatus
(
NtSetInformationFile
(
file
,
&
io
,
info
,
size
,
FileLinkInformation
)
);
NtClose
(
file
);
err:
RtlFreeUnicodeString
(
&
ntSource
);
RtlFreeUnicodeString
(
&
ntDest
);
HeapFree
(
GetProcessHeap
(),
0
,
info
);
return
ret
;
}
/*************************************************************************
* CreateHardLinkA (KERNEL32.@)
*/
BOOL
WINAPI
CreateHardLinkA
(
LPCSTR
lpFileName
,
LPCSTR
lpExistingFileName
,
LPSECURITY_ATTRIBUTES
lpSecurityAttributes
)
{
WCHAR
*
sourceW
,
*
destW
;
BOOL
res
;
if
(
!
(
sourceW
=
FILE_name_AtoW
(
lpExistingFileName
,
TRUE
)))
{
return
FALSE
;
}
if
(
!
(
destW
=
FILE_name_AtoW
(
lpFileName
,
TRUE
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
sourceW
);
return
FALSE
;
}
res
=
CreateHardLinkW
(
destW
,
sourceW
,
lpSecurityAttributes
);
HeapFree
(
GetProcessHeap
(),
0
,
sourceW
);
HeapFree
(
GetProcessHeap
(),
0
,
destW
);
return
res
;
}
/***********************************************************************
/***********************************************************************
* CreateDirectoryExA (KERNEL32.@)
* CreateDirectoryExA (KERNEL32.@)
*/
*/
...
@@ -821,15 +381,6 @@ WCHAR * CDECL wine_get_dos_file_name( LPCSTR str )
...
@@ -821,15 +381,6 @@ WCHAR * CDECL wine_get_dos_file_name( LPCSTR str )
}
}
/*************************************************************************
/*************************************************************************
* CreateSymbolicLinkW (KERNEL32.@)
*/
BOOLEAN
WINAPI
CreateSymbolicLinkW
(
LPCWSTR
link
,
LPCWSTR
target
,
DWORD
flags
)
{
FIXME
(
"(%s %s %d): stub
\n
"
,
debugstr_w
(
link
),
debugstr_w
(
target
),
flags
);
return
TRUE
;
}
/*************************************************************************
* CreateSymbolicLinkA (KERNEL32.@)
* CreateSymbolicLinkA (KERNEL32.@)
*/
*/
BOOLEAN
WINAPI
CreateSymbolicLinkA
(
LPCSTR
link
,
LPCSTR
target
,
DWORD
flags
)
BOOLEAN
WINAPI
CreateSymbolicLinkA
(
LPCSTR
link
,
LPCSTR
target
,
DWORD
flags
)
...
...
dlls/kernelbase/file.c
View file @
b6c94018
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
#include "winioctl.h"
#include "winioctl.h"
#include "wincon.h"
#include "wincon.h"
#include "fileapi.h"
#include "fileapi.h"
#include "shlwapi.h"
#include "ddk/ntddk.h"
#include "ddk/ntddk.h"
#include "ddk/ntddser.h"
#include "ddk/ntddser.h"
...
@@ -112,6 +113,136 @@ static inline BOOL contains_path( const WCHAR *name )
...
@@ -112,6 +113,136 @@ static inline BOOL contains_path( const WCHAR *name )
/***********************************************************************
/***********************************************************************
* 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 registry key 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
int
info_size
=
FIELD_OFFSET
(
KEY_VALUE_PARTIAL_INFORMATION
,
Data
);
OBJECT_ATTRIBUTES
attr
;
UNICODE_STRING
nameW
,
source_name
,
dest_name
;
KEY_VALUE_PARTIAL_INFORMATION
*
info
;
BOOL
rc
=
FALSE
;
HANDLE
key
=
0
;
DWORD
len1
,
len2
;
DWORD
size
=
0
;
BYTE
*
buffer
=
NULL
;
WCHAR
*
p
;
if
(
!
RtlDosPathNameToNtPathName_U
(
source
,
&
source_name
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
dest_name
.
Buffer
=
NULL
;
if
(
dest
&&
!
RtlDosPathNameToNtPathName_U
(
dest
,
&
dest_name
,
NULL
,
NULL
))
{
RtlFreeUnicodeString
(
&
source_name
);
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
ObjectName
=
&
nameW
;
attr
.
Attributes
=
0
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
RtlInitUnicodeString
(
&
nameW
,
L"
\\
Registry
\\
Machine
\\
System
\\
CurrentControlSet
\\
Control
\\
Session Manager"
);
if
(
NtCreateKey
(
&
key
,
KEY_ALL_ACCESS
,
&
attr
,
0
,
NULL
,
0
,
NULL
)
!=
STATUS_SUCCESS
)
{
RtlFreeUnicodeString
(
&
source_name
);
RtlFreeUnicodeString
(
&
dest_name
);
return
FALSE
;
}
len1
=
source_name
.
Length
+
sizeof
(
WCHAR
);
if
(
dest
)
{
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
,
L"PendingFileRenameOperations"
);
/* First we check if the key exists and if so how many bytes it already contains. */
if
(
NtQueryValueKey
(
key
,
&
nameW
,
KeyValuePartialInformation
,
NULL
,
0
,
&
size
)
==
STATUS_BUFFER_TOO_SMALL
)
{
if
(
!
(
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
+
len1
+
len2
+
sizeof
(
WCHAR
)
)))
goto
done
;
if
(
NtQueryValueKey
(
key
,
&
nameW
,
KeyValuePartialInformation
,
buffer
,
size
,
&
size
))
goto
done
;
info
=
(
KEY_VALUE_PARTIAL_INFORMATION
*
)
buffer
;
if
(
info
->
Type
!=
REG_MULTI_SZ
)
goto
done
;
if
(
size
>
sizeof
(
info
))
size
-=
sizeof
(
WCHAR
);
/* remove terminating null (will be added back later) */
}
else
{
size
=
info_size
;
if
(
!
(
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
+
len1
+
len2
+
sizeof
(
WCHAR
)
)))
goto
done
;
}
memcpy
(
buffer
+
size
,
source_name
.
Buffer
,
len1
);
size
+=
len1
;
p
=
(
WCHAR
*
)(
buffer
+
size
);
if
(
dest
)
{
if
(
flags
&
MOVEFILE_REPLACE_EXISTING
)
*
p
++
=
'!'
;
memcpy
(
p
,
dest_name
.
Buffer
,
len2
);
size
+=
len2
;
}
else
{
*
p
=
0
;
size
+=
sizeof
(
WCHAR
);
}
/* add final null */
p
=
(
WCHAR
*
)(
buffer
+
size
);
*
p
=
0
;
size
+=
sizeof
(
WCHAR
);
rc
=
!
NtSetValueKey
(
key
,
&
nameW
,
0
,
REG_MULTI_SZ
,
buffer
+
info_size
,
size
-
info_size
);
done:
RtlFreeUnicodeString
(
&
source_name
);
RtlFreeUnicodeString
(
&
dest_name
);
if
(
key
)
NtClose
(
key
);
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
return
rc
;
}
/***********************************************************************
* append_ext
* append_ext
*/
*/
static
WCHAR
*
append_ext
(
const
WCHAR
*
name
,
const
WCHAR
*
ext
)
static
WCHAR
*
append_ext
(
const
WCHAR
*
name
,
const
WCHAR
*
ext
)
...
@@ -337,6 +468,20 @@ DWORD file_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen )
...
@@ -337,6 +468,20 @@ DWORD file_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen )
}
}
/***********************************************************************
* is_same_file
*/
static
BOOL
is_same_file
(
HANDLE
h1
,
HANDLE
h2
)
{
FILE_ID_INFORMATION
id1
,
id2
;
IO_STATUS_BLOCK
io
;
return
!
NtQueryInformationFile
(
h1
,
&
io
,
&
id1
,
sizeof
(
id1
),
FileIdInformation
)
&&
!
NtQueryInformationFile
(
h2
,
&
io
,
&
id2
,
sizeof
(
id2
),
FileIdInformation
)
&&
!
memcmp
(
&
id1
,
&
id2
,
sizeof
(
FILE_ID_INFORMATION
)
);
}
/******************************************************************************
/******************************************************************************
* AreFileApisANSI (kernelbase.@)
* AreFileApisANSI (kernelbase.@)
*/
*/
...
@@ -347,6 +492,107 @@ BOOL WINAPI DECLSPEC_HOTPATCH AreFileApisANSI(void)
...
@@ -347,6 +492,107 @@ BOOL WINAPI DECLSPEC_HOTPATCH AreFileApisANSI(void)
/***********************************************************************
/***********************************************************************
* CopyFileExW (kernelbase.@)
*/
BOOL
WINAPI
CopyFileExW
(
const
WCHAR
*
source
,
const
WCHAR
*
dest
,
LPPROGRESS_ROUTINE
progress
,
void
*
param
,
BOOL
*
cancel_ptr
,
DWORD
flags
)
{
static
const
int
buffer_size
=
65536
;
HANDLE
h1
,
h2
;
BY_HANDLE_FILE_INFORMATION
info
;
DWORD
count
;
BOOL
ret
=
FALSE
;
char
*
buffer
;
if
(
!
source
||
!
dest
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
if
(
!
(
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
buffer_size
)))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
}
TRACE
(
"%s -> %s, %x
\n
"
,
debugstr_w
(
source
),
debugstr_w
(
dest
),
flags
);
if
((
h1
=
CreateFileW
(
source
,
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
|
FILE_SHARE_DELETE
,
NULL
,
OPEN_EXISTING
,
0
,
0
))
==
INVALID_HANDLE_VALUE
)
{
WARN
(
"Unable to open source %s
\n
"
,
debugstr_w
(
source
));
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
return
FALSE
;
}
if
(
!
GetFileInformationByHandle
(
h1
,
&
info
))
{
WARN
(
"GetFileInformationByHandle returned error for %s
\n
"
,
debugstr_w
(
source
));
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
CloseHandle
(
h1
);
return
FALSE
;
}
if
(
!
(
flags
&
COPY_FILE_FAIL_IF_EXISTS
))
{
BOOL
same_file
=
FALSE
;
h2
=
CreateFileW
(
dest
,
0
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
0
,
0
);
if
(
h2
!=
INVALID_HANDLE_VALUE
)
{
same_file
=
is_same_file
(
h1
,
h2
);
CloseHandle
(
h2
);
}
if
(
same_file
)
{
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
CloseHandle
(
h1
);
SetLastError
(
ERROR_SHARING_VIOLATION
);
return
FALSE
;
}
}
if
((
h2
=
CreateFileW
(
dest
,
GENERIC_WRITE
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
(
flags
&
COPY_FILE_FAIL_IF_EXISTS
)
?
CREATE_NEW
:
CREATE_ALWAYS
,
info
.
dwFileAttributes
,
h1
))
==
INVALID_HANDLE_VALUE
)
{
WARN
(
"Unable to open dest %s
\n
"
,
debugstr_w
(
dest
));
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
CloseHandle
(
h1
);
return
FALSE
;
}
while
(
ReadFile
(
h1
,
buffer
,
buffer_size
,
&
count
,
NULL
)
&&
count
)
{
char
*
p
=
buffer
;
while
(
count
!=
0
)
{
DWORD
res
;
if
(
!
WriteFile
(
h2
,
p
,
count
,
&
res
,
NULL
)
||
!
res
)
goto
done
;
p
+=
res
;
count
-=
res
;
}
}
ret
=
TRUE
;
done:
/* Maintain the timestamp of source file to destination file */
SetFileTime
(
h2
,
NULL
,
NULL
,
&
info
.
ftLastWriteTime
);
HeapFree
(
GetProcessHeap
(),
0
,
buffer
);
CloseHandle
(
h1
);
CloseHandle
(
h2
);
return
ret
;
}
/**************************************************************************
* CopyFileW (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CopyFileW
(
const
WCHAR
*
source
,
const
WCHAR
*
dest
,
BOOL
fail_if_exists
)
{
return
CopyFileExW
(
source
,
dest
,
NULL
,
NULL
,
NULL
,
fail_if_exists
?
COPY_FILE_FAIL_IF_EXISTS
:
0
);
}
/***********************************************************************
* CreateDirectoryA (kernelbase.@)
* CreateDirectoryA (kernelbase.@)
*/
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateDirectoryA
(
LPCSTR
path
,
LPSECURITY_ATTRIBUTES
sa
)
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateDirectoryA
(
LPCSTR
path
,
LPSECURITY_ATTRIBUTES
sa
)
...
@@ -622,6 +868,88 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileW( LPCWSTR filename, DWORD access, DWO
...
@@ -622,6 +868,88 @@ HANDLE WINAPI DECLSPEC_HOTPATCH CreateFileW( LPCWSTR filename, DWORD access, DWO
}
}
/*************************************************************************
* CreateHardLinkA (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
CreateHardLinkA
(
const
char
*
dest
,
const
char
*
source
,
SECURITY_ATTRIBUTES
*
attr
)
{
WCHAR
*
sourceW
,
*
destW
;
BOOL
res
;
if
(
!
(
sourceW
=
file_name_AtoW
(
source
,
TRUE
)))
return
FALSE
;
if
(
!
(
destW
=
file_name_AtoW
(
dest
,
TRUE
)))
{
HeapFree
(
GetProcessHeap
(),
0
,
sourceW
);
return
FALSE
;
}
res
=
CreateHardLinkW
(
destW
,
sourceW
,
attr
);
HeapFree
(
GetProcessHeap
(),
0
,
sourceW
);
HeapFree
(
GetProcessHeap
(),
0
,
destW
);
return
res
;
}
/*************************************************************************
* CreateHardLinkW (kernelbase.@)
*/
BOOL
WINAPI
CreateHardLinkW
(
LPCWSTR
dest
,
LPCWSTR
source
,
SECURITY_ATTRIBUTES
*
sec_attr
)
{
UNICODE_STRING
ntDest
,
ntSource
;
FILE_LINK_INFORMATION
*
info
=
NULL
;
OBJECT_ATTRIBUTES
attr
;
IO_STATUS_BLOCK
io
;
BOOL
ret
=
FALSE
;
HANDLE
file
;
ULONG
size
;
TRACE
(
"(%s, %s, %p)
\n
"
,
debugstr_w
(
dest
),
debugstr_w
(
source
),
sec_attr
);
ntDest
.
Buffer
=
ntSource
.
Buffer
=
NULL
;
if
(
!
RtlDosPathNameToNtPathName_U
(
dest
,
&
ntDest
,
NULL
,
NULL
)
||
!
RtlDosPathNameToNtPathName_U
(
source
,
&
ntSource
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
goto
done
;
}
size
=
offsetof
(
FILE_LINK_INFORMATION
,
FileName
)
+
ntDest
.
Length
;
if
(
!
(
info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
)))
{
SetLastError
(
ERROR_OUTOFMEMORY
);
goto
done
;
}
InitializeObjectAttributes
(
&
attr
,
&
ntSource
,
OBJ_CASE_INSENSITIVE
,
0
,
NULL
);
if
(
!
(
ret
=
set_ntstatus
(
NtOpenFile
(
&
file
,
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
FILE_SYNCHRONOUS_IO_NONALERT
)
)))
goto
done
;
info
->
ReplaceIfExists
=
FALSE
;
info
->
RootDirectory
=
NULL
;
info
->
FileNameLength
=
ntDest
.
Length
;
memcpy
(
info
->
FileName
,
ntDest
.
Buffer
,
ntDest
.
Length
);
ret
=
set_ntstatus
(
NtSetInformationFile
(
file
,
&
io
,
info
,
size
,
FileLinkInformation
)
);
NtClose
(
file
);
done:
RtlFreeUnicodeString
(
&
ntSource
);
RtlFreeUnicodeString
(
&
ntDest
);
HeapFree
(
GetProcessHeap
(),
0
,
info
);
return
ret
;
}
/*************************************************************************
* CreateSymbolicLinkW (kernelbase.@)
*/
BOOLEAN
WINAPI
/* DECLSPEC_HOTPATCH */
CreateSymbolicLinkW
(
LPCWSTR
link
,
LPCWSTR
target
,
DWORD
flags
)
{
FIXME
(
"(%s %s %d): stub
\n
"
,
debugstr_w
(
link
),
debugstr_w
(
target
),
flags
);
return
TRUE
;
}
/***********************************************************************
/***********************************************************************
* DeleteFileA (kernelbase.@)
* DeleteFileA (kernelbase.@)
*/
*/
...
@@ -1332,6 +1660,185 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetFileAttributesExW( LPCWSTR name, GET_FILEEX_INF
...
@@ -1332,6 +1660,185 @@ BOOL WINAPI DECLSPEC_HOTPATCH GetFileAttributesExW( LPCWSTR name, GET_FILEEX_INF
/***********************************************************************
/***********************************************************************
* GetFinalPathNameByHandleA (kernelbase.@)
*/
DWORD
WINAPI
DECLSPEC_HOTPATCH
GetFinalPathNameByHandleA
(
HANDLE
file
,
LPSTR
path
,
DWORD
count
,
DWORD
flags
)
{
WCHAR
*
str
;
DWORD
result
,
len
;
TRACE
(
"(%p,%p,%d,%x)
\n
"
,
file
,
path
,
count
,
flags
);
len
=
GetFinalPathNameByHandleW
(
file
,
NULL
,
0
,
flags
);
if
(
len
==
0
)
return
0
;
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
));
if
(
!
str
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
0
;
}
result
=
GetFinalPathNameByHandleW
(
file
,
str
,
len
,
flags
);
if
(
result
!=
len
-
1
)
{
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
0
;
}
len
=
file_name_WtoA
(
str
,
-
1
,
NULL
,
0
);
if
(
count
<
len
)
{
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
len
-
1
;
}
file_name_WtoA
(
str
,
-
1
,
path
,
count
);
HeapFree
(
GetProcessHeap
(),
0
,
str
);
return
len
-
1
;
}
/***********************************************************************
* GetFinalPathNameByHandleW (kernelbase.@)
*/
DWORD
WINAPI
DECLSPEC_HOTPATCH
GetFinalPathNameByHandleW
(
HANDLE
file
,
LPWSTR
path
,
DWORD
count
,
DWORD
flags
)
{
WCHAR
buffer
[
sizeof
(
OBJECT_NAME_INFORMATION
)
+
MAX_PATH
+
1
];
OBJECT_NAME_INFORMATION
*
info
=
(
OBJECT_NAME_INFORMATION
*
)
&
buffer
;
WCHAR
drive_part
[
MAX_PATH
];
DWORD
drive_part_len
=
0
;
NTSTATUS
status
;
DWORD
result
=
0
;
ULONG
dummy
;
WCHAR
*
ptr
;
TRACE
(
"(%p,%p,%d,%x)
\n
"
,
file
,
path
,
count
,
flags
);
if
(
flags
&
~
(
FILE_NAME_OPENED
|
VOLUME_NAME_GUID
|
VOLUME_NAME_NONE
|
VOLUME_NAME_NT
))
{
WARN
(
"Unknown flags: %x
\n
"
,
flags
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
0
;
}
/* get object name */
status
=
NtQueryObject
(
file
,
ObjectNameInformation
,
&
buffer
,
sizeof
(
buffer
)
-
sizeof
(
WCHAR
),
&
dummy
);
if
(
!
set_ntstatus
(
status
))
return
0
;
if
(
!
info
->
Name
.
Buffer
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
0
;
}
if
(
info
->
Name
.
Length
<
4
*
sizeof
(
WCHAR
)
||
info
->
Name
.
Buffer
[
0
]
!=
'\\'
||
info
->
Name
.
Buffer
[
1
]
!=
'?'
||
info
->
Name
.
Buffer
[
2
]
!=
'?'
||
info
->
Name
.
Buffer
[
3
]
!=
'\\'
)
{
FIXME
(
"Unexpected object name: %s
\n
"
,
debugstr_wn
(
info
->
Name
.
Buffer
,
info
->
Name
.
Length
/
sizeof
(
WCHAR
)));
SetLastError
(
ERROR_GEN_FAILURE
);
return
0
;
}
/* add terminating null character, remove "\\??\\" */
info
->
Name
.
Buffer
[
info
->
Name
.
Length
/
sizeof
(
WCHAR
)]
=
0
;
info
->
Name
.
Length
-=
4
*
sizeof
(
WCHAR
);
info
->
Name
.
Buffer
+=
4
;
/* FILE_NAME_OPENED is not supported yet, and would require Wineserver changes */
if
(
flags
&
FILE_NAME_OPENED
)
{
FIXME
(
"FILE_NAME_OPENED not supported
\n
"
);
flags
&=
~
FILE_NAME_OPENED
;
}
/* Get information required for VOLUME_NAME_NONE, VOLUME_NAME_GUID and VOLUME_NAME_NT */
if
(
flags
==
VOLUME_NAME_NONE
||
flags
==
VOLUME_NAME_GUID
||
flags
==
VOLUME_NAME_NT
)
{
if
(
!
GetVolumePathNameW
(
info
->
Name
.
Buffer
,
drive_part
,
MAX_PATH
))
return
0
;
drive_part_len
=
lstrlenW
(
drive_part
);
if
(
!
drive_part_len
||
drive_part_len
>
lstrlenW
(
info
->
Name
.
Buffer
)
||
drive_part
[
drive_part_len
-
1
]
!=
'\\'
||
CompareStringOrdinal
(
info
->
Name
.
Buffer
,
drive_part_len
,
drive_part
,
drive_part_len
,
TRUE
)
!=
CSTR_EQUAL
)
{
FIXME
(
"Path %s returned by GetVolumePathNameW does not match file path %s
\n
"
,
debugstr_w
(
drive_part
),
debugstr_w
(
info
->
Name
.
Buffer
)
);
SetLastError
(
ERROR_GEN_FAILURE
);
return
0
;
}
}
if
(
flags
==
VOLUME_NAME_NONE
)
{
ptr
=
info
->
Name
.
Buffer
+
drive_part_len
-
1
;
result
=
lstrlenW
(
ptr
);
if
(
result
<
count
)
memcpy
(
path
,
ptr
,
(
result
+
1
)
*
sizeof
(
WCHAR
));
else
result
++
;
}
else
if
(
flags
==
VOLUME_NAME_GUID
)
{
WCHAR
volume_prefix
[
51
];
/* GetVolumeNameForVolumeMountPointW sets error code on failure */
if
(
!
GetVolumeNameForVolumeMountPointW
(
drive_part
,
volume_prefix
,
50
))
return
0
;
ptr
=
info
->
Name
.
Buffer
+
drive_part_len
;
result
=
lstrlenW
(
volume_prefix
)
+
lstrlenW
(
ptr
);
if
(
result
<
count
)
{
lstrcpyW
(
path
,
volume_prefix
);
lstrcatW
(
path
,
ptr
);
}
else
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
result
++
;
}
}
else
if
(
flags
==
VOLUME_NAME_NT
)
{
WCHAR
nt_prefix
[
MAX_PATH
];
/* QueryDosDeviceW sets error code on failure */
drive_part
[
drive_part_len
-
1
]
=
0
;
if
(
!
QueryDosDeviceW
(
drive_part
,
nt_prefix
,
MAX_PATH
))
return
0
;
ptr
=
info
->
Name
.
Buffer
+
drive_part_len
-
1
;
result
=
lstrlenW
(
nt_prefix
)
+
lstrlenW
(
ptr
);
if
(
result
<
count
)
{
lstrcpyW
(
path
,
nt_prefix
);
lstrcatW
(
path
,
ptr
);
}
else
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
result
++
;
}
}
else
if
(
flags
==
VOLUME_NAME_DOS
)
{
result
=
4
+
lstrlenW
(
info
->
Name
.
Buffer
);
if
(
result
<
count
)
{
lstrcpyW
(
path
,
L"
\\\\
?
\\
"
);
lstrcatW
(
path
,
info
->
Name
.
Buffer
);
}
else
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
result
++
;
}
}
else
{
/* Windows crashes here, but we prefer returning ERROR_INVALID_PARAMETER */
WARN
(
"Invalid combination of flags: %x
\n
"
,
flags
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
}
return
result
;
}
/***********************************************************************
* GetFullPathNameA (kernelbase.@)
* GetFullPathNameA (kernelbase.@)
*/
*/
DWORD
WINAPI
DECLSPEC_HOTPATCH
GetFullPathNameA
(
LPCSTR
name
,
DWORD
len
,
LPSTR
buffer
,
LPSTR
*
lastpart
)
DWORD
WINAPI
DECLSPEC_HOTPATCH
GetFullPathNameA
(
LPCSTR
name
,
DWORD
len
,
LPSTR
buffer
,
LPSTR
*
lastpart
)
...
@@ -1891,6 +2398,94 @@ UINT WINAPI DECLSPEC_HOTPATCH GetWindowsDirectoryW( LPWSTR path, UINT count )
...
@@ -1891,6 +2398,94 @@ UINT WINAPI DECLSPEC_HOTPATCH GetWindowsDirectoryW( LPWSTR path, UINT count )
}
}
/**************************************************************************
* MoveFileExW (kernelbase.@)
*/
BOOL
WINAPI
MoveFileExW
(
const
WCHAR
*
source
,
const
WCHAR
*
dest
,
DWORD
flag
)
{
return
MoveFileWithProgressW
(
source
,
dest
,
NULL
,
NULL
,
flag
);
}
/**************************************************************************
* MoveFileWithProgressW (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
MoveFileWithProgressW
(
const
WCHAR
*
source
,
const
WCHAR
*
dest
,
LPPROGRESS_ROUTINE
progress
,
void
*
param
,
DWORD
flag
)
{
FILE_RENAME_INFORMATION
*
rename_info
;
FILE_BASIC_INFORMATION
info
;
UNICODE_STRING
nt_name
;
OBJECT_ATTRIBUTES
attr
;
IO_STATUS_BLOCK
io
;
NTSTATUS
status
;
HANDLE
source_handle
=
0
;
ULONG
size
;
TRACE
(
"(%s,%s,%p,%p,%04x)
\n
"
,
debugstr_w
(
source
),
debugstr_w
(
dest
),
progress
,
param
,
flag
);
if
(
flag
&
MOVEFILE_DELAY_UNTIL_REBOOT
)
return
add_boot_rename_entry
(
source
,
dest
,
flag
);
if
(
!
dest
)
return
DeleteFileW
(
source
);
/* check if we are allowed to rename the source */
if
(
!
RtlDosPathNameToNtPathName_U
(
source
,
&
nt_name
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
Attributes
=
OBJ_CASE_INSENSITIVE
;
attr
.
ObjectName
=
&
nt_name
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
status
=
NtOpenFile
(
&
source_handle
,
DELETE
|
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
|
FILE_SHARE_DELETE
,
FILE_SYNCHRONOUS_IO_NONALERT
);
RtlFreeUnicodeString
(
&
nt_name
);
if
(
!
set_ntstatus
(
status
))
goto
error
;
status
=
NtQueryInformationFile
(
source_handle
,
&
io
,
&
info
,
sizeof
(
info
),
FileBasicInformation
);
if
(
!
set_ntstatus
(
status
))
goto
error
;
if
(
!
RtlDosPathNameToNtPathName_U
(
dest
,
&
nt_name
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
goto
error
;
}
size
=
offsetof
(
FILE_RENAME_INFORMATION
,
FileName
)
+
nt_name
.
Length
;
if
(
!
(
rename_info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
)))
goto
error
;
rename_info
->
ReplaceIfExists
=
!!
(
flag
&
MOVEFILE_REPLACE_EXISTING
);
rename_info
->
RootDirectory
=
NULL
;
rename_info
->
FileNameLength
=
nt_name
.
Length
;
memcpy
(
rename_info
->
FileName
,
nt_name
.
Buffer
,
nt_name
.
Length
);
RtlFreeUnicodeString
(
&
nt_name
);
status
=
NtSetInformationFile
(
source_handle
,
&
io
,
rename_info
,
size
,
FileRenameInformation
);
HeapFree
(
GetProcessHeap
(),
0
,
rename_info
);
if
(
status
==
STATUS_NOT_SAME_DEVICE
&&
(
flag
&
MOVEFILE_COPY_ALLOWED
))
{
NtClose
(
source_handle
);
if
(
!
CopyFileExW
(
source
,
dest
,
progress
,
param
,
NULL
,
flag
&
MOVEFILE_REPLACE_EXISTING
?
0
:
COPY_FILE_FAIL_IF_EXISTS
))
return
FALSE
;
return
DeleteFileW
(
source
);
}
NtClose
(
source_handle
);
return
set_ntstatus
(
status
);
error
:
if
(
source_handle
)
NtClose
(
source_handle
);
return
FALSE
;
}
/***********************************************************************
/***********************************************************************
* NeedCurrentDirectoryForExePathA (kernelbase.@)
* NeedCurrentDirectoryForExePathA (kernelbase.@)
*/
*/
...
@@ -1917,6 +2512,111 @@ BOOL WINAPI DECLSPEC_HOTPATCH NeedCurrentDirectoryForExePathW( LPCWSTR name )
...
@@ -1917,6 +2512,111 @@ BOOL WINAPI DECLSPEC_HOTPATCH NeedCurrentDirectoryForExePathW( LPCWSTR name )
/***********************************************************************
/***********************************************************************
* ReplaceFileW (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
ReplaceFileW
(
const
WCHAR
*
replaced
,
const
WCHAR
*
replacement
,
const
WCHAR
*
backup
,
DWORD
flags
,
void
*
exclude
,
void
*
reserved
)
{
UNICODE_STRING
nt_replaced_name
,
nt_replacement_name
;
HANDLE
hReplacement
=
NULL
;
NTSTATUS
status
;
IO_STATUS_BLOCK
io
;
OBJECT_ATTRIBUTES
attr
;
FILE_BASIC_INFORMATION
info
;
TRACE
(
"%s %s %s 0x%08x %p %p
\n
"
,
debugstr_w
(
replaced
),
debugstr_w
(
replacement
),
debugstr_w
(
backup
),
flags
,
exclude
,
reserved
);
if
(
flags
)
FIXME
(
"Ignoring flags %x
\n
"
,
flags
);
/* First two arguments are mandatory */
if
(
!
replaced
||
!
replacement
)
{
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
FALSE
;
}
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
Attributes
=
OBJ_CASE_INSENSITIVE
;
attr
.
ObjectName
=
NULL
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
/* Open the "replaced" file for reading */
if
(
!
RtlDosPathNameToNtPathName_U
(
replaced
,
&
nt_replaced_name
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
attr
.
ObjectName
=
&
nt_replaced_name
;
/* Replacement should fail if replaced is READ_ONLY */
status
=
NtQueryAttributesFile
(
&
attr
,
&
info
);
RtlFreeUnicodeString
(
&
nt_replaced_name
);
if
(
!
set_ntstatus
(
status
))
return
FALSE
;
if
(
info
.
FileAttributes
&
FILE_ATTRIBUTE_READONLY
)
{
SetLastError
(
ERROR_ACCESS_DENIED
);
return
FALSE
;
}
/*
* Open the replacement file for reading, writing, and deleting
* (writing and deleting are needed when finished)
*/
if
(
!
RtlDosPathNameToNtPathName_U
(
replacement
,
&
nt_replacement_name
,
NULL
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
FALSE
;
}
attr
.
ObjectName
=
&
nt_replacement_name
;
status
=
NtOpenFile
(
&
hReplacement
,
GENERIC_READ
|
GENERIC_WRITE
|
DELETE
|
WRITE_DAC
|
SYNCHRONIZE
,
&
attr
,
&
io
,
0
,
FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_NON_DIRECTORY_FILE
);
RtlFreeUnicodeString
(
&
nt_replacement_name
);
if
(
!
set_ntstatus
(
status
))
return
FALSE
;
NtClose
(
hReplacement
);
/* If the user wants a backup then that needs to be performed first */
if
(
backup
)
{
if
(
!
MoveFileExW
(
replaced
,
backup
,
MOVEFILE_REPLACE_EXISTING
))
return
FALSE
;
}
else
{
/* ReplaceFile() can replace an open target. To do this, we need to move
* it out of the way first. */
WCHAR
temp_path
[
MAX_PATH
],
temp_file
[
MAX_PATH
];
lstrcpynW
(
temp_path
,
replaced
,
ARRAY_SIZE
(
temp_path
)
);
PathRemoveFileSpecW
(
temp_path
);
if
(
!
GetTempFileNameW
(
temp_path
,
L"rf"
,
0
,
temp_file
)
||
!
MoveFileExW
(
replaced
,
temp_file
,
MOVEFILE_REPLACE_EXISTING
))
return
FALSE
;
DeleteFileW
(
temp_file
);
}
/*
* Now that the backup has been performed (if requested), copy the replacement
* into place
*/
if
(
!
MoveFileExW
(
replacement
,
replaced
,
0
))
{
/* on failure we need to indicate whether a backup was made */
if
(
!
backup
)
SetLastError
(
ERROR_UNABLE_TO_MOVE_REPLACEMENT
);
else
SetLastError
(
ERROR_UNABLE_TO_MOVE_REPLACEMENT_2
);
return
FALSE
;
}
return
TRUE
;
}
/***********************************************************************
* SearchPathA (kernelbase.@)
* SearchPathA (kernelbase.@)
*/
*/
DWORD
WINAPI
DECLSPEC_HOTPATCH
SearchPathA
(
LPCSTR
path
,
LPCSTR
name
,
LPCSTR
ext
,
DWORD
WINAPI
DECLSPEC_HOTPATCH
SearchPathA
(
LPCSTR
path
,
LPCSTR
name
,
LPCSTR
ext
,
...
...
dlls/kernelbase/kernelbase.spec
View file @
b6c94018
...
@@ -166,8 +166,8 @@
...
@@ -166,8 +166,8 @@
@ stdcall ConvertToAutoInheritPrivateObjectSecurity(ptr ptr ptr ptr long ptr)
@ stdcall ConvertToAutoInheritPrivateObjectSecurity(ptr ptr ptr ptr long ptr)
# @ stub CopyContext
# @ stub CopyContext
# @ stub CopyFile2
# @ stub CopyFile2
@ stdcall CopyFileExW(wstr wstr ptr ptr ptr long)
kernel32.CopyFileExW
@ stdcall CopyFileExW(wstr wstr ptr ptr ptr long)
@ stdcall CopyFileW(wstr wstr long)
kernel32.CopyFileW
@ stdcall CopyFileW(wstr wstr long)
# @ stub -arch=x86_64 CopyMemoryNonTemporal
# @ stub -arch=x86_64 CopyMemoryNonTemporal
@ stdcall CopySid(long ptr ptr)
@ stdcall CopySid(long ptr ptr)
# @ stub CouldMultiUserAppsBehaviorBePossibleForPackage
# @ stub CouldMultiUserAppsBehaviorBePossibleForPackage
...
@@ -191,8 +191,8 @@
...
@@ -191,8 +191,8 @@
@ stdcall CreateFileMappingNumaW(long ptr long long long wstr long)
@ stdcall CreateFileMappingNumaW(long ptr long long long wstr long)
@ stdcall CreateFileMappingW(long ptr long long long wstr)
@ stdcall CreateFileMappingW(long ptr long long long wstr)
@ stdcall CreateFileW(wstr long long ptr long long long)
@ stdcall CreateFileW(wstr long long ptr long long long)
@ stdcall CreateHardLinkA(str str ptr)
kernel32.CreateHardLinkA
@ stdcall CreateHardLinkA(str str ptr)
@ stdcall CreateHardLinkW(wstr wstr ptr)
kernel32.CreateHardLinkW
@ stdcall CreateHardLinkW(wstr wstr ptr)
@ stdcall CreateIoCompletionPort(long long long long)
@ stdcall CreateIoCompletionPort(long long long long)
@ stdcall CreateMemoryResourceNotification(long)
@ stdcall CreateMemoryResourceNotification(long)
@ stdcall CreateMutexA(ptr long str)
@ stdcall CreateMutexA(ptr long str)
...
@@ -221,7 +221,7 @@
...
@@ -221,7 +221,7 @@
# @ stub CreateStateContainer
# @ stub CreateStateContainer
# @ stub CreateStateLock
# @ stub CreateStateLock
# @ stub CreateStateSubcontainer
# @ stub CreateStateSubcontainer
@ stdcall CreateSymbolicLinkW(wstr wstr long)
kernel32.CreateSymbolicLinkW
@ stdcall CreateSymbolicLinkW(wstr wstr long)
@ stdcall CreateThread(ptr long ptr long long ptr)
@ stdcall CreateThread(ptr long ptr long long ptr)
@ stdcall CreateThreadpool(ptr)
@ stdcall CreateThreadpool(ptr)
@ stdcall CreateThreadpoolCleanupGroup()
@ stdcall CreateThreadpoolCleanupGroup()
...
@@ -524,8 +524,8 @@
...
@@ -524,8 +524,8 @@
@ stdcall GetFileVersionInfoSizeExW(long wstr ptr)
@ stdcall GetFileVersionInfoSizeExW(long wstr ptr)
@ stdcall GetFileVersionInfoSizeW(wstr ptr)
@ stdcall GetFileVersionInfoSizeW(wstr ptr)
@ stdcall GetFileVersionInfoW(wstr long long ptr)
@ stdcall GetFileVersionInfoW(wstr long long ptr)
@ stdcall GetFinalPathNameByHandleA(long ptr long long)
kernel32.GetFinalPathNameByHandleA
@ stdcall GetFinalPathNameByHandleA(long ptr long long)
@ stdcall GetFinalPathNameByHandleW(long ptr long long)
kernel32.GetFinalPathNameByHandleW
@ stdcall GetFinalPathNameByHandleW(long ptr long long)
@ stdcall GetFullPathNameA(str long ptr ptr)
@ stdcall GetFullPathNameA(str long ptr ptr)
@ stdcall GetFullPathNameW(wstr long ptr ptr)
@ stdcall GetFullPathNameW(wstr long ptr ptr)
# @ stub GetGPOListInternalA
# @ stub GetGPOListInternalA
...
@@ -953,9 +953,9 @@
...
@@ -953,9 +953,9 @@
@ stdcall MapViewOfFileEx(long long long long long ptr)
@ stdcall MapViewOfFileEx(long long long long long ptr)
@ stdcall MapViewOfFileExNuma(long long long long long ptr long)
@ stdcall MapViewOfFileExNuma(long long long long long ptr long)
# @ stub MapViewOfFileFromApp
# @ stub MapViewOfFileFromApp
@ stdcall MoveFileExW(wstr wstr long)
kernel32.MoveFileExW
@ stdcall MoveFileExW(wstr wstr long)
# @ stub MoveFileWithProgressTransactedW
# @ stub MoveFileWithProgressTransactedW
@ stdcall MoveFileWithProgressW(wstr wstr ptr ptr long)
kernel32.MoveFileWithProgressW
@ stdcall MoveFileWithProgressW(wstr wstr ptr ptr long)
@ stdcall MulDiv(long long long) kernel32.MulDiv
@ stdcall MulDiv(long long long) kernel32.MulDiv
@ stdcall MultiByteToWideChar(long long str long ptr long)
@ stdcall MultiByteToWideChar(long long str long ptr long)
# @ stub NamedPipeEventEnum
# @ stub NamedPipeEventEnum
...
@@ -1339,7 +1339,7 @@
...
@@ -1339,7 +1339,7 @@
@ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler
@ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler
@ stdcall RemoveVectoredExceptionHandler(ptr) ntdll.RtlRemoveVectoredExceptionHandler
@ stdcall RemoveVectoredExceptionHandler(ptr) ntdll.RtlRemoveVectoredExceptionHandler
# @ stub ReplaceFileExInternal
# @ stub ReplaceFileExInternal
@ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr)
kernel32.ReplaceFileW
@ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr)
@ stdcall ResetEvent(long)
@ stdcall ResetEvent(long)
# @ stub ResetState
# @ stub ResetState
@ stdcall ResetWriteWatch(ptr long)
@ stdcall ResetWriteWatch(ptr long)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment