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
8f032165
Commit
8f032165
authored
Mar 17, 2004
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reimplemented FindFirstFile/FindNextFile on top of
NtQueryDirectoryFile.
parent
f5e1c130
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
317 additions
and
498 deletions
+317
-498
file.c
dlls/kernel/file.c
+315
-0
file.c
dlls/kernel/tests/file.c
+2
-3
dos_fs.c
files/dos_fs.c
+0
-495
No files found.
dlls/kernel/file.c
View file @
8f032165
...
...
@@ -40,6 +40,8 @@
#include "wine/winbase16.h"
#include "kernel_private.h"
#include "wine/exception.h"
#include "excpt.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "async.h"
...
...
@@ -48,6 +50,26 @@ WINE_DEFAULT_DEBUG_CHANNEL(file);
HANDLE
dos_handles
[
DOS_TABLE_SIZE
];
/* info structure for FindFirstFile handle */
typedef
struct
{
HANDLE
handle
;
/* handle to directory */
CRITICAL_SECTION
cs
;
/* crit section protecting this structure */
UNICODE_STRING
mask
;
/* file mask */
BOOL
is_root
;
/* is directory the root of the drive? */
UINT
data_pos
;
/* current position in dir data */
UINT
data_len
;
/* length of dir data */
BYTE
data
[
8192
];
/* directory data */
}
FIND_FIRST_INFO
;
static
WINE_EXCEPTION_FILTER
(
page_fault
)
{
if
(
GetExceptionCode
()
==
EXCEPTION_ACCESS_VIOLATION
)
return
EXCEPTION_EXECUTE_HANDLER
;
return
EXCEPTION_CONTINUE_SEARCH
;
}
/**************************************************************************
* Operations on file handles *
**************************************************************************/
...
...
@@ -557,3 +579,296 @@ BOOL WINAPI ReplaceFileA(LPCSTR lpReplacedFileName,LPCSTR lpReplacementFileName,
SetLastError
(
ERROR_UNABLE_TO_MOVE_REPLACEMENT
);
return
FALSE
;
}
/*************************************************************************
* FindFirstFileExW (KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstFileExW
(
LPCWSTR
filename
,
FINDEX_INFO_LEVELS
level
,
LPVOID
data
,
FINDEX_SEARCH_OPS
search_op
,
LPVOID
filter
,
DWORD
flags
)
{
WCHAR
buffer
[
MAX_PATH
];
WCHAR
*
mask
,
*
tmp
=
buffer
;
FIND_FIRST_INFO
*
info
=
NULL
;
DWORD
size
;
if
((
search_op
!=
FindExSearchNameMatch
)
||
(
flags
!=
0
))
{
FIXME
(
"options not implemented 0x%08x 0x%08lx
\n
"
,
search_op
,
flags
);
return
INVALID_HANDLE_VALUE
;
}
if
(
level
!=
FindExInfoStandard
)
{
FIXME
(
"info level %d not implemented
\n
"
,
level
);
return
INVALID_HANDLE_VALUE
;
}
size
=
RtlGetFullPathName_U
(
filename
,
sizeof
(
buffer
),
buffer
,
&
mask
);
if
(
!
size
)
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
(
size
>
sizeof
(
buffer
))
{
tmp
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
);
if
(
!
tmp
)
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
INVALID_HANDLE_VALUE
;
}
size
=
RtlGetFullPathName_U
(
filename
,
size
,
tmp
,
&
mask
);
}
if
(
!
mask
||
!*
mask
)
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
goto
error
;
}
if
(
!
(
info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
info
))))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
goto
error
;
}
if
(
!
RtlCreateUnicodeString
(
&
info
->
mask
,
mask
))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
goto
error
;
}
*
mask
=
0
;
/* check if path is the root of the drive */
info
->
is_root
=
FALSE
;
if
(
tmp
[
0
]
&&
tmp
[
1
]
==
':'
)
{
WCHAR
*
p
=
tmp
+
2
;
while
(
*
p
==
'\\'
)
p
++
;
info
->
is_root
=
(
*
p
==
0
);
}
info
->
handle
=
CreateFileW
(
tmp
,
GENERIC_READ
,
FILE_SHARE_READ
|
FILE_SHARE_WRITE
,
NULL
,
OPEN_EXISTING
,
FILE_FLAG_BACKUP_SEMANTICS
,
0
);
if
(
info
->
handle
==
INVALID_HANDLE_VALUE
)
{
RtlFreeUnicodeString
(
&
info
->
mask
);
goto
error
;
}
RtlInitializeCriticalSection
(
&
info
->
cs
);
info
->
data_pos
=
0
;
info
->
data_len
=
0
;
if
(
tmp
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
tmp
);
if
(
!
FindNextFileW
(
(
HANDLE
)
info
,
data
))
{
TRACE
(
"%s not found
\n
"
,
debugstr_w
(
filename
)
);
FindClose
(
(
HANDLE
)
info
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
return
(
HANDLE
)
info
;
error:
if
(
tmp
!=
buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
tmp
);
if
(
info
)
HeapFree
(
GetProcessHeap
(),
0
,
info
);
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
;
if
(
handle
==
INVALID_HANDLE_VALUE
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
ret
;
}
info
=
(
FIND_FIRST_INFO
*
)
handle
;
RtlEnterCriticalSection
(
&
info
->
cs
);
for
(;;)
{
if
(
info
->
data_pos
>=
info
->
data_len
)
/* need to read some more data */
{
IO_STATUS_BLOCK
io
;
NtQueryDirectoryFile
(
info
->
handle
,
0
,
NULL
,
NULL
,
&
io
,
info
->
data
,
sizeof
(
info
->
data
),
FileBothDirectoryInformation
,
FALSE
,
&
info
->
mask
,
FALSE
);
if
(
io
.
u
.
Status
)
{
SetLastError
(
RtlNtStatusToDosError
(
io
.
u
.
Status
)
);
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
;
memcpy
(
data
->
cAlternateFileName
,
dir_info
->
ShortName
,
dir_info
->
ShortNameLength
);
data
->
cAlternateFileName
[
dir_info
->
ShortNameLength
/
sizeof
(
WCHAR
)]
=
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
FindClose
(
HANDLE
handle
)
{
FIND_FIRST_INFO
*
info
=
(
FIND_FIRST_INFO
*
)
handle
;
if
(
!
handle
||
handle
==
INVALID_HANDLE_VALUE
)
goto
error
;
__TRY
{
RtlEnterCriticalSection
(
&
info
->
cs
);
if
(
info
->
handle
)
CloseHandle
(
info
->
handle
);
info
->
handle
=
0
;
RtlFreeUnicodeString
(
&
info
->
mask
);
info
->
mask
.
Buffer
=
NULL
;
info
->
data_pos
=
0
;
info
->
data_len
=
0
;
}
__EXCEPT
(
page_fault
)
{
WARN
(
"Illegal handle %p
\n
"
,
handle
);
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
__ENDTRY
RtlLeaveCriticalSection
(
&
info
->
cs
);
RtlDeleteCriticalSection
(
&
info
->
cs
);
HeapFree
(
GetProcessHeap
(),
0
,
info
);
return
TRUE
;
error:
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
/*************************************************************************
* 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
;
UNICODE_STRING
pathW
;
if
(
!
lpFileName
)
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
pathW
,
lpFileName
))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
INVALID_HANDLE_VALUE
;
}
handle
=
FindFirstFileExW
(
pathW
.
Buffer
,
fInfoLevelId
,
&
dataW
,
fSearchOp
,
lpSearchFilter
,
dwAdditionalFlags
);
RtlFreeUnicodeString
(
&
pathW
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
return
handle
;
dataA
=
(
WIN32_FIND_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
;
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cFileName
,
-
1
,
dataA
->
cFileName
,
sizeof
(
dataA
->
cFileName
),
NULL
,
NULL
);
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cAlternateFileName
,
-
1
,
dataA
->
cAlternateFileName
,
sizeof
(
dataA
->
cAlternateFileName
),
NULL
,
NULL
);
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
;
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cFileName
,
-
1
,
data
->
cFileName
,
sizeof
(
data
->
cFileName
),
NULL
,
NULL
);
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cAlternateFileName
,
-
1
,
data
->
cAlternateFileName
,
sizeof
(
data
->
cAlternateFileName
),
NULL
,
NULL
);
return
TRUE
;
}
dlls/kernel/tests/file.c
View file @
8f032165
...
...
@@ -270,9 +270,8 @@ static void test__lcreat( void )
}
else
{
/* only NT succeeds */
_lclose
(
filehandle
);
find
=
FindFirstFileA
(
slashname
,
&
search_results
);
if
(
INVALID_HANDLE_VALUE
==
find
)
ok
(
0
,
"file
\"
%s
\"
not found
\n
"
,
slashname
);
else
{
if
(
INVALID_HANDLE_VALUE
!=
find
)
{
ok
(
0
!=
FindClose
(
find
),
"FindClose complains (%ld)
\n
"
,
GetLastError
());
slashname
[
strlen
(
slashname
)
-
1
]
=
0
;
ok
(
!
strcmp
(
slashname
,
search_results
.
cFileName
),
...
...
files/dos_fs.c
View file @
8f032165
...
...
@@ -92,8 +92,6 @@ typedef struct
#undef VFAT_IOCTL_READDIR_BOTH
/* just in case... */
#endif
/* linux */
#define IS_OPTION_TRUE(ch) ((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
/* Chars we don't want to see in DOS file names */
#define INVALID_DOS_CHARS "*?<>|\"+=,;[] \345"
...
...
@@ -147,29 +145,6 @@ typedef struct
WCHAR
names
[
1
];
}
DOS_DIR
;
/* Info structure for FindFirstFile handle */
typedef
struct
{
char
*
path
;
/* unix path */
LPWSTR
long_mask
;
int
drive
;
int
cur_pos
;
CRITICAL_SECTION
cs
;
union
{
DOS_DIR
*
dos_dir
;
SMB_DIR
*
smb_dir
;
}
u
;
}
FIND_FIRST_INFO
;
static
WINE_EXCEPTION_FILTER
(
page_fault
)
{
if
(
GetExceptionCode
()
==
EXCEPTION_ACCESS_VIOLATION
)
return
EXCEPTION_EXECUTE_HANDLER
;
return
EXCEPTION_CONTINUE_SEARCH
;
}
/* return non-zero if c is the end of a directory name */
static
inline
int
is_end_of_name
(
WCHAR
c
)
...
...
@@ -346,97 +321,6 @@ static void DOSFS_ToDosDTAFormat( LPCWSTR name, LPWSTR buffer )
/***********************************************************************
* DOSFS_MatchLong
*
* Check a long file name against a mask.
*
* Tests (done in W95 DOS shell - case insensitive):
* *.txt test1.test.txt *
* *st1* test1.txt *
* *.t??????.t* test1.ta.tornado.txt *
* *tornado* test1.ta.tornado.txt *
* t*t test1.ta.tornado.txt *
* ?est* test1.txt *
* ?est??? test1.txt -
* *test1.txt* test1.txt *
* h?l?o*t.dat hellothisisatest.dat *
*/
static
int
DOSFS_MatchLong
(
LPCWSTR
mask
,
LPCWSTR
name
)
{
LPCWSTR
lastjoker
=
NULL
;
LPCWSTR
next_to_retry
=
NULL
;
static
const
WCHAR
asterisk_dot_asterisk
[]
=
{
'*'
,
'.'
,
'*'
,
0
};
TRACE
(
"(%s, %s)
\n
"
,
debugstr_w
(
mask
),
debugstr_w
(
name
));
if
(
!
strcmpW
(
mask
,
asterisk_dot_asterisk
))
return
1
;
while
(
*
name
&&
*
mask
)
{
if
(
*
mask
==
'*'
)
{
mask
++
;
while
(
*
mask
==
'*'
)
mask
++
;
/* Skip consecutive '*' */
lastjoker
=
mask
;
if
(
!*
mask
)
return
1
;
/* end of mask is all '*', so match */
/* skip to the next match after the joker(s) */
if
(
is_case_sensitive
)
while
(
*
name
&&
(
*
name
!=
*
mask
))
name
++
;
else
while
(
*
name
&&
(
toupperW
(
*
name
)
!=
toupperW
(
*
mask
)))
name
++
;
if
(
!*
name
)
break
;
next_to_retry
=
name
;
}
else
if
(
*
mask
!=
'?'
)
{
int
mismatch
=
0
;
if
(
is_case_sensitive
)
{
if
(
*
mask
!=
*
name
)
mismatch
=
1
;
}
else
{
if
(
toupperW
(
*
mask
)
!=
toupperW
(
*
name
))
mismatch
=
1
;
}
if
(
!
mismatch
)
{
mask
++
;
name
++
;
if
(
*
mask
==
'\0'
)
{
if
(
*
name
==
'\0'
)
return
1
;
if
(
lastjoker
)
mask
=
lastjoker
;
}
}
else
/* mismatch ! */
{
if
(
lastjoker
)
/* we had an '*', so we can try unlimitedly */
{
mask
=
lastjoker
;
/* this scan sequence was a mismatch, so restart
* 1 char after the first char we checked last time */
next_to_retry
++
;
name
=
next_to_retry
;
}
else
return
0
;
/* bad luck */
}
}
else
/* '?' */
{
mask
++
;
name
++
;
}
}
while
((
*
mask
==
'.'
)
||
(
*
mask
==
'*'
))
mask
++
;
/* Ignore trailing '.' or '*' in mask */
return
(
!*
name
&&
!*
mask
);
}
/***********************************************************************
* DOSFS_AddDirEntry
*
* Used to construct an array of filenames in DOSFS_OpenDir
...
...
@@ -1147,385 +1031,6 @@ BOOL WINAPI wine_get_unix_file_name( LPCWSTR dosW, LPSTR buffer, DWORD len )
/***********************************************************************
* get_show_dir_symlinks_option
*/
static
BOOL
get_show_dir_symlinks_option
(
void
)
{
static
const
WCHAR
WineW
[]
=
{
'M'
,
'a'
,
'c'
,
'h'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'S'
,
'o'
,
'f'
,
't'
,
'w'
,
'a'
,
'r'
,
'e'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
'\\'
,
'C'
,
'o'
,
'n'
,
'f'
,
'i'
,
'g'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'e'
,
0
};
static
const
WCHAR
ShowDirSymlinksW
[]
=
{
'S'
,
'h'
,
'o'
,
'w'
,
'D'
,
'i'
,
'r'
,
'S'
,
'y'
,
'm'
,
'l'
,
'i'
,
'n'
,
'k'
,
's'
,
0
};
char
tmp
[
80
];
HKEY
hkey
;
DWORD
dummy
;
OBJECT_ATTRIBUTES
attr
;
UNICODE_STRING
nameW
;
BOOL
ret
=
FALSE
;
attr
.
Length
=
sizeof
(
attr
);
attr
.
RootDirectory
=
0
;
attr
.
ObjectName
=
&
nameW
;
attr
.
Attributes
=
0
;
attr
.
SecurityDescriptor
=
NULL
;
attr
.
SecurityQualityOfService
=
NULL
;
RtlInitUnicodeString
(
&
nameW
,
WineW
);
if
(
!
NtOpenKey
(
&
hkey
,
KEY_ALL_ACCESS
,
&
attr
))
{
RtlInitUnicodeString
(
&
nameW
,
ShowDirSymlinksW
);
if
(
!
NtQueryValueKey
(
hkey
,
&
nameW
,
KeyValuePartialInformation
,
tmp
,
sizeof
(
tmp
),
&
dummy
))
{
WCHAR
*
str
=
(
WCHAR
*
)((
KEY_VALUE_PARTIAL_INFORMATION
*
)
tmp
)
->
Data
;
ret
=
IS_OPTION_TRUE
(
str
[
0
]
);
}
NtClose
(
hkey
);
}
return
ret
;
}
/***********************************************************************
* DOSFS_FindNextEx
*/
static
int
DOSFS_FindNextEx
(
FIND_FIRST_INFO
*
info
,
WIN32_FIND_DATAW
*
entry
)
{
char
*
p
,
buffer
[
MAX_PATHNAME_LEN
];
const
char
*
drive_path
;
int
drive_root
;
LPCWSTR
long_name
,
short_name
;
BY_HANDLE_FILE_INFORMATION
fileinfo
;
BOOL
is_symlink
;
drive_path
=
info
->
path
+
strlen
(
DRIVE_GetRoot
(
info
->
drive
));
while
((
*
drive_path
==
'/'
)
||
(
*
drive_path
==
'\\'
))
drive_path
++
;
drive_root
=
!*
drive_path
;
lstrcpynA
(
buffer
,
info
->
path
,
sizeof
(
buffer
)
-
1
);
strcat
(
buffer
,
"/"
);
p
=
buffer
+
strlen
(
buffer
);
while
(
DOSFS_ReadDir
(
info
->
u
.
dos_dir
,
&
long_name
,
&
short_name
))
{
info
->
cur_pos
++
;
/* Don't return '.' and '..' in the root of the drive */
if
(
drive_root
&&
(
long_name
[
0
]
==
'.'
)
&&
(
!
long_name
[
1
]
||
((
long_name
[
1
]
==
'.'
)
&&
!
long_name
[
2
])))
continue
;
/* Check the long mask */
if
(
info
->
long_mask
&&
*
info
->
long_mask
)
{
if
(
!
DOSFS_MatchLong
(
info
->
long_mask
,
long_name
))
continue
;
}
/* Check the file attributes */
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
long_name
,
-
1
,
p
,
sizeof
(
buffer
)
-
(
int
)(
p
-
buffer
),
NULL
,
NULL
);
if
(
!
FILE_Stat
(
buffer
,
&
fileinfo
,
&
is_symlink
))
{
WARN
(
"can't stat %s
\n
"
,
buffer
);
continue
;
}
if
(
is_symlink
&&
(
fileinfo
.
dwFileAttributes
&
FILE_ATTRIBUTE_DIRECTORY
))
{
static
int
show_dir_symlinks
=
-
1
;
if
(
show_dir_symlinks
==
-
1
)
show_dir_symlinks
=
get_show_dir_symlinks_option
();
if
(
!
show_dir_symlinks
)
continue
;
}
/* We now have a matching entry; fill the result and return */
entry
->
dwFileAttributes
=
fileinfo
.
dwFileAttributes
;
entry
->
ftCreationTime
=
fileinfo
.
ftCreationTime
;
entry
->
ftLastAccessTime
=
fileinfo
.
ftLastAccessTime
;
entry
->
ftLastWriteTime
=
fileinfo
.
ftLastWriteTime
;
entry
->
nFileSizeHigh
=
fileinfo
.
nFileSizeHigh
;
entry
->
nFileSizeLow
=
fileinfo
.
nFileSizeLow
;
if
(
short_name
)
DOSFS_ToDosDTAFormat
(
short_name
,
entry
->
cAlternateFileName
);
else
DOSFS_Hash
(
long_name
,
entry
->
cAlternateFileName
,
FALSE
);
lstrcpynW
(
entry
->
cFileName
,
long_name
,
sizeof
(
entry
->
cFileName
)
/
sizeof
(
entry
->
cFileName
[
0
])
);
TRACE
(
"returning %s (%s) %02lx %ld
\n
"
,
debugstr_w
(
entry
->
cFileName
),
debugstr_w
(
entry
->
cAlternateFileName
),
entry
->
dwFileAttributes
,
entry
->
nFileSizeLow
);
return
1
;
}
return
0
;
/* End of directory */
}
/*************************************************************************
* FindFirstFileExW (KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstFileExW
(
LPCWSTR
lpFileName
,
FINDEX_INFO_LEVELS
fInfoLevelId
,
LPVOID
lpFindFileData
,
FINDEX_SEARCH_OPS
fSearchOp
,
LPVOID
lpSearchFilter
,
DWORD
dwAdditionalFlags
)
{
FIND_FIRST_INFO
*
info
;
if
(
!
lpFileName
)
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
((
fSearchOp
!=
FindExSearchNameMatch
)
||
(
dwAdditionalFlags
!=
0
))
{
FIXME
(
"options not implemented 0x%08x 0x%08lx
\n
"
,
fSearchOp
,
dwAdditionalFlags
);
return
INVALID_HANDLE_VALUE
;
}
switch
(
fInfoLevelId
)
{
case
FindExInfoStandard
:
{
WIN32_FIND_DATAW
*
data
=
(
WIN32_FIND_DATAW
*
)
lpFindFileData
;
char
*
p
;
INT
long_mask_len
;
data
->
dwReserved0
=
data
->
dwReserved1
=
0x0
;
if
(
lpFileName
[
0
]
==
'\\'
&&
lpFileName
[
1
]
==
'\\'
)
{
ERR
(
"UNC path name
\n
"
);
if
(
!
(
info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
FIND_FIRST_INFO
))))
break
;
info
->
u
.
smb_dir
=
SMB_FindFirst
(
lpFileName
);
if
(
!
info
->
u
.
smb_dir
)
{
HeapFree
(
GetProcessHeap
(),
0
,
info
);
break
;
}
info
->
drive
=
-
1
;
RtlInitializeCriticalSection
(
&
info
->
cs
);
}
else
{
DOS_FULL_NAME
full_name
;
if
(
lpFileName
[
0
]
&&
lpFileName
[
1
]
==
':'
)
{
/* don't allow root directories */
if
(
!
lpFileName
[
2
]
||
((
lpFileName
[
2
]
==
'/'
||
lpFileName
[
2
]
==
'\\'
)
&&
!
lpFileName
[
3
]))
{
SetLastError
(
ERROR_FILE_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
}
if
(
!
DOSFS_GetFullName
(
lpFileName
,
FALSE
,
&
full_name
))
break
;
if
(
!
(
info
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
FIND_FIRST_INFO
))))
break
;
RtlInitializeCriticalSection
(
&
info
->
cs
);
info
->
path
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
full_name
.
long_name
)
+
1
);
strcpy
(
info
->
path
,
full_name
.
long_name
);
p
=
strrchr
(
info
->
path
,
'/'
);
*
p
++
=
'\0'
;
long_mask_len
=
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
p
,
-
1
,
NULL
,
0
);
info
->
long_mask
=
HeapAlloc
(
GetProcessHeap
(),
0
,
long_mask_len
*
sizeof
(
WCHAR
)
);
MultiByteToWideChar
(
CP_UNIXCP
,
0
,
p
,
-
1
,
info
->
long_mask
,
long_mask_len
);
info
->
drive
=
full_name
.
drive
;
info
->
cur_pos
=
0
;
info
->
u
.
dos_dir
=
DOSFS_OpenDir
(
info
->
path
);
}
if
(
!
FindNextFileW
(
(
HANDLE
)
info
,
data
))
{
FindClose
(
(
HANDLE
)
info
);
SetLastError
(
ERROR_FILE_NOT_FOUND
);
break
;
}
return
(
HANDLE
)
info
;
}
break
;
default:
FIXME
(
"fInfoLevelId 0x%08x not implemented
\n
"
,
fInfoLevelId
);
}
return
INVALID_HANDLE_VALUE
;
}
/*************************************************************************
* 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
;
UNICODE_STRING
pathW
;
if
(
!
lpFileName
)
{
SetLastError
(
ERROR_PATH_NOT_FOUND
);
return
INVALID_HANDLE_VALUE
;
}
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
pathW
,
lpFileName
))
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
INVALID_HANDLE_VALUE
;
}
handle
=
FindFirstFileExW
(
pathW
.
Buffer
,
fInfoLevelId
,
&
dataW
,
fSearchOp
,
lpSearchFilter
,
dwAdditionalFlags
);
RtlFreeUnicodeString
(
&
pathW
);
if
(
handle
==
INVALID_HANDLE_VALUE
)
return
handle
;
dataA
=
(
WIN32_FIND_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
;
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cFileName
,
-
1
,
dataA
->
cFileName
,
sizeof
(
dataA
->
cFileName
),
NULL
,
NULL
);
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cAlternateFileName
,
-
1
,
dataA
->
cAlternateFileName
,
sizeof
(
dataA
->
cAlternateFileName
),
NULL
,
NULL
);
return
handle
;
}
/*************************************************************************
* FindFirstFileW (KERNEL32.@)
*/
HANDLE
WINAPI
FindFirstFileW
(
LPCWSTR
lpFileName
,
WIN32_FIND_DATAW
*
lpFindData
)
{
return
FindFirstFileExW
(
lpFileName
,
FindExInfoStandard
,
lpFindData
,
FindExSearchNameMatch
,
NULL
,
0
);
}
/*************************************************************************
* FindNextFileW (KERNEL32.@)
*/
BOOL
WINAPI
FindNextFileW
(
HANDLE
handle
,
WIN32_FIND_DATAW
*
data
)
{
FIND_FIRST_INFO
*
info
;
BOOL
ret
=
FALSE
;
DWORD
gle
=
ERROR_NO_MORE_FILES
;
if
(
handle
==
INVALID_HANDLE_VALUE
)
{
SetLastError
(
ERROR_INVALID_HANDLE
);
return
ret
;
}
info
=
(
FIND_FIRST_INFO
*
)
handle
;
RtlEnterCriticalSection
(
&
info
->
cs
);
if
(
info
->
drive
==
-
1
)
{
ret
=
SMB_FindNext
(
info
->
u
.
smb_dir
,
data
);
if
(
!
ret
)
{
SMB_CloseDir
(
info
->
u
.
smb_dir
);
HeapFree
(
GetProcessHeap
(),
0
,
info
->
path
);
}
goto
done
;
}
else
if
(
!
info
->
path
||
!
info
->
u
.
dos_dir
)
{
goto
done
;
}
else
if
(
!
DOSFS_FindNextEx
(
info
,
data
))
{
DOSFS_CloseDir
(
info
->
u
.
dos_dir
);
info
->
u
.
dos_dir
=
NULL
;
HeapFree
(
GetProcessHeap
(),
0
,
info
->
path
);
info
->
path
=
NULL
;
HeapFree
(
GetProcessHeap
(),
0
,
info
->
long_mask
);
info
->
long_mask
=
NULL
;
goto
done
;
}
ret
=
TRUE
;
done:
RtlLeaveCriticalSection
(
&
info
->
cs
);
if
(
!
ret
)
SetLastError
(
gle
);
return
ret
;
}
/*************************************************************************
* 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
;
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cFileName
,
-
1
,
data
->
cFileName
,
sizeof
(
data
->
cFileName
),
NULL
,
NULL
);
WideCharToMultiByte
(
CP_ACP
,
0
,
dataW
.
cAlternateFileName
,
-
1
,
data
->
cAlternateFileName
,
sizeof
(
data
->
cAlternateFileName
),
NULL
,
NULL
);
return
TRUE
;
}
/*************************************************************************
* FindClose (KERNEL32.@)
*/
BOOL
WINAPI
FindClose
(
HANDLE
handle
)
{
FIND_FIRST_INFO
*
info
=
(
FIND_FIRST_INFO
*
)
handle
;
if
(
handle
==
INVALID_HANDLE_VALUE
)
goto
error
;
__TRY
{
RtlEnterCriticalSection
(
&
info
->
cs
);
if
(
info
)
{
if
(
info
->
u
.
dos_dir
)
DOSFS_CloseDir
(
info
->
u
.
dos_dir
);
if
(
info
->
path
)
HeapFree
(
GetProcessHeap
(),
0
,
info
->
path
);
if
(
info
->
long_mask
)
HeapFree
(
GetProcessHeap
(),
0
,
info
->
long_mask
);
}
}
__EXCEPT
(
page_fault
)
{
WARN
(
"Illegal handle %p
\n
"
,
handle
);
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
__ENDTRY
if
(
!
info
)
goto
error
;
RtlLeaveCriticalSection
(
&
info
->
cs
);
RtlDeleteCriticalSection
(
&
info
->
cs
);
HeapFree
(
GetProcessHeap
(),
0
,
info
);
return
TRUE
;
error:
SetLastError
(
ERROR_INVALID_HANDLE
);
return
FALSE
;
}
/***********************************************************************
* MulDiv (KERNEL32.@)
* RETURNS
* Result of multiplication and division
...
...
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