2 * File handling functions
4 * Copyright 1993 John Burton
5 * Copyright 1996, 2004 Alexandre Julliard
6 * Copyright 2008 Jeff Zaroyko
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
30 #define WIN32_NO_STATUS
39 #include "ddk/ntddk.h"
40 #include "ddk/ntddser.h"
42 #include "kernelbase.h"
43 #include "wine/exception.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(file
);
48 /* info structure for FindFirstFile handle */
51 DWORD magic
; /* magic number */
52 HANDLE handle
; /* handle to directory */
53 CRITICAL_SECTION cs
; /* crit section protecting this structure */
54 FINDEX_SEARCH_OPS search_op
; /* Flags passed to FindFirst. */
55 FINDEX_INFO_LEVELS level
; /* Level passed to FindFirst */
56 UNICODE_STRING path
; /* NT path used to open the directory */
57 BOOL is_root
; /* is directory the root of the drive? */
58 BOOL wildcard
; /* did the mask contain wildcard characters? */
59 UINT data_pos
; /* current position in dir data */
60 UINT data_len
; /* length of dir data */
61 UINT data_size
; /* size of data buffer, or 0 when everything has been read */
62 BYTE data
[1]; /* directory data */
65 #define FIND_FIRST_MAGIC 0xc0ffee11
67 static const UINT max_entry_size
= offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[256] );
69 const WCHAR windows_dir
[] = L
"C:\\windows";
70 const WCHAR system_dir
[] = L
"C:\\windows\\system32";
72 static BOOL oem_file_apis
;
75 static void WINAPI
read_write_apc( void *apc_user
, PIO_STATUS_BLOCK io
, ULONG reserved
)
77 LPOVERLAPPED_COMPLETION_ROUTINE func
= apc_user
;
78 func( RtlNtStatusToDosError( io
->u
.Status
), io
->Information
, (LPOVERLAPPED
)io
);
81 static const WCHAR
*get_machine_wow64_dir( WORD machine
)
85 case IMAGE_FILE_MACHINE_TARGET_HOST
: return system_dir
;
86 case IMAGE_FILE_MACHINE_I386
: return L
"C:\\windows\\syswow64";
87 case IMAGE_FILE_MACHINE_ARMNT
: return L
"C:\\windows\\sysarm32";
88 case IMAGE_FILE_MACHINE_AMD64
: return L
"C:\\windows\\sysx8664";
89 case IMAGE_FILE_MACHINE_ARM64
: return L
"C:\\windows\\sysarm64";
95 /***********************************************************************
96 * Operations on file names
97 ***********************************************************************/
100 /***********************************************************************
103 * Check if the file name contains a path; helper for SearchPathW.
104 * A relative path is not considered a path unless it starts with ./ or ../
106 static inline BOOL
contains_path( const WCHAR
*name
)
108 if (RtlDetermineDosPathNameType_U( name
) != RELATIVE_PATH
) return TRUE
;
109 if (name
[0] != '.') return FALSE
;
110 if (name
[1] == '/' || name
[1] == '\\') return TRUE
;
111 return (name
[1] == '.' && (name
[2] == '/' || name
[2] == '\\'));
115 /***********************************************************************
116 * add_boot_rename_entry
118 * Adds an entry to the registry that is loaded when windows boots and
119 * checks if there are some files to be removed or renamed/moved.
120 * <fn1> has to be valid and <fn2> may be NULL. If both pointers are
121 * non-NULL then the file is moved, otherwise it is deleted. The
122 * entry of the registry key is always appended with two zero
123 * terminated strings. If <fn2> is NULL then the second entry is
124 * simply a single 0-byte. Otherwise the second filename goes
125 * there. The entries are prepended with \??\ before the path and the
126 * second filename gets also a '!' as the first character if
127 * MOVEFILE_REPLACE_EXISTING is set. After the final string another
128 * 0-byte follows to indicate the end of the strings.
130 * \??\D:\test\file1[0]
131 * !\??\D:\test\file1_renamed[0]
132 * \??\D:\Test|delete[0]
133 * [0] <- file is to be deleted, second string empty
134 * \??\D:\test\file2[0]
135 * !\??\D:\test\file2_renamed[0]
136 * [0] <- indicates end of strings
139 * \??\D:\test\file1[0]
140 * !\??\D:\test\file1_renamed[0]
141 * \??\D:\Test|delete[0]
142 * [0] <- file is to be deleted, second string empty
143 * [0] <- indicates end of strings
146 static BOOL
add_boot_rename_entry( LPCWSTR source
, LPCWSTR dest
, DWORD flags
)
148 static const int info_size
= FIELD_OFFSET( KEY_VALUE_PARTIAL_INFORMATION
, Data
);
150 OBJECT_ATTRIBUTES attr
;
151 UNICODE_STRING session_manager
= RTL_CONSTANT_STRING( L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager" );
152 UNICODE_STRING pending_file_rename_operations
= RTL_CONSTANT_STRING( L
"PendingFileRenameOperations" );
153 UNICODE_STRING source_name
, dest_name
;
154 KEY_VALUE_PARTIAL_INFORMATION
*info
;
162 if (!RtlDosPathNameToNtPathName_U( source
, &source_name
, NULL
, NULL
))
164 SetLastError( ERROR_PATH_NOT_FOUND
);
167 dest_name
.Buffer
= NULL
;
168 if (dest
&& !RtlDosPathNameToNtPathName_U( dest
, &dest_name
, NULL
, NULL
))
170 RtlFreeUnicodeString( &source_name
);
171 SetLastError( ERROR_PATH_NOT_FOUND
);
175 attr
.Length
= sizeof(attr
);
176 attr
.RootDirectory
= 0;
177 attr
.ObjectName
= &session_manager
;
179 attr
.SecurityDescriptor
= NULL
;
180 attr
.SecurityQualityOfService
= NULL
;
182 if (NtCreateKey( &key
, KEY_ALL_ACCESS
, &attr
, 0, NULL
, 0, NULL
) != STATUS_SUCCESS
)
184 RtlFreeUnicodeString( &source_name
);
185 RtlFreeUnicodeString( &dest_name
);
189 len1
= source_name
.Length
+ sizeof(WCHAR
);
192 len2
= dest_name
.Length
+ sizeof(WCHAR
);
193 if (flags
& MOVEFILE_REPLACE_EXISTING
)
194 len2
+= sizeof(WCHAR
); /* Plus 1 because of the leading '!' */
196 else len2
= sizeof(WCHAR
); /* minimum is the 0 characters for the empty second string */
198 /* First we check if the key exists and if so how many bytes it already contains. */
199 if (NtQueryValueKey( key
, &pending_file_rename_operations
, KeyValuePartialInformation
,
200 NULL
, 0, &size
) == STATUS_BUFFER_TOO_SMALL
)
202 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
+ len1
+ len2
+ sizeof(WCHAR
) ))) goto done
;
203 if (NtQueryValueKey( key
, &pending_file_rename_operations
, KeyValuePartialInformation
, buffer
, size
, &size
)) goto done
;
204 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)buffer
;
205 if (info
->Type
!= REG_MULTI_SZ
) goto done
;
206 if (size
> sizeof(info
)) size
-= sizeof(WCHAR
); /* remove terminating null (will be added back later) */
211 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, size
+ len1
+ len2
+ sizeof(WCHAR
) ))) goto done
;
214 memcpy( buffer
+ size
, source_name
.Buffer
, len1
);
216 p
= (WCHAR
*)(buffer
+ size
);
219 if (flags
& MOVEFILE_REPLACE_EXISTING
) *p
++ = '!';
220 memcpy( p
, dest_name
.Buffer
, len2
);
226 size
+= sizeof(WCHAR
);
230 p
= (WCHAR
*)(buffer
+ size
);
232 size
+= sizeof(WCHAR
);
233 rc
= !NtSetValueKey( key
, &pending_file_rename_operations
, 0, REG_MULTI_SZ
, buffer
+ info_size
, size
- info_size
);
236 RtlFreeUnicodeString( &source_name
);
237 RtlFreeUnicodeString( &dest_name
);
238 if (key
) NtClose(key
);
239 HeapFree( GetProcessHeap(), 0, buffer
);
244 /***********************************************************************
247 static WCHAR
*append_ext( const WCHAR
*name
, const WCHAR
*ext
)
253 if (!ext
) return NULL
;
254 p
= wcsrchr( name
, '.' );
255 if (p
&& !wcschr( p
, '/' ) && !wcschr( p
, '\\' )) return NULL
;
257 len
= lstrlenW( name
) + lstrlenW( ext
);
258 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) )))
260 lstrcpyW( ret
, name
);
261 lstrcatW( ret
, ext
);
267 /***********************************************************************
268 * find_actctx_dllpath
270 * Find the path (if any) of the dll from the activation context.
271 * Returned path doesn't include a name.
273 static NTSTATUS
find_actctx_dllpath( const WCHAR
*name
, WCHAR
**path
)
275 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*info
;
276 ACTCTX_SECTION_KEYED_DATA data
;
277 UNICODE_STRING nameW
;
279 SIZE_T needed
, size
= 1024;
282 RtlInitUnicodeString( &nameW
, name
);
283 data
.cbSize
= sizeof(data
);
284 status
= RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
, NULL
,
285 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
,
287 if (status
!= STATUS_SUCCESS
) return status
;
291 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
293 status
= STATUS_NO_MEMORY
;
296 status
= RtlQueryInformationActivationContext( 0, data
.hActCtx
, &data
.ulAssemblyRosterIndex
,
297 AssemblyDetailedInformationInActivationContext
,
298 info
, size
, &needed
);
299 if (status
== STATUS_SUCCESS
) break;
300 if (status
!= STATUS_BUFFER_TOO_SMALL
) goto done
;
301 RtlFreeHeap( GetProcessHeap(), 0, info
);
303 /* restart with larger buffer */
306 if (!info
->lpAssemblyManifestPath
)
308 status
= STATUS_SXS_KEY_NOT_FOUND
;
312 if ((p
= wcsrchr( info
->lpAssemblyManifestPath
, '\\' )))
314 DWORD dirlen
= info
->ulAssemblyDirectoryNameLength
/ sizeof(WCHAR
);
318 CompareStringOrdinal( p
, dirlen
, info
->lpAssemblyDirectoryName
, dirlen
, TRUE
) != CSTR_EQUAL
||
319 wcsicmp( p
+ dirlen
, L
".manifest" ))
321 /* manifest name does not match directory name, so it's not a global
322 * windows/winsxs manifest; use the manifest directory name instead */
323 dirlen
= p
- info
->lpAssemblyManifestPath
;
324 needed
= (dirlen
+ 1) * sizeof(WCHAR
);
325 if (!(*path
= p
= HeapAlloc( GetProcessHeap(), 0, needed
)))
327 status
= STATUS_NO_MEMORY
;
330 memcpy( p
, info
->lpAssemblyManifestPath
, dirlen
* sizeof(WCHAR
) );
336 if (!info
->lpAssemblyDirectoryName
)
338 status
= STATUS_SXS_KEY_NOT_FOUND
;
342 needed
= sizeof(L
"C:\\windows\\winsxs\\") + info
->ulAssemblyDirectoryNameLength
+ sizeof(WCHAR
);
344 if (!(*path
= p
= RtlAllocateHeap( GetProcessHeap(), 0, needed
)))
346 status
= STATUS_NO_MEMORY
;
349 lstrcpyW( p
, L
"C:\\windows\\winsxs\\" );
351 memcpy( p
, info
->lpAssemblyDirectoryName
, info
->ulAssemblyDirectoryNameLength
);
352 p
+= info
->ulAssemblyDirectoryNameLength
/ sizeof(WCHAR
);
356 RtlFreeHeap( GetProcessHeap(), 0, info
);
357 RtlReleaseActivationContext( data
.hActCtx
);
362 /***********************************************************************
365 static DWORD
copy_filename( const WCHAR
*name
, WCHAR
*buffer
, DWORD len
)
367 UINT ret
= lstrlenW( name
) + 1;
368 if (buffer
&& len
>= ret
)
370 lstrcpyW( buffer
, name
);
377 /***********************************************************************
380 * copy a file name back to OEM/Ansi, but only if the buffer is large enough
382 static DWORD
copy_filename_WtoA( LPCWSTR nameW
, LPSTR buffer
, DWORD len
)
387 RtlInitUnicodeString( &strW
, nameW
);
389 ret
= oem_file_apis
? RtlUnicodeStringToOemSize( &strW
) : RtlUnicodeStringToAnsiSize( &strW
);
390 if (buffer
&& ret
<= len
)
395 str
.MaximumLength
= min( len
, UNICODE_STRING_MAX_CHARS
);
397 RtlUnicodeStringToOemString( &str
, &strW
, FALSE
);
399 RtlUnicodeStringToAnsiString( &str
, &strW
, FALSE
);
400 ret
= str
.Length
; /* length without terminating 0 */
406 /***********************************************************************
409 * Convert a file name to Unicode, taking into account the OEM/Ansi API mode.
411 * If alloc is FALSE uses the TEB static buffer, so it can only be used when
412 * there is no possibility for the function to do that twice, taking into
413 * account any called function.
415 WCHAR
*file_name_AtoW( LPCSTR name
, BOOL alloc
)
418 UNICODE_STRING strW
, *pstrW
;
421 RtlInitAnsiString( &str
, name
);
422 pstrW
= alloc
? &strW
: &NtCurrentTeb()->StaticUnicodeString
;
424 status
= RtlOemStringToUnicodeString( pstrW
, &str
, alloc
);
426 status
= RtlAnsiStringToUnicodeString( pstrW
, &str
, alloc
);
427 if (status
== STATUS_SUCCESS
) return pstrW
->Buffer
;
429 if (status
== STATUS_BUFFER_OVERFLOW
)
430 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
432 SetLastError( RtlNtStatusToDosError(status
) );
437 /***********************************************************************
440 * Convert a file name back to OEM/Ansi. Returns number of bytes copied.
442 DWORD
file_name_WtoA( LPCWSTR src
, INT srclen
, LPSTR dest
, INT destlen
)
446 if (srclen
< 0) srclen
= lstrlenW( src
) + 1;
452 strW
.Buffer
= (WCHAR
*)src
;
453 strW
.Length
= srclen
* sizeof(WCHAR
);
454 ret
= RtlUnicodeStringToOemSize( &strW
) - 1;
457 RtlUnicodeToMultiByteSize( &ret
, src
, srclen
* sizeof(WCHAR
) );
462 RtlUnicodeToOemN( dest
, destlen
, &ret
, src
, srclen
* sizeof(WCHAR
) );
464 RtlUnicodeToMultiByteN( dest
, destlen
, &ret
, src
, srclen
* sizeof(WCHAR
) );
470 /***********************************************************************
473 static BOOL
is_same_file( HANDLE h1
, HANDLE h2
)
475 FILE_OBJECTID_BUFFER id1
, id2
;
478 return (!NtFsControlFile( h1
, 0, NULL
, NULL
, &io
, FSCTL_GET_OBJECT_ID
, NULL
, 0, &id1
, sizeof(id1
) ) &&
479 !NtFsControlFile( h2
, 0, NULL
, NULL
, &io
, FSCTL_GET_OBJECT_ID
, NULL
, 0, &id2
, sizeof(id2
) ) &&
480 !memcmp( &id1
.ObjectId
, &id2
.ObjectId
, sizeof(id1
.ObjectId
) ));
484 /******************************************************************************
485 * AreFileApisANSI (kernelbase.@)
487 BOOL WINAPI DECLSPEC_HOTPATCH
AreFileApisANSI(void)
489 return !oem_file_apis
;
493 /***********************************************************************
494 * CopyFileExW (kernelbase.@)
496 BOOL WINAPI
CopyFileExW( const WCHAR
*source
, const WCHAR
*dest
, LPPROGRESS_ROUTINE progress
,
497 void *param
, BOOL
*cancel_ptr
, DWORD flags
)
499 static const int buffer_size
= 65536;
501 FILE_BASIC_INFORMATION info
;
507 if (!source
|| !dest
)
509 SetLastError( ERROR_INVALID_PARAMETER
);
512 if (!(buffer
= HeapAlloc( GetProcessHeap(), 0, buffer_size
)))
514 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
518 TRACE("%s -> %s, %lx\n", debugstr_w(source
), debugstr_w(dest
), flags
);
520 if (flags
& COPY_FILE_RESTARTABLE
)
521 FIXME("COPY_FILE_RESTARTABLE is not supported\n");
522 if (flags
& COPY_FILE_COPY_SYMLINK
)
523 FIXME("COPY_FILE_COPY_SYMLINK is not supported\n");
524 if (flags
& COPY_FILE_OPEN_SOURCE_FOR_WRITE
)
525 FIXME("COPY_FILE_OPEN_SOURCE_FOR_WRITE is not supported\n");
527 if ((h1
= CreateFileW( source
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
528 NULL
, OPEN_EXISTING
, 0, 0 )) == INVALID_HANDLE_VALUE
)
530 WARN("Unable to open source %s\n", debugstr_w(source
));
531 HeapFree( GetProcessHeap(), 0, buffer
);
535 if (!set_ntstatus( NtQueryInformationFile( h1
, &io
, &info
, sizeof(info
), FileBasicInformation
)))
537 WARN("GetFileInformationByHandle returned error for %s\n", debugstr_w(source
));
538 HeapFree( GetProcessHeap(), 0, buffer
);
543 if (!(flags
& COPY_FILE_FAIL_IF_EXISTS
))
545 BOOL same_file
= FALSE
;
546 h2
= CreateFileW( dest
, 0, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
547 if (h2
!= INVALID_HANDLE_VALUE
)
549 same_file
= is_same_file( h1
, h2
);
554 HeapFree( GetProcessHeap(), 0, buffer
);
556 SetLastError( ERROR_SHARING_VIOLATION
);
561 if ((h2
= CreateFileW( dest
, GENERIC_WRITE
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
,
562 (flags
& COPY_FILE_FAIL_IF_EXISTS
) ? CREATE_NEW
: CREATE_ALWAYS
,
563 info
.FileAttributes
, h1
)) == INVALID_HANDLE_VALUE
)
565 WARN("Unable to open dest %s\n", debugstr_w(dest
));
566 HeapFree( GetProcessHeap(), 0, buffer
);
571 while (ReadFile( h1
, buffer
, buffer_size
, &count
, NULL
) && count
)
577 if (!WriteFile( h2
, p
, count
, &res
, NULL
) || !res
) goto done
;
584 /* Maintain the timestamp of source file to destination file */
585 info
.FileAttributes
= 0;
586 NtSetInformationFile( h2
, &io
, &info
, sizeof(info
), FileBasicInformation
);
587 HeapFree( GetProcessHeap(), 0, buffer
);
590 if (ret
) SetLastError( 0 );
595 /**************************************************************************
596 * CopyFileW (kernelbase.@)
598 BOOL WINAPI DECLSPEC_HOTPATCH
CopyFileW( const WCHAR
*source
, const WCHAR
*dest
, BOOL fail_if_exists
)
600 return CopyFileExW( source
, dest
, NULL
, NULL
, NULL
, fail_if_exists
? COPY_FILE_FAIL_IF_EXISTS
: 0 );
604 /***********************************************************************
605 * CreateDirectoryA (kernelbase.@)
607 BOOL WINAPI DECLSPEC_HOTPATCH
CreateDirectoryA( LPCSTR path
, LPSECURITY_ATTRIBUTES sa
)
611 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return FALSE
;
612 return CreateDirectoryW( pathW
, sa
);
616 /***********************************************************************
617 * CreateDirectoryW (kernelbase.@)
619 BOOL WINAPI DECLSPEC_HOTPATCH
CreateDirectoryW( LPCWSTR path
, LPSECURITY_ATTRIBUTES sa
)
621 OBJECT_ATTRIBUTES attr
;
622 UNICODE_STRING nt_name
;
627 TRACE( "%s\n", debugstr_w(path
) );
629 if (!RtlDosPathNameToNtPathName_U( path
, &nt_name
, NULL
, NULL
))
631 SetLastError( ERROR_PATH_NOT_FOUND
);
634 attr
.Length
= sizeof(attr
);
635 attr
.RootDirectory
= 0;
636 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
637 attr
.ObjectName
= &nt_name
;
638 attr
.SecurityDescriptor
= sa
? sa
->lpSecurityDescriptor
: NULL
;
639 attr
.SecurityQualityOfService
= NULL
;
641 status
= NtCreateFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, NULL
,
642 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
, FILE_CREATE
,
643 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
644 if (status
== STATUS_SUCCESS
) NtClose( handle
);
646 RtlFreeUnicodeString( &nt_name
);
647 return set_ntstatus( status
);
651 /***********************************************************************
652 * CreateDirectoryEx (kernelbase.@)
654 BOOL WINAPI DECLSPEC_HOTPATCH
CreateDirectoryExW( LPCWSTR
template, LPCWSTR path
,
655 LPSECURITY_ATTRIBUTES sa
)
657 return CreateDirectoryW( path
, sa
);
661 /*************************************************************************
662 * CreateFile2 (kernelbase.@)
664 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFile2( LPCWSTR name
, DWORD access
, DWORD sharing
, DWORD creation
,
665 CREATEFILE2_EXTENDED_PARAMETERS
*params
)
667 static const DWORD attributes_mask
= FILE_ATTRIBUTE_READONLY
|
668 FILE_ATTRIBUTE_HIDDEN
|
669 FILE_ATTRIBUTE_SYSTEM
|
670 FILE_ATTRIBUTE_ARCHIVE
|
671 FILE_ATTRIBUTE_NORMAL
|
672 FILE_ATTRIBUTE_TEMPORARY
|
673 FILE_ATTRIBUTE_OFFLINE
|
674 FILE_ATTRIBUTE_ENCRYPTED
|
675 FILE_ATTRIBUTE_INTEGRITY_STREAM
;
676 static const DWORD flags_mask
= FILE_FLAG_BACKUP_SEMANTICS
|
677 FILE_FLAG_DELETE_ON_CLOSE
|
678 FILE_FLAG_NO_BUFFERING
|
679 FILE_FLAG_OPEN_NO_RECALL
|
680 FILE_FLAG_OPEN_REPARSE_POINT
|
681 FILE_FLAG_OVERLAPPED
|
682 FILE_FLAG_POSIX_SEMANTICS
|
683 FILE_FLAG_RANDOM_ACCESS
|
684 FILE_FLAG_SEQUENTIAL_SCAN
|
685 FILE_FLAG_WRITE_THROUGH
;
687 LPSECURITY_ATTRIBUTES sa
= params
? params
->lpSecurityAttributes
: NULL
;
688 HANDLE
template = params
? params
->hTemplateFile
: NULL
;
689 DWORD attributes
= params
? params
->dwFileAttributes
: 0;
690 DWORD flags
= params
? params
->dwFileFlags
: 0;
692 FIXME( "(%s %lx %lx %lx %p), partial stub\n", debugstr_w(name
), access
, sharing
, creation
, params
);
694 if (attributes
& ~attributes_mask
) FIXME( "unsupported attributes %#lx\n", attributes
);
695 if (flags
& ~flags_mask
) FIXME( "unsupported flags %#lx\n", flags
);
696 attributes
&= attributes_mask
;
699 return CreateFileW( name
, access
, sharing
, sa
, creation
, flags
| attributes
, template );
703 /*************************************************************************
704 * CreateFileA (kernelbase.@)
706 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileA( LPCSTR name
, DWORD access
, DWORD sharing
,
707 LPSECURITY_ATTRIBUTES sa
, DWORD creation
,
708 DWORD attributes
, HANDLE
template)
712 if ((GetVersion() & 0x80000000) && IsBadStringPtrA( name
, -1 )) return INVALID_HANDLE_VALUE
;
713 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return INVALID_HANDLE_VALUE
;
714 return CreateFileW( nameW
, access
, sharing
, sa
, creation
, attributes
, template );
717 static UINT
get_nt_file_options( DWORD attributes
)
721 if (attributes
& FILE_FLAG_BACKUP_SEMANTICS
)
722 options
|= FILE_OPEN_FOR_BACKUP_INTENT
;
724 options
|= FILE_NON_DIRECTORY_FILE
;
725 if (attributes
& FILE_FLAG_DELETE_ON_CLOSE
)
726 options
|= FILE_DELETE_ON_CLOSE
;
727 if (attributes
& FILE_FLAG_NO_BUFFERING
)
728 options
|= FILE_NO_INTERMEDIATE_BUFFERING
;
729 if (!(attributes
& FILE_FLAG_OVERLAPPED
))
730 options
|= FILE_SYNCHRONOUS_IO_NONALERT
;
731 if (attributes
& FILE_FLAG_RANDOM_ACCESS
)
732 options
|= FILE_RANDOM_ACCESS
;
733 if (attributes
& FILE_FLAG_SEQUENTIAL_SCAN
)
734 options
|= FILE_SEQUENTIAL_ONLY
;
735 if (attributes
& FILE_FLAG_WRITE_THROUGH
)
736 options
|= FILE_WRITE_THROUGH
;
740 /*************************************************************************
741 * CreateFileW (kernelbase.@)
743 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileW( LPCWSTR filename
, DWORD access
, DWORD sharing
,
744 LPSECURITY_ATTRIBUTES sa
, DWORD creation
,
745 DWORD attributes
, HANDLE
template )
748 OBJECT_ATTRIBUTES attr
;
749 UNICODE_STRING nameW
;
752 const WCHAR
*vxd_name
= NULL
;
753 SECURITY_QUALITY_OF_SERVICE qos
;
755 static const UINT nt_disposition
[5] =
757 FILE_CREATE
, /* CREATE_NEW */
758 FILE_OVERWRITE_IF
, /* CREATE_ALWAYS */
759 FILE_OPEN
, /* OPEN_EXISTING */
760 FILE_OPEN_IF
, /* OPEN_ALWAYS */
761 FILE_OVERWRITE
/* TRUNCATE_EXISTING */
767 if (!filename
|| !filename
[0])
769 SetLastError( ERROR_PATH_NOT_FOUND
);
770 return INVALID_HANDLE_VALUE
;
773 TRACE( "%s %s%s%s%s%s%s%s creation %ld attributes 0x%lx\n", debugstr_w(filename
),
774 (access
& GENERIC_READ
) ? "GENERIC_READ " : "",
775 (access
& GENERIC_WRITE
) ? "GENERIC_WRITE " : "",
776 (access
& GENERIC_EXECUTE
) ? "GENERIC_EXECUTE " : "",
777 !access
? "QUERY_ACCESS " : "",
778 (sharing
& FILE_SHARE_READ
) ? "FILE_SHARE_READ " : "",
779 (sharing
& FILE_SHARE_WRITE
) ? "FILE_SHARE_WRITE " : "",
780 (sharing
& FILE_SHARE_DELETE
) ? "FILE_SHARE_DELETE " : "",
781 creation
, attributes
);
783 if ((GetVersion() & 0x80000000) && !wcsncmp( filename
, L
"\\\\.\\", 4 ) &&
784 !RtlIsDosDeviceName_U( filename
+ 4 ) &&
785 wcsnicmp( filename
+ 4, L
"PIPE\\", 5 ) &&
786 wcsnicmp( filename
+ 4, L
"MAILSLOT\\", 9 ))
788 vxd_name
= filename
+ 4;
789 if (!creation
) creation
= OPEN_EXISTING
;
792 if (creation
< CREATE_NEW
|| creation
> TRUNCATE_EXISTING
)
794 SetLastError( ERROR_INVALID_PARAMETER
);
795 return INVALID_HANDLE_VALUE
;
798 if (!RtlDosPathNameToNtPathName_U( filename
, &nameW
, NULL
, NULL
))
800 SetLastError( ERROR_PATH_NOT_FOUND
);
801 return INVALID_HANDLE_VALUE
;
804 /* now call NtCreateFile */
806 if (attributes
& FILE_FLAG_DELETE_ON_CLOSE
)
809 attr
.Length
= sizeof(attr
);
810 attr
.RootDirectory
= 0;
811 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
812 attr
.ObjectName
= &nameW
;
813 attr
.SecurityDescriptor
= sa
? sa
->lpSecurityDescriptor
: NULL
;
814 if (attributes
& SECURITY_SQOS_PRESENT
)
816 qos
.Length
= sizeof(qos
);
817 qos
.ImpersonationLevel
= (attributes
>> 16) & 0x3;
818 qos
.ContextTrackingMode
= attributes
& SECURITY_CONTEXT_TRACKING
? SECURITY_DYNAMIC_TRACKING
: SECURITY_STATIC_TRACKING
;
819 qos
.EffectiveOnly
= (attributes
& SECURITY_EFFECTIVE_ONLY
) != 0;
820 attr
.SecurityQualityOfService
= &qos
;
823 attr
.SecurityQualityOfService
= NULL
;
825 if (sa
&& sa
->bInheritHandle
) attr
.Attributes
|= OBJ_INHERIT
;
827 status
= NtCreateFile( &ret
, access
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
, &attr
, &io
,
828 NULL
, attributes
& FILE_ATTRIBUTE_VALID_FLAGS
, sharing
,
829 nt_disposition
[creation
- CREATE_NEW
],
830 get_nt_file_options( attributes
), NULL
, 0 );
833 if (vxd_name
&& vxd_name
[0])
835 static HANDLE (*vxd_open
)(LPCWSTR
,DWORD
,SECURITY_ATTRIBUTES
*);
836 if (!vxd_open
) vxd_open
= (void *)GetProcAddress( GetModuleHandleW(L
"krnl386.exe16"),
838 if (vxd_open
&& (ret
= vxd_open( vxd_name
, access
, sa
))) goto done
;
841 WARN("Unable to create file %s (status %lx)\n", debugstr_w(filename
), status
);
842 ret
= INVALID_HANDLE_VALUE
;
844 /* In the case file creation was rejected due to CREATE_NEW flag
845 * was specified and file with that name already exists, correct
846 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
847 * Note: RtlNtStatusToDosError is not the subject to blame here.
849 if (status
== STATUS_OBJECT_NAME_COLLISION
)
850 SetLastError( ERROR_FILE_EXISTS
);
852 SetLastError( RtlNtStatusToDosError(status
) );
856 if ((creation
== CREATE_ALWAYS
&& io
.Information
== FILE_OVERWRITTEN
) ||
857 (creation
== OPEN_ALWAYS
&& io
.Information
== FILE_OPENED
))
858 SetLastError( ERROR_ALREADY_EXISTS
);
862 RtlFreeUnicodeString( &nameW
);
865 if (!ret
) ret
= INVALID_HANDLE_VALUE
;
866 TRACE("returning %p\n", ret
);
871 /*************************************************************************
872 * CreateHardLinkA (kernelbase.@)
874 BOOL WINAPI DECLSPEC_HOTPATCH
CreateHardLinkA( const char *dest
, const char *source
,
875 SECURITY_ATTRIBUTES
*attr
)
877 WCHAR
*sourceW
, *destW
;
880 if (!(sourceW
= file_name_AtoW( source
, TRUE
))) return FALSE
;
881 if (!(destW
= file_name_AtoW( dest
, TRUE
)))
883 HeapFree( GetProcessHeap(), 0, sourceW
);
886 res
= CreateHardLinkW( destW
, sourceW
, attr
);
887 HeapFree( GetProcessHeap(), 0, sourceW
);
888 HeapFree( GetProcessHeap(), 0, destW
);
893 /*************************************************************************
894 * CreateHardLinkW (kernelbase.@)
896 BOOL WINAPI
CreateHardLinkW( LPCWSTR dest
, LPCWSTR source
, SECURITY_ATTRIBUTES
*sec_attr
)
898 UNICODE_STRING ntDest
, ntSource
;
899 FILE_LINK_INFORMATION
*info
= NULL
;
900 OBJECT_ATTRIBUTES attr
;
906 TRACE( "(%s, %s, %p)\n", debugstr_w(dest
), debugstr_w(source
), sec_attr
);
908 ntDest
.Buffer
= ntSource
.Buffer
= NULL
;
909 if (!RtlDosPathNameToNtPathName_U( dest
, &ntDest
, NULL
, NULL
) ||
910 !RtlDosPathNameToNtPathName_U( source
, &ntSource
, NULL
, NULL
))
912 SetLastError( ERROR_PATH_NOT_FOUND
);
916 size
= offsetof( FILE_LINK_INFORMATION
, FileName
) + ntDest
.Length
;
917 if (!(info
= HeapAlloc( GetProcessHeap(), 0, size
)))
919 SetLastError( ERROR_OUTOFMEMORY
);
923 InitializeObjectAttributes( &attr
, &ntSource
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
924 if (!(ret
= set_ntstatus( NtOpenFile( &file
, SYNCHRONIZE
, &attr
, &io
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
925 FILE_SYNCHRONOUS_IO_NONALERT
) )))
928 info
->ReplaceIfExists
= FALSE
;
929 info
->RootDirectory
= NULL
;
930 info
->FileNameLength
= ntDest
.Length
;
931 memcpy( info
->FileName
, ntDest
.Buffer
, ntDest
.Length
);
932 ret
= set_ntstatus( NtSetInformationFile( file
, &io
, info
, size
, FileLinkInformation
) );
936 RtlFreeUnicodeString( &ntSource
);
937 RtlFreeUnicodeString( &ntDest
);
938 HeapFree( GetProcessHeap(), 0, info
);
943 /*************************************************************************
944 * CreateSymbolicLinkW (kernelbase.@)
946 BOOLEAN WINAPI
/* DECLSPEC_HOTPATCH */ CreateSymbolicLinkW( LPCWSTR link
, LPCWSTR target
, DWORD flags
)
948 FIXME( "(%s %s %ld): stub\n", debugstr_w(link
), debugstr_w(target
), flags
);
953 /***********************************************************************
954 * DeleteFileA (kernelbase.@)
956 BOOL WINAPI DECLSPEC_HOTPATCH
DeleteFileA( LPCSTR path
)
960 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return FALSE
;
961 return DeleteFileW( pathW
);
965 /***********************************************************************
966 * DeleteFileW (kernelbase.@)
968 BOOL WINAPI DECLSPEC_HOTPATCH
DeleteFileW( LPCWSTR path
)
970 UNICODE_STRING nameW
;
971 OBJECT_ATTRIBUTES attr
;
976 TRACE( "%s\n", debugstr_w(path
) );
978 if (!RtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
))
980 SetLastError( ERROR_PATH_NOT_FOUND
);
984 attr
.Length
= sizeof(attr
);
985 attr
.RootDirectory
= 0;
986 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
987 attr
.ObjectName
= &nameW
;
988 attr
.SecurityDescriptor
= NULL
;
989 attr
.SecurityQualityOfService
= NULL
;
991 status
= NtCreateFile(&hFile
, SYNCHRONIZE
| DELETE
, &attr
, &io
, NULL
, 0,
992 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
993 FILE_OPEN
, FILE_DELETE_ON_CLOSE
| FILE_NON_DIRECTORY_FILE
, NULL
, 0);
994 if (status
== STATUS_SUCCESS
) status
= NtClose(hFile
);
996 RtlFreeUnicodeString( &nameW
);
997 return set_ntstatus( status
);
1001 /****************************************************************************
1002 * FindCloseChangeNotification (kernelbase.@)
1004 BOOL WINAPI DECLSPEC_HOTPATCH
FindCloseChangeNotification( HANDLE handle
)
1006 return CloseHandle( handle
);
1010 /****************************************************************************
1011 * FindFirstChangeNotificationA (kernelbase.@)
1013 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstChangeNotificationA( LPCSTR path
, BOOL subtree
, DWORD filter
)
1017 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return INVALID_HANDLE_VALUE
;
1018 return FindFirstChangeNotificationW( pathW
, subtree
, filter
);
1023 * NtNotifyChangeDirectoryFile may write back to the IO_STATUS_BLOCK
1024 * asynchronously. We don't care about the contents, but it can't
1025 * be placed on the stack since it will go out of scope when we return.
1027 static IO_STATUS_BLOCK dummy_iosb
;
1029 /****************************************************************************
1030 * FindFirstChangeNotificationW (kernelbase.@)
1032 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstChangeNotificationW( LPCWSTR path
, BOOL subtree
, DWORD filter
)
1034 UNICODE_STRING nt_name
;
1035 OBJECT_ATTRIBUTES attr
;
1037 HANDLE handle
= INVALID_HANDLE_VALUE
;
1039 TRACE( "%s %d %lx\n", debugstr_w(path
), subtree
, filter
);
1041 if (!RtlDosPathNameToNtPathName_U( path
, &nt_name
, NULL
, NULL
))
1043 SetLastError( ERROR_PATH_NOT_FOUND
);
1047 attr
.Length
= sizeof(attr
);
1048 attr
.RootDirectory
= 0;
1049 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1050 attr
.ObjectName
= &nt_name
;
1051 attr
.SecurityDescriptor
= NULL
;
1052 attr
.SecurityQualityOfService
= NULL
;
1054 status
= NtOpenFile( &handle
, FILE_LIST_DIRECTORY
| SYNCHRONIZE
, &attr
, &dummy_iosb
,
1055 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
1056 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
1057 RtlFreeUnicodeString( &nt_name
);
1059 if (!set_ntstatus( status
)) return INVALID_HANDLE_VALUE
;
1061 status
= NtNotifyChangeDirectoryFile( handle
, NULL
, NULL
, NULL
, &dummy_iosb
, NULL
, 0, filter
, subtree
);
1062 if (status
!= STATUS_PENDING
)
1065 SetLastError( RtlNtStatusToDosError(status
) );
1066 return INVALID_HANDLE_VALUE
;
1072 /****************************************************************************
1073 * FindNextChangeNotification (kernelbase.@)
1075 BOOL WINAPI DECLSPEC_HOTPATCH
FindNextChangeNotification( HANDLE handle
)
1077 NTSTATUS status
= NtNotifyChangeDirectoryFile( handle
, NULL
, NULL
, NULL
, &dummy_iosb
,
1078 NULL
, 0, FILE_NOTIFY_CHANGE_SIZE
, 0 );
1079 if (status
== STATUS_PENDING
) return TRUE
;
1080 return set_ntstatus( status
);
1084 /******************************************************************************
1085 * FindFirstFileExA (kernelbase.@)
1087 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileExA( const char *filename
, FINDEX_INFO_LEVELS level
,
1088 void *data
, FINDEX_SEARCH_OPS search_op
,
1089 void *filter
, DWORD flags
)
1092 WIN32_FIND_DATAA
*dataA
= data
;
1093 WIN32_FIND_DATAW dataW
;
1096 if (!(nameW
= file_name_AtoW( filename
, FALSE
))) return INVALID_HANDLE_VALUE
;
1098 handle
= FindFirstFileExW( nameW
, level
, &dataW
, search_op
, filter
, flags
);
1099 if (handle
== INVALID_HANDLE_VALUE
) return handle
;
1101 dataA
->dwFileAttributes
= dataW
.dwFileAttributes
;
1102 dataA
->ftCreationTime
= dataW
.ftCreationTime
;
1103 dataA
->ftLastAccessTime
= dataW
.ftLastAccessTime
;
1104 dataA
->ftLastWriteTime
= dataW
.ftLastWriteTime
;
1105 dataA
->nFileSizeHigh
= dataW
.nFileSizeHigh
;
1106 dataA
->nFileSizeLow
= dataW
.nFileSizeLow
;
1107 file_name_WtoA( dataW
.cFileName
, -1, dataA
->cFileName
, sizeof(dataA
->cFileName
) );
1108 file_name_WtoA( dataW
.cAlternateFileName
, -1, dataA
->cAlternateFileName
,
1109 sizeof(dataA
->cAlternateFileName
) );
1114 /******************************************************************************
1115 * FindFirstFileExW (kernelbase.@)
1117 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileExW( LPCWSTR filename
, FINDEX_INFO_LEVELS level
,
1118 LPVOID data
, FINDEX_SEARCH_OPS search_op
,
1119 LPVOID filter
, DWORD flags
)
1122 BOOL has_wildcard
= FALSE
;
1123 FIND_FIRST_INFO
*info
= NULL
;
1124 UNICODE_STRING nt_name
;
1125 OBJECT_ATTRIBUTES attr
;
1128 DWORD size
, device
= 0;
1130 TRACE( "%s %d %p %d %p %lx\n", debugstr_w(filename
), level
, data
, search_op
, filter
, flags
);
1132 if (flags
& ~FIND_FIRST_EX_LARGE_FETCH
)
1134 FIXME("flags not implemented 0x%08lx\n", flags
);
1136 if (search_op
!= FindExSearchNameMatch
&& search_op
!= FindExSearchLimitToDirectories
)
1138 FIXME( "search_op not implemented 0x%08x\n", search_op
);
1139 SetLastError( ERROR_INVALID_PARAMETER
);
1140 return INVALID_HANDLE_VALUE
;
1142 if (level
!= FindExInfoStandard
&& level
!= FindExInfoBasic
)
1144 FIXME("info level %d not implemented\n", level
);
1145 SetLastError( ERROR_INVALID_PARAMETER
);
1146 return INVALID_HANDLE_VALUE
;
1149 if (!RtlDosPathNameToNtPathName_U( filename
, &nt_name
, &mask
, NULL
))
1151 SetLastError( ERROR_PATH_NOT_FOUND
);
1152 return INVALID_HANDLE_VALUE
;
1155 if (!mask
&& (device
= RtlIsDosDeviceName_U( filename
)))
1159 /* we still need to check that the directory can be opened */
1163 if (!(dir
= HeapAlloc( GetProcessHeap(), 0, HIWORD(device
) + sizeof(WCHAR
) )))
1165 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1168 memcpy( dir
, filename
, HIWORD(device
) );
1169 dir
[HIWORD(device
)/sizeof(WCHAR
)] = 0;
1171 RtlFreeUnicodeString( &nt_name
);
1172 if (!RtlDosPathNameToNtPathName_U( dir
? dir
: L
".", &nt_name
, &mask
, NULL
))
1174 HeapFree( GetProcessHeap(), 0, dir
);
1175 SetLastError( ERROR_PATH_NOT_FOUND
);
1178 HeapFree( GetProcessHeap(), 0, dir
);
1181 else if (!mask
|| !*mask
)
1183 SetLastError( ERROR_FILE_NOT_FOUND
);
1188 nt_name
.Length
= (mask
- nt_name
.Buffer
) * sizeof(WCHAR
);
1189 has_wildcard
= wcspbrk( mask
, L
"*?" ) != NULL
;
1190 size
= has_wildcard
? 8192 : max_entry_size
;
1193 if (!(info
= HeapAlloc( GetProcessHeap(), 0, offsetof( FIND_FIRST_INFO
, data
[size
] ))))
1195 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1199 /* check if path is the root of the drive, skipping the \??\ prefix */
1200 info
->is_root
= FALSE
;
1201 if (nt_name
.Length
>= 6 * sizeof(WCHAR
) && nt_name
.Buffer
[5] == ':')
1204 while (pos
* sizeof(WCHAR
) < nt_name
.Length
&& nt_name
.Buffer
[pos
] == '\\') pos
++;
1205 info
->is_root
= (pos
* sizeof(WCHAR
) >= nt_name
.Length
);
1208 attr
.Length
= sizeof(attr
);
1209 attr
.RootDirectory
= 0;
1210 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1211 attr
.ObjectName
= &nt_name
;
1212 attr
.SecurityDescriptor
= NULL
;
1213 attr
.SecurityQualityOfService
= NULL
;
1215 status
= NtOpenFile( &info
->handle
, FILE_LIST_DIRECTORY
| SYNCHRONIZE
, &attr
, &io
,
1216 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1217 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
);
1218 if (status
!= STATUS_SUCCESS
)
1220 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1221 SetLastError( ERROR_PATH_NOT_FOUND
);
1223 SetLastError( RtlNtStatusToDosError(status
) );
1227 RtlInitializeCriticalSection( &info
->cs
);
1228 info
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FIND_FIRST_INFO.cs");
1229 info
->path
= nt_name
;
1230 info
->magic
= FIND_FIRST_MAGIC
;
1231 info
->wildcard
= has_wildcard
;
1234 info
->data_size
= size
;
1235 info
->search_op
= search_op
;
1236 info
->level
= level
;
1240 WIN32_FIND_DATAW
*wfd
= data
;
1242 memset( wfd
, 0, sizeof(*wfd
) );
1243 memcpy( wfd
->cFileName
, filename
+ HIWORD(device
)/sizeof(WCHAR
), LOWORD(device
) );
1244 wfd
->dwFileAttributes
= FILE_ATTRIBUTE_ARCHIVE
;
1245 CloseHandle( info
->handle
);
1250 UNICODE_STRING mask_str
;
1252 RtlInitUnicodeString( &mask_str
, mask
);
1253 status
= NtQueryDirectoryFile( info
->handle
, 0, NULL
, NULL
, &io
, info
->data
, info
->data_size
,
1254 FileBothDirectoryInformation
, FALSE
, &mask_str
, TRUE
);
1258 SetLastError( RtlNtStatusToDosError( status
) );
1259 return INVALID_HANDLE_VALUE
;
1262 info
->data_len
= io
.Information
;
1263 if (!has_wildcard
) info
->data_size
= 0; /* we read everything */
1265 if (!FindNextFileW( info
, data
))
1267 TRACE( "%s not found\n", debugstr_w(filename
) );
1269 SetLastError( ERROR_FILE_NOT_FOUND
);
1270 return INVALID_HANDLE_VALUE
;
1272 if (!has_wildcard
) /* we can't find two files with the same name */
1274 CloseHandle( info
->handle
);
1281 HeapFree( GetProcessHeap(), 0, info
);
1282 RtlFreeUnicodeString( &nt_name
);
1283 return INVALID_HANDLE_VALUE
;
1287 /******************************************************************************
1288 * FindFirstFileA (kernelbase.@)
1290 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileA( const char *filename
, WIN32_FIND_DATAA
*data
)
1292 return FindFirstFileExA( filename
, FindExInfoStandard
, data
, FindExSearchNameMatch
, NULL
, 0 );
1296 /******************************************************************************
1297 * FindFirstFileW (kernelbase.@)
1299 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileW( const WCHAR
*filename
, WIN32_FIND_DATAW
*data
)
1301 return FindFirstFileExW( filename
, FindExInfoStandard
, data
, FindExSearchNameMatch
, NULL
, 0 );
1305 /**************************************************************************
1306 * FindFirstStreamW (kernelbase.@)
1308 HANDLE WINAPI
FindFirstStreamW( const WCHAR
*filename
, STREAM_INFO_LEVELS level
, void *data
, DWORD flags
)
1310 FIXME("(%s, %d, %p, %lx): stub!\n", debugstr_w(filename
), level
, data
, flags
);
1311 SetLastError( ERROR_HANDLE_EOF
);
1312 return INVALID_HANDLE_VALUE
;
1316 /******************************************************************************
1317 * FindNextFileA (kernelbase.@)
1319 BOOL WINAPI DECLSPEC_HOTPATCH
FindNextFileA( HANDLE handle
, WIN32_FIND_DATAA
*data
)
1321 WIN32_FIND_DATAW dataW
;
1323 if (!FindNextFileW( handle
, &dataW
)) return FALSE
;
1324 data
->dwFileAttributes
= dataW
.dwFileAttributes
;
1325 data
->ftCreationTime
= dataW
.ftCreationTime
;
1326 data
->ftLastAccessTime
= dataW
.ftLastAccessTime
;
1327 data
->ftLastWriteTime
= dataW
.ftLastWriteTime
;
1328 data
->nFileSizeHigh
= dataW
.nFileSizeHigh
;
1329 data
->nFileSizeLow
= dataW
.nFileSizeLow
;
1330 file_name_WtoA( dataW
.cFileName
, -1, data
->cFileName
, sizeof(data
->cFileName
) );
1331 file_name_WtoA( dataW
.cAlternateFileName
, -1, data
->cAlternateFileName
,
1332 sizeof(data
->cAlternateFileName
) );
1337 /******************************************************************************
1338 * FindNextFileW (kernelbase.@)
1340 BOOL WINAPI DECLSPEC_HOTPATCH
FindNextFileW( HANDLE handle
, WIN32_FIND_DATAW
*data
)
1342 FIND_FIRST_INFO
*info
= handle
;
1343 FILE_BOTH_DIR_INFORMATION
*dir_info
;
1347 TRACE( "%p %p\n", handle
, data
);
1349 if (!handle
|| handle
== INVALID_HANDLE_VALUE
|| info
->magic
!= FIND_FIRST_MAGIC
)
1351 SetLastError( ERROR_INVALID_HANDLE
);
1355 RtlEnterCriticalSection( &info
->cs
);
1357 if (!info
->handle
) SetLastError( ERROR_NO_MORE_FILES
);
1360 if (info
->data_pos
>= info
->data_len
) /* need to read some more data */
1364 if (info
->data_size
)
1365 status
= NtQueryDirectoryFile( info
->handle
, 0, NULL
, NULL
, &io
, info
->data
, info
->data_size
,
1366 FileBothDirectoryInformation
, FALSE
, NULL
, FALSE
);
1368 status
= STATUS_NO_MORE_FILES
;
1370 if (!set_ntstatus( status
))
1372 if (status
== STATUS_NO_MORE_FILES
)
1374 CloseHandle( info
->handle
);
1379 info
->data_len
= io
.Information
;
1383 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(info
->data
+ info
->data_pos
);
1385 if (dir_info
->NextEntryOffset
) info
->data_pos
+= dir_info
->NextEntryOffset
;
1386 else info
->data_pos
= info
->data_len
;
1388 /* don't return '.' and '..' in the root of the drive */
1391 if (dir_info
->FileNameLength
== sizeof(WCHAR
) && dir_info
->FileName
[0] == '.') continue;
1392 if (dir_info
->FileNameLength
== 2 * sizeof(WCHAR
) &&
1393 dir_info
->FileName
[0] == '.' && dir_info
->FileName
[1] == '.') continue;
1396 data
->dwFileAttributes
= dir_info
->FileAttributes
;
1397 data
->ftCreationTime
= *(FILETIME
*)&dir_info
->CreationTime
;
1398 data
->ftLastAccessTime
= *(FILETIME
*)&dir_info
->LastAccessTime
;
1399 data
->ftLastWriteTime
= *(FILETIME
*)&dir_info
->LastWriteTime
;
1400 data
->nFileSizeHigh
= dir_info
->EndOfFile
.QuadPart
>> 32;
1401 data
->nFileSizeLow
= (DWORD
)dir_info
->EndOfFile
.QuadPart
;
1402 data
->dwReserved0
= 0;
1403 data
->dwReserved1
= 0;
1405 memcpy( data
->cFileName
, dir_info
->FileName
, dir_info
->FileNameLength
);
1406 data
->cFileName
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
1408 if (info
->level
!= FindExInfoBasic
)
1410 memcpy( data
->cAlternateFileName
, dir_info
->ShortName
, dir_info
->ShortNameLength
);
1411 data
->cAlternateFileName
[dir_info
->ShortNameLength
/sizeof(WCHAR
)] = 0;
1414 data
->cAlternateFileName
[0] = 0;
1416 TRACE( "returning %s (%s)\n",
1417 debugstr_w(data
->cFileName
), debugstr_w(data
->cAlternateFileName
) );
1423 RtlLeaveCriticalSection( &info
->cs
);
1428 /**************************************************************************
1429 * FindNextStreamW (kernelbase.@)
1431 BOOL WINAPI
FindNextStreamW( HANDLE handle
, void *data
)
1433 FIXME( "(%p, %p): stub!\n", handle
, data
);
1434 SetLastError( ERROR_HANDLE_EOF
);
1439 /******************************************************************************
1440 * FindClose (kernelbase.@)
1442 BOOL WINAPI DECLSPEC_HOTPATCH
FindClose( HANDLE handle
)
1444 FIND_FIRST_INFO
*info
= handle
;
1446 if (!handle
|| handle
== INVALID_HANDLE_VALUE
)
1448 SetLastError( ERROR_INVALID_HANDLE
);
1454 if (info
->magic
== FIND_FIRST_MAGIC
)
1456 RtlEnterCriticalSection( &info
->cs
);
1457 if (info
->magic
== FIND_FIRST_MAGIC
) /* in case someone else freed it in the meantime */
1460 if (info
->handle
) CloseHandle( info
->handle
);
1462 RtlFreeUnicodeString( &info
->path
);
1465 RtlLeaveCriticalSection( &info
->cs
);
1466 info
->cs
.DebugInfo
->Spare
[0] = 0;
1467 RtlDeleteCriticalSection( &info
->cs
);
1468 HeapFree( GetProcessHeap(), 0, info
);
1474 WARN( "illegal handle %p\n", handle
);
1475 SetLastError( ERROR_INVALID_HANDLE
);
1484 /******************************************************************************
1485 * GetCompressedFileSizeA (kernelbase.@)
1487 DWORD WINAPI DECLSPEC_HOTPATCH
GetCompressedFileSizeA( LPCSTR name
, LPDWORD size_high
)
1491 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return INVALID_FILE_SIZE
;
1492 return GetCompressedFileSizeW( nameW
, size_high
);
1496 /******************************************************************************
1497 * GetCompressedFileSizeW (kernelbase.@)
1499 DWORD WINAPI DECLSPEC_HOTPATCH
GetCompressedFileSizeW( LPCWSTR name
, LPDWORD size_high
)
1501 UNICODE_STRING nt_name
;
1502 OBJECT_ATTRIBUTES attr
;
1508 TRACE("%s %p\n", debugstr_w(name
), size_high
);
1510 if (!RtlDosPathNameToNtPathName_U( name
, &nt_name
, NULL
, NULL
))
1512 SetLastError( ERROR_PATH_NOT_FOUND
);
1513 return INVALID_FILE_SIZE
;
1516 attr
.Length
= sizeof(attr
);
1517 attr
.RootDirectory
= 0;
1518 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1519 attr
.ObjectName
= &nt_name
;
1520 attr
.SecurityDescriptor
= NULL
;
1521 attr
.SecurityQualityOfService
= NULL
;
1523 status
= NtOpenFile( &handle
, SYNCHRONIZE
, &attr
, &io
, 0, FILE_SYNCHRONOUS_IO_NONALERT
);
1524 RtlFreeUnicodeString( &nt_name
);
1525 if (!set_ntstatus( status
)) return INVALID_FILE_SIZE
;
1527 /* we don't support compressed files, simply return the file size */
1528 ret
= GetFileSize( handle
, size_high
);
1534 /***********************************************************************
1535 * GetCurrentDirectoryA (kernelbase.@)
1537 UINT WINAPI DECLSPEC_HOTPATCH
GetCurrentDirectoryA( UINT buflen
, LPSTR buf
)
1539 WCHAR bufferW
[MAX_PATH
];
1542 if (buflen
&& buf
&& ((ULONG_PTR
)buf
>> 16) == 0)
1544 /* Win9x catches access violations here, returning zero.
1545 * This behaviour resulted in some people not noticing
1546 * that they got the argument order wrong. So let's be
1547 * nice and fail gracefully if buf is invalid and looks
1548 * more like a buflen. */
1549 SetLastError( ERROR_INVALID_PARAMETER
);
1553 ret
= RtlGetCurrentDirectory_U( sizeof(bufferW
), bufferW
);
1555 if (ret
> sizeof(bufferW
))
1557 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1560 return copy_filename_WtoA( bufferW
, buf
, buflen
);
1564 /***********************************************************************
1565 * GetCurrentDirectoryW (kernelbase.@)
1567 UINT WINAPI DECLSPEC_HOTPATCH
GetCurrentDirectoryW( UINT buflen
, LPWSTR buf
)
1569 return RtlGetCurrentDirectory_U( buflen
* sizeof(WCHAR
), buf
) / sizeof(WCHAR
);
1573 /**************************************************************************
1574 * GetFileAttributesA (kernelbase.@)
1576 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileAttributesA( LPCSTR name
)
1580 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return INVALID_FILE_ATTRIBUTES
;
1581 return GetFileAttributesW( nameW
);
1585 /**************************************************************************
1586 * GetFileAttributesW (kernelbase.@)
1588 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileAttributesW( LPCWSTR name
)
1590 FILE_BASIC_INFORMATION info
;
1591 UNICODE_STRING nt_name
;
1592 OBJECT_ATTRIBUTES attr
;
1595 TRACE( "%s\n", debugstr_w(name
) );
1597 if (!RtlDosPathNameToNtPathName_U( name
, &nt_name
, NULL
, NULL
))
1599 SetLastError( ERROR_PATH_NOT_FOUND
);
1600 return INVALID_FILE_ATTRIBUTES
;
1603 attr
.Length
= sizeof(attr
);
1604 attr
.RootDirectory
= 0;
1605 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1606 attr
.ObjectName
= &nt_name
;
1607 attr
.SecurityDescriptor
= NULL
;
1608 attr
.SecurityQualityOfService
= NULL
;
1610 status
= NtQueryAttributesFile( &attr
, &info
);
1611 RtlFreeUnicodeString( &nt_name
);
1613 if (status
== STATUS_SUCCESS
) return info
.FileAttributes
;
1615 /* NtQueryAttributesFile fails on devices, but GetFileAttributesW succeeds */
1616 if (RtlIsDosDeviceName_U( name
)) return FILE_ATTRIBUTE_ARCHIVE
;
1618 SetLastError( RtlNtStatusToDosError(status
) );
1619 return INVALID_FILE_ATTRIBUTES
;
1623 /**************************************************************************
1624 * GetFileAttributesExA (kernelbase.@)
1626 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileAttributesExA( LPCSTR name
, GET_FILEEX_INFO_LEVELS level
, void *ptr
)
1630 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return FALSE
;
1631 return GetFileAttributesExW( nameW
, level
, ptr
);
1635 /**************************************************************************
1636 * GetFileAttributesExW (kernelbase.@)
1638 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileAttributesExW( LPCWSTR name
, GET_FILEEX_INFO_LEVELS level
, void *ptr
)
1640 FILE_NETWORK_OPEN_INFORMATION info
;
1641 WIN32_FILE_ATTRIBUTE_DATA
*data
= ptr
;
1642 UNICODE_STRING nt_name
;
1643 OBJECT_ATTRIBUTES attr
;
1646 TRACE("%s %d %p\n", debugstr_w(name
), level
, ptr
);
1648 if (level
!= GetFileExInfoStandard
)
1650 SetLastError( ERROR_INVALID_PARAMETER
);
1654 if (!RtlDosPathNameToNtPathName_U( name
, &nt_name
, NULL
, NULL
))
1656 SetLastError( ERROR_PATH_NOT_FOUND
);
1660 attr
.Length
= sizeof(attr
);
1661 attr
.RootDirectory
= 0;
1662 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1663 attr
.ObjectName
= &nt_name
;
1664 attr
.SecurityDescriptor
= NULL
;
1665 attr
.SecurityQualityOfService
= NULL
;
1667 status
= NtQueryFullAttributesFile( &attr
, &info
);
1668 RtlFreeUnicodeString( &nt_name
);
1669 if (!set_ntstatus( status
)) return FALSE
;
1671 data
->dwFileAttributes
= info
.FileAttributes
;
1672 data
->ftCreationTime
.dwLowDateTime
= info
.CreationTime
.u
.LowPart
;
1673 data
->ftCreationTime
.dwHighDateTime
= info
.CreationTime
.u
.HighPart
;
1674 data
->ftLastAccessTime
.dwLowDateTime
= info
.LastAccessTime
.u
.LowPart
;
1675 data
->ftLastAccessTime
.dwHighDateTime
= info
.LastAccessTime
.u
.HighPart
;
1676 data
->ftLastWriteTime
.dwLowDateTime
= info
.LastWriteTime
.u
.LowPart
;
1677 data
->ftLastWriteTime
.dwHighDateTime
= info
.LastWriteTime
.u
.HighPart
;
1678 data
->nFileSizeLow
= info
.EndOfFile
.u
.LowPart
;
1679 data
->nFileSizeHigh
= info
.EndOfFile
.u
.HighPart
;
1684 /***********************************************************************
1685 * GetFinalPathNameByHandleA (kernelbase.@)
1687 DWORD WINAPI DECLSPEC_HOTPATCH
GetFinalPathNameByHandleA( HANDLE file
, LPSTR path
,
1688 DWORD count
, DWORD flags
)
1693 TRACE( "(%p,%p,%ld,%lx)\n", file
, path
, count
, flags
);
1695 len
= GetFinalPathNameByHandleW(file
, NULL
, 0, flags
);
1696 if (len
== 0) return 0;
1698 str
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1701 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1705 result
= GetFinalPathNameByHandleW(file
, str
, len
, flags
);
1706 if (result
!= len
- 1)
1708 HeapFree(GetProcessHeap(), 0, str
);
1712 len
= file_name_WtoA( str
, -1, NULL
, 0 );
1715 HeapFree(GetProcessHeap(), 0, str
);
1718 file_name_WtoA( str
, -1, path
, count
);
1719 HeapFree(GetProcessHeap(), 0, str
);
1724 /***********************************************************************
1725 * GetFinalPathNameByHandleW (kernelbase.@)
1727 DWORD WINAPI DECLSPEC_HOTPATCH
GetFinalPathNameByHandleW( HANDLE file
, LPWSTR path
,
1728 DWORD count
, DWORD flags
)
1730 WCHAR buffer
[sizeof(OBJECT_NAME_INFORMATION
) + MAX_PATH
+ 1];
1731 OBJECT_NAME_INFORMATION
*info
= (OBJECT_NAME_INFORMATION
*)&buffer
;
1732 WCHAR drive_part
[MAX_PATH
];
1733 DWORD drive_part_len
= 0;
1739 TRACE( "(%p,%p,%ld,%lx)\n", file
, path
, count
, flags
);
1741 if (flags
& ~(FILE_NAME_OPENED
| VOLUME_NAME_GUID
| VOLUME_NAME_NONE
| VOLUME_NAME_NT
))
1743 WARN("Unknown flags: %lx\n", flags
);
1744 SetLastError( ERROR_INVALID_PARAMETER
);
1748 /* get object name */
1749 status
= NtQueryObject( file
, ObjectNameInformation
, &buffer
, sizeof(buffer
) - sizeof(WCHAR
), &dummy
);
1750 if (!set_ntstatus( status
)) return 0;
1752 if (!info
->Name
.Buffer
)
1754 SetLastError( ERROR_INVALID_HANDLE
);
1757 if (info
->Name
.Length
< 4 * sizeof(WCHAR
) || info
->Name
.Buffer
[0] != '\\' ||
1758 info
->Name
.Buffer
[1] != '?' || info
->Name
.Buffer
[2] != '?' || info
->Name
.Buffer
[3] != '\\' )
1760 FIXME("Unexpected object name: %s\n", debugstr_wn(info
->Name
.Buffer
, info
->Name
.Length
/ sizeof(WCHAR
)));
1761 SetLastError( ERROR_GEN_FAILURE
);
1765 /* add terminating null character, remove "\\??\\" */
1766 info
->Name
.Buffer
[info
->Name
.Length
/ sizeof(WCHAR
)] = 0;
1767 info
->Name
.Length
-= 4 * sizeof(WCHAR
);
1768 info
->Name
.Buffer
+= 4;
1770 /* FILE_NAME_OPENED is not supported yet, and would require Wineserver changes */
1771 if (flags
& FILE_NAME_OPENED
)
1773 FIXME("FILE_NAME_OPENED not supported\n");
1774 flags
&= ~FILE_NAME_OPENED
;
1777 /* Get information required for VOLUME_NAME_NONE, VOLUME_NAME_GUID and VOLUME_NAME_NT */
1778 if (flags
== VOLUME_NAME_NONE
|| flags
== VOLUME_NAME_GUID
|| flags
== VOLUME_NAME_NT
)
1780 if (!GetVolumePathNameW( info
->Name
.Buffer
, drive_part
, MAX_PATH
)) return 0;
1781 drive_part_len
= lstrlenW(drive_part
);
1782 if (!drive_part_len
|| drive_part_len
> lstrlenW(info
->Name
.Buffer
) ||
1783 drive_part
[drive_part_len
-1] != '\\' ||
1784 CompareStringOrdinal( info
->Name
.Buffer
, drive_part_len
, drive_part
, drive_part_len
, TRUE
) != CSTR_EQUAL
)
1786 FIXME( "Path %s returned by GetVolumePathNameW does not match file path %s\n",
1787 debugstr_w(drive_part
), debugstr_w(info
->Name
.Buffer
) );
1788 SetLastError( ERROR_GEN_FAILURE
);
1793 if (flags
== VOLUME_NAME_NONE
)
1795 ptr
= info
->Name
.Buffer
+ drive_part_len
- 1;
1796 result
= lstrlenW(ptr
);
1797 if (result
< count
) memcpy(path
, ptr
, (result
+ 1) * sizeof(WCHAR
));
1800 else if (flags
== VOLUME_NAME_GUID
)
1802 WCHAR volume_prefix
[51];
1804 /* GetVolumeNameForVolumeMountPointW sets error code on failure */
1805 if (!GetVolumeNameForVolumeMountPointW( drive_part
, volume_prefix
, 50 )) return 0;
1806 ptr
= info
->Name
.Buffer
+ drive_part_len
;
1807 result
= lstrlenW(volume_prefix
) + lstrlenW(ptr
);
1810 lstrcpyW(path
, volume_prefix
);
1811 lstrcatW(path
, ptr
);
1815 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1819 else if (flags
== VOLUME_NAME_NT
)
1821 WCHAR nt_prefix
[MAX_PATH
];
1823 /* QueryDosDeviceW sets error code on failure */
1824 drive_part
[drive_part_len
- 1] = 0;
1825 if (!QueryDosDeviceW( drive_part
, nt_prefix
, MAX_PATH
)) return 0;
1826 ptr
= info
->Name
.Buffer
+ drive_part_len
- 1;
1827 result
= lstrlenW(nt_prefix
) + lstrlenW(ptr
);
1830 lstrcpyW(path
, nt_prefix
);
1831 lstrcatW(path
, ptr
);
1835 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1839 else if (flags
== VOLUME_NAME_DOS
)
1841 result
= 4 + lstrlenW(info
->Name
.Buffer
);
1844 lstrcpyW(path
, L
"\\\\?\\");
1845 lstrcatW(path
, info
->Name
.Buffer
);
1849 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1855 /* Windows crashes here, but we prefer returning ERROR_INVALID_PARAMETER */
1856 WARN("Invalid combination of flags: %lx\n", flags
);
1857 SetLastError( ERROR_INVALID_PARAMETER
);
1863 /***********************************************************************
1864 * GetFullPathNameA (kernelbase.@)
1866 DWORD WINAPI DECLSPEC_HOTPATCH
GetFullPathNameA( LPCSTR name
, DWORD len
, LPSTR buffer
, LPSTR
*lastpart
)
1869 WCHAR bufferW
[MAX_PATH
], *lastpartW
= NULL
;
1872 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return 0;
1874 ret
= GetFullPathNameW( nameW
, MAX_PATH
, bufferW
, &lastpartW
);
1879 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1882 ret
= copy_filename_WtoA( bufferW
, buffer
, len
);
1883 if (ret
< len
&& lastpart
)
1886 *lastpart
= buffer
+ file_name_WtoA( bufferW
, lastpartW
- bufferW
, NULL
, 0 );
1894 /***********************************************************************
1895 * GetFullPathNameW (kernelbase.@)
1897 DWORD WINAPI DECLSPEC_HOTPATCH
GetFullPathNameW( LPCWSTR name
, DWORD len
, LPWSTR buffer
, LPWSTR
*lastpart
)
1899 return RtlGetFullPathName_U( name
, len
* sizeof(WCHAR
), buffer
, lastpart
) / sizeof(WCHAR
);
1903 /***********************************************************************
1904 * GetLongPathNameA (kernelbase.@)
1906 DWORD WINAPI DECLSPEC_HOTPATCH
GetLongPathNameA( LPCSTR shortpath
, LPSTR longpath
, DWORD longlen
)
1909 WCHAR longpathW
[MAX_PATH
];
1912 TRACE( "%s\n", debugstr_a( shortpath
));
1914 if (!(shortpathW
= file_name_AtoW( shortpath
, FALSE
))) return 0;
1916 ret
= GetLongPathNameW( shortpathW
, longpathW
, MAX_PATH
);
1921 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1924 return copy_filename_WtoA( longpathW
, longpath
, longlen
);
1928 /***********************************************************************
1929 * GetLongPathNameW (kernelbase.@)
1931 DWORD WINAPI DECLSPEC_HOTPATCH
GetLongPathNameW( LPCWSTR shortpath
, LPWSTR longpath
, DWORD longlen
)
1933 WCHAR tmplongpath
[1024];
1934 DWORD sp
= 0, lp
= 0, tmplen
;
1935 WIN32_FIND_DATAW wfd
;
1936 UNICODE_STRING nameW
;
1940 TRACE("%s,%p,%lu\n", debugstr_w(shortpath
), longpath
, longlen
);
1944 SetLastError( ERROR_INVALID_PARAMETER
);
1949 SetLastError( ERROR_PATH_NOT_FOUND
);
1953 if (shortpath
[0] == '\\' && shortpath
[1] == '\\')
1955 FIXME( "UNC pathname %s\n", debugstr_w(shortpath
) );
1956 tmplen
= lstrlenW( shortpath
);
1957 if (tmplen
< longlen
)
1959 if (longpath
!= shortpath
) lstrcpyW( longpath
, shortpath
);
1965 /* check for drive letter */
1966 if (shortpath
[0] != '/' && shortpath
[1] == ':' )
1968 tmplongpath
[0] = shortpath
[0];
1969 tmplongpath
[1] = ':';
1973 if (wcspbrk( shortpath
+ sp
, L
"*?" ))
1975 SetLastError( ERROR_INVALID_NAME
);
1979 while (shortpath
[sp
])
1981 /* check for path delimiters and reproduce them */
1982 if (shortpath
[sp
] == '\\' || shortpath
[sp
] == '/')
1984 tmplongpath
[lp
++] = shortpath
[sp
++];
1985 tmplongpath
[lp
] = 0; /* terminate string */
1989 for (p
= shortpath
+ sp
; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
1990 tmplen
= p
- (shortpath
+ sp
);
1991 lstrcpynW( tmplongpath
+ lp
, shortpath
+ sp
, tmplen
+ 1 );
1993 if (tmplongpath
[lp
] == '.')
1995 if (tmplen
== 1 || (tmplen
== 2 && tmplongpath
[lp
+ 1] == '.'))
2003 /* Check if the file exists */
2004 handle
= FindFirstFileW( tmplongpath
, &wfd
);
2005 if (handle
== INVALID_HANDLE_VALUE
)
2007 TRACE( "not found %s\n", debugstr_w( tmplongpath
));
2008 SetLastError ( ERROR_FILE_NOT_FOUND
);
2011 FindClose( handle
);
2013 /* Use the existing file name if it's a short name */
2014 RtlInitUnicodeString( &nameW
, tmplongpath
+ lp
);
2015 if (RtlIsNameLegalDOS8Dot3( &nameW
, NULL
, NULL
)) lstrcpyW( tmplongpath
+ lp
, wfd
.cFileName
);
2016 lp
+= lstrlenW( tmplongpath
+ lp
);
2019 tmplen
= lstrlenW( shortpath
) - 1;
2020 if ((shortpath
[tmplen
] == '/' || shortpath
[tmplen
] == '\\') &&
2021 (tmplongpath
[lp
- 1] != '/' && tmplongpath
[lp
- 1] != '\\'))
2022 tmplongpath
[lp
++] = shortpath
[tmplen
];
2023 tmplongpath
[lp
] = 0;
2025 tmplen
= lstrlenW( tmplongpath
) + 1;
2026 if (tmplen
<= longlen
)
2028 lstrcpyW( longpath
, tmplongpath
);
2029 TRACE("returning %s\n", debugstr_w( longpath
));
2030 tmplen
--; /* length without 0 */
2036 /***********************************************************************
2037 * GetShortPathNameW (kernelbase.@)
2039 DWORD WINAPI DECLSPEC_HOTPATCH
GetShortPathNameW( LPCWSTR longpath
, LPWSTR shortpath
, DWORD shortlen
)
2041 WIN32_FIND_DATAW wfd
;
2042 WCHAR
*tmpshortpath
;
2045 DWORD sp
= 0, lp
= 0, tmplen
, buf_len
;
2047 TRACE( "%s,%p,%lu\n", debugstr_w(longpath
), shortpath
, shortlen
);
2051 SetLastError( ERROR_INVALID_PARAMETER
);
2056 SetLastError( ERROR_BAD_PATHNAME
);
2060 /* code below only removes characters from string, never adds, so this is
2061 * the largest buffer that tmpshortpath will need to have */
2062 buf_len
= lstrlenW(longpath
) + 1;
2063 tmpshortpath
= HeapAlloc( GetProcessHeap(), 0, buf_len
* sizeof(WCHAR
) );
2066 SetLastError( ERROR_OUTOFMEMORY
);
2070 if (longpath
[0] == '\\' && longpath
[1] == '\\' && longpath
[2] == '?' && longpath
[3] == '\\')
2072 memcpy( tmpshortpath
, longpath
, 4 * sizeof(WCHAR
) );
2076 if (wcspbrk( longpath
+ lp
, L
"*?" ))
2078 HeapFree( GetProcessHeap(), 0, tmpshortpath
);
2079 SetLastError( ERROR_INVALID_NAME
);
2083 /* check for drive letter */
2084 if (longpath
[lp
] != '/' && longpath
[lp
+ 1] == ':' )
2086 tmpshortpath
[sp
] = longpath
[lp
];
2087 tmpshortpath
[sp
+ 1] = ':';
2092 while (longpath
[lp
])
2094 /* check for path delimiters and reproduce them */
2095 if (longpath
[lp
] == '\\' || longpath
[lp
] == '/')
2097 tmpshortpath
[sp
++] = longpath
[lp
++];
2098 tmpshortpath
[sp
] = 0; /* terminate string */
2103 for (; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
2104 tmplen
= p
- (longpath
+ lp
);
2105 lstrcpynW( tmpshortpath
+ sp
, longpath
+ lp
, tmplen
+ 1 );
2107 if (tmpshortpath
[sp
] == '.')
2109 if (tmplen
== 1 || (tmplen
== 2 && tmpshortpath
[sp
+ 1] == '.'))
2117 /* Check if the file exists and use the existing short file name */
2118 handle
= FindFirstFileW( tmpshortpath
, &wfd
);
2119 if (handle
== INVALID_HANDLE_VALUE
) goto notfound
;
2120 FindClose( handle
);
2122 /* In rare cases (like "a.abcd") short path may be longer than original path.
2123 * Make sure we have enough space in temp buffer. */
2124 if (wfd
.cAlternateFileName
[0] && tmplen
< lstrlenW(wfd
.cAlternateFileName
))
2127 buf_len
+= lstrlenW( wfd
.cAlternateFileName
) - tmplen
;
2128 new_buf
= HeapReAlloc( GetProcessHeap(), 0, tmpshortpath
, buf_len
* sizeof(WCHAR
) );
2131 HeapFree( GetProcessHeap(), 0, tmpshortpath
);
2132 SetLastError( ERROR_OUTOFMEMORY
);
2135 tmpshortpath
= new_buf
;
2138 lstrcpyW( tmpshortpath
+ sp
, wfd
.cAlternateFileName
[0] ? wfd
.cAlternateFileName
: wfd
.cFileName
);
2139 sp
+= lstrlenW( tmpshortpath
+ sp
);
2142 tmpshortpath
[sp
] = 0;
2144 tmplen
= lstrlenW( tmpshortpath
) + 1;
2145 if (tmplen
<= shortlen
)
2147 lstrcpyW( shortpath
, tmpshortpath
);
2148 TRACE( "returning %s\n", debugstr_w( shortpath
));
2149 tmplen
--; /* length without 0 */
2152 HeapFree( GetProcessHeap(), 0, tmpshortpath
);
2156 HeapFree( GetProcessHeap(), 0, tmpshortpath
);
2157 TRACE( "not found\n" );
2158 SetLastError( ERROR_FILE_NOT_FOUND
);
2163 /***********************************************************************
2164 * GetSystemDirectoryA (kernelbase.@)
2166 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemDirectoryA( LPSTR path
, UINT count
)
2168 return copy_filename_WtoA( system_dir
, path
, count
);
2172 /***********************************************************************
2173 * GetSystemDirectoryW (kernelbase.@)
2175 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemDirectoryW( LPWSTR path
, UINT count
)
2177 return copy_filename( system_dir
, path
, count
);
2181 /***********************************************************************
2182 * GetSystemWindowsDirectoryA (kernelbase.@)
2184 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemWindowsDirectoryA( LPSTR path
, UINT count
)
2186 return GetWindowsDirectoryA( path
, count
);
2190 /***********************************************************************
2191 * GetSystemWindowsDirectoryW (kernelbase.@)
2193 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemWindowsDirectoryW( LPWSTR path
, UINT count
)
2195 return GetWindowsDirectoryW( path
, count
);
2199 /***********************************************************************
2200 * GetSystemWow64DirectoryA (kernelbase.@)
2202 UINT WINAPI
/* DECLSPEC_HOTPATCH */ GetSystemWow64DirectoryA( LPSTR path
, UINT count
)
2204 if (!is_win64
&& !is_wow64
)
2206 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
2209 return copy_filename_WtoA( get_machine_wow64_dir( IMAGE_FILE_MACHINE_I386
), path
, count
);
2213 /***********************************************************************
2214 * GetSystemWow64DirectoryW (kernelbase.@)
2216 UINT WINAPI
/* DECLSPEC_HOTPATCH */ GetSystemWow64DirectoryW( LPWSTR path
, UINT count
)
2218 if (!is_win64
&& !is_wow64
)
2220 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
2223 return copy_filename( get_machine_wow64_dir( IMAGE_FILE_MACHINE_I386
), path
, count
);
2227 /***********************************************************************
2228 * GetSystemWow64Directory2A (kernelbase.@)
2230 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemWow64Directory2A( LPSTR path
, UINT count
, WORD machine
)
2232 const WCHAR
*dir
= get_machine_wow64_dir( machine
);
2234 return dir
? copy_filename_WtoA( dir
, path
, count
) : 0;
2238 /***********************************************************************
2239 * GetSystemWow64Directory2W (kernelbase.@)
2241 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemWow64Directory2W( LPWSTR path
, UINT count
, WORD machine
)
2243 const WCHAR
*dir
= get_machine_wow64_dir( machine
);
2245 return dir
? copy_filename( dir
, path
, count
) : 0;
2249 /***********************************************************************
2250 * GetTempFileNameA (kernelbase.@)
2252 UINT WINAPI DECLSPEC_HOTPATCH
GetTempFileNameA( LPCSTR path
, LPCSTR prefix
, UINT unique
, LPSTR buffer
)
2254 WCHAR
*pathW
, *prefixW
= NULL
;
2255 WCHAR bufferW
[MAX_PATH
];
2258 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return 0;
2259 if (prefix
&& !(prefixW
= file_name_AtoW( prefix
, TRUE
))) return 0;
2261 ret
= GetTempFileNameW( pathW
, prefixW
, unique
, bufferW
);
2262 if (ret
) file_name_WtoA( bufferW
, -1, buffer
, MAX_PATH
);
2264 HeapFree( GetProcessHeap(), 0, prefixW
);
2269 /***********************************************************************
2270 * GetTempFileNameW (kernelbase.@)
2272 UINT WINAPI DECLSPEC_HOTPATCH
GetTempFileNameW( LPCWSTR path
, LPCWSTR prefix
, UINT unique
, LPWSTR buffer
)
2278 if (!path
|| !buffer
)
2280 SetLastError( ERROR_INVALID_PARAMETER
);
2284 /* ensure that the provided directory exists */
2285 attr
= GetFileAttributesW( path
);
2286 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
2288 TRACE( "path not found %s\n", debugstr_w( path
));
2289 SetLastError( ERROR_DIRECTORY
);
2293 lstrcpyW( buffer
, path
);
2294 p
= buffer
+ lstrlenW(buffer
);
2296 /* add a \, if there isn't one */
2297 if ((p
== buffer
) || (p
[-1] != '\\')) *p
++ = '\\';
2299 if (prefix
) for (i
= 3; (i
> 0) && (*prefix
); i
--) *p
++ = *prefix
++;
2302 if (unique
) swprintf( p
, MAX_PATH
- (p
- buffer
), L
"%x.tmp", unique
);
2305 /* get a "random" unique number and try to create the file */
2307 UINT num
= NtGetTickCount() & 0xffff;
2310 /* avoid using the same name twice in a short interval */
2311 if (last
- num
< 10) num
= last
+ 1;
2316 swprintf( p
, MAX_PATH
- (p
- buffer
), L
"%x.tmp", unique
);
2317 handle
= CreateFileW( buffer
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
2318 if (handle
!= INVALID_HANDLE_VALUE
)
2319 { /* We created it */
2320 CloseHandle( handle
);
2324 if (GetLastError() != ERROR_FILE_EXISTS
&& GetLastError() != ERROR_SHARING_VIOLATION
)
2325 break; /* No need to go on */
2326 if (!(++unique
& 0xffff)) unique
= 1;
2327 } while (unique
!= num
);
2329 TRACE( "returning %s\n", debugstr_w( buffer
));
2334 /***********************************************************************
2335 * GetTempPathA (kernelbase.@)
2337 DWORD WINAPI DECLSPEC_HOTPATCH
GetTempPathA( DWORD count
, LPSTR path
)
2339 WCHAR pathW
[MAX_PATH
];
2342 if (!(ret
= GetTempPathW( MAX_PATH
, pathW
))) return 0;
2345 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
2348 return copy_filename_WtoA( pathW
, path
, count
);
2352 /***********************************************************************
2353 * GetTempPathW (kernelbase.@)
2355 DWORD WINAPI DECLSPEC_HOTPATCH
GetTempPathW( DWORD count
, LPWSTR path
)
2357 WCHAR tmp_path
[MAX_PATH
];
2360 if (!(ret
= GetEnvironmentVariableW( L
"TMP", tmp_path
, MAX_PATH
)) &&
2361 !(ret
= GetEnvironmentVariableW( L
"TEMP", tmp_path
, MAX_PATH
)) &&
2362 !(ret
= GetEnvironmentVariableW( L
"USERPROFILE", tmp_path
, MAX_PATH
)) &&
2363 !(ret
= GetWindowsDirectoryW( tmp_path
, MAX_PATH
)))
2368 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
2371 ret
= GetFullPathNameW( tmp_path
, MAX_PATH
, tmp_path
, NULL
);
2374 if (ret
> MAX_PATH
- 2)
2376 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
2379 if (tmp_path
[ret
-1] != '\\')
2381 tmp_path
[ret
++] = '\\';
2382 tmp_path
[ret
] = '\0';
2385 ret
++; /* add space for terminating 0 */
2388 lstrcpynW( path
, tmp_path
, count
);
2389 /* the remaining buffer must be zeroed up to 32766 bytes in XP or 32767
2390 * bytes after it, we will assume the > XP behavior for now */
2391 memset( path
+ ret
, 0, (min(count
, 32767) - ret
) * sizeof(WCHAR
) );
2392 ret
--; /* return length without 0 */
2396 /* the buffer must be cleared if contents will not fit */
2397 memset( path
, 0, count
* sizeof(WCHAR
) );
2400 TRACE( "returning %u, %s\n", ret
, debugstr_w( path
));
2405 /***********************************************************************
2406 * GetWindowsDirectoryA (kernelbase.@)
2408 UINT WINAPI DECLSPEC_HOTPATCH
GetWindowsDirectoryA( LPSTR path
, UINT count
)
2410 return copy_filename_WtoA( windows_dir
, path
, count
);
2414 /***********************************************************************
2415 * GetWindowsDirectoryW (kernelbase.@)
2417 UINT WINAPI DECLSPEC_HOTPATCH
GetWindowsDirectoryW( LPWSTR path
, UINT count
)
2419 return copy_filename( windows_dir
, path
, count
);
2423 /**************************************************************************
2424 * MoveFileExW (kernelbase.@)
2426 BOOL WINAPI
MoveFileExW( const WCHAR
*source
, const WCHAR
*dest
, DWORD flag
)
2428 return MoveFileWithProgressW( source
, dest
, NULL
, NULL
, flag
);
2432 /**************************************************************************
2433 * MoveFileWithProgressW (kernelbase.@)
2435 BOOL WINAPI DECLSPEC_HOTPATCH
MoveFileWithProgressW( const WCHAR
*source
, const WCHAR
*dest
,
2436 LPPROGRESS_ROUTINE progress
,
2437 void *param
, DWORD flag
)
2439 FILE_RENAME_INFORMATION
*rename_info
;
2440 FILE_BASIC_INFORMATION info
;
2441 UNICODE_STRING nt_name
;
2442 OBJECT_ATTRIBUTES attr
;
2445 HANDLE source_handle
= 0;
2448 TRACE( "(%s,%s,%p,%p,%04lx)\n", debugstr_w(source
), debugstr_w(dest
), progress
, param
, flag
);
2450 if (flag
& MOVEFILE_DELAY_UNTIL_REBOOT
) return add_boot_rename_entry( source
, dest
, flag
);
2452 if (!dest
) return DeleteFileW( source
);
2454 /* check if we are allowed to rename the source */
2456 if (!RtlDosPathNameToNtPathName_U( source
, &nt_name
, NULL
, NULL
))
2458 SetLastError( ERROR_PATH_NOT_FOUND
);
2461 attr
.Length
= sizeof(attr
);
2462 attr
.RootDirectory
= 0;
2463 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2464 attr
.ObjectName
= &nt_name
;
2465 attr
.SecurityDescriptor
= NULL
;
2466 attr
.SecurityQualityOfService
= NULL
;
2468 status
= NtOpenFile( &source_handle
, DELETE
| SYNCHRONIZE
, &attr
, &io
,
2469 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
2470 FILE_SYNCHRONOUS_IO_NONALERT
);
2471 RtlFreeUnicodeString( &nt_name
);
2472 if (!set_ntstatus( status
)) goto error
;
2474 status
= NtQueryInformationFile( source_handle
, &io
, &info
, sizeof(info
), FileBasicInformation
);
2475 if (!set_ntstatus( status
)) goto error
;
2477 if (!RtlDosPathNameToNtPathName_U( dest
, &nt_name
, NULL
, NULL
))
2479 SetLastError( ERROR_PATH_NOT_FOUND
);
2483 size
= offsetof( FILE_RENAME_INFORMATION
, FileName
) + nt_name
.Length
;
2484 if (!(rename_info
= HeapAlloc( GetProcessHeap(), 0, size
))) goto error
;
2486 rename_info
->ReplaceIfExists
= !!(flag
& MOVEFILE_REPLACE_EXISTING
);
2487 rename_info
->RootDirectory
= NULL
;
2488 rename_info
->FileNameLength
= nt_name
.Length
;
2489 memcpy( rename_info
->FileName
, nt_name
.Buffer
, nt_name
.Length
);
2490 RtlFreeUnicodeString( &nt_name
);
2491 status
= NtSetInformationFile( source_handle
, &io
, rename_info
, size
, FileRenameInformation
);
2492 HeapFree( GetProcessHeap(), 0, rename_info
);
2493 if (status
== STATUS_NOT_SAME_DEVICE
&& (flag
& MOVEFILE_COPY_ALLOWED
))
2495 NtClose( source_handle
);
2496 if (!CopyFileExW( source
, dest
, progress
, param
, NULL
,
2497 flag
& MOVEFILE_REPLACE_EXISTING
? 0 : COPY_FILE_FAIL_IF_EXISTS
))
2499 return DeleteFileW( source
);
2502 NtClose( source_handle
);
2503 return set_ntstatus( status
);
2506 if (source_handle
) NtClose( source_handle
);
2511 /***********************************************************************
2512 * NeedCurrentDirectoryForExePathA (kernelbase.@)
2514 BOOL WINAPI DECLSPEC_HOTPATCH
NeedCurrentDirectoryForExePathA( LPCSTR name
)
2518 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return TRUE
;
2519 return NeedCurrentDirectoryForExePathW( nameW
);
2523 /***********************************************************************
2524 * NeedCurrentDirectoryForExePathW (kernelbase.@)
2526 BOOL WINAPI DECLSPEC_HOTPATCH
NeedCurrentDirectoryForExePathW( LPCWSTR name
)
2530 if (wcschr( name
, '\\' )) return TRUE
;
2531 /* check the existence of the variable, not value */
2532 return !GetEnvironmentVariableW( L
"NoDefaultCurrentDirectoryInExePath", &env_val
, 1 );
2536 /***********************************************************************
2537 * ReplaceFileW (kernelbase.@)
2539 BOOL WINAPI DECLSPEC_HOTPATCH
ReplaceFileW( const WCHAR
*replaced
, const WCHAR
*replacement
,
2540 const WCHAR
*backup
, DWORD flags
,
2541 void *exclude
, void *reserved
)
2543 UNICODE_STRING nt_replaced_name
, nt_replacement_name
;
2544 HANDLE hReplacement
= NULL
;
2547 OBJECT_ATTRIBUTES attr
;
2548 FILE_BASIC_INFORMATION info
;
2550 TRACE( "%s %s %s 0x%08lx %p %p\n", debugstr_w(replaced
), debugstr_w(replacement
), debugstr_w(backup
),
2551 flags
, exclude
, reserved
);
2553 if (flags
) FIXME("Ignoring flags %lx\n", flags
);
2555 /* First two arguments are mandatory */
2556 if (!replaced
|| !replacement
)
2558 SetLastError(ERROR_INVALID_PARAMETER
);
2562 attr
.Length
= sizeof(attr
);
2563 attr
.RootDirectory
= 0;
2564 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2565 attr
.ObjectName
= NULL
;
2566 attr
.SecurityDescriptor
= NULL
;
2567 attr
.SecurityQualityOfService
= NULL
;
2569 /* Open the "replaced" file for reading */
2570 if (!RtlDosPathNameToNtPathName_U( replaced
, &nt_replaced_name
, NULL
, NULL
))
2572 SetLastError( ERROR_PATH_NOT_FOUND
);
2575 attr
.ObjectName
= &nt_replaced_name
;
2577 /* Replacement should fail if replaced is READ_ONLY */
2578 status
= NtQueryAttributesFile(&attr
, &info
);
2579 RtlFreeUnicodeString(&nt_replaced_name
);
2580 if (!set_ntstatus( status
)) return FALSE
;
2582 if (info
.FileAttributes
& FILE_ATTRIBUTE_READONLY
)
2584 SetLastError( ERROR_ACCESS_DENIED
);
2589 * Open the replacement file for reading, writing, and deleting
2590 * (writing and deleting are needed when finished)
2592 if (!RtlDosPathNameToNtPathName_U( replacement
, &nt_replacement_name
, NULL
, NULL
))
2594 SetLastError( ERROR_PATH_NOT_FOUND
);
2597 attr
.ObjectName
= &nt_replacement_name
;
2598 status
= NtOpenFile( &hReplacement
, GENERIC_READ
| GENERIC_WRITE
| DELETE
| WRITE_DAC
| SYNCHRONIZE
,
2599 &attr
, &io
, 0, FILE_SYNCHRONOUS_IO_NONALERT
| FILE_NON_DIRECTORY_FILE
);
2600 RtlFreeUnicodeString(&nt_replacement_name
);
2601 if (!set_ntstatus( status
)) return FALSE
;
2602 NtClose( hReplacement
);
2604 /* If the user wants a backup then that needs to be performed first */
2607 if (!MoveFileExW( replaced
, backup
, MOVEFILE_REPLACE_EXISTING
)) return FALSE
;
2611 /* ReplaceFile() can replace an open target. To do this, we need to move
2612 * it out of the way first. */
2613 WCHAR temp_path
[MAX_PATH
], temp_file
[MAX_PATH
];
2615 lstrcpynW( temp_path
, replaced
, ARRAY_SIZE( temp_path
) );
2616 PathRemoveFileSpecW( temp_path
);
2617 if (!GetTempFileNameW( temp_path
, L
"rf", 0, temp_file
) ||
2618 !MoveFileExW( replaced
, temp_file
, MOVEFILE_REPLACE_EXISTING
))
2621 DeleteFileW( temp_file
);
2625 * Now that the backup has been performed (if requested), copy the replacement
2628 if (!MoveFileExW( replacement
, replaced
, 0 ))
2630 /* on failure we need to indicate whether a backup was made */
2632 SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT
);
2634 SetLastError( ERROR_UNABLE_TO_MOVE_REPLACEMENT_2
);
2641 /***********************************************************************
2642 * SearchPathA (kernelbase.@)
2644 DWORD WINAPI DECLSPEC_HOTPATCH
SearchPathA( LPCSTR path
, LPCSTR name
, LPCSTR ext
,
2645 DWORD buflen
, LPSTR buffer
, LPSTR
*lastpart
)
2647 WCHAR
*pathW
= NULL
, *nameW
, *extW
= NULL
;
2648 WCHAR bufferW
[MAX_PATH
];
2653 SetLastError( ERROR_INVALID_PARAMETER
);
2657 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return 0;
2658 if (path
&& !(pathW
= file_name_AtoW( path
, TRUE
))) return 0;
2659 if (ext
&& !(extW
= file_name_AtoW( ext
, TRUE
)))
2661 RtlFreeHeap( GetProcessHeap(), 0, pathW
);
2665 ret
= SearchPathW( pathW
, nameW
, extW
, MAX_PATH
, bufferW
, NULL
);
2667 RtlFreeHeap( GetProcessHeap(), 0, pathW
);
2668 RtlFreeHeap( GetProcessHeap(), 0, extW
);
2673 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
2676 ret
= copy_filename_WtoA( bufferW
, buffer
, buflen
);
2677 if (buflen
> ret
&& lastpart
) *lastpart
= strrchr(buffer
, '\\') + 1;
2682 /***********************************************************************
2683 * SearchPathW (kernelbase.@)
2685 DWORD WINAPI DECLSPEC_HOTPATCH
SearchPathW( LPCWSTR path
, LPCWSTR name
, LPCWSTR ext
, DWORD buflen
,
2686 LPWSTR buffer
, LPWSTR
*lastpart
)
2691 if (!name
|| !name
[0])
2693 SetLastError( ERROR_INVALID_PARAMETER
);
2697 /* If the name contains an explicit path, ignore the path */
2699 if (contains_path( name
))
2701 /* try first without extension */
2702 if (RtlDoesFileExists_U( name
)) return GetFullPathNameW( name
, buflen
, buffer
, lastpart
);
2704 if ((name_ext
= append_ext( name
, ext
)))
2706 if (RtlDoesFileExists_U( name_ext
))
2707 ret
= GetFullPathNameW( name_ext
, buflen
, buffer
, lastpart
);
2708 RtlFreeHeap( GetProcessHeap(), 0, name_ext
);
2711 else if (path
&& path
[0]) /* search in the specified path */
2713 ret
= RtlDosSearchPath_U( path
, name
, ext
, buflen
* sizeof(WCHAR
),
2714 buffer
, lastpart
) / sizeof(WCHAR
);
2716 else /* search in active context and default path */
2718 WCHAR
*dll_path
= NULL
, *name_ext
= append_ext( name
, ext
);
2720 if (name_ext
) name
= name_ext
;
2722 /* When file is found with activation context no attempt is made
2723 to check if it's really exist, path is returned only basing on context info. */
2724 if (find_actctx_dllpath( name
, &dll_path
) == STATUS_SUCCESS
)
2726 ret
= lstrlenW( dll_path
) + lstrlenW( name
) + 1;
2728 /* count null termination char too */
2731 lstrcpyW( buffer
, dll_path
);
2732 lstrcatW( buffer
, name
);
2733 if (lastpart
) *lastpart
= buffer
+ lstrlenW( dll_path
);
2736 else if (lastpart
) *lastpart
= NULL
;
2737 RtlFreeHeap( GetProcessHeap(), 0, dll_path
);
2739 else if (!RtlGetSearchPath( &dll_path
))
2741 ret
= RtlDosSearchPath_U( dll_path
, name
, NULL
, buflen
* sizeof(WCHAR
),
2742 buffer
, lastpart
) / sizeof(WCHAR
);
2743 RtlReleasePath( dll_path
);
2745 RtlFreeHeap( GetProcessHeap(), 0, name_ext
);
2748 if (!ret
) SetLastError( ERROR_FILE_NOT_FOUND
);
2749 else TRACE( "found %s\n", debugstr_w(buffer
) );
2754 /***********************************************************************
2755 * SetCurrentDirectoryA (kernelbase.@)
2757 BOOL WINAPI DECLSPEC_HOTPATCH
SetCurrentDirectoryA( LPCSTR dir
)
2760 UNICODE_STRING strW
;
2762 if (!(dirW
= file_name_AtoW( dir
, FALSE
))) return FALSE
;
2763 RtlInitUnicodeString( &strW
, dirW
);
2764 return set_ntstatus( RtlSetCurrentDirectory_U( &strW
));
2768 /***********************************************************************
2769 * SetCurrentDirectoryW (kernelbase.@)
2771 BOOL WINAPI DECLSPEC_HOTPATCH
SetCurrentDirectoryW( LPCWSTR dir
)
2773 UNICODE_STRING dirW
;
2775 RtlInitUnicodeString( &dirW
, dir
);
2776 return set_ntstatus( RtlSetCurrentDirectory_U( &dirW
));
2780 /**************************************************************************
2781 * SetFileApisToANSI (kernelbase.@)
2783 void WINAPI DECLSPEC_HOTPATCH
SetFileApisToANSI(void)
2785 oem_file_apis
= FALSE
;
2789 /**************************************************************************
2790 * SetFileApisToOEM (kernelbase.@)
2792 void WINAPI DECLSPEC_HOTPATCH
SetFileApisToOEM(void)
2794 oem_file_apis
= TRUE
;
2798 /**************************************************************************
2799 * SetFileAttributesA (kernelbase.@)
2801 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileAttributesA( LPCSTR name
, DWORD attributes
)
2805 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return FALSE
;
2806 return SetFileAttributesW( nameW
, attributes
);
2810 /**************************************************************************
2811 * SetFileAttributesW (kernelbase.@)
2813 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileAttributesW( LPCWSTR name
, DWORD attributes
)
2815 UNICODE_STRING nt_name
;
2816 OBJECT_ATTRIBUTES attr
;
2821 TRACE( "%s %lx\n", debugstr_w(name
), attributes
);
2823 if (!RtlDosPathNameToNtPathName_U( name
, &nt_name
, NULL
, NULL
))
2825 SetLastError( ERROR_PATH_NOT_FOUND
);
2829 attr
.Length
= sizeof(attr
);
2830 attr
.RootDirectory
= 0;
2831 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2832 attr
.ObjectName
= &nt_name
;
2833 attr
.SecurityDescriptor
= NULL
;
2834 attr
.SecurityQualityOfService
= NULL
;
2836 status
= NtOpenFile( &handle
, SYNCHRONIZE
, &attr
, &io
, 0, FILE_SYNCHRONOUS_IO_NONALERT
);
2837 RtlFreeUnicodeString( &nt_name
);
2839 if (status
== STATUS_SUCCESS
)
2841 FILE_BASIC_INFORMATION info
;
2843 memset( &info
, 0, sizeof(info
) );
2844 info
.FileAttributes
= attributes
| FILE_ATTRIBUTE_NORMAL
; /* make sure it's not zero */
2845 status
= NtSetInformationFile( handle
, &io
, &info
, sizeof(info
), FileBasicInformation
);
2848 return set_ntstatus( status
);
2852 /***********************************************************************
2853 * Wow64DisableWow64FsRedirection (kernelbase.@)
2855 BOOL WINAPI DECLSPEC_HOTPATCH
Wow64DisableWow64FsRedirection( PVOID
*old_value
)
2857 return set_ntstatus( RtlWow64EnableFsRedirectionEx( TRUE
, (ULONG
*)old_value
));
2861 /***********************************************************************
2862 * Wow64EnableWow64FsRedirection (kernelbase.@)
2864 * Microsoft C++ Redistributable installers are depending on all %eax bits being set.
2866 DWORD
/*BOOLEAN*/ WINAPI
kernelbase_Wow64EnableWow64FsRedirection( BOOLEAN enable
)
2868 return set_ntstatus( RtlWow64EnableFsRedirection( enable
));
2872 /***********************************************************************
2873 * Wow64RevertWow64FsRedirection (kernelbase.@)
2875 BOOL WINAPI DECLSPEC_HOTPATCH
Wow64RevertWow64FsRedirection( PVOID old_value
)
2877 return set_ntstatus( RtlWow64EnableFsRedirection( !old_value
));
2881 /***********************************************************************
2882 * Operations on file handles
2883 ***********************************************************************/
2886 /***********************************************************************
2887 * CancelIo (kernelbase.@)
2889 BOOL WINAPI DECLSPEC_HOTPATCH
CancelIo( HANDLE handle
)
2893 return set_ntstatus( NtCancelIoFile( handle
, &io
) );
2897 /***********************************************************************
2898 * CancelIoEx (kernelbase.@)
2900 BOOL WINAPI DECLSPEC_HOTPATCH
CancelIoEx( HANDLE handle
, LPOVERLAPPED overlapped
)
2904 return set_ntstatus( NtCancelIoFileEx( handle
, (PIO_STATUS_BLOCK
)overlapped
, &io
) );
2908 /***********************************************************************
2909 * CancelSynchronousIo (kernelbase.@)
2911 BOOL WINAPI DECLSPEC_HOTPATCH
CancelSynchronousIo( HANDLE thread
)
2915 return set_ntstatus( NtCancelSynchronousIoFile( thread
, NULL
, &io
));
2919 /***********************************************************************
2920 * FlushFileBuffers (kernelbase.@)
2922 BOOL WINAPI DECLSPEC_HOTPATCH
FlushFileBuffers( HANDLE file
)
2924 IO_STATUS_BLOCK iosb
;
2926 return set_ntstatus( NtFlushBuffersFile( file
, &iosb
));
2930 /***********************************************************************
2931 * GetFileInformationByHandle (kernelbase.@)
2933 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileInformationByHandle( HANDLE file
, BY_HANDLE_FILE_INFORMATION
*info
)
2935 FILE_FS_VOLUME_INFORMATION volume_info
;
2936 FILE_ALL_INFORMATION all_info
;
2940 status
= NtQueryInformationFile( file
, &io
, &all_info
, sizeof(all_info
), FileAllInformation
);
2941 if (status
== STATUS_BUFFER_OVERFLOW
) status
= STATUS_SUCCESS
;
2942 if (!set_ntstatus( status
)) return FALSE
;
2944 info
->dwFileAttributes
= all_info
.BasicInformation
.FileAttributes
;
2945 info
->ftCreationTime
.dwHighDateTime
= all_info
.BasicInformation
.CreationTime
.u
.HighPart
;
2946 info
->ftCreationTime
.dwLowDateTime
= all_info
.BasicInformation
.CreationTime
.u
.LowPart
;
2947 info
->ftLastAccessTime
.dwHighDateTime
= all_info
.BasicInformation
.LastAccessTime
.u
.HighPart
;
2948 info
->ftLastAccessTime
.dwLowDateTime
= all_info
.BasicInformation
.LastAccessTime
.u
.LowPart
;
2949 info
->ftLastWriteTime
.dwHighDateTime
= all_info
.BasicInformation
.LastWriteTime
.u
.HighPart
;
2950 info
->ftLastWriteTime
.dwLowDateTime
= all_info
.BasicInformation
.LastWriteTime
.u
.LowPart
;
2951 info
->dwVolumeSerialNumber
= 0;
2952 info
->nFileSizeHigh
= all_info
.StandardInformation
.EndOfFile
.u
.HighPart
;
2953 info
->nFileSizeLow
= all_info
.StandardInformation
.EndOfFile
.u
.LowPart
;
2954 info
->nNumberOfLinks
= all_info
.StandardInformation
.NumberOfLinks
;
2955 info
->nFileIndexHigh
= all_info
.InternalInformation
.IndexNumber
.u
.HighPart
;
2956 info
->nFileIndexLow
= all_info
.InternalInformation
.IndexNumber
.u
.LowPart
;
2958 status
= NtQueryVolumeInformationFile( file
, &io
, &volume_info
, sizeof(volume_info
), FileFsVolumeInformation
);
2959 if (status
== STATUS_SUCCESS
|| status
== STATUS_BUFFER_OVERFLOW
)
2960 info
->dwVolumeSerialNumber
= volume_info
.VolumeSerialNumber
;
2966 /***********************************************************************
2967 * GetFileInformationByHandleEx (kernelbase.@)
2969 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileInformationByHandleEx( HANDLE handle
, FILE_INFO_BY_HANDLE_CLASS
class,
2970 LPVOID info
, DWORD size
)
2977 case FileRemoteProtocolInfo
:
2978 case FileStorageInfo
:
2979 case FileDispositionInfoEx
:
2980 case FileRenameInfoEx
:
2981 case FileCaseSensitiveInfo
:
2982 case FileNormalizedNameInfo
:
2983 FIXME( "%p, %u, %p, %lu\n", handle
, class, info
, size
);
2984 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
2987 case FileStreamInfo
:
2988 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileStreamInformation
);
2991 case FileCompressionInfo
:
2992 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileCompressionInformation
);
2995 case FileAlignmentInfo
:
2996 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileAlignmentInformation
);
2999 case FileAttributeTagInfo
:
3000 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileAttributeTagInformation
);
3004 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileBasicInformation
);
3007 case FileStandardInfo
:
3008 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileStandardInformation
);
3012 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileNameInformation
);
3016 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileIdInformation
);
3019 case FileIdBothDirectoryRestartInfo
:
3020 case FileIdBothDirectoryInfo
:
3021 status
= NtQueryDirectoryFile( handle
, NULL
, NULL
, NULL
, &io
, info
, size
,
3022 FileIdBothDirectoryInformation
, FALSE
, NULL
,
3023 (class == FileIdBothDirectoryRestartInfo
) );
3026 case FileFullDirectoryInfo
:
3027 case FileFullDirectoryRestartInfo
:
3028 status
= NtQueryDirectoryFile( handle
, NULL
, NULL
, NULL
, &io
, info
, size
,
3029 FileFullDirectoryInformation
, FALSE
, NULL
,
3030 (class == FileFullDirectoryRestartInfo
) );
3033 case FileIdExtdDirectoryInfo
:
3034 case FileIdExtdDirectoryRestartInfo
:
3035 status
= NtQueryDirectoryFile( handle
, NULL
, NULL
, NULL
, &io
, info
, size
,
3036 FileIdExtdDirectoryInformation
, FALSE
, NULL
,
3037 (class == FileIdExtdDirectoryRestartInfo
) );
3040 case FileRenameInfo
:
3041 case FileDispositionInfo
:
3042 case FileAllocationInfo
:
3043 case FileIoPriorityHintInfo
:
3044 case FileEndOfFileInfo
:
3046 SetLastError( ERROR_INVALID_PARAMETER
);
3049 return set_ntstatus( status
);
3053 /***********************************************************************
3054 * GetFileSize (kernelbase.@)
3056 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileSize( HANDLE file
, LPDWORD size_high
)
3060 if (!GetFileSizeEx( file
, &size
)) return INVALID_FILE_SIZE
;
3061 if (size_high
) *size_high
= size
.u
.HighPart
;
3062 if (size
.u
.LowPart
== INVALID_FILE_SIZE
) SetLastError( 0 );
3063 return size
.u
.LowPart
;
3067 /***********************************************************************
3068 * GetFileSizeEx (kernelbase.@)
3070 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileSizeEx( HANDLE file
, PLARGE_INTEGER size
)
3072 FILE_STANDARD_INFORMATION info
;
3075 if (!set_ntstatus( NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
)))
3078 *size
= info
.EndOfFile
;
3083 /***********************************************************************
3084 * GetFileTime (kernelbase.@)
3086 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileTime( HANDLE file
, FILETIME
*creation
,
3087 FILETIME
*access
, FILETIME
*write
)
3089 FILE_BASIC_INFORMATION info
;
3092 if (!set_ntstatus( NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileBasicInformation
)))
3097 creation
->dwHighDateTime
= info
.CreationTime
.u
.HighPart
;
3098 creation
->dwLowDateTime
= info
.CreationTime
.u
.LowPart
;
3102 access
->dwHighDateTime
= info
.LastAccessTime
.u
.HighPart
;
3103 access
->dwLowDateTime
= info
.LastAccessTime
.u
.LowPart
;
3107 write
->dwHighDateTime
= info
.LastWriteTime
.u
.HighPart
;
3108 write
->dwLowDateTime
= info
.LastWriteTime
.u
.LowPart
;
3114 /***********************************************************************
3115 * GetFileType (kernelbase.@)
3117 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileType( HANDLE file
)
3119 FILE_FS_DEVICE_INFORMATION info
;
3122 if (file
== (HANDLE
)STD_INPUT_HANDLE
||
3123 file
== (HANDLE
)STD_OUTPUT_HANDLE
||
3124 file
== (HANDLE
)STD_ERROR_HANDLE
)
3125 file
= GetStdHandle( (DWORD_PTR
)file
);
3127 if (!set_ntstatus( NtQueryVolumeInformationFile( file
, &io
, &info
, sizeof(info
),
3128 FileFsDeviceInformation
)))
3129 return FILE_TYPE_UNKNOWN
;
3131 switch (info
.DeviceType
)
3133 case FILE_DEVICE_NULL
:
3134 case FILE_DEVICE_CONSOLE
:
3135 case FILE_DEVICE_SERIAL_PORT
:
3136 case FILE_DEVICE_PARALLEL_PORT
:
3137 case FILE_DEVICE_TAPE
:
3138 case FILE_DEVICE_UNKNOWN
:
3139 return FILE_TYPE_CHAR
;
3140 case FILE_DEVICE_NAMED_PIPE
:
3141 return FILE_TYPE_PIPE
;
3143 return FILE_TYPE_DISK
;
3148 /***********************************************************************
3149 * GetOverlappedResult (kernelbase.@)
3151 BOOL WINAPI DECLSPEC_HOTPATCH
GetOverlappedResult( HANDLE file
, LPOVERLAPPED overlapped
,
3152 LPDWORD result
, BOOL wait
)
3154 return GetOverlappedResultEx( file
, overlapped
, result
, wait
? INFINITE
: 0, FALSE
);
3158 /***********************************************************************
3159 * GetOverlappedResultEx (kernelbase.@)
3161 BOOL WINAPI DECLSPEC_HOTPATCH
GetOverlappedResultEx( HANDLE file
, OVERLAPPED
*overlapped
,
3162 DWORD
*result
, DWORD timeout
, BOOL alertable
)
3167 TRACE( "(%p %p %p %lu %d)\n", file
, overlapped
, result
, timeout
, alertable
);
3169 /* Paired with the write-release in set_async_iosb() in ntdll; see the
3170 * latter for details. */
3171 status
= ReadAcquire( (LONG
*)&overlapped
->Internal
);
3172 if (status
== STATUS_PENDING
)
3176 SetLastError( ERROR_IO_INCOMPLETE
);
3179 ret
= WaitForSingleObjectEx( overlapped
->hEvent
? overlapped
->hEvent
: file
, timeout
, alertable
);
3180 if (ret
== WAIT_FAILED
)
3184 SetLastError( ret
);
3188 /* We don't need to give this load acquire semantics; the wait above
3189 * already guarantees that the IOSB and output buffer are filled. */
3190 status
= overlapped
->Internal
;
3191 if (status
== STATUS_PENDING
) status
= STATUS_SUCCESS
;
3194 *result
= overlapped
->InternalHigh
;
3195 return set_ntstatus( status
);
3199 /**************************************************************************
3200 * LockFile (kernelbase.@)
3202 BOOL WINAPI DECLSPEC_HOTPATCH
LockFile( HANDLE file
, DWORD offset_low
, DWORD offset_high
,
3203 DWORD count_low
, DWORD count_high
)
3205 LARGE_INTEGER count
, offset
;
3207 TRACE( "%p %lx%08lx %lx%08lx\n", file
, offset_high
, offset_low
, count_high
, count_low
);
3209 count
.u
.LowPart
= count_low
;
3210 count
.u
.HighPart
= count_high
;
3211 offset
.u
.LowPart
= offset_low
;
3212 offset
.u
.HighPart
= offset_high
;
3213 return set_ntstatus( NtLockFile( file
, 0, NULL
, NULL
, NULL
, &offset
, &count
, NULL
, TRUE
, TRUE
));
3217 /**************************************************************************
3218 * LockFileEx (kernelbase.@)
3220 BOOL WINAPI DECLSPEC_HOTPATCH
LockFileEx( HANDLE file
, DWORD flags
, DWORD reserved
,
3221 DWORD count_low
, DWORD count_high
, LPOVERLAPPED overlapped
)
3223 LARGE_INTEGER count
, offset
;
3224 LPVOID cvalue
= NULL
;
3228 SetLastError( ERROR_INVALID_PARAMETER
);
3232 TRACE( "%p %lx%08lx %lx%08lx flags %lx\n",
3233 file
, overlapped
->u
.s
.OffsetHigh
, overlapped
->u
.s
.Offset
, count_high
, count_low
, flags
);
3235 count
.u
.LowPart
= count_low
;
3236 count
.u
.HighPart
= count_high
;
3237 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3238 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3240 if (((ULONG_PTR
)overlapped
->hEvent
& 1) == 0) cvalue
= overlapped
;
3242 return set_ntstatus( NtLockFile( file
, overlapped
->hEvent
, NULL
, cvalue
,
3243 NULL
, &offset
, &count
, NULL
,
3244 flags
& LOCKFILE_FAIL_IMMEDIATELY
,
3245 flags
& LOCKFILE_EXCLUSIVE_LOCK
));
3249 /***********************************************************************
3250 * OpenFileById (kernelbase.@)
3252 HANDLE WINAPI DECLSPEC_HOTPATCH
OpenFileById( HANDLE handle
, LPFILE_ID_DESCRIPTOR id
, DWORD access
,
3253 DWORD share
, LPSECURITY_ATTRIBUTES sec_attr
, DWORD flags
)
3257 OBJECT_ATTRIBUTES attr
;
3259 UNICODE_STRING objectName
;
3263 SetLastError( ERROR_INVALID_PARAMETER
);
3264 return INVALID_HANDLE_VALUE
;
3267 options
= FILE_OPEN_BY_FILE_ID
;
3268 if (flags
& FILE_FLAG_BACKUP_SEMANTICS
)
3269 options
|= FILE_OPEN_FOR_BACKUP_INTENT
;
3271 options
|= FILE_NON_DIRECTORY_FILE
;
3272 if (flags
& FILE_FLAG_NO_BUFFERING
) options
|= FILE_NO_INTERMEDIATE_BUFFERING
;
3273 if (!(flags
& FILE_FLAG_OVERLAPPED
)) options
|= FILE_SYNCHRONOUS_IO_NONALERT
;
3274 if (flags
& FILE_FLAG_RANDOM_ACCESS
) options
|= FILE_RANDOM_ACCESS
;
3275 if (flags
& FILE_FLAG_SEQUENTIAL_SCAN
) options
|= FILE_SEQUENTIAL_ONLY
;
3276 flags
&= FILE_ATTRIBUTE_VALID_FLAGS
;
3278 objectName
.Length
= sizeof(ULONGLONG
);
3279 objectName
.Buffer
= (WCHAR
*)&id
->u
.FileId
;
3280 attr
.Length
= sizeof(attr
);
3281 attr
.RootDirectory
= handle
;
3282 attr
.Attributes
= 0;
3283 attr
.ObjectName
= &objectName
;
3284 attr
.SecurityDescriptor
= sec_attr
? sec_attr
->lpSecurityDescriptor
: NULL
;
3285 attr
.SecurityQualityOfService
= NULL
;
3286 if (sec_attr
&& sec_attr
->bInheritHandle
) attr
.Attributes
|= OBJ_INHERIT
;
3288 if (!set_ntstatus( NtCreateFile( &result
, access
| SYNCHRONIZE
, &attr
, &io
, NULL
, flags
,
3289 share
, OPEN_EXISTING
, options
, NULL
, 0 )))
3290 return INVALID_HANDLE_VALUE
;
3295 /***********************************************************************
3296 * ReOpenFile (kernelbase.@)
3298 HANDLE WINAPI DECLSPEC_HOTPATCH
ReOpenFile( HANDLE handle
, DWORD access
, DWORD sharing
, DWORD attributes
)
3300 SECURITY_QUALITY_OF_SERVICE qos
;
3301 OBJECT_ATTRIBUTES attr
;
3302 UNICODE_STRING empty
= { 0 };
3307 TRACE("handle %p, access %#lx, sharing %#lx, attributes %#lx.\n", handle
, access
, sharing
, attributes
);
3309 if (attributes
& 0x7ffff) /* FILE_ATTRIBUTE_* flags are invalid */
3311 SetLastError(ERROR_INVALID_PARAMETER
);
3312 return INVALID_HANDLE_VALUE
;
3315 if (attributes
& FILE_FLAG_DELETE_ON_CLOSE
)
3318 InitializeObjectAttributes( &attr
, &empty
, OBJ_CASE_INSENSITIVE
, handle
, NULL
);
3319 if (attributes
& SECURITY_SQOS_PRESENT
)
3321 qos
.Length
= sizeof(qos
);
3322 qos
.ImpersonationLevel
= (attributes
>> 16) & 0x3;
3323 qos
.ContextTrackingMode
= attributes
& SECURITY_CONTEXT_TRACKING
? SECURITY_DYNAMIC_TRACKING
: SECURITY_STATIC_TRACKING
;
3324 qos
.EffectiveOnly
= (attributes
& SECURITY_EFFECTIVE_ONLY
) != 0;
3325 attr
.SecurityQualityOfService
= &qos
;
3328 status
= NtCreateFile( &file
, access
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
, &attr
, &io
, NULL
,
3329 0, sharing
, FILE_OPEN
, get_nt_file_options( attributes
), NULL
, 0 );
3330 if (!set_ntstatus( status
))
3331 return INVALID_HANDLE_VALUE
;
3336 static void WINAPI
invoke_completion( void *context
, IO_STATUS_BLOCK
*io
, ULONG res
)
3338 LPOVERLAPPED_COMPLETION_ROUTINE completion
= context
;
3339 completion( RtlNtStatusToDosError( io
->u
.Status
), io
->Information
, (LPOVERLAPPED
)io
);
3342 /****************************************************************************
3343 * ReadDirectoryChangesW (kernelbase.@)
3345 BOOL WINAPI DECLSPEC_HOTPATCH
ReadDirectoryChangesW( HANDLE handle
, LPVOID buffer
, DWORD len
,
3346 BOOL subtree
, DWORD filter
, LPDWORD returned
,
3347 LPOVERLAPPED overlapped
,
3348 LPOVERLAPPED_COMPLETION_ROUTINE completion
)
3350 OVERLAPPED ov
, *pov
;
3351 IO_STATUS_BLOCK
*ios
;
3353 LPVOID cvalue
= NULL
;
3355 TRACE( "%p %p %08lx %d %08lx %p %p %p\n",
3356 handle
, buffer
, len
, subtree
, filter
, returned
, overlapped
, completion
);
3360 memset( &ov
, 0, sizeof ov
);
3361 ov
.hEvent
= CreateEventW( NULL
, 0, 0, NULL
);
3367 if (completion
) cvalue
= completion
;
3368 else if (((ULONG_PTR
)overlapped
->hEvent
& 1) == 0) cvalue
= overlapped
;
3371 ios
= (PIO_STATUS_BLOCK
)pov
;
3372 ios
->u
.Status
= STATUS_PENDING
;
3374 status
= NtNotifyChangeDirectoryFile( handle
, completion
&& overlapped
? NULL
: pov
->hEvent
,
3375 completion
&& overlapped
? invoke_completion
: NULL
,
3376 cvalue
, ios
, buffer
, len
, filter
, subtree
);
3377 if (status
== STATUS_PENDING
)
3379 if (overlapped
) return TRUE
;
3380 WaitForSingleObjectEx( ov
.hEvent
, INFINITE
, TRUE
);
3381 if (returned
) *returned
= ios
->Information
;
3382 status
= ios
->u
.Status
;
3384 if (!overlapped
) CloseHandle( ov
.hEvent
);
3385 return set_ntstatus( status
);
3389 /***********************************************************************
3390 * ReadFile (kernelbase.@)
3392 BOOL WINAPI DECLSPEC_HOTPATCH
ReadFile( HANDLE file
, LPVOID buffer
, DWORD count
,
3393 LPDWORD result
, LPOVERLAPPED overlapped
)
3395 LARGE_INTEGER offset
;
3396 PLARGE_INTEGER poffset
= NULL
;
3397 IO_STATUS_BLOCK iosb
;
3398 PIO_STATUS_BLOCK io_status
= &iosb
;
3401 LPVOID cvalue
= NULL
;
3403 TRACE( "%p %p %ld %p %p\n", file
, buffer
, count
, result
, overlapped
);
3405 if (result
) *result
= 0;
3409 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3410 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3412 event
= overlapped
->hEvent
;
3413 io_status
= (PIO_STATUS_BLOCK
)overlapped
;
3414 if (((ULONG_PTR
)event
& 1) == 0) cvalue
= overlapped
;
3416 else io_status
->Information
= 0;
3417 io_status
->u
.Status
= STATUS_PENDING
;
3419 status
= NtReadFile( file
, event
, NULL
, cvalue
, io_status
, buffer
, count
, poffset
, NULL
);
3421 if (status
== STATUS_PENDING
&& !overlapped
)
3423 WaitForSingleObject( file
, INFINITE
);
3424 status
= io_status
->u
.Status
;
3427 if (result
) *result
= overlapped
&& status
? 0 : io_status
->Information
;
3429 if (status
== STATUS_END_OF_FILE
)
3431 if (overlapped
!= NULL
)
3433 SetLastError( RtlNtStatusToDosError(status
) );
3437 else if (status
&& status
!= STATUS_TIMEOUT
)
3439 SetLastError( RtlNtStatusToDosError(status
) );
3446 /***********************************************************************
3447 * ReadFileEx (kernelbase.@)
3449 BOOL WINAPI DECLSPEC_HOTPATCH
ReadFileEx( HANDLE file
, LPVOID buffer
, DWORD count
, LPOVERLAPPED overlapped
,
3450 LPOVERLAPPED_COMPLETION_ROUTINE completion
)
3452 PIO_STATUS_BLOCK io
;
3453 LARGE_INTEGER offset
;
3456 TRACE( "(file=%p, buffer=%p, bytes=%lu, ovl=%p, ovl_fn=%p)\n",
3457 file
, buffer
, count
, overlapped
, completion
);
3461 SetLastError( ERROR_INVALID_PARAMETER
);
3464 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3465 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3466 io
= (PIO_STATUS_BLOCK
)overlapped
;
3467 io
->u
.Status
= STATUS_PENDING
;
3468 io
->Information
= 0;
3470 status
= NtReadFile( file
, NULL
, read_write_apc
, completion
, io
, buffer
, count
, &offset
, NULL
);
3471 if (status
== STATUS_PENDING
) return TRUE
;
3472 return set_ntstatus( status
);
3476 /***********************************************************************
3477 * ReadFileScatter (kernelbase.@)
3479 BOOL WINAPI DECLSPEC_HOTPATCH
ReadFileScatter( HANDLE file
, FILE_SEGMENT_ELEMENT
*segments
, DWORD count
,
3480 LPDWORD reserved
, LPOVERLAPPED overlapped
)
3482 PIO_STATUS_BLOCK io
;
3483 LARGE_INTEGER offset
;
3484 void *cvalue
= NULL
;
3486 TRACE( "(%p %p %lu %p)\n", file
, segments
, count
, overlapped
);
3488 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3489 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3490 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
3491 io
= (PIO_STATUS_BLOCK
)overlapped
;
3492 io
->u
.Status
= STATUS_PENDING
;
3493 io
->Information
= 0;
3495 return set_ntstatus( NtReadFileScatter( file
, overlapped
->hEvent
, NULL
, cvalue
, io
,
3496 segments
, count
, &offset
, NULL
));
3500 /***********************************************************************
3501 * RemoveDirectoryA (kernelbase.@)
3503 BOOL WINAPI DECLSPEC_HOTPATCH
RemoveDirectoryA( LPCSTR path
)
3507 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return FALSE
;
3508 return RemoveDirectoryW( pathW
);
3512 /***********************************************************************
3513 * RemoveDirectoryW (kernelbase.@)
3515 BOOL WINAPI DECLSPEC_HOTPATCH
RemoveDirectoryW( LPCWSTR path
)
3517 OBJECT_ATTRIBUTES attr
;
3518 UNICODE_STRING nt_name
;
3523 TRACE( "%s\n", debugstr_w(path
) );
3525 status
= RtlDosPathNameToNtPathName_U_WithStatus( path
, &nt_name
, NULL
, NULL
);
3526 if (!set_ntstatus( status
)) return FALSE
;
3528 InitializeObjectAttributes( &attr
, &nt_name
, OBJ_CASE_INSENSITIVE
, 0, NULL
);
3529 status
= NtOpenFile( &handle
, DELETE
| SYNCHRONIZE
, &attr
, &io
,
3530 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
3531 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
3532 RtlFreeUnicodeString( &nt_name
);
3536 FILE_DISPOSITION_INFORMATION info
= { TRUE
};
3537 status
= NtSetInformationFile( handle
, &io
, &info
, sizeof(info
), FileDispositionInformation
);
3540 return set_ntstatus( status
);
3544 /**************************************************************************
3545 * SetEndOfFile (kernelbase.@)
3547 BOOL WINAPI DECLSPEC_HOTPATCH
SetEndOfFile( HANDLE file
)
3549 FILE_POSITION_INFORMATION pos
;
3550 FILE_END_OF_FILE_INFORMATION eof
;
3554 if (!(status
= NtQueryInformationFile( file
, &io
, &pos
, sizeof(pos
), FilePositionInformation
)))
3556 eof
.EndOfFile
= pos
.CurrentByteOffset
;
3557 status
= NtSetInformationFile( file
, &io
, &eof
, sizeof(eof
), FileEndOfFileInformation
);
3559 return set_ntstatus( status
);
3563 /***********************************************************************
3564 * SetFileInformationByHandle (kernelbase.@)
3566 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileInformationByHandle( HANDLE file
, FILE_INFO_BY_HANDLE_CLASS
class,
3567 void *info
, DWORD size
)
3572 TRACE( "%p %u %p %lu\n", file
, class, info
, size
);
3577 case FileAllocationInfo
:
3578 case FileStreamInfo
:
3579 case FileIdBothDirectoryInfo
:
3580 case FileIdBothDirectoryRestartInfo
:
3581 case FileFullDirectoryInfo
:
3582 case FileFullDirectoryRestartInfo
:
3583 case FileStorageInfo
:
3584 case FileAlignmentInfo
:
3586 case FileIdExtdDirectoryInfo
:
3587 case FileIdExtdDirectoryRestartInfo
:
3588 FIXME( "%p, %u, %p, %lu\n", file
, class, info
, size
);
3589 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
3592 case FileEndOfFileInfo
:
3593 status
= NtSetInformationFile( file
, &io
, info
, size
, FileEndOfFileInformation
);
3596 status
= NtSetInformationFile( file
, &io
, info
, size
, FileBasicInformation
);
3598 case FileDispositionInfo
:
3599 status
= NtSetInformationFile( file
, &io
, info
, size
, FileDispositionInformation
);
3601 case FileIoPriorityHintInfo
:
3602 status
= NtSetInformationFile( file
, &io
, info
, size
, FileIoPriorityHintInformation
);
3604 case FileRenameInfo
:
3606 FILE_RENAME_INFORMATION
*rename_info
;
3607 UNICODE_STRING nt_name
;
3610 if ((status
= RtlDosPathNameToNtPathName_U_WithStatus( ((FILE_RENAME_INFORMATION
*)info
)->FileName
,
3611 &nt_name
, NULL
, NULL
)))
3614 size
= sizeof(*rename_info
) + nt_name
.Length
;
3615 if ((rename_info
= HeapAlloc( GetProcessHeap(), 0, size
)))
3617 memcpy( rename_info
, info
, sizeof(*rename_info
) );
3618 memcpy( rename_info
->FileName
, nt_name
.Buffer
, nt_name
.Length
+ sizeof(WCHAR
) );
3619 rename_info
->FileNameLength
= nt_name
.Length
;
3620 status
= NtSetInformationFile( file
, &io
, rename_info
, size
, FileRenameInformation
);
3621 HeapFree( GetProcessHeap(), 0, rename_info
);
3623 RtlFreeUnicodeString( &nt_name
);
3626 case FileStandardInfo
:
3627 case FileCompressionInfo
:
3628 case FileAttributeTagInfo
:
3629 case FileRemoteProtocolInfo
:
3631 SetLastError( ERROR_INVALID_PARAMETER
);
3634 return set_ntstatus( status
);
3638 /***********************************************************************
3639 * SetFilePointer (kernelbase.@)
3641 DWORD WINAPI DECLSPEC_HOTPATCH
SetFilePointer( HANDLE file
, LONG distance
, LONG
*highword
, DWORD method
)
3643 LARGE_INTEGER dist
, newpos
;
3647 dist
.u
.LowPart
= distance
;
3648 dist
.u
.HighPart
= *highword
;
3650 else dist
.QuadPart
= distance
;
3652 if (!SetFilePointerEx( file
, dist
, &newpos
, method
)) return INVALID_SET_FILE_POINTER
;
3654 if (highword
) *highword
= newpos
.u
.HighPart
;
3655 if (newpos
.u
.LowPart
== INVALID_SET_FILE_POINTER
) SetLastError( 0 );
3656 return newpos
.u
.LowPart
;
3660 /***********************************************************************
3661 * SetFilePointerEx (kernelbase.@)
3663 BOOL WINAPI DECLSPEC_HOTPATCH
SetFilePointerEx( HANDLE file
, LARGE_INTEGER distance
,
3664 LARGE_INTEGER
*newpos
, DWORD method
)
3668 FILE_POSITION_INFORMATION info
;
3669 FILE_STANDARD_INFORMATION eof
;
3674 pos
= distance
.QuadPart
;
3677 if (NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FilePositionInformation
))
3679 pos
= info
.CurrentByteOffset
.QuadPart
+ distance
.QuadPart
;
3682 if (NtQueryInformationFile( file
, &io
, &eof
, sizeof(eof
), FileStandardInformation
))
3684 pos
= eof
.EndOfFile
.QuadPart
+ distance
.QuadPart
;
3687 SetLastError( ERROR_INVALID_PARAMETER
);
3693 SetLastError( ERROR_NEGATIVE_SEEK
);
3697 info
.CurrentByteOffset
.QuadPart
= pos
;
3698 if (!NtSetInformationFile( file
, &io
, &info
, sizeof(info
), FilePositionInformation
))
3700 if (newpos
) newpos
->QuadPart
= pos
;
3705 return set_ntstatus( io
.u
.Status
);
3709 /***********************************************************************
3710 * SetFileTime (kernelbase.@)
3712 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileTime( HANDLE file
, const FILETIME
*ctime
,
3713 const FILETIME
*atime
, const FILETIME
*mtime
)
3715 FILE_BASIC_INFORMATION info
;
3718 memset( &info
, 0, sizeof(info
) );
3721 info
.CreationTime
.u
.HighPart
= ctime
->dwHighDateTime
;
3722 info
.CreationTime
.u
.LowPart
= ctime
->dwLowDateTime
;
3726 info
.LastAccessTime
.u
.HighPart
= atime
->dwHighDateTime
;
3727 info
.LastAccessTime
.u
.LowPart
= atime
->dwLowDateTime
;
3731 info
.LastWriteTime
.u
.HighPart
= mtime
->dwHighDateTime
;
3732 info
.LastWriteTime
.u
.LowPart
= mtime
->dwLowDateTime
;
3735 return set_ntstatus( NtSetInformationFile( file
, &io
, &info
, sizeof(info
), FileBasicInformation
));
3739 /***********************************************************************
3740 * SetFileValidData (kernelbase.@)
3742 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileValidData( HANDLE file
, LONGLONG length
)
3744 FILE_VALID_DATA_LENGTH_INFORMATION info
;
3747 info
.ValidDataLength
.QuadPart
= length
;
3748 return set_ntstatus( NtSetInformationFile( file
, &io
, &info
, sizeof(info
),
3749 FileValidDataLengthInformation
));
3753 /**************************************************************************
3754 * UnlockFile (kernelbase.@)
3756 BOOL WINAPI DECLSPEC_HOTPATCH
UnlockFile( HANDLE file
, DWORD offset_low
, DWORD offset_high
,
3757 DWORD count_low
, DWORD count_high
)
3759 LARGE_INTEGER count
, offset
;
3761 count
.u
.LowPart
= count_low
;
3762 count
.u
.HighPart
= count_high
;
3763 offset
.u
.LowPart
= offset_low
;
3764 offset
.u
.HighPart
= offset_high
;
3765 return set_ntstatus( NtUnlockFile( file
, NULL
, &offset
, &count
, NULL
));
3769 /**************************************************************************
3770 * UnlockFileEx (kernelbase.@)
3772 BOOL WINAPI DECLSPEC_HOTPATCH
UnlockFileEx( HANDLE file
, DWORD reserved
,
3773 DWORD count_low
, DWORD count_high
, LPOVERLAPPED overlapped
)
3777 SetLastError( ERROR_INVALID_PARAMETER
);
3780 if (overlapped
->hEvent
) FIXME("Unimplemented overlapped operation\n");
3782 return UnlockFile( file
, overlapped
->u
.s
.Offset
, overlapped
->u
.s
.OffsetHigh
, count_low
, count_high
);
3786 /***********************************************************************
3787 * WriteFile (kernelbase.@)
3789 BOOL WINAPI DECLSPEC_HOTPATCH
WriteFile( HANDLE file
, LPCVOID buffer
, DWORD count
,
3790 LPDWORD result
, LPOVERLAPPED overlapped
)
3792 HANDLE event
= NULL
;
3793 LARGE_INTEGER offset
;
3794 PLARGE_INTEGER poffset
= NULL
;
3796 IO_STATUS_BLOCK iosb
;
3797 PIO_STATUS_BLOCK piosb
= &iosb
;
3798 LPVOID cvalue
= NULL
;
3800 TRACE( "%p %p %ld %p %p\n", file
, buffer
, count
, result
, overlapped
);
3804 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3805 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3807 event
= overlapped
->hEvent
;
3808 piosb
= (PIO_STATUS_BLOCK
)overlapped
;
3809 if (((ULONG_PTR
)event
& 1) == 0) cvalue
= overlapped
;
3811 else piosb
->Information
= 0;
3812 piosb
->u
.Status
= STATUS_PENDING
;
3814 status
= NtWriteFile( file
, event
, NULL
, cvalue
, piosb
, buffer
, count
, poffset
, NULL
);
3816 if (status
== STATUS_PENDING
&& !overlapped
)
3818 WaitForSingleObject( file
, INFINITE
);
3819 status
= piosb
->u
.Status
;
3822 if (result
) *result
= overlapped
&& status
? 0 : piosb
->Information
;
3824 if (status
&& status
!= STATUS_TIMEOUT
)
3826 SetLastError( RtlNtStatusToDosError(status
) );
3833 /***********************************************************************
3834 * WriteFileEx (kernelbase.@)
3836 BOOL WINAPI DECLSPEC_HOTPATCH
WriteFileEx( HANDLE file
, LPCVOID buffer
,
3837 DWORD count
, LPOVERLAPPED overlapped
,
3838 LPOVERLAPPED_COMPLETION_ROUTINE completion
)
3840 LARGE_INTEGER offset
;
3842 PIO_STATUS_BLOCK io
;
3844 TRACE( "%p %p %ld %p %p\n", file
, buffer
, count
, overlapped
, completion
);
3848 SetLastError( ERROR_INVALID_PARAMETER
);
3851 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3852 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3854 io
= (PIO_STATUS_BLOCK
)overlapped
;
3855 io
->u
.Status
= STATUS_PENDING
;
3856 io
->Information
= 0;
3858 status
= NtWriteFile( file
, NULL
, read_write_apc
, completion
, io
, buffer
, count
, &offset
, NULL
);
3859 if (status
== STATUS_PENDING
) return TRUE
;
3860 return set_ntstatus( status
);
3864 /***********************************************************************
3865 * WriteFileGather (kernelbase.@)
3867 BOOL WINAPI DECLSPEC_HOTPATCH
WriteFileGather( HANDLE file
, FILE_SEGMENT_ELEMENT
*segments
, DWORD count
,
3868 LPDWORD reserved
, LPOVERLAPPED overlapped
)
3870 PIO_STATUS_BLOCK io
;
3871 LARGE_INTEGER offset
;
3872 void *cvalue
= NULL
;
3874 TRACE( "%p %p %lu %p\n", file
, segments
, count
, overlapped
);
3876 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3877 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3878 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
3879 io
= (PIO_STATUS_BLOCK
)overlapped
;
3880 io
->u
.Status
= STATUS_PENDING
;
3881 io
->Information
= 0;
3883 return set_ntstatus( NtWriteFileGather( file
, overlapped
->hEvent
, NULL
, cvalue
,
3884 io
, segments
, count
, &offset
, NULL
));
3888 /***********************************************************************
3889 * Operations on file times
3890 ***********************************************************************/
3893 /*********************************************************************
3894 * CompareFileTime (kernelbase.@)
3896 INT WINAPI DECLSPEC_HOTPATCH
CompareFileTime( const FILETIME
*x
, const FILETIME
*y
)
3898 if (!x
|| !y
) return -1;
3899 if (x
->dwHighDateTime
> y
->dwHighDateTime
) return 1;
3900 if (x
->dwHighDateTime
< y
->dwHighDateTime
) return -1;
3901 if (x
->dwLowDateTime
> y
->dwLowDateTime
) return 1;
3902 if (x
->dwLowDateTime
< y
->dwLowDateTime
) return -1;
3907 /*********************************************************************
3908 * FileTimeToLocalFileTime (kernelbase.@)
3910 BOOL WINAPI DECLSPEC_HOTPATCH
FileTimeToLocalFileTime( const FILETIME
*utc
, FILETIME
*local
)
3912 return set_ntstatus( RtlSystemTimeToLocalTime( (const LARGE_INTEGER
*)utc
, (LARGE_INTEGER
*)local
));
3916 /*********************************************************************
3917 * FileTimeToSystemTime (kernelbase.@)
3919 BOOL WINAPI DECLSPEC_HOTPATCH
FileTimeToSystemTime( const FILETIME
*ft
, SYSTEMTIME
*systime
)
3922 const LARGE_INTEGER
*li
= (const LARGE_INTEGER
*)ft
;
3924 if (li
->QuadPart
< 0)
3926 SetLastError( ERROR_INVALID_PARAMETER
);
3929 RtlTimeToTimeFields( li
, &tf
);
3930 systime
->wYear
= tf
.Year
;
3931 systime
->wMonth
= tf
.Month
;
3932 systime
->wDay
= tf
.Day
;
3933 systime
->wHour
= tf
.Hour
;
3934 systime
->wMinute
= tf
.Minute
;
3935 systime
->wSecond
= tf
.Second
;
3936 systime
->wMilliseconds
= tf
.Milliseconds
;
3937 systime
->wDayOfWeek
= tf
.Weekday
;
3942 /*********************************************************************
3943 * GetLocalTime (kernelbase.@)
3945 void WINAPI DECLSPEC_HOTPATCH
GetLocalTime( SYSTEMTIME
*systime
)
3947 LARGE_INTEGER ft
, ft2
;
3949 NtQuerySystemTime( &ft
);
3950 RtlSystemTimeToLocalTime( &ft
, &ft2
);
3951 FileTimeToSystemTime( (FILETIME
*)&ft2
, systime
);
3955 /*********************************************************************
3956 * GetSystemTime (kernelbase.@)
3958 void WINAPI DECLSPEC_HOTPATCH
GetSystemTime( SYSTEMTIME
*systime
)
3962 NtQuerySystemTime( &ft
);
3963 FileTimeToSystemTime( (FILETIME
*)&ft
, systime
);
3967 /***********************************************************************
3968 * GetSystemTimeAdjustment (kernelbase.@)
3970 BOOL WINAPI DECLSPEC_HOTPATCH
GetSystemTimeAdjustment( DWORD
*adjust
, DWORD
*increment
, BOOL
*disabled
)
3972 SYSTEM_TIME_ADJUSTMENT_QUERY st
;
3975 if (!set_ntstatus( NtQuerySystemInformation( SystemTimeAdjustmentInformation
, &st
, sizeof(st
), &len
)))
3977 *adjust
= st
.TimeAdjustment
;
3978 *increment
= st
.TimeIncrement
;
3979 *disabled
= st
.TimeAdjustmentDisabled
;
3984 /***********************************************************************
3985 * GetSystemTimeAsFileTime (kernelbase.@)
3987 void WINAPI DECLSPEC_HOTPATCH
GetSystemTimeAsFileTime( FILETIME
*time
)
3989 NtQuerySystemTime( (LARGE_INTEGER
*)time
);
3993 /***********************************************************************
3994 * GetSystemTimePreciseAsFileTime (kernelbase.@)
3996 void WINAPI DECLSPEC_HOTPATCH
GetSystemTimePreciseAsFileTime( FILETIME
*time
)
4000 t
.QuadPart
= RtlGetSystemTimePrecise();
4001 time
->dwLowDateTime
= t
.u
.LowPart
;
4002 time
->dwHighDateTime
= t
.u
.HighPart
;
4006 /*********************************************************************
4007 * LocalFileTimeToFileTime (kernelbase.@)
4009 BOOL WINAPI DECLSPEC_HOTPATCH
LocalFileTimeToFileTime( const FILETIME
*local
, FILETIME
*utc
)
4011 return set_ntstatus( RtlLocalTimeToSystemTime( (const LARGE_INTEGER
*)local
, (LARGE_INTEGER
*)utc
));
4015 /***********************************************************************
4016 * SetLocalTime (kernelbase.@)
4018 BOOL WINAPI DECLSPEC_HOTPATCH
SetLocalTime( const SYSTEMTIME
*systime
)
4023 if (!SystemTimeToFileTime( systime
, &ft
)) return FALSE
;
4024 RtlLocalTimeToSystemTime( (LARGE_INTEGER
*)&ft
, &st
);
4025 return set_ntstatus( NtSetSystemTime( &st
, NULL
));
4029 /***********************************************************************
4030 * SetSystemTime (kernelbase.@)
4032 BOOL WINAPI DECLSPEC_HOTPATCH
SetSystemTime( const SYSTEMTIME
*systime
)
4036 if (!SystemTimeToFileTime( systime
, &ft
)) return FALSE
;
4037 return set_ntstatus( NtSetSystemTime( (LARGE_INTEGER
*)&ft
, NULL
));
4041 /***********************************************************************
4042 * SetSystemTimeAdjustment (kernelbase.@)
4044 BOOL WINAPI DECLSPEC_HOTPATCH
SetSystemTimeAdjustment( DWORD adjust
, BOOL disabled
)
4046 SYSTEM_TIME_ADJUSTMENT st
;
4048 st
.TimeAdjustment
= adjust
;
4049 st
.TimeAdjustmentDisabled
= disabled
;
4050 return set_ntstatus( NtSetSystemInformation( SystemTimeAdjustmentInformation
, &st
, sizeof(st
) ));
4054 /*********************************************************************
4055 * SystemTimeToFileTime (kernelbase.@)
4057 BOOL WINAPI DECLSPEC_HOTPATCH
SystemTimeToFileTime( const SYSTEMTIME
*systime
, FILETIME
*ft
)
4061 tf
.Year
= systime
->wYear
;
4062 tf
.Month
= systime
->wMonth
;
4063 tf
.Day
= systime
->wDay
;
4064 tf
.Hour
= systime
->wHour
;
4065 tf
.Minute
= systime
->wMinute
;
4066 tf
.Second
= systime
->wSecond
;
4067 tf
.Milliseconds
= systime
->wMilliseconds
;
4068 if (RtlTimeFieldsToTime( &tf
, (LARGE_INTEGER
*)ft
)) return TRUE
;
4069 SetLastError( ERROR_INVALID_PARAMETER
);
4074 /***********************************************************************
4076 ***********************************************************************/
4079 static void dump_dcb( const DCB
*dcb
)
4081 TRACE( "size=%d rate=%ld fParity=%d Parity=%d stopbits=%d %sIXON %sIXOFF CTS=%d RTS=%d DSR=%d DTR=%d %sCRTSCTS\n",
4082 dcb
->ByteSize
, dcb
->BaudRate
, dcb
->fParity
, dcb
->Parity
,
4083 (dcb
->StopBits
== ONESTOPBIT
) ? 1 : (dcb
->StopBits
== TWOSTOPBITS
) ? 2 : 0,
4084 dcb
->fOutX
? "" : "~", dcb
->fInX
? "" : "~",
4085 dcb
->fOutxCtsFlow
, dcb
->fRtsControl
, dcb
->fOutxDsrFlow
, dcb
->fDtrControl
,
4086 (dcb
->fOutxCtsFlow
|| dcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
) ? "" : "~" );
4089 /*****************************************************************************
4090 * ClearCommBreak (kernelbase.@)
4092 BOOL WINAPI DECLSPEC_HOTPATCH
ClearCommBreak( HANDLE handle
)
4094 return EscapeCommFunction( handle
, CLRBREAK
);
4098 /*****************************************************************************
4099 * ClearCommError (kernelbase.@)
4101 BOOL WINAPI DECLSPEC_HOTPATCH
ClearCommError( HANDLE handle
, DWORD
*errors
, COMSTAT
*stat
)
4105 if (!DeviceIoControl( handle
, IOCTL_SERIAL_GET_COMMSTATUS
, NULL
, 0, &ss
, sizeof(ss
), NULL
, NULL
))
4108 TRACE( "status %#lx,%#lx, in %lu, out %lu, eof %d, wait %d\n", ss
.Errors
, ss
.HoldReasons
,
4109 ss
.AmountInInQueue
, ss
.AmountInOutQueue
, ss
.EofReceived
, ss
.WaitForImmediate
);
4114 if (ss
.Errors
& SERIAL_ERROR_BREAK
) *errors
|= CE_BREAK
;
4115 if (ss
.Errors
& SERIAL_ERROR_FRAMING
) *errors
|= CE_FRAME
;
4116 if (ss
.Errors
& SERIAL_ERROR_OVERRUN
) *errors
|= CE_OVERRUN
;
4117 if (ss
.Errors
& SERIAL_ERROR_QUEUEOVERRUN
) *errors
|= CE_RXOVER
;
4118 if (ss
.Errors
& SERIAL_ERROR_PARITY
) *errors
|= CE_RXPARITY
;
4122 stat
->fCtsHold
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_CTS
);
4123 stat
->fDsrHold
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_DSR
);
4124 stat
->fRlsdHold
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_DCD
);
4125 stat
->fXoffHold
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_XON
);
4126 stat
->fXoffSent
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_XOFF_SENT
);
4127 stat
->fEof
= !!ss
.EofReceived
;
4128 stat
->fTxim
= !!ss
.WaitForImmediate
;
4129 stat
->cbInQue
= ss
.AmountInInQueue
;
4130 stat
->cbOutQue
= ss
.AmountInOutQueue
;
4136 /****************************************************************************
4137 * DeviceIoControl (kernelbase.@)
4139 BOOL WINAPI DECLSPEC_HOTPATCH
DeviceIoControl( HANDLE handle
, DWORD code
, void *in_buff
, DWORD in_count
,
4140 void *out_buff
, DWORD out_count
, DWORD
*returned
,
4141 OVERLAPPED
*overlapped
)
4143 IO_STATUS_BLOCK iosb
, *piosb
= &iosb
;
4144 void *cvalue
= NULL
;
4148 TRACE( "(%p,%lx,%p,%ld,%p,%ld,%p,%p)\n",
4149 handle
, code
, in_buff
, in_count
, out_buff
, out_count
, returned
, overlapped
);
4153 piosb
= (IO_STATUS_BLOCK
*)overlapped
;
4154 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
4155 event
= overlapped
->hEvent
;
4156 overlapped
->Internal
= STATUS_PENDING
;
4157 overlapped
->InternalHigh
= 0;
4160 if (HIWORD(code
) == FILE_DEVICE_FILE_SYSTEM
)
4161 status
= NtFsControlFile( handle
, event
, NULL
, cvalue
, piosb
, code
,
4162 in_buff
, in_count
, out_buff
, out_count
);
4164 status
= NtDeviceIoControlFile( handle
, event
, NULL
, cvalue
, piosb
, code
,
4165 in_buff
, in_count
, out_buff
, out_count
);
4167 if (returned
&& !NT_ERROR(status
)) *returned
= piosb
->Information
;
4168 if (status
== STATUS_PENDING
|| !NT_SUCCESS( status
)) return set_ntstatus( status
);
4173 /*****************************************************************************
4174 * EscapeCommFunction (kernelbase.@)
4176 BOOL WINAPI DECLSPEC_HOTPATCH
EscapeCommFunction( HANDLE handle
, DWORD func
)
4178 static const DWORD ioctls
[] =
4181 IOCTL_SERIAL_SET_XOFF
, /* SETXOFF */
4182 IOCTL_SERIAL_SET_XON
, /* SETXON */
4183 IOCTL_SERIAL_SET_RTS
, /* SETRTS */
4184 IOCTL_SERIAL_CLR_RTS
, /* CLRRTS */
4185 IOCTL_SERIAL_SET_DTR
, /* SETDTR */
4186 IOCTL_SERIAL_CLR_DTR
, /* CLRDTR */
4187 IOCTL_SERIAL_RESET_DEVICE
, /* RESETDEV */
4188 IOCTL_SERIAL_SET_BREAK_ON
, /* SETBREAK */
4189 IOCTL_SERIAL_SET_BREAK_OFF
/* CLRBREAK */
4192 if (func
>= ARRAY_SIZE(ioctls
) || !ioctls
[func
])
4194 SetLastError( ERROR_INVALID_PARAMETER
);
4197 return DeviceIoControl( handle
, ioctls
[func
], NULL
, 0, NULL
, 0, NULL
, NULL
);
4201 /***********************************************************************
4202 * GetCommConfig (kernelbase.@)
4204 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommConfig( HANDLE handle
, COMMCONFIG
*config
, DWORD
*size
)
4206 if (!config
) return FALSE
;
4208 TRACE( "(%p, %p, %p %lu)\n", handle
, config
, size
, *size
);
4210 if (*size
< sizeof(COMMCONFIG
))
4212 *size
= sizeof(COMMCONFIG
);
4215 *size
= sizeof(COMMCONFIG
);
4216 config
->dwSize
= sizeof(COMMCONFIG
);
4217 config
->wVersion
= 1;
4218 config
->wReserved
= 0;
4219 config
->dwProviderSubType
= PST_RS232
;
4220 config
->dwProviderOffset
= 0;
4221 config
->dwProviderSize
= 0;
4222 return GetCommState( handle
, &config
->dcb
);
4226 /*****************************************************************************
4227 * GetCommMask (kernelbase.@)
4229 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommMask( HANDLE handle
, DWORD
*mask
)
4231 return DeviceIoControl( handle
, IOCTL_SERIAL_GET_WAIT_MASK
, NULL
, 0, mask
, sizeof(*mask
),
4236 /***********************************************************************
4237 * GetCommModemStatus (kernelbase.@)
4239 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommModemStatus( HANDLE handle
, DWORD
*status
)
4241 return DeviceIoControl( handle
, IOCTL_SERIAL_GET_MODEMSTATUS
, NULL
, 0, status
, sizeof(*status
),
4246 /***********************************************************************
4247 * GetCommProperties (kernelbase.@)
4249 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommProperties( HANDLE handle
, COMMPROP
*prop
)
4251 return DeviceIoControl( handle
, IOCTL_SERIAL_GET_PROPERTIES
, NULL
, 0, prop
, sizeof(*prop
), NULL
, NULL
);
4255 /*****************************************************************************
4256 * GetCommState (kernelbase.@)
4258 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommState( HANDLE handle
, DCB
*dcb
)
4260 SERIAL_BAUD_RATE sbr
;
4261 SERIAL_LINE_CONTROL slc
;
4262 SERIAL_HANDFLOW shf
;
4267 SetLastError( ERROR_INVALID_PARAMETER
);
4270 if (!DeviceIoControl(handle
, IOCTL_SERIAL_GET_BAUD_RATE
, NULL
, 0, &sbr
, sizeof(sbr
), NULL
, NULL
) ||
4271 !DeviceIoControl(handle
, IOCTL_SERIAL_GET_LINE_CONTROL
, NULL
, 0, &slc
, sizeof(slc
), NULL
, NULL
) ||
4272 !DeviceIoControl(handle
, IOCTL_SERIAL_GET_HANDFLOW
, NULL
, 0, &shf
, sizeof(shf
), NULL
, NULL
) ||
4273 !DeviceIoControl(handle
, IOCTL_SERIAL_GET_CHARS
, NULL
, 0, &sc
, sizeof(sc
), NULL
, NULL
))
4276 dcb
->DCBlength
= sizeof(*dcb
);
4277 dcb
->BaudRate
= sbr
.BaudRate
;
4278 /* yes, they seem no never be (re)set on NT */
4281 dcb
->fOutxCtsFlow
= !!(shf
.ControlHandShake
& SERIAL_CTS_HANDSHAKE
);
4282 dcb
->fOutxDsrFlow
= !!(shf
.ControlHandShake
& SERIAL_DSR_HANDSHAKE
);
4283 dcb
->fDsrSensitivity
= !!(shf
.ControlHandShake
& SERIAL_DSR_SENSITIVITY
);
4284 dcb
->fTXContinueOnXoff
= !!(shf
.FlowReplace
& SERIAL_XOFF_CONTINUE
);
4285 dcb
->fOutX
= !!(shf
.FlowReplace
& SERIAL_AUTO_TRANSMIT
);
4286 dcb
->fInX
= !!(shf
.FlowReplace
& SERIAL_AUTO_RECEIVE
);
4287 dcb
->fErrorChar
= !!(shf
.FlowReplace
& SERIAL_ERROR_CHAR
);
4288 dcb
->fNull
= !!(shf
.FlowReplace
& SERIAL_NULL_STRIPPING
);
4289 dcb
->fAbortOnError
= !!(shf
.ControlHandShake
& SERIAL_ERROR_ABORT
);
4290 dcb
->XonLim
= shf
.XonLimit
;
4291 dcb
->XoffLim
= shf
.XoffLimit
;
4292 dcb
->ByteSize
= slc
.WordLength
;
4293 dcb
->Parity
= slc
.Parity
;
4294 dcb
->StopBits
= slc
.StopBits
;
4295 dcb
->XonChar
= sc
.XonChar
;
4296 dcb
->XoffChar
= sc
.XoffChar
;
4297 dcb
->ErrorChar
= sc
.ErrorChar
;
4298 dcb
->EofChar
= sc
.EofChar
;
4299 dcb
->EvtChar
= sc
.EventChar
;
4301 switch (shf
.ControlHandShake
& (SERIAL_DTR_CONTROL
| SERIAL_DTR_HANDSHAKE
))
4303 case SERIAL_DTR_CONTROL
: dcb
->fDtrControl
= DTR_CONTROL_ENABLE
; break;
4304 case SERIAL_DTR_HANDSHAKE
: dcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
; break;
4305 default: dcb
->fDtrControl
= DTR_CONTROL_DISABLE
; break;
4307 switch (shf
.FlowReplace
& (SERIAL_RTS_CONTROL
| SERIAL_RTS_HANDSHAKE
))
4309 case SERIAL_RTS_CONTROL
: dcb
->fRtsControl
= RTS_CONTROL_ENABLE
; break;
4310 case SERIAL_RTS_HANDSHAKE
: dcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
; break;
4311 case SERIAL_RTS_CONTROL
| SERIAL_RTS_HANDSHAKE
:
4312 dcb
->fRtsControl
= RTS_CONTROL_TOGGLE
; break;
4313 default: dcb
->fRtsControl
= RTS_CONTROL_DISABLE
; break;
4320 /*****************************************************************************
4321 * GetCommTimeouts (kernelbase.@)
4323 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommTimeouts( HANDLE handle
, COMMTIMEOUTS
*timeouts
)
4327 SetLastError( ERROR_INVALID_PARAMETER
);
4330 return DeviceIoControl( handle
, IOCTL_SERIAL_GET_TIMEOUTS
, NULL
, 0, timeouts
, sizeof(*timeouts
),
4334 /********************************************************************
4335 * PurgeComm (kernelbase.@)
4337 BOOL WINAPI DECLSPEC_HOTPATCH
PurgeComm(HANDLE handle
, DWORD flags
)
4339 return DeviceIoControl( handle
, IOCTL_SERIAL_PURGE
, &flags
, sizeof(flags
),
4340 NULL
, 0, NULL
, NULL
);
4344 /*****************************************************************************
4345 * SetCommBreak (kernelbase.@)
4347 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommBreak( HANDLE handle
)
4349 return EscapeCommFunction( handle
, SETBREAK
);
4353 /***********************************************************************
4354 * SetCommConfig (kernelbase.@)
4356 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommConfig( HANDLE handle
, COMMCONFIG
*config
, DWORD size
)
4358 TRACE( "(%p, %p, %lu)\n", handle
, config
, size
);
4359 return SetCommState( handle
, &config
->dcb
);
4363 /*****************************************************************************
4364 * SetCommMask (kernelbase.@)
4366 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommMask( HANDLE handle
, DWORD mask
)
4368 return DeviceIoControl( handle
, IOCTL_SERIAL_SET_WAIT_MASK
, &mask
, sizeof(mask
),
4369 NULL
, 0, NULL
, NULL
);
4373 /*****************************************************************************
4374 * SetCommState (kernelbase.@)
4376 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommState( HANDLE handle
, DCB
*dcb
)
4378 SERIAL_BAUD_RATE sbr
;
4379 SERIAL_LINE_CONTROL slc
;
4380 SERIAL_HANDFLOW shf
;
4385 SetLastError( ERROR_INVALID_PARAMETER
);
4390 sbr
.BaudRate
= dcb
->BaudRate
;
4391 slc
.StopBits
= dcb
->StopBits
;
4392 slc
.Parity
= dcb
->Parity
;
4393 slc
.WordLength
= dcb
->ByteSize
;
4394 shf
.ControlHandShake
= 0;
4395 shf
.FlowReplace
= 0;
4396 if (dcb
->fOutxCtsFlow
) shf
.ControlHandShake
|= SERIAL_CTS_HANDSHAKE
;
4397 if (dcb
->fOutxDsrFlow
) shf
.ControlHandShake
|= SERIAL_DSR_HANDSHAKE
;
4398 switch (dcb
->fDtrControl
)
4400 case DTR_CONTROL_DISABLE
: break;
4401 case DTR_CONTROL_ENABLE
: shf
.ControlHandShake
|= SERIAL_DTR_CONTROL
; break;
4402 case DTR_CONTROL_HANDSHAKE
: shf
.ControlHandShake
|= SERIAL_DTR_HANDSHAKE
; break;
4404 SetLastError( ERROR_INVALID_PARAMETER
);
4407 switch (dcb
->fRtsControl
)
4409 case RTS_CONTROL_DISABLE
: break;
4410 case RTS_CONTROL_ENABLE
: shf
.FlowReplace
|= SERIAL_RTS_CONTROL
; break;
4411 case RTS_CONTROL_HANDSHAKE
: shf
.FlowReplace
|= SERIAL_RTS_HANDSHAKE
; break;
4412 case RTS_CONTROL_TOGGLE
: shf
.FlowReplace
|= SERIAL_RTS_CONTROL
| SERIAL_RTS_HANDSHAKE
; break;
4414 SetLastError( ERROR_INVALID_PARAMETER
);
4417 if (dcb
->fDsrSensitivity
) shf
.ControlHandShake
|= SERIAL_DSR_SENSITIVITY
;
4418 if (dcb
->fAbortOnError
) shf
.ControlHandShake
|= SERIAL_ERROR_ABORT
;
4419 if (dcb
->fErrorChar
) shf
.FlowReplace
|= SERIAL_ERROR_CHAR
;
4420 if (dcb
->fNull
) shf
.FlowReplace
|= SERIAL_NULL_STRIPPING
;
4421 if (dcb
->fTXContinueOnXoff
) shf
.FlowReplace
|= SERIAL_XOFF_CONTINUE
;
4422 if (dcb
->fOutX
) shf
.FlowReplace
|= SERIAL_AUTO_TRANSMIT
;
4423 if (dcb
->fInX
) shf
.FlowReplace
|= SERIAL_AUTO_RECEIVE
;
4424 shf
.XonLimit
= dcb
->XonLim
;
4425 shf
.XoffLimit
= dcb
->XoffLim
;
4426 sc
.EofChar
= dcb
->EofChar
;
4427 sc
.ErrorChar
= dcb
->ErrorChar
;
4429 sc
.EventChar
= dcb
->EvtChar
;
4430 sc
.XonChar
= dcb
->XonChar
;
4431 sc
.XoffChar
= dcb
->XoffChar
;
4433 /* note: change DTR/RTS lines after setting the comm attributes,
4434 * so flow control does not interfere.
4436 return (DeviceIoControl( handle
, IOCTL_SERIAL_SET_BAUD_RATE
, &sbr
, sizeof(sbr
), NULL
, 0, NULL
, NULL
) &&
4437 DeviceIoControl( handle
, IOCTL_SERIAL_SET_LINE_CONTROL
, &slc
, sizeof(slc
), NULL
, 0, NULL
, NULL
) &&
4438 DeviceIoControl( handle
, IOCTL_SERIAL_SET_HANDFLOW
, &shf
, sizeof(shf
), NULL
, 0, NULL
, NULL
) &&
4439 DeviceIoControl( handle
, IOCTL_SERIAL_SET_CHARS
, &sc
, sizeof(sc
), NULL
, 0, NULL
, NULL
));
4443 /*****************************************************************************
4444 * SetCommTimeouts (kernelbase.@)
4446 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommTimeouts( HANDLE handle
, COMMTIMEOUTS
*timeouts
)
4450 SetLastError( ERROR_INVALID_PARAMETER
);
4453 return DeviceIoControl( handle
, IOCTL_SERIAL_SET_TIMEOUTS
, timeouts
, sizeof(*timeouts
),
4454 NULL
, 0, NULL
, NULL
);
4458 /*****************************************************************************
4459 * SetupComm (kernelbase.@)
4461 BOOL WINAPI DECLSPEC_HOTPATCH
SetupComm( HANDLE handle
, DWORD in_size
, DWORD out_size
)
4463 SERIAL_QUEUE_SIZE sqs
;
4465 sqs
.InSize
= in_size
;
4466 sqs
.OutSize
= out_size
;
4467 return DeviceIoControl( handle
, IOCTL_SERIAL_SET_QUEUE_SIZE
, &sqs
, sizeof(sqs
), NULL
, 0, NULL
, NULL
);
4471 /*****************************************************************************
4472 * TransmitCommChar (kernelbase.@)
4474 BOOL WINAPI DECLSPEC_HOTPATCH
TransmitCommChar( HANDLE handle
, CHAR ch
)
4476 return DeviceIoControl( handle
, IOCTL_SERIAL_IMMEDIATE_CHAR
, &ch
, sizeof(ch
), NULL
, 0, NULL
, NULL
);
4480 /***********************************************************************
4481 * WaitCommEvent (kernelbase.@)
4483 BOOL WINAPI DECLSPEC_HOTPATCH
WaitCommEvent( HANDLE handle
, DWORD
*events
, OVERLAPPED
*overlapped
)
4485 return DeviceIoControl( handle
, IOCTL_SERIAL_WAIT_ON_MASK
, NULL
, 0, events
, sizeof(*events
),