Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
9b0877db
Commit
9b0877db
authored
Dec 11, 2019
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel32: Move FindFirst/NextFile functions to kernelbase.
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
6731f33d
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
414 additions
and
487 deletions
+414
-487
file.c
dlls/kernel32/file.c
+0
-473
kernel32.spec
dlls/kernel32/kernel32.spec
+7
-7
file.c
dlls/kernelbase/file.c
+400
-0
kernelbase.spec
dlls/kernelbase/kernelbase.spec
+7
-7
No files found.
dlls/kernel32/file.c
View file @
9b0877db
...
...
@@ -50,28 +50,6 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
file
);
/* info structure for FindFirstFile handle */
typedef
struct
{
DWORD
magic
;
/* magic number */
HANDLE
handle
;
/* handle to directory */
CRITICAL_SECTION
cs
;
/* crit section protecting this structure */
FINDEX_SEARCH_OPS
search_op
;
/* Flags passed to FindFirst. */
FINDEX_INFO_LEVELS
level
;
/* Level passed to FindFirst */
UNICODE_STRING
path
;
/* NT path used to open the directory */
BOOL
is_root
;
/* is directory the root of the drive? */
BOOL
wildcard
;
/* did the mask contain wildcard characters? */
UINT
data_pos
;
/* current position in dir data */
UINT
data_len
;
/* length of dir data */
UINT
data_size
;
/* size of data buffer, or 0 when everything has been read */
BYTE
data
[
1
];
/* directory data */
}
FIND_FIRST_INFO
;
#define FIND_FIRST_MAGIC 0xc0ffee11
static
const
UINT
max_entry_size
=
offsetof
(
FILE_BOTH_DIRECTORY_INFORMATION
,
FileName
[
256
]
);
static
const
WCHAR
wildcardsW
[]
=
{
'*'
,
'?'
,
0
};
static
const
WCHAR
krnl386W
[]
=
{
'k'
,
'r'
,
'n'
,
'l'
,
'3'
,
'8'
,
'6'
,
'.'
,
'e'
,
'x'
,
'e'
,
'1'
,
'6'
,
0
};
/***********************************************************************
...
...
@@ -114,58 +92,6 @@ static HANDLE create_file_OF( LPCSTR path, INT mode )
/***********************************************************************
* check_dir_symlink
*
* Check if a dir symlink should be returned by FindNextFile.
*/
static
BOOL
check_dir_symlink
(
FIND_FIRST_INFO
*
info
,
const
FILE_BOTH_DIR_INFORMATION
*
file_info
)
{
UNICODE_STRING
str
;
ANSI_STRING
unix_name
;
struct
stat
st
,
parent_st
;
BOOL
ret
=
TRUE
;
DWORD
len
;
str
.
MaximumLength
=
info
->
path
.
Length
+
sizeof
(
WCHAR
)
+
file_info
->
FileNameLength
;
if
(
!
(
str
.
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
str
.
MaximumLength
)))
return
TRUE
;
memcpy
(
str
.
Buffer
,
info
->
path
.
Buffer
,
info
->
path
.
Length
);
len
=
info
->
path
.
Length
/
sizeof
(
WCHAR
);
if
(
!
len
||
str
.
Buffer
[
len
-
1
]
!=
'\\'
)
str
.
Buffer
[
len
++
]
=
'\\'
;
memcpy
(
str
.
Buffer
+
len
,
file_info
->
FileName
,
file_info
->
FileNameLength
);
str
.
Length
=
len
*
sizeof
(
WCHAR
)
+
file_info
->
FileNameLength
;
unix_name
.
Buffer
=
NULL
;
if
(
!
wine_nt_to_unix_file_name
(
&
str
,
&
unix_name
,
OPEN_EXISTING
,
FALSE
)
&&
!
stat
(
unix_name
.
Buffer
,
&
st
))
{
char
*
p
=
unix_name
.
Buffer
+
unix_name
.
Length
-
1
;
/* skip trailing slashes */
while
(
p
>
unix_name
.
Buffer
&&
*
p
==
'/'
)
p
--
;
while
(
ret
&&
p
>
unix_name
.
Buffer
)
{
while
(
p
>
unix_name
.
Buffer
&&
*
p
!=
'/'
)
p
--
;
while
(
p
>
unix_name
.
Buffer
&&
*
p
==
'/'
)
p
--
;
p
[
1
]
=
0
;
if
(
!
stat
(
unix_name
.
Buffer
,
&
parent_st
)
&&
parent_st
.
st_dev
==
st
.
st_dev
&&
parent_st
.
st_ino
==
st
.
st_ino
)
{
WARN
(
"suppressing dir symlink %s pointing to parent %s
\n
"
,
debugstr_wn
(
str
.
Buffer
,
str
.
Length
/
sizeof
(
WCHAR
)
),
debugstr_a
(
unix_name
.
Buffer
));
ret
=
FALSE
;
}
}
}
RtlFreeAnsiString
(
&
unix_name
);
RtlFreeUnicodeString
(
&
str
);
return
ret
;
}
/***********************************************************************
* FILE_SetDosError
*
* Set the DOS error code from errno.
...
...
@@ -662,405 +588,6 @@ BOOL WINAPI ReplaceFileA(LPCSTR lpReplacedFileName,LPCSTR lpReplacementFileName,
}
/*************************************************************************
* FindFirstFileExW (KERNEL32.@)
*
* NOTE: The FindExSearchLimitToDirectories is ignored - it gives the same
* results as FindExSearchNameMatch
*/
HANDLE
WINAPI
FindFirstFileExW
(
LPCWSTR
filename
,
FINDEX_INFO_LEVELS
level
,
LPVOID
data
,
FINDEX_SEARCH_OPS
search_op
,
LPVOID
filter
,
DWORD
flags
)
{
WCHAR
*
mask
;
BOOL
has_wildcard
=
FALSE
;
FIND_FIRST_INFO
*
info
=
NULL
;
UNICODE_STRING
nt_name
;
OBJECT_ATTRIBUTES
attr
;
IO_STATUS_BLOCK
io
;
NTSTATUS
status
;
DWORD
size
,
device
=
0
;
TRACE
(
"%s %d %p %d %p %x
\n
"
,
debugstr_w
(
filename
),
level
,
data
,
search_op
,
filter
,
flags
);
if
(
flags
&
~
FIND_FIRST_EX_LARGE_FETCH
)
{
FIXME
(
"flags not implemented 0x%08x
\n
"
,
flags
);
}
if
(
search_op
!=
FindExSearchNameMatch
&&
search_op
!=
FindExSearchLimitToDirectories
)
{
FIXME
(
"search_op not implemented 0x%08x
\n
"
,
search_op
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
INVALID_HANDLE_VALUE
;
}
if
(
level
!=
FindExInfoStandard
&&
level
!=
FindExInfoBasic
)
{
FIXME
(
"info level %d not implemented
\n
"
,
level
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
INVALID_HANDLE_VALUE
;
}
if
(
!
RtlDosPathNameToNtPathName_U
(
filename
,
&
nt_name
,
&
mask
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
(
!
mask
&&
(
device
=
RtlIsDosDeviceName_U
(
filename
)))
{
static
const
WCHAR
dotW
[]
=
{
'.'
,
0
};
WCHAR
*
dir
=
NULL
;
/* we still need to check that the directory can be opened */
if
(
HIWORD
(
device
))
{
if
(
!
(
dir
=
HeapAlloc
(
GetProcessHeap
(),
0
,
HIWORD
(
device
)
+
sizeof
(
WCHAR
)
)))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
goto
error
;
}
memcpy
(
dir
,
filename
,
HIWORD
(
device
)
);
dir
[
HIWORD
(
device
)
/
sizeof
(
WCHAR
)]
=
0
;
}
RtlFreeUnicodeString
(
&
nt_name
);
if
(
!
RtlDosPathNameToNtPathName_U
(
dir
?
dir
:
dotW
,
&
nt_name
,
&
mask
,
NULL
))
{
HeapFree
(
GetProcessHeap
(),
0
,
dir
);
SetLastError
(
ERROR_PATH_NOT_FOUND
);
goto
error
;
}
HeapFree
(
GetProcessHeap
(),
0
,
dir
);
size
=
0
;
}
else
if
(
!
mask
||
!*
mask
)
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
goto
error
;
}
else
{
nt_name
.
Length
=
(
mask
-
nt_name
.
Buffer
)
*
sizeof
(
WCHAR
);
has_wildcard
=
strpbrkW
(
mask
,
wildcardsW
)
!=
NULL
;
size
=
has_wildcard
?
8192
:
max_entry_size
;
}
if
(
!
(
info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
offsetof
(
FIND_FIRST_INFO
,
data
[
size
]
))))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
goto
error
;
}
/* check if path is the root of the drive, skipping the \??\ prefix */
info
->
is_root
=
FALSE
;
if
(
nt_name
.
Length
>=
6
*
sizeof
(
WCHAR
)
&&
nt_name
.
Buffer
[
5
]
==
':'
)
{
DWORD
pos
=
6
;
while
(
pos
*
sizeof
(
WCHAR
)
<
nt_name
.
Length
&&
nt_name
.
Buffer
[
pos
]
==
'\\'
)
pos
++
;
info
->
is_root
=
(
pos
*
sizeof
(
WCHAR
)
>=
nt_name
.
Length
);
}
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
Attributes
=
OBJ_CASE_INSENSITIVE
;
attr
.
ObjectName
=
&
nt_name
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
status
=
NtOpenFile
(
&
info
->
handle
,
GENERIC_READ
|
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
FILE_DIRECTORY_FILE
|
FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_OPEN_FOR_BACKUP_INTENT
);
if
(
status
!=
STATUS_SUCCESS
)
{
if
(
status
==
STATUS_OBJECT_NAME_NOT_FOUND
)
SetLastError
(
ERROR_PATH_NOT_FOUND
);
else
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
goto
error
;
}
RtlInitializeCriticalSection
(
&
info
->
cs
);
info
->
cs
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": FIND_FIRST_INFO.cs"
);
info
->
path
=
nt_name
;
info
->
magic
=
FIND_FIRST_MAGIC
;
info
->
wildcard
=
has_wildcard
;
info
->
data_pos
=
0
;
info
->
data_len
=
0
;
info
->
data_size
=
size
;
info
->
search_op
=
search_op
;
info
->
level
=
level
;
if
(
device
)
{
WIN32_FIND_DATAW
*
wfd
=
data
;
memset
(
wfd
,
0
,
sizeof
(
*
wfd
)
);
memcpy
(
wfd
->
cFileName
,
filename
+
HIWORD
(
device
)
/
sizeof
(
WCHAR
),
LOWORD
(
device
)
);
wfd
->
dwFileAttributes
=
FILE_ATTRIBUTE_ARCHIVE
;
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
}
else
{
UNICODE_STRING
mask_str
;
RtlInitUnicodeString
(
&
mask_str
,
mask
);
status
=
NtQueryDirectoryFile
(
info
->
handle
,
0
,
NULL
,
NULL
,
&
io
,
info
->
data
,
info
->
data_size
,
FileBothDirectoryInformation
,
FALSE
,
&
mask_str
,
TRUE
);
if
(
status
)
{
FindClose
(
info
);
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
return
INVALID_HANDLE_VALUE
;
}
info
->
data_len
=
io
.
Information
;
if
(
!
has_wildcard
)
info
->
data_size
=
0
;
/* we read everything */
if
(
!
FindNextFileW
(
info
,
data
))
{
TRACE
(
"%s not found
\n
"
,
debugstr_w
(
filename
)
);
FindClose
(
info
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
(
!
has_wildcard
)
/* we can't find two files with the same name */
{
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
}
}
return
info
;
error:
HeapFree
(
GetProcessHeap
(),
0
,
info
);
RtlFreeUnicodeString
(
&
nt_name
);
return
INVALID_HANDLE_VALUE
;
}
/*************************************************************************
* FindNextFileW (KERNEL32.@)
*/
BOOL
WINAPI
FindNextFileW
(
HANDLE
handle
,
WIN32_FIND_DATAW
*
data
)
{
FIND_FIRST_INFO
*
info
;
FILE_BOTH_DIR_INFORMATION
*
dir_info
;
BOOL
ret
=
FALSE
;
NTSTATUS
status
;
TRACE
(
"%p %p
\n
"
,
handle
,
data
);
if
(
!
handle
||
handle
==
INVALID_HANDLE_VALUE
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
ret
;
}
info
=
handle
;
if
(
info
->
magic
!=
FIND_FIRST_MAGIC
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
ret
;
}
RtlEnterCriticalSection
(
&
info
->
cs
);
if
(
!
info
->
handle
)
SetLastError
(
ERROR_NO_MORE_FILES
);
else
for
(;;)
{
if
(
info
->
data_pos
>=
info
->
data_len
)
/* need to read some more data */
{
IO_STATUS_BLOCK
io
;
if
(
info
->
data_size
)
status
=
NtQueryDirectoryFile
(
info
->
handle
,
0
,
NULL
,
NULL
,
&
io
,
info
->
data
,
info
->
data_size
,
FileBothDirectoryInformation
,
FALSE
,
NULL
,
FALSE
);
else
status
=
STATUS_NO_MORE_FILES
;
if
(
status
)
{
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
if
(
status
==
STATUS_NO_MORE_FILES
)
{
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
}
break
;
}
info
->
data_len
=
io
.
Information
;
info
->
data_pos
=
0
;
}
dir_info
=
(
FILE_BOTH_DIR_INFORMATION
*
)(
info
->
data
+
info
->
data_pos
);
if
(
dir_info
->
NextEntryOffset
)
info
->
data_pos
+=
dir_info
->
NextEntryOffset
;
else
info
->
data_pos
=
info
->
data_len
;
/* don't return '.' and '..' in the root of the drive */
if
(
info
->
is_root
)
{
if
(
dir_info
->
FileNameLength
==
sizeof
(
WCHAR
)
&&
dir_info
->
FileName
[
0
]
==
'.'
)
continue
;
if
(
dir_info
->
FileNameLength
==
2
*
sizeof
(
WCHAR
)
&&
dir_info
->
FileName
[
0
]
==
'.'
&&
dir_info
->
FileName
[
1
]
==
'.'
)
continue
;
}
/* check for dir symlink */
if
((
dir_info
->
FileAttributes
&
FILE_ATTRIBUTE_DIRECTORY
)
&&
(
dir_info
->
FileAttributes
&
FILE_ATTRIBUTE_REPARSE_POINT
)
&&
info
->
wildcard
)
{
if
(
!
check_dir_symlink
(
info
,
dir_info
))
continue
;
}
data
->
dwFileAttributes
=
dir_info
->
FileAttributes
;
data
->
ftCreationTime
=
*
(
FILETIME
*
)
&
dir_info
->
CreationTime
;
data
->
ftLastAccessTime
=
*
(
FILETIME
*
)
&
dir_info
->
LastAccessTime
;
data
->
ftLastWriteTime
=
*
(
FILETIME
*
)
&
dir_info
->
LastWriteTime
;
data
->
nFileSizeHigh
=
dir_info
->
EndOfFile
.
QuadPart
>>
32
;
data
->
nFileSizeLow
=
(
DWORD
)
dir_info
->
EndOfFile
.
QuadPart
;
data
->
dwReserved0
=
0
;
data
->
dwReserved1
=
0
;
memcpy
(
data
->
cFileName
,
dir_info
->
FileName
,
dir_info
->
FileNameLength
);
data
->
cFileName
[
dir_info
->
FileNameLength
/
sizeof
(
WCHAR
)]
=
0
;
if
(
info
->
level
!=
FindExInfoBasic
)
{
memcpy
(
data
->
cAlternateFileName
,
dir_info
->
ShortName
,
dir_info
->
ShortNameLength
);
data
->
cAlternateFileName
[
dir_info
->
ShortNameLength
/
sizeof
(
WCHAR
)]
=
0
;
}
else
data
->
cAlternateFileName
[
0
]
=
0
;
TRACE
(
"returning %s (%s)
\n
"
,
debugstr_w
(
data
->
cFileName
),
debugstr_w
(
data
->
cAlternateFileName
)
);
ret
=
TRUE
;
break
;
}
RtlLeaveCriticalSection
(
&
info
->
cs
);
return
ret
;
}
/*************************************************************************
* FindClose (KERNEL32.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
FindClose
(
HANDLE
handle
)
{
FIND_FIRST_INFO
*
info
=
handle
;
if
(
!
handle
||
handle
==
INVALID_HANDLE_VALUE
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
__TRY
{
if
(
info
->
magic
==
FIND_FIRST_MAGIC
)
{
RtlEnterCriticalSection
(
&
info
->
cs
);
if
(
info
->
magic
==
FIND_FIRST_MAGIC
)
/* in case someone else freed it in the meantime */
{
info
->
magic
=
0
;
if
(
info
->
handle
)
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
RtlFreeUnicodeString
(
&
info
->
path
);
info
->
data_pos
=
0
;
info
->
data_len
=
0
;
RtlLeaveCriticalSection
(
&
info
->
cs
);
info
->
cs
.
DebugInfo
->
Spare
[
0
]
=
0
;
RtlDeleteCriticalSection
(
&
info
->
cs
);
HeapFree
(
GetProcessHeap
(),
0
,
info
);
}
}
}
__EXCEPT_PAGE_FAULT
{
WARN
(
"Illegal handle %p
\n
"
,
handle
);
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
__ENDTRY
return
TRUE
;
}
/*************************************************************************
* FindFirstFileA (KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstFileA
(
LPCSTR
lpFileName
,
WIN32_FIND_DATAA
*
lpFindData
)
{
return
FindFirstFileExA
(
lpFileName
,
FindExInfoStandard
,
lpFindData
,
FindExSearchNameMatch
,
NULL
,
0
);
}
/*************************************************************************
* FindFirstFileExA (KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstFileExA
(
LPCSTR
lpFileName
,
FINDEX_INFO_LEVELS
fInfoLevelId
,
LPVOID
lpFindFileData
,
FINDEX_SEARCH_OPS
fSearchOp
,
LPVOID
lpSearchFilter
,
DWORD
dwAdditionalFlags
)
{
HANDLE
handle
;
WIN32_FIND_DATAA
*
dataA
;
WIN32_FIND_DATAW
dataW
;
WCHAR
*
nameW
;
if
(
!
(
nameW
=
FILE_name_AtoW
(
lpFileName
,
FALSE
)))
return
INVALID_HANDLE_VALUE
;
handle
=
FindFirstFileExW
(
nameW
,
fInfoLevelId
,
&
dataW
,
fSearchOp
,
lpSearchFilter
,
dwAdditionalFlags
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
return
handle
;
dataA
=
lpFindFileData
;
dataA
->
dwFileAttributes
=
dataW
.
dwFileAttributes
;
dataA
->
ftCreationTime
=
dataW
.
ftCreationTime
;
dataA
->
ftLastAccessTime
=
dataW
.
ftLastAccessTime
;
dataA
->
ftLastWriteTime
=
dataW
.
ftLastWriteTime
;
dataA
->
nFileSizeHigh
=
dataW
.
nFileSizeHigh
;
dataA
->
nFileSizeLow
=
dataW
.
nFileSizeLow
;
FILE_name_WtoA
(
dataW
.
cFileName
,
-
1
,
dataA
->
cFileName
,
sizeof
(
dataA
->
cFileName
)
);
FILE_name_WtoA
(
dataW
.
cAlternateFileName
,
-
1
,
dataA
->
cAlternateFileName
,
sizeof
(
dataA
->
cAlternateFileName
)
);
return
handle
;
}
/*************************************************************************
* FindFirstFileW (KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstFileW
(
LPCWSTR
lpFileName
,
WIN32_FIND_DATAW
*
lpFindData
)
{
return
FindFirstFileExW
(
lpFileName
,
FindExInfoStandard
,
lpFindData
,
FindExSearchNameMatch
,
NULL
,
0
);
}
/*************************************************************************
* FindNextFileA (KERNEL32.@)
*/
BOOL
WINAPI
FindNextFileA
(
HANDLE
handle
,
WIN32_FIND_DATAA
*
data
)
{
WIN32_FIND_DATAW
dataW
;
if
(
!
FindNextFileW
(
handle
,
&
dataW
))
return
FALSE
;
data
->
dwFileAttributes
=
dataW
.
dwFileAttributes
;
data
->
ftCreationTime
=
dataW
.
ftCreationTime
;
data
->
ftLastAccessTime
=
dataW
.
ftLastAccessTime
;
data
->
ftLastWriteTime
=
dataW
.
ftLastWriteTime
;
data
->
nFileSizeHigh
=
dataW
.
nFileSizeHigh
;
data
->
nFileSizeLow
=
dataW
.
nFileSizeLow
;
FILE_name_WtoA
(
dataW
.
cFileName
,
-
1
,
data
->
cFileName
,
sizeof
(
data
->
cFileName
)
);
FILE_name_WtoA
(
dataW
.
cAlternateFileName
,
-
1
,
data
->
cAlternateFileName
,
sizeof
(
data
->
cAlternateFileName
)
);
return
TRUE
;
}
/**************************************************************************
* FindFirstStreamW (KERNEL32.@)
*/
...
...
dlls/kernel32/kernel32.spec
View file @
9b0877db
...
...
@@ -475,18 +475,18 @@
@ stdcall -import FindActCtxSectionStringW(long ptr long wstr ptr)
@ stdcall FindAtomA(str)
@ stdcall FindAtomW(wstr)
@ stdcall FindClose(long)
@ stdcall
-import
FindClose(long)
@ stdcall -import FindCloseChangeNotification(long)
@ stdcall -import FindFirstChangeNotificationA(str long long)
@ stdcall -import FindFirstChangeNotificationW(wstr long long)
@ stdcall FindFirstFileA(str ptr)
@ stdcall FindFirstFileExA(str long ptr long ptr long)
@ stdcall FindFirstFileExW(wstr long ptr long ptr long)
@ stdcall
-import
FindFirstFileA(str ptr)
@ stdcall
-import
FindFirstFileExA(str long ptr long ptr long)
@ stdcall
-import
FindFirstFileExW(wstr long ptr long ptr long)
# @ stub FindFirstFileNameTransactedW
# @ stub FindFirstFileNameW
# @ stub FindFirstFileTransactedA
# @ stub FindFirstFileTransactedW
@ stdcall FindFirstFileW(wstr ptr)
@ stdcall
-import
FindFirstFileW(wstr ptr)
# @ stub FindFirstStreamTransactedW
@ stdcall FindFirstStreamW(wstr long ptr long)
@ stdcall FindFirstVolumeA(ptr long)
...
...
@@ -494,9 +494,9 @@
@ stdcall FindFirstVolumeMountPointW(wstr ptr long)
@ stdcall FindFirstVolumeW(ptr long)
@ stdcall -import FindNextChangeNotification(long)
@ stdcall FindNextFileA(long ptr)
@ stdcall
-import
FindNextFileA(long ptr)
# @ stub FindNextFileNameW
@ stdcall FindNextFileW(long ptr)
@ stdcall
-import
FindNextFileW(long ptr)
@ stdcall FindNextStreamW(long ptr)
@ stdcall FindNextVolumeA(long ptr long)
@ stub FindNextVolumeMountPointA
...
...
dlls/kernelbase/file.c
View file @
9b0877db
...
...
@@ -43,6 +43,27 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
file
);
/* info structure for FindFirstFile handle */
typedef
struct
{
DWORD
magic
;
/* magic number */
HANDLE
handle
;
/* handle to directory */
CRITICAL_SECTION
cs
;
/* crit section protecting this structure */
FINDEX_SEARCH_OPS
search_op
;
/* Flags passed to FindFirst. */
FINDEX_INFO_LEVELS
level
;
/* Level passed to FindFirst */
UNICODE_STRING
path
;
/* NT path used to open the directory */
BOOL
is_root
;
/* is directory the root of the drive? */
BOOL
wildcard
;
/* did the mask contain wildcard characters? */
UINT
data_pos
;
/* current position in dir data */
UINT
data_len
;
/* length of dir data */
UINT
data_size
;
/* size of data buffer, or 0 when everything has been read */
BYTE
data
[
1
];
/* directory data */
}
FIND_FIRST_INFO
;
#define FIND_FIRST_MAGIC 0xc0ffee11
static
const
UINT
max_entry_size
=
offsetof
(
FILE_BOTH_DIRECTORY_INFORMATION
,
FileName
[
256
]
);
const
WCHAR
windows_dir
[]
=
{
'C'
,
':'
,
'\\'
,
'w'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
's'
,
0
};
const
WCHAR
system_dir
[]
=
{
'C'
,
':'
,
'\\'
,
'w'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
's'
,
'\\'
,
's'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
'3'
,
'2'
,
0
};
...
...
@@ -735,6 +756,385 @@ BOOL WINAPI DECLSPEC_HOTPATCH FindNextChangeNotification( HANDLE handle )
/******************************************************************************
* FindFirstFileExA (kernelbase.@)
*/
HANDLE
WINAPI
DECLSPEC_HOTPATCH
FindFirstFileExA
(
const
char
*
filename
,
FINDEX_INFO_LEVELS
level
,
void
*
data
,
FINDEX_SEARCH_OPS
search_op
,
void
*
filter
,
DWORD
flags
)
{
HANDLE
handle
;
WIN32_FIND_DATAA
*
dataA
=
data
;
WIN32_FIND_DATAW
dataW
;
WCHAR
*
nameW
;
if
(
!
(
nameW
=
file_name_AtoW
(
filename
,
FALSE
)))
return
INVALID_HANDLE_VALUE
;
handle
=
FindFirstFileExW
(
nameW
,
level
,
&
dataW
,
search_op
,
filter
,
flags
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
return
handle
;
dataA
->
dwFileAttributes
=
dataW
.
dwFileAttributes
;
dataA
->
ftCreationTime
=
dataW
.
ftCreationTime
;
dataA
->
ftLastAccessTime
=
dataW
.
ftLastAccessTime
;
dataA
->
ftLastWriteTime
=
dataW
.
ftLastWriteTime
;
dataA
->
nFileSizeHigh
=
dataW
.
nFileSizeHigh
;
dataA
->
nFileSizeLow
=
dataW
.
nFileSizeLow
;
file_name_WtoA
(
dataW
.
cFileName
,
-
1
,
dataA
->
cFileName
,
sizeof
(
dataA
->
cFileName
)
);
file_name_WtoA
(
dataW
.
cAlternateFileName
,
-
1
,
dataA
->
cAlternateFileName
,
sizeof
(
dataA
->
cAlternateFileName
)
);
return
handle
;
}
/******************************************************************************
* FindFirstFileExW (kernelbase.@)
*/
HANDLE
WINAPI
DECLSPEC_HOTPATCH
FindFirstFileExW
(
LPCWSTR
filename
,
FINDEX_INFO_LEVELS
level
,
LPVOID
data
,
FINDEX_SEARCH_OPS
search_op
,
LPVOID
filter
,
DWORD
flags
)
{
WCHAR
*
mask
;
BOOL
has_wildcard
=
FALSE
;
FIND_FIRST_INFO
*
info
=
NULL
;
UNICODE_STRING
nt_name
;
OBJECT_ATTRIBUTES
attr
;
IO_STATUS_BLOCK
io
;
NTSTATUS
status
;
DWORD
size
,
device
=
0
;
TRACE
(
"%s %d %p %d %p %x
\n
"
,
debugstr_w
(
filename
),
level
,
data
,
search_op
,
filter
,
flags
);
if
(
flags
&
~
FIND_FIRST_EX_LARGE_FETCH
)
{
FIXME
(
"flags not implemented 0x%08x
\n
"
,
flags
);
}
if
(
search_op
!=
FindExSearchNameMatch
&&
search_op
!=
FindExSearchLimitToDirectories
)
{
FIXME
(
"search_op not implemented 0x%08x
\n
"
,
search_op
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
INVALID_HANDLE_VALUE
;
}
if
(
level
!=
FindExInfoStandard
&&
level
!=
FindExInfoBasic
)
{
FIXME
(
"info level %d not implemented
\n
"
,
level
);
SetLastError
(
ERROR_INVALID_PARAMETER
);
return
INVALID_HANDLE_VALUE
;
}
if
(
!
RtlDosPathNameToNtPathName_U
(
filename
,
&
nt_name
,
&
mask
,
NULL
))
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
(
!
mask
&&
(
device
=
RtlIsDosDeviceName_U
(
filename
)))
{
static
const
WCHAR
dotW
[]
=
{
'.'
,
0
};
WCHAR
*
dir
=
NULL
;
/* we still need to check that the directory can be opened */
if
(
HIWORD
(
device
))
{
if
(
!
(
dir
=
HeapAlloc
(
GetProcessHeap
(),
0
,
HIWORD
(
device
)
+
sizeof
(
WCHAR
)
)))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
goto
error
;
}
memcpy
(
dir
,
filename
,
HIWORD
(
device
)
);
dir
[
HIWORD
(
device
)
/
sizeof
(
WCHAR
)]
=
0
;
}
RtlFreeUnicodeString
(
&
nt_name
);
if
(
!
RtlDosPathNameToNtPathName_U
(
dir
?
dir
:
dotW
,
&
nt_name
,
&
mask
,
NULL
))
{
HeapFree
(
GetProcessHeap
(),
0
,
dir
);
SetLastError
(
ERROR_PATH_NOT_FOUND
);
goto
error
;
}
HeapFree
(
GetProcessHeap
(),
0
,
dir
);
size
=
0
;
}
else
if
(
!
mask
||
!*
mask
)
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
goto
error
;
}
else
{
nt_name
.
Length
=
(
mask
-
nt_name
.
Buffer
)
*
sizeof
(
WCHAR
);
has_wildcard
=
wcspbrk
(
mask
,
L"*?"
)
!=
NULL
;
size
=
has_wildcard
?
8192
:
max_entry_size
;
}
if
(
!
(
info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
offsetof
(
FIND_FIRST_INFO
,
data
[
size
]
))))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
goto
error
;
}
/* check if path is the root of the drive, skipping the \??\ prefix */
info
->
is_root
=
FALSE
;
if
(
nt_name
.
Length
>=
6
*
sizeof
(
WCHAR
)
&&
nt_name
.
Buffer
[
5
]
==
':'
)
{
DWORD
pos
=
6
;
while
(
pos
*
sizeof
(
WCHAR
)
<
nt_name
.
Length
&&
nt_name
.
Buffer
[
pos
]
==
'\\'
)
pos
++
;
info
->
is_root
=
(
pos
*
sizeof
(
WCHAR
)
>=
nt_name
.
Length
);
}
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
Attributes
=
OBJ_CASE_INSENSITIVE
;
attr
.
ObjectName
=
&
nt_name
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
status
=
NtOpenFile
(
&
info
->
handle
,
GENERIC_READ
|
SYNCHRONIZE
,
&
attr
,
&
io
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
FILE_DIRECTORY_FILE
|
FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_OPEN_FOR_BACKUP_INTENT
);
if
(
status
!=
STATUS_SUCCESS
)
{
if
(
status
==
STATUS_OBJECT_NAME_NOT_FOUND
)
SetLastError
(
ERROR_PATH_NOT_FOUND
);
else
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
goto
error
;
}
RtlInitializeCriticalSection
(
&
info
->
cs
);
info
->
cs
.
DebugInfo
->
Spare
[
0
]
=
(
DWORD_PTR
)(
__FILE__
": FIND_FIRST_INFO.cs"
);
info
->
path
=
nt_name
;
info
->
magic
=
FIND_FIRST_MAGIC
;
info
->
wildcard
=
has_wildcard
;
info
->
data_pos
=
0
;
info
->
data_len
=
0
;
info
->
data_size
=
size
;
info
->
search_op
=
search_op
;
info
->
level
=
level
;
if
(
device
)
{
WIN32_FIND_DATAW
*
wfd
=
data
;
memset
(
wfd
,
0
,
sizeof
(
*
wfd
)
);
memcpy
(
wfd
->
cFileName
,
filename
+
HIWORD
(
device
)
/
sizeof
(
WCHAR
),
LOWORD
(
device
)
);
wfd
->
dwFileAttributes
=
FILE_ATTRIBUTE_ARCHIVE
;
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
}
else
{
UNICODE_STRING
mask_str
;
RtlInitUnicodeString
(
&
mask_str
,
mask
);
status
=
NtQueryDirectoryFile
(
info
->
handle
,
0
,
NULL
,
NULL
,
&
io
,
info
->
data
,
info
->
data_size
,
FileBothDirectoryInformation
,
FALSE
,
&
mask_str
,
TRUE
);
if
(
status
)
{
FindClose
(
info
);
SetLastError
(
RtlNtStatusToDosError
(
status
)
);
return
INVALID_HANDLE_VALUE
;
}
info
->
data_len
=
io
.
Information
;
if
(
!
has_wildcard
)
info
->
data_size
=
0
;
/* we read everything */
if
(
!
FindNextFileW
(
info
,
data
))
{
TRACE
(
"%s not found
\n
"
,
debugstr_w
(
filename
)
);
FindClose
(
info
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
(
!
has_wildcard
)
/* we can't find two files with the same name */
{
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
}
}
return
info
;
error:
HeapFree
(
GetProcessHeap
(),
0
,
info
);
RtlFreeUnicodeString
(
&
nt_name
);
return
INVALID_HANDLE_VALUE
;
}
/******************************************************************************
* FindFirstFileA (kernelbase.@)
*/
HANDLE
WINAPI
DECLSPEC_HOTPATCH
FindFirstFileA
(
const
char
*
filename
,
WIN32_FIND_DATAA
*
data
)
{
return
FindFirstFileExA
(
filename
,
FindExInfoStandard
,
data
,
FindExSearchNameMatch
,
NULL
,
0
);
}
/******************************************************************************
* FindFirstFileW (kernelbase.@)
*/
HANDLE
WINAPI
DECLSPEC_HOTPATCH
FindFirstFileW
(
const
WCHAR
*
filename
,
WIN32_FIND_DATAW
*
data
)
{
return
FindFirstFileExW
(
filename
,
FindExInfoStandard
,
data
,
FindExSearchNameMatch
,
NULL
,
0
);
}
/******************************************************************************
* FindNextFileA (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
FindNextFileA
(
HANDLE
handle
,
WIN32_FIND_DATAA
*
data
)
{
WIN32_FIND_DATAW
dataW
;
if
(
!
FindNextFileW
(
handle
,
&
dataW
))
return
FALSE
;
data
->
dwFileAttributes
=
dataW
.
dwFileAttributes
;
data
->
ftCreationTime
=
dataW
.
ftCreationTime
;
data
->
ftLastAccessTime
=
dataW
.
ftLastAccessTime
;
data
->
ftLastWriteTime
=
dataW
.
ftLastWriteTime
;
data
->
nFileSizeHigh
=
dataW
.
nFileSizeHigh
;
data
->
nFileSizeLow
=
dataW
.
nFileSizeLow
;
file_name_WtoA
(
dataW
.
cFileName
,
-
1
,
data
->
cFileName
,
sizeof
(
data
->
cFileName
)
);
file_name_WtoA
(
dataW
.
cAlternateFileName
,
-
1
,
data
->
cAlternateFileName
,
sizeof
(
data
->
cAlternateFileName
)
);
return
TRUE
;
}
/******************************************************************************
* FindNextFileW (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
FindNextFileW
(
HANDLE
handle
,
WIN32_FIND_DATAW
*
data
)
{
FIND_FIRST_INFO
*
info
=
handle
;
FILE_BOTH_DIR_INFORMATION
*
dir_info
;
BOOL
ret
=
FALSE
;
NTSTATUS
status
;
TRACE
(
"%p %p
\n
"
,
handle
,
data
);
if
(
!
handle
||
handle
==
INVALID_HANDLE_VALUE
||
info
->
magic
!=
FIND_FIRST_MAGIC
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
ret
;
}
RtlEnterCriticalSection
(
&
info
->
cs
);
if
(
!
info
->
handle
)
SetLastError
(
ERROR_NO_MORE_FILES
);
else
for
(;;)
{
if
(
info
->
data_pos
>=
info
->
data_len
)
/* need to read some more data */
{
IO_STATUS_BLOCK
io
;
if
(
info
->
data_size
)
status
=
NtQueryDirectoryFile
(
info
->
handle
,
0
,
NULL
,
NULL
,
&
io
,
info
->
data
,
info
->
data_size
,
FileBothDirectoryInformation
,
FALSE
,
NULL
,
FALSE
);
else
status
=
STATUS_NO_MORE_FILES
;
if
(
!
set_ntstatus
(
status
))
{
if
(
status
==
STATUS_NO_MORE_FILES
)
{
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
}
break
;
}
info
->
data_len
=
io
.
Information
;
info
->
data_pos
=
0
;
}
dir_info
=
(
FILE_BOTH_DIR_INFORMATION
*
)(
info
->
data
+
info
->
data_pos
);
if
(
dir_info
->
NextEntryOffset
)
info
->
data_pos
+=
dir_info
->
NextEntryOffset
;
else
info
->
data_pos
=
info
->
data_len
;
/* don't return '.' and '..' in the root of the drive */
if
(
info
->
is_root
)
{
if
(
dir_info
->
FileNameLength
==
sizeof
(
WCHAR
)
&&
dir_info
->
FileName
[
0
]
==
'.'
)
continue
;
if
(
dir_info
->
FileNameLength
==
2
*
sizeof
(
WCHAR
)
&&
dir_info
->
FileName
[
0
]
==
'.'
&&
dir_info
->
FileName
[
1
]
==
'.'
)
continue
;
}
data
->
dwFileAttributes
=
dir_info
->
FileAttributes
;
data
->
ftCreationTime
=
*
(
FILETIME
*
)
&
dir_info
->
CreationTime
;
data
->
ftLastAccessTime
=
*
(
FILETIME
*
)
&
dir_info
->
LastAccessTime
;
data
->
ftLastWriteTime
=
*
(
FILETIME
*
)
&
dir_info
->
LastWriteTime
;
data
->
nFileSizeHigh
=
dir_info
->
EndOfFile
.
QuadPart
>>
32
;
data
->
nFileSizeLow
=
(
DWORD
)
dir_info
->
EndOfFile
.
QuadPart
;
data
->
dwReserved0
=
0
;
data
->
dwReserved1
=
0
;
memcpy
(
data
->
cFileName
,
dir_info
->
FileName
,
dir_info
->
FileNameLength
);
data
->
cFileName
[
dir_info
->
FileNameLength
/
sizeof
(
WCHAR
)]
=
0
;
if
(
info
->
level
!=
FindExInfoBasic
)
{
memcpy
(
data
->
cAlternateFileName
,
dir_info
->
ShortName
,
dir_info
->
ShortNameLength
);
data
->
cAlternateFileName
[
dir_info
->
ShortNameLength
/
sizeof
(
WCHAR
)]
=
0
;
}
else
data
->
cAlternateFileName
[
0
]
=
0
;
TRACE
(
"returning %s (%s)
\n
"
,
debugstr_w
(
data
->
cFileName
),
debugstr_w
(
data
->
cAlternateFileName
)
);
ret
=
TRUE
;
break
;
}
RtlLeaveCriticalSection
(
&
info
->
cs
);
return
ret
;
}
/******************************************************************************
* FindClose (kernelbase.@)
*/
BOOL
WINAPI
DECLSPEC_HOTPATCH
FindClose
(
HANDLE
handle
)
{
FIND_FIRST_INFO
*
info
=
handle
;
if
(
!
handle
||
handle
==
INVALID_HANDLE_VALUE
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
__TRY
{
if
(
info
->
magic
==
FIND_FIRST_MAGIC
)
{
RtlEnterCriticalSection
(
&
info
->
cs
);
if
(
info
->
magic
==
FIND_FIRST_MAGIC
)
/* in case someone else freed it in the meantime */
{
info
->
magic
=
0
;
if
(
info
->
handle
)
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
RtlFreeUnicodeString
(
&
info
->
path
);
info
->
data_pos
=
0
;
info
->
data_len
=
0
;
RtlLeaveCriticalSection
(
&
info
->
cs
);
info
->
cs
.
DebugInfo
->
Spare
[
0
]
=
0
;
RtlDeleteCriticalSection
(
&
info
->
cs
);
HeapFree
(
GetProcessHeap
(),
0
,
info
);
}
}
}
__EXCEPT_PAGE_FAULT
{
WARN
(
"illegal handle %p
\n
"
,
handle
);
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
__ENDTRY
return
TRUE
;
}
/******************************************************************************
* GetCompressedFileSizeA (kernelbase.@)
*/
DWORD
WINAPI
DECLSPEC_HOTPATCH
GetCompressedFileSizeA
(
LPCSTR
name
,
LPDWORD
size_high
)
...
...
dlls/kernelbase/kernelbase.spec
View file @
9b0877db
...
...
@@ -350,24 +350,24 @@
@ stdcall FillConsoleOutputCharacterW(long long long long ptr)
@ stdcall FindActCtxSectionGuid(long ptr long ptr ptr)
@ stdcall FindActCtxSectionStringW(long ptr long wstr ptr)
@ stdcall FindClose(long)
kernel32.FindClose
@ stdcall FindClose(long)
@ stdcall FindCloseChangeNotification(long)
@ stdcall FindFirstChangeNotificationA(str long long)
@ stdcall FindFirstChangeNotificationW(wstr long long)
@ stdcall FindFirstFileA(str ptr)
kernel32.FindFirstFileA
@ stdcall FindFirstFileExA(str long ptr long ptr long)
kernel32.FindFirstFileExA
@ stdcall FindFirstFileExW(wstr long ptr long ptr long)
kernel32.FindFirstFileExW
@ stdcall FindFirstFileA(str ptr)
@ stdcall FindFirstFileExA(str long ptr long ptr long)
@ stdcall FindFirstFileExW(wstr long ptr long ptr long)
# @ stub FindFirstFileNameW
@ stdcall FindFirstFileW(wstr ptr)
kernel32.FindFirstFileW
@ stdcall FindFirstFileW(wstr ptr)
@ stdcall FindFirstFreeAce(ptr ptr)
@ stdcall FindFirstStreamW(wstr long ptr long) kernel32.FindFirstStreamW
@ stdcall FindFirstVolumeW(ptr long) kernel32.FindFirstVolumeW
@ stdcall FindNLSString(long long wstr long wstr long ptr)
@ stdcall FindNLSStringEx(wstr long wstr long wstr long ptr ptr ptr long)
@ stdcall FindNextChangeNotification(long)
@ stdcall FindNextFileA(long ptr)
kernel32.FindNextFileA
@ stdcall FindNextFileA(long ptr)
# @ stub FindNextFileNameW
@ stdcall FindNextFileW(long ptr)
kernel32.FindNextFileW
@ stdcall FindNextFileW(long ptr)
@ stdcall FindNextStreamW(long ptr) kernel32.FindNextStreamW
@ stdcall FindNextVolumeW(long ptr long) kernel32.FindNextVolumeW
# @ stub FindPackagesByPackageFamily
...
...
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