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
38 #include "ddk/ntddk.h"
39 #include "ddk/ntddser.h"
41 #include "kernelbase.h"
42 #include "wine/exception.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(file
);
47 /* info structure for FindFirstFile handle */
50 DWORD magic
; /* magic number */
51 HANDLE handle
; /* handle to directory */
52 CRITICAL_SECTION cs
; /* crit section protecting this structure */
53 FINDEX_SEARCH_OPS search_op
; /* Flags passed to FindFirst. */
54 FINDEX_INFO_LEVELS level
; /* Level passed to FindFirst */
55 UNICODE_STRING path
; /* NT path used to open the directory */
56 BOOL is_root
; /* is directory the root of the drive? */
57 BOOL wildcard
; /* did the mask contain wildcard characters? */
58 UINT data_pos
; /* current position in dir data */
59 UINT data_len
; /* length of dir data */
60 UINT data_size
; /* size of data buffer, or 0 when everything has been read */
61 BYTE data
[1]; /* directory data */
64 #define FIND_FIRST_MAGIC 0xc0ffee11
66 static const UINT max_entry_size
= offsetof( FILE_BOTH_DIRECTORY_INFORMATION
, FileName
[256] );
68 const WCHAR windows_dir
[] = L
"C:\\windows";
69 const WCHAR system_dir
[] = L
"C:\\windows\\system32";
71 static BOOL oem_file_apis
;
74 static void WINAPI
read_write_apc( void *apc_user
, PIO_STATUS_BLOCK io
, ULONG reserved
)
76 LPOVERLAPPED_COMPLETION_ROUTINE func
= apc_user
;
77 func( RtlNtStatusToDosError( io
->u
.Status
), io
->Information
, (LPOVERLAPPED
)io
);
80 static const WCHAR
*get_machine_wow64_dir( WORD machine
)
84 case IMAGE_FILE_MACHINE_TARGET_HOST
: return system_dir
;
85 case IMAGE_FILE_MACHINE_I386
: return L
"C:\\windows\\syswow64";
86 case IMAGE_FILE_MACHINE_ARMNT
: return L
"C:\\windows\\sysarm32";
87 case IMAGE_FILE_MACHINE_AMD64
: return L
"C:\\windows\\sysx8664";
88 case IMAGE_FILE_MACHINE_ARM64
: return L
"C:\\windows\\sysarm64";
94 /***********************************************************************
95 * Operations on file names
96 ***********************************************************************/
99 /***********************************************************************
102 * Check if the file name contains a path; helper for SearchPathW.
103 * A relative path is not considered a path unless it starts with ./ or ../
105 static inline BOOL
contains_path( const WCHAR
*name
)
107 if (RtlDetermineDosPathNameType_U( name
) != RELATIVE_PATH
) return TRUE
;
108 if (name
[0] != '.') return FALSE
;
109 if (name
[1] == '/' || name
[1] == '\\') return TRUE
;
110 return (name
[1] == '.' && (name
[2] == '/' || name
[2] == '\\'));
114 /***********************************************************************
117 static WCHAR
*append_ext( const WCHAR
*name
, const WCHAR
*ext
)
123 if (!ext
) return NULL
;
124 p
= wcsrchr( name
, '.' );
125 if (p
&& !wcschr( p
, '/' ) && !wcschr( p
, '\\' )) return NULL
;
127 len
= lstrlenW( name
) + lstrlenW( ext
);
128 if ((ret
= RtlAllocateHeap( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) )))
130 lstrcpyW( ret
, name
);
131 lstrcatW( ret
, ext
);
137 /***********************************************************************
138 * find_actctx_dllpath
140 * Find the path (if any) of the dll from the activation context.
141 * Returned path doesn't include a name.
143 static NTSTATUS
find_actctx_dllpath( const WCHAR
*name
, WCHAR
**path
)
145 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION
*info
;
146 ACTCTX_SECTION_KEYED_DATA data
;
147 UNICODE_STRING nameW
;
149 SIZE_T needed
, size
= 1024;
152 RtlInitUnicodeString( &nameW
, name
);
153 data
.cbSize
= sizeof(data
);
154 status
= RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX
, NULL
,
155 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION
,
157 if (status
!= STATUS_SUCCESS
) return status
;
161 if (!(info
= RtlAllocateHeap( GetProcessHeap(), 0, size
)))
163 status
= STATUS_NO_MEMORY
;
166 status
= RtlQueryInformationActivationContext( 0, data
.hActCtx
, &data
.ulAssemblyRosterIndex
,
167 AssemblyDetailedInformationInActivationContext
,
168 info
, size
, &needed
);
169 if (status
== STATUS_SUCCESS
) break;
170 if (status
!= STATUS_BUFFER_TOO_SMALL
) goto done
;
171 RtlFreeHeap( GetProcessHeap(), 0, info
);
173 /* restart with larger buffer */
176 if (!info
->lpAssemblyManifestPath
)
178 status
= STATUS_SXS_KEY_NOT_FOUND
;
182 if ((p
= wcsrchr( info
->lpAssemblyManifestPath
, '\\' )))
184 DWORD dirlen
= info
->ulAssemblyDirectoryNameLength
/ sizeof(WCHAR
);
188 CompareStringOrdinal( p
, dirlen
, info
->lpAssemblyDirectoryName
, dirlen
, TRUE
) != CSTR_EQUAL
||
189 wcsicmp( p
+ dirlen
, L
".manifest" ))
191 /* manifest name does not match directory name, so it's not a global
192 * windows/winsxs manifest; use the manifest directory name instead */
193 dirlen
= p
- info
->lpAssemblyManifestPath
;
194 needed
= (dirlen
+ 1) * sizeof(WCHAR
);
195 if (!(*path
= p
= HeapAlloc( GetProcessHeap(), 0, needed
)))
197 status
= STATUS_NO_MEMORY
;
200 memcpy( p
, info
->lpAssemblyManifestPath
, dirlen
* sizeof(WCHAR
) );
206 if (!info
->lpAssemblyDirectoryName
)
208 status
= STATUS_SXS_KEY_NOT_FOUND
;
212 needed
= sizeof(L
"C:\\windows\\winsxs\\") + info
->ulAssemblyDirectoryNameLength
+ sizeof(WCHAR
);
214 if (!(*path
= p
= RtlAllocateHeap( GetProcessHeap(), 0, needed
)))
216 status
= STATUS_NO_MEMORY
;
219 lstrcpyW( p
, L
"C:\\windows\\winsxs\\" );
221 memcpy( p
, info
->lpAssemblyDirectoryName
, info
->ulAssemblyDirectoryNameLength
);
222 p
+= info
->ulAssemblyDirectoryNameLength
/ sizeof(WCHAR
);
226 RtlFreeHeap( GetProcessHeap(), 0, info
);
227 RtlReleaseActivationContext( data
.hActCtx
);
232 /***********************************************************************
235 static DWORD
copy_filename( const WCHAR
*name
, WCHAR
*buffer
, DWORD len
)
237 UINT ret
= lstrlenW( name
) + 1;
238 if (buffer
&& len
>= ret
)
240 lstrcpyW( buffer
, name
);
247 /***********************************************************************
250 * copy a file name back to OEM/Ansi, but only if the buffer is large enough
252 static DWORD
copy_filename_WtoA( LPCWSTR nameW
, LPSTR buffer
, DWORD len
)
257 RtlInitUnicodeString( &strW
, nameW
);
259 ret
= oem_file_apis
? RtlUnicodeStringToOemSize( &strW
) : RtlUnicodeStringToAnsiSize( &strW
);
260 if (buffer
&& ret
<= len
)
265 str
.MaximumLength
= min( len
, UNICODE_STRING_MAX_CHARS
);
267 RtlUnicodeStringToOemString( &str
, &strW
, FALSE
);
269 RtlUnicodeStringToAnsiString( &str
, &strW
, FALSE
);
270 ret
= str
.Length
; /* length without terminating 0 */
276 /***********************************************************************
279 * Convert a file name to Unicode, taking into account the OEM/Ansi API mode.
281 * If alloc is FALSE uses the TEB static buffer, so it can only be used when
282 * there is no possibility for the function to do that twice, taking into
283 * account any called function.
285 WCHAR
*file_name_AtoW( LPCSTR name
, BOOL alloc
)
288 UNICODE_STRING strW
, *pstrW
;
291 RtlInitAnsiString( &str
, name
);
292 pstrW
= alloc
? &strW
: &NtCurrentTeb()->StaticUnicodeString
;
294 status
= RtlOemStringToUnicodeString( pstrW
, &str
, alloc
);
296 status
= RtlAnsiStringToUnicodeString( pstrW
, &str
, alloc
);
297 if (status
== STATUS_SUCCESS
) return pstrW
->Buffer
;
299 if (status
== STATUS_BUFFER_OVERFLOW
)
300 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
302 SetLastError( RtlNtStatusToDosError(status
) );
307 /***********************************************************************
310 * Convert a file name back to OEM/Ansi. Returns number of bytes copied.
312 DWORD
file_name_WtoA( LPCWSTR src
, INT srclen
, LPSTR dest
, INT destlen
)
316 if (srclen
< 0) srclen
= lstrlenW( src
) + 1;
322 strW
.Buffer
= (WCHAR
*)src
;
323 strW
.Length
= srclen
* sizeof(WCHAR
);
324 ret
= RtlUnicodeStringToOemSize( &strW
) - 1;
327 RtlUnicodeToMultiByteSize( &ret
, src
, srclen
* sizeof(WCHAR
) );
332 RtlUnicodeToOemN( dest
, destlen
, &ret
, src
, srclen
* sizeof(WCHAR
) );
334 RtlUnicodeToMultiByteN( dest
, destlen
, &ret
, src
, srclen
* sizeof(WCHAR
) );
340 /******************************************************************************
341 * AreFileApisANSI (kernelbase.@)
343 BOOL WINAPI DECLSPEC_HOTPATCH
AreFileApisANSI(void)
345 return !oem_file_apis
;
349 /***********************************************************************
350 * CreateDirectoryA (kernelbase.@)
352 BOOL WINAPI DECLSPEC_HOTPATCH
CreateDirectoryA( LPCSTR path
, LPSECURITY_ATTRIBUTES sa
)
356 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return FALSE
;
357 return CreateDirectoryW( pathW
, sa
);
361 /***********************************************************************
362 * CreateDirectoryW (kernelbase.@)
364 BOOL WINAPI DECLSPEC_HOTPATCH
CreateDirectoryW( LPCWSTR path
, LPSECURITY_ATTRIBUTES sa
)
366 OBJECT_ATTRIBUTES attr
;
367 UNICODE_STRING nt_name
;
372 TRACE( "%s\n", debugstr_w(path
) );
374 if (!RtlDosPathNameToNtPathName_U( path
, &nt_name
, NULL
, NULL
))
376 SetLastError( ERROR_PATH_NOT_FOUND
);
379 attr
.Length
= sizeof(attr
);
380 attr
.RootDirectory
= 0;
381 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
382 attr
.ObjectName
= &nt_name
;
383 attr
.SecurityDescriptor
= sa
? sa
->lpSecurityDescriptor
: NULL
;
384 attr
.SecurityQualityOfService
= NULL
;
386 status
= NtCreateFile( &handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
, NULL
,
387 FILE_ATTRIBUTE_NORMAL
, FILE_SHARE_READ
, FILE_CREATE
,
388 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
389 if (status
== STATUS_SUCCESS
) NtClose( handle
);
391 RtlFreeUnicodeString( &nt_name
);
392 return set_ntstatus( status
);
396 /***********************************************************************
397 * CreateDirectoryEx (kernelbase.@)
399 BOOL WINAPI DECLSPEC_HOTPATCH
CreateDirectoryExW( LPCWSTR
template, LPCWSTR path
,
400 LPSECURITY_ATTRIBUTES sa
)
402 return CreateDirectoryW( path
, sa
);
406 /*************************************************************************
407 * CreateFile2 (kernelbase.@)
409 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFile2( LPCWSTR name
, DWORD access
, DWORD sharing
, DWORD creation
,
410 CREATEFILE2_EXTENDED_PARAMETERS
*params
)
412 LPSECURITY_ATTRIBUTES sa
= params
? params
->lpSecurityAttributes
: NULL
;
413 DWORD attributes
= params
? params
->dwFileAttributes
: 0;
414 HANDLE
template = params
? params
->hTemplateFile
: NULL
;
416 FIXME( "(%s %x %x %x %p), partial stub\n", debugstr_w(name
), access
, sharing
, creation
, params
);
418 return CreateFileW( name
, access
, sharing
, sa
, creation
, attributes
, template );
422 /*************************************************************************
423 * CreateFileA (kernelbase.@)
425 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileA( LPCSTR name
, DWORD access
, DWORD sharing
,
426 LPSECURITY_ATTRIBUTES sa
, DWORD creation
,
427 DWORD attributes
, HANDLE
template)
431 if ((GetVersion() & 0x80000000) && IsBadStringPtrA( name
, -1 )) return INVALID_HANDLE_VALUE
;
432 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return INVALID_HANDLE_VALUE
;
433 return CreateFileW( nameW
, access
, sharing
, sa
, creation
, attributes
, template );
436 static UINT
get_nt_file_options( DWORD attributes
)
440 if (attributes
& FILE_FLAG_BACKUP_SEMANTICS
)
441 options
|= FILE_OPEN_FOR_BACKUP_INTENT
;
443 options
|= FILE_NON_DIRECTORY_FILE
;
444 if (attributes
& FILE_FLAG_DELETE_ON_CLOSE
)
445 options
|= FILE_DELETE_ON_CLOSE
;
446 if (attributes
& FILE_FLAG_NO_BUFFERING
)
447 options
|= FILE_NO_INTERMEDIATE_BUFFERING
;
448 if (!(attributes
& FILE_FLAG_OVERLAPPED
))
449 options
|= FILE_SYNCHRONOUS_IO_NONALERT
;
450 if (attributes
& FILE_FLAG_RANDOM_ACCESS
)
451 options
|= FILE_RANDOM_ACCESS
;
452 if (attributes
& FILE_FLAG_WRITE_THROUGH
)
453 options
|= FILE_WRITE_THROUGH
;
457 /*************************************************************************
458 * CreateFileW (kernelbase.@)
460 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateFileW( LPCWSTR filename
, DWORD access
, DWORD sharing
,
461 LPSECURITY_ATTRIBUTES sa
, DWORD creation
,
462 DWORD attributes
, HANDLE
template )
465 OBJECT_ATTRIBUTES attr
;
466 UNICODE_STRING nameW
;
470 const WCHAR
*vxd_name
= NULL
;
471 SECURITY_QUALITY_OF_SERVICE qos
;
473 static const UINT nt_disposition
[5] =
475 FILE_CREATE
, /* CREATE_NEW */
476 FILE_OVERWRITE_IF
, /* CREATE_ALWAYS */
477 FILE_OPEN
, /* OPEN_EXISTING */
478 FILE_OPEN_IF
, /* OPEN_ALWAYS */
479 FILE_OVERWRITE
/* TRUNCATE_EXISTING */
485 if (!filename
|| !filename
[0])
487 SetLastError( ERROR_PATH_NOT_FOUND
);
488 return INVALID_HANDLE_VALUE
;
491 TRACE( "%s %s%s%s%s%s%s%s creation %d attributes 0x%x\n", debugstr_w(filename
),
492 (access
& GENERIC_READ
) ? "GENERIC_READ " : "",
493 (access
& GENERIC_WRITE
) ? "GENERIC_WRITE " : "",
494 (access
& GENERIC_EXECUTE
) ? "GENERIC_EXECUTE " : "",
495 !access
? "QUERY_ACCESS " : "",
496 (sharing
& FILE_SHARE_READ
) ? "FILE_SHARE_READ " : "",
497 (sharing
& FILE_SHARE_WRITE
) ? "FILE_SHARE_WRITE " : "",
498 (sharing
& FILE_SHARE_DELETE
) ? "FILE_SHARE_DELETE " : "",
499 creation
, attributes
);
501 /* Open a console for CONIN$ or CONOUT$ */
503 if (!wcsicmp( filename
, L
"CONIN$" ))
504 return open_console( FALSE
, access
, sa
, creation
? OPEN_EXISTING
: 0 );
505 if (!wcsicmp( filename
, L
"CONOUT$" ))
506 return open_console( TRUE
, access
, sa
, creation
? OPEN_EXISTING
: 0 );
508 if (!wcsncmp( filename
, L
"\\\\.\\", 4 ))
510 if ((filename
[4] && filename
[5] == ':' && !filename
[6]) ||
511 !wcsnicmp( filename
+ 4, L
"PIPE\\", 5 ) ||
512 !wcsnicmp( filename
+ 4, L
"MAILSLOT\\", 9 ))
516 else if ((dosdev
= RtlIsDosDeviceName_U( filename
+ 4 )))
518 dosdev
+= MAKELONG( 0, 4*sizeof(WCHAR
) ); /* adjust position to start of filename */
520 else if (GetVersion() & 0x80000000)
522 vxd_name
= filename
+ 4;
523 if (!creation
) creation
= OPEN_EXISTING
;
526 else dosdev
= RtlIsDosDeviceName_U( filename
);
530 if (LOWORD(dosdev
) == 3 * sizeof(WCHAR
) &&
531 !wcsnicmp( filename
+ HIWORD(dosdev
)/sizeof(WCHAR
), L
"CON", 3 ))
533 switch (access
& (GENERIC_READ
|GENERIC_WRITE
))
536 return open_console( FALSE
, access
, sa
, OPEN_EXISTING
);
538 return open_console( TRUE
, access
, sa
, OPEN_EXISTING
);
540 SetLastError( ERROR_FILE_NOT_FOUND
);
541 return INVALID_HANDLE_VALUE
;
546 if (creation
< CREATE_NEW
|| creation
> TRUNCATE_EXISTING
)
548 SetLastError( ERROR_INVALID_PARAMETER
);
549 return INVALID_HANDLE_VALUE
;
552 if (!RtlDosPathNameToNtPathName_U( filename
, &nameW
, NULL
, NULL
))
554 SetLastError( ERROR_PATH_NOT_FOUND
);
555 return INVALID_HANDLE_VALUE
;
558 /* now call NtCreateFile */
560 if (attributes
& FILE_FLAG_DELETE_ON_CLOSE
)
563 attr
.Length
= sizeof(attr
);
564 attr
.RootDirectory
= 0;
565 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
566 attr
.ObjectName
= &nameW
;
567 attr
.SecurityDescriptor
= sa
? sa
->lpSecurityDescriptor
: NULL
;
568 if (attributes
& SECURITY_SQOS_PRESENT
)
570 qos
.Length
= sizeof(qos
);
571 qos
.ImpersonationLevel
= (attributes
>> 16) & 0x3;
572 qos
.ContextTrackingMode
= attributes
& SECURITY_CONTEXT_TRACKING
? SECURITY_DYNAMIC_TRACKING
: SECURITY_STATIC_TRACKING
;
573 qos
.EffectiveOnly
= (attributes
& SECURITY_EFFECTIVE_ONLY
) != 0;
574 attr
.SecurityQualityOfService
= &qos
;
577 attr
.SecurityQualityOfService
= NULL
;
579 if (sa
&& sa
->bInheritHandle
) attr
.Attributes
|= OBJ_INHERIT
;
581 status
= NtCreateFile( &ret
, access
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
, &attr
, &io
,
582 NULL
, attributes
& FILE_ATTRIBUTE_VALID_FLAGS
, sharing
,
583 nt_disposition
[creation
- CREATE_NEW
],
584 get_nt_file_options( attributes
), NULL
, 0 );
587 if (vxd_name
&& vxd_name
[0])
589 static HANDLE (*vxd_open
)(LPCWSTR
,DWORD
,SECURITY_ATTRIBUTES
*);
590 if (!vxd_open
) vxd_open
= (void *)GetProcAddress( GetModuleHandleW(L
"krnl386.exe16"),
592 if (vxd_open
&& (ret
= vxd_open( vxd_name
, access
, sa
))) goto done
;
595 WARN("Unable to create file %s (status %x)\n", debugstr_w(filename
), status
);
596 ret
= INVALID_HANDLE_VALUE
;
598 /* In the case file creation was rejected due to CREATE_NEW flag
599 * was specified and file with that name already exists, correct
600 * last error is ERROR_FILE_EXISTS and not ERROR_ALREADY_EXISTS.
601 * Note: RtlNtStatusToDosError is not the subject to blame here.
603 if (status
== STATUS_OBJECT_NAME_COLLISION
)
604 SetLastError( ERROR_FILE_EXISTS
);
606 SetLastError( RtlNtStatusToDosError(status
) );
610 if ((creation
== CREATE_ALWAYS
&& io
.Information
== FILE_OVERWRITTEN
) ||
611 (creation
== OPEN_ALWAYS
&& io
.Information
== FILE_OPENED
))
612 SetLastError( ERROR_ALREADY_EXISTS
);
616 RtlFreeUnicodeString( &nameW
);
619 if (!ret
) ret
= INVALID_HANDLE_VALUE
;
620 TRACE("returning %p\n", ret
);
625 /***********************************************************************
626 * DeleteFileA (kernelbase.@)
628 BOOL WINAPI DECLSPEC_HOTPATCH
DeleteFileA( LPCSTR path
)
632 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return FALSE
;
633 return DeleteFileW( pathW
);
637 /***********************************************************************
638 * DeleteFileW (kernelbase.@)
640 BOOL WINAPI DECLSPEC_HOTPATCH
DeleteFileW( LPCWSTR path
)
642 UNICODE_STRING nameW
;
643 OBJECT_ATTRIBUTES attr
;
648 TRACE( "%s\n", debugstr_w(path
) );
650 if (!RtlDosPathNameToNtPathName_U( path
, &nameW
, NULL
, NULL
))
652 SetLastError( ERROR_PATH_NOT_FOUND
);
656 attr
.Length
= sizeof(attr
);
657 attr
.RootDirectory
= 0;
658 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
659 attr
.ObjectName
= &nameW
;
660 attr
.SecurityDescriptor
= NULL
;
661 attr
.SecurityQualityOfService
= NULL
;
663 status
= NtCreateFile(&hFile
, SYNCHRONIZE
| DELETE
, &attr
, &io
, NULL
, 0,
664 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
665 FILE_OPEN
, FILE_DELETE_ON_CLOSE
| FILE_NON_DIRECTORY_FILE
, NULL
, 0);
666 if (status
== STATUS_SUCCESS
) status
= NtClose(hFile
);
668 RtlFreeUnicodeString( &nameW
);
669 return set_ntstatus( status
);
673 /****************************************************************************
674 * FindCloseChangeNotification (kernelbase.@)
676 BOOL WINAPI DECLSPEC_HOTPATCH
FindCloseChangeNotification( HANDLE handle
)
678 return CloseHandle( handle
);
682 /****************************************************************************
683 * FindFirstChangeNotificationA (kernelbase.@)
685 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstChangeNotificationA( LPCSTR path
, BOOL subtree
, DWORD filter
)
689 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return INVALID_HANDLE_VALUE
;
690 return FindFirstChangeNotificationW( pathW
, subtree
, filter
);
695 * NtNotifyChangeDirectoryFile may write back to the IO_STATUS_BLOCK
696 * asynchronously. We don't care about the contents, but it can't
697 * be placed on the stack since it will go out of scope when we return.
699 static IO_STATUS_BLOCK dummy_iosb
;
701 /****************************************************************************
702 * FindFirstChangeNotificationW (kernelbase.@)
704 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstChangeNotificationW( LPCWSTR path
, BOOL subtree
, DWORD filter
)
706 UNICODE_STRING nt_name
;
707 OBJECT_ATTRIBUTES attr
;
709 HANDLE handle
= INVALID_HANDLE_VALUE
;
711 TRACE( "%s %d %x\n", debugstr_w(path
), subtree
, filter
);
713 if (!RtlDosPathNameToNtPathName_U( path
, &nt_name
, NULL
, NULL
))
715 SetLastError( ERROR_PATH_NOT_FOUND
);
719 attr
.Length
= sizeof(attr
);
720 attr
.RootDirectory
= 0;
721 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
722 attr
.ObjectName
= &nt_name
;
723 attr
.SecurityDescriptor
= NULL
;
724 attr
.SecurityQualityOfService
= NULL
;
726 status
= NtOpenFile( &handle
, FILE_LIST_DIRECTORY
| SYNCHRONIZE
, &attr
, &dummy_iosb
,
727 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
,
728 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
);
729 RtlFreeUnicodeString( &nt_name
);
731 if (!set_ntstatus( status
)) return INVALID_HANDLE_VALUE
;
733 status
= NtNotifyChangeDirectoryFile( handle
, NULL
, NULL
, NULL
, &dummy_iosb
, NULL
, 0, filter
, subtree
);
734 if (status
!= STATUS_PENDING
)
737 SetLastError( RtlNtStatusToDosError(status
) );
738 return INVALID_HANDLE_VALUE
;
744 /****************************************************************************
745 * FindNextChangeNotification (kernelbase.@)
747 BOOL WINAPI DECLSPEC_HOTPATCH
FindNextChangeNotification( HANDLE handle
)
749 NTSTATUS status
= NtNotifyChangeDirectoryFile( handle
, NULL
, NULL
, NULL
, &dummy_iosb
,
750 NULL
, 0, FILE_NOTIFY_CHANGE_SIZE
, 0 );
751 if (status
== STATUS_PENDING
) return TRUE
;
752 return set_ntstatus( status
);
756 /******************************************************************************
757 * FindFirstFileExA (kernelbase.@)
759 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileExA( const char *filename
, FINDEX_INFO_LEVELS level
,
760 void *data
, FINDEX_SEARCH_OPS search_op
,
761 void *filter
, DWORD flags
)
764 WIN32_FIND_DATAA
*dataA
= data
;
765 WIN32_FIND_DATAW dataW
;
768 if (!(nameW
= file_name_AtoW( filename
, FALSE
))) return INVALID_HANDLE_VALUE
;
770 handle
= FindFirstFileExW( nameW
, level
, &dataW
, search_op
, filter
, flags
);
771 if (handle
== INVALID_HANDLE_VALUE
) return handle
;
773 dataA
->dwFileAttributes
= dataW
.dwFileAttributes
;
774 dataA
->ftCreationTime
= dataW
.ftCreationTime
;
775 dataA
->ftLastAccessTime
= dataW
.ftLastAccessTime
;
776 dataA
->ftLastWriteTime
= dataW
.ftLastWriteTime
;
777 dataA
->nFileSizeHigh
= dataW
.nFileSizeHigh
;
778 dataA
->nFileSizeLow
= dataW
.nFileSizeLow
;
779 file_name_WtoA( dataW
.cFileName
, -1, dataA
->cFileName
, sizeof(dataA
->cFileName
) );
780 file_name_WtoA( dataW
.cAlternateFileName
, -1, dataA
->cAlternateFileName
,
781 sizeof(dataA
->cAlternateFileName
) );
786 /******************************************************************************
787 * FindFirstFileExW (kernelbase.@)
789 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileExW( LPCWSTR filename
, FINDEX_INFO_LEVELS level
,
790 LPVOID data
, FINDEX_SEARCH_OPS search_op
,
791 LPVOID filter
, DWORD flags
)
794 BOOL has_wildcard
= FALSE
;
795 FIND_FIRST_INFO
*info
= NULL
;
796 UNICODE_STRING nt_name
;
797 OBJECT_ATTRIBUTES attr
;
800 DWORD size
, device
= 0;
802 TRACE( "%s %d %p %d %p %x\n", debugstr_w(filename
), level
, data
, search_op
, filter
, flags
);
804 if (flags
& ~FIND_FIRST_EX_LARGE_FETCH
)
806 FIXME("flags not implemented 0x%08x\n", flags
);
808 if (search_op
!= FindExSearchNameMatch
&& search_op
!= FindExSearchLimitToDirectories
)
810 FIXME( "search_op not implemented 0x%08x\n", search_op
);
811 SetLastError( ERROR_INVALID_PARAMETER
);
812 return INVALID_HANDLE_VALUE
;
814 if (level
!= FindExInfoStandard
&& level
!= FindExInfoBasic
)
816 FIXME("info level %d not implemented\n", level
);
817 SetLastError( ERROR_INVALID_PARAMETER
);
818 return INVALID_HANDLE_VALUE
;
821 if (!RtlDosPathNameToNtPathName_U( filename
, &nt_name
, &mask
, NULL
))
823 SetLastError( ERROR_PATH_NOT_FOUND
);
824 return INVALID_HANDLE_VALUE
;
827 if (!mask
&& (device
= RtlIsDosDeviceName_U( filename
)))
831 /* we still need to check that the directory can be opened */
835 if (!(dir
= HeapAlloc( GetProcessHeap(), 0, HIWORD(device
) + sizeof(WCHAR
) )))
837 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
840 memcpy( dir
, filename
, HIWORD(device
) );
841 dir
[HIWORD(device
)/sizeof(WCHAR
)] = 0;
843 RtlFreeUnicodeString( &nt_name
);
844 if (!RtlDosPathNameToNtPathName_U( dir
? dir
: L
".", &nt_name
, &mask
, NULL
))
846 HeapFree( GetProcessHeap(), 0, dir
);
847 SetLastError( ERROR_PATH_NOT_FOUND
);
850 HeapFree( GetProcessHeap(), 0, dir
);
853 else if (!mask
|| !*mask
)
855 SetLastError( ERROR_FILE_NOT_FOUND
);
860 nt_name
.Length
= (mask
- nt_name
.Buffer
) * sizeof(WCHAR
);
861 has_wildcard
= wcspbrk( mask
, L
"*?" ) != NULL
;
862 size
= has_wildcard
? 8192 : max_entry_size
;
865 if (!(info
= HeapAlloc( GetProcessHeap(), 0, offsetof( FIND_FIRST_INFO
, data
[size
] ))))
867 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
871 /* check if path is the root of the drive, skipping the \??\ prefix */
872 info
->is_root
= FALSE
;
873 if (nt_name
.Length
>= 6 * sizeof(WCHAR
) && nt_name
.Buffer
[5] == ':')
876 while (pos
* sizeof(WCHAR
) < nt_name
.Length
&& nt_name
.Buffer
[pos
] == '\\') pos
++;
877 info
->is_root
= (pos
* sizeof(WCHAR
) >= nt_name
.Length
);
880 attr
.Length
= sizeof(attr
);
881 attr
.RootDirectory
= 0;
882 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
883 attr
.ObjectName
= &nt_name
;
884 attr
.SecurityDescriptor
= NULL
;
885 attr
.SecurityQualityOfService
= NULL
;
887 status
= NtOpenFile( &info
->handle
, GENERIC_READ
| SYNCHRONIZE
, &attr
, &io
,
888 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
889 FILE_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
| FILE_OPEN_FOR_BACKUP_INTENT
);
890 if (status
!= STATUS_SUCCESS
)
892 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
893 SetLastError( ERROR_PATH_NOT_FOUND
);
895 SetLastError( RtlNtStatusToDosError(status
) );
899 RtlInitializeCriticalSection( &info
->cs
);
900 info
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": FIND_FIRST_INFO.cs");
901 info
->path
= nt_name
;
902 info
->magic
= FIND_FIRST_MAGIC
;
903 info
->wildcard
= has_wildcard
;
906 info
->data_size
= size
;
907 info
->search_op
= search_op
;
912 WIN32_FIND_DATAW
*wfd
= data
;
914 memset( wfd
, 0, sizeof(*wfd
) );
915 memcpy( wfd
->cFileName
, filename
+ HIWORD(device
)/sizeof(WCHAR
), LOWORD(device
) );
916 wfd
->dwFileAttributes
= FILE_ATTRIBUTE_ARCHIVE
;
917 CloseHandle( info
->handle
);
922 UNICODE_STRING mask_str
;
924 RtlInitUnicodeString( &mask_str
, mask
);
925 status
= NtQueryDirectoryFile( info
->handle
, 0, NULL
, NULL
, &io
, info
->data
, info
->data_size
,
926 FileBothDirectoryInformation
, FALSE
, &mask_str
, TRUE
);
930 SetLastError( RtlNtStatusToDosError( status
) );
931 return INVALID_HANDLE_VALUE
;
934 info
->data_len
= io
.Information
;
935 if (!has_wildcard
) info
->data_size
= 0; /* we read everything */
937 if (!FindNextFileW( info
, data
))
939 TRACE( "%s not found\n", debugstr_w(filename
) );
941 SetLastError( ERROR_FILE_NOT_FOUND
);
942 return INVALID_HANDLE_VALUE
;
944 if (!has_wildcard
) /* we can't find two files with the same name */
946 CloseHandle( info
->handle
);
953 HeapFree( GetProcessHeap(), 0, info
);
954 RtlFreeUnicodeString( &nt_name
);
955 return INVALID_HANDLE_VALUE
;
959 /******************************************************************************
960 * FindFirstFileA (kernelbase.@)
962 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileA( const char *filename
, WIN32_FIND_DATAA
*data
)
964 return FindFirstFileExA( filename
, FindExInfoStandard
, data
, FindExSearchNameMatch
, NULL
, 0 );
968 /******************************************************************************
969 * FindFirstFileW (kernelbase.@)
971 HANDLE WINAPI DECLSPEC_HOTPATCH
FindFirstFileW( const WCHAR
*filename
, WIN32_FIND_DATAW
*data
)
973 return FindFirstFileExW( filename
, FindExInfoStandard
, data
, FindExSearchNameMatch
, NULL
, 0 );
977 /******************************************************************************
978 * FindNextFileA (kernelbase.@)
980 BOOL WINAPI DECLSPEC_HOTPATCH
FindNextFileA( HANDLE handle
, WIN32_FIND_DATAA
*data
)
982 WIN32_FIND_DATAW dataW
;
984 if (!FindNextFileW( handle
, &dataW
)) return FALSE
;
985 data
->dwFileAttributes
= dataW
.dwFileAttributes
;
986 data
->ftCreationTime
= dataW
.ftCreationTime
;
987 data
->ftLastAccessTime
= dataW
.ftLastAccessTime
;
988 data
->ftLastWriteTime
= dataW
.ftLastWriteTime
;
989 data
->nFileSizeHigh
= dataW
.nFileSizeHigh
;
990 data
->nFileSizeLow
= dataW
.nFileSizeLow
;
991 file_name_WtoA( dataW
.cFileName
, -1, data
->cFileName
, sizeof(data
->cFileName
) );
992 file_name_WtoA( dataW
.cAlternateFileName
, -1, data
->cAlternateFileName
,
993 sizeof(data
->cAlternateFileName
) );
998 /******************************************************************************
999 * FindNextFileW (kernelbase.@)
1001 BOOL WINAPI DECLSPEC_HOTPATCH
FindNextFileW( HANDLE handle
, WIN32_FIND_DATAW
*data
)
1003 FIND_FIRST_INFO
*info
= handle
;
1004 FILE_BOTH_DIR_INFORMATION
*dir_info
;
1008 TRACE( "%p %p\n", handle
, data
);
1010 if (!handle
|| handle
== INVALID_HANDLE_VALUE
|| info
->magic
!= FIND_FIRST_MAGIC
)
1012 SetLastError( ERROR_INVALID_HANDLE
);
1016 RtlEnterCriticalSection( &info
->cs
);
1018 if (!info
->handle
) SetLastError( ERROR_NO_MORE_FILES
);
1021 if (info
->data_pos
>= info
->data_len
) /* need to read some more data */
1025 if (info
->data_size
)
1026 status
= NtQueryDirectoryFile( info
->handle
, 0, NULL
, NULL
, &io
, info
->data
, info
->data_size
,
1027 FileBothDirectoryInformation
, FALSE
, NULL
, FALSE
);
1029 status
= STATUS_NO_MORE_FILES
;
1031 if (!set_ntstatus( status
))
1033 if (status
== STATUS_NO_MORE_FILES
)
1035 CloseHandle( info
->handle
);
1040 info
->data_len
= io
.Information
;
1044 dir_info
= (FILE_BOTH_DIR_INFORMATION
*)(info
->data
+ info
->data_pos
);
1046 if (dir_info
->NextEntryOffset
) info
->data_pos
+= dir_info
->NextEntryOffset
;
1047 else info
->data_pos
= info
->data_len
;
1049 /* don't return '.' and '..' in the root of the drive */
1052 if (dir_info
->FileNameLength
== sizeof(WCHAR
) && dir_info
->FileName
[0] == '.') continue;
1053 if (dir_info
->FileNameLength
== 2 * sizeof(WCHAR
) &&
1054 dir_info
->FileName
[0] == '.' && dir_info
->FileName
[1] == '.') continue;
1057 data
->dwFileAttributes
= dir_info
->FileAttributes
;
1058 data
->ftCreationTime
= *(FILETIME
*)&dir_info
->CreationTime
;
1059 data
->ftLastAccessTime
= *(FILETIME
*)&dir_info
->LastAccessTime
;
1060 data
->ftLastWriteTime
= *(FILETIME
*)&dir_info
->LastWriteTime
;
1061 data
->nFileSizeHigh
= dir_info
->EndOfFile
.QuadPart
>> 32;
1062 data
->nFileSizeLow
= (DWORD
)dir_info
->EndOfFile
.QuadPart
;
1063 data
->dwReserved0
= 0;
1064 data
->dwReserved1
= 0;
1066 memcpy( data
->cFileName
, dir_info
->FileName
, dir_info
->FileNameLength
);
1067 data
->cFileName
[dir_info
->FileNameLength
/sizeof(WCHAR
)] = 0;
1069 if (info
->level
!= FindExInfoBasic
)
1071 memcpy( data
->cAlternateFileName
, dir_info
->ShortName
, dir_info
->ShortNameLength
);
1072 data
->cAlternateFileName
[dir_info
->ShortNameLength
/sizeof(WCHAR
)] = 0;
1075 data
->cAlternateFileName
[0] = 0;
1077 TRACE( "returning %s (%s)\n",
1078 debugstr_w(data
->cFileName
), debugstr_w(data
->cAlternateFileName
) );
1084 RtlLeaveCriticalSection( &info
->cs
);
1089 /******************************************************************************
1090 * FindClose (kernelbase.@)
1092 BOOL WINAPI DECLSPEC_HOTPATCH
FindClose( HANDLE handle
)
1094 FIND_FIRST_INFO
*info
= handle
;
1096 if (!handle
|| handle
== INVALID_HANDLE_VALUE
)
1098 SetLastError( ERROR_INVALID_HANDLE
);
1104 if (info
->magic
== FIND_FIRST_MAGIC
)
1106 RtlEnterCriticalSection( &info
->cs
);
1107 if (info
->magic
== FIND_FIRST_MAGIC
) /* in case someone else freed it in the meantime */
1110 if (info
->handle
) CloseHandle( info
->handle
);
1112 RtlFreeUnicodeString( &info
->path
);
1115 RtlLeaveCriticalSection( &info
->cs
);
1116 info
->cs
.DebugInfo
->Spare
[0] = 0;
1117 RtlDeleteCriticalSection( &info
->cs
);
1118 HeapFree( GetProcessHeap(), 0, info
);
1124 WARN( "illegal handle %p\n", handle
);
1125 SetLastError( ERROR_INVALID_HANDLE
);
1134 /******************************************************************************
1135 * GetCompressedFileSizeA (kernelbase.@)
1137 DWORD WINAPI DECLSPEC_HOTPATCH
GetCompressedFileSizeA( LPCSTR name
, LPDWORD size_high
)
1141 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return INVALID_FILE_SIZE
;
1142 return GetCompressedFileSizeW( nameW
, size_high
);
1146 /******************************************************************************
1147 * GetCompressedFileSizeW (kernelbase.@)
1149 DWORD WINAPI DECLSPEC_HOTPATCH
GetCompressedFileSizeW( LPCWSTR name
, LPDWORD size_high
)
1151 UNICODE_STRING nt_name
;
1152 OBJECT_ATTRIBUTES attr
;
1158 TRACE("%s %p\n", debugstr_w(name
), size_high
);
1160 if (!RtlDosPathNameToNtPathName_U( name
, &nt_name
, NULL
, NULL
))
1162 SetLastError( ERROR_PATH_NOT_FOUND
);
1163 return INVALID_FILE_SIZE
;
1166 attr
.Length
= sizeof(attr
);
1167 attr
.RootDirectory
= 0;
1168 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1169 attr
.ObjectName
= &nt_name
;
1170 attr
.SecurityDescriptor
= NULL
;
1171 attr
.SecurityQualityOfService
= NULL
;
1173 status
= NtOpenFile( &handle
, SYNCHRONIZE
, &attr
, &io
, 0, FILE_SYNCHRONOUS_IO_NONALERT
);
1174 RtlFreeUnicodeString( &nt_name
);
1175 if (!set_ntstatus( status
)) return INVALID_FILE_SIZE
;
1177 /* we don't support compressed files, simply return the file size */
1178 ret
= GetFileSize( handle
, size_high
);
1184 /***********************************************************************
1185 * GetCurrentDirectoryA (kernelbase.@)
1187 UINT WINAPI DECLSPEC_HOTPATCH
GetCurrentDirectoryA( UINT buflen
, LPSTR buf
)
1189 WCHAR bufferW
[MAX_PATH
];
1192 if (buflen
&& buf
&& ((ULONG_PTR
)buf
>> 16) == 0)
1194 /* Win9x catches access violations here, returning zero.
1195 * This behaviour resulted in some people not noticing
1196 * that they got the argument order wrong. So let's be
1197 * nice and fail gracefully if buf is invalid and looks
1198 * more like a buflen. */
1199 SetLastError( ERROR_INVALID_PARAMETER
);
1203 ret
= RtlGetCurrentDirectory_U( sizeof(bufferW
), bufferW
);
1205 if (ret
> sizeof(bufferW
))
1207 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1210 return copy_filename_WtoA( bufferW
, buf
, buflen
);
1214 /***********************************************************************
1215 * GetCurrentDirectoryW (kernelbase.@)
1217 UINT WINAPI DECLSPEC_HOTPATCH
GetCurrentDirectoryW( UINT buflen
, LPWSTR buf
)
1219 return RtlGetCurrentDirectory_U( buflen
* sizeof(WCHAR
), buf
) / sizeof(WCHAR
);
1223 /**************************************************************************
1224 * GetFileAttributesA (kernelbase.@)
1226 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileAttributesA( LPCSTR name
)
1230 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return INVALID_FILE_ATTRIBUTES
;
1231 return GetFileAttributesW( nameW
);
1235 /**************************************************************************
1236 * GetFileAttributesW (kernelbase.@)
1238 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileAttributesW( LPCWSTR name
)
1240 FILE_BASIC_INFORMATION info
;
1241 UNICODE_STRING nt_name
;
1242 OBJECT_ATTRIBUTES attr
;
1245 TRACE( "%s\n", debugstr_w(name
) );
1247 if (!RtlDosPathNameToNtPathName_U( name
, &nt_name
, NULL
, NULL
))
1249 SetLastError( ERROR_PATH_NOT_FOUND
);
1250 return INVALID_FILE_ATTRIBUTES
;
1253 attr
.Length
= sizeof(attr
);
1254 attr
.RootDirectory
= 0;
1255 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1256 attr
.ObjectName
= &nt_name
;
1257 attr
.SecurityDescriptor
= NULL
;
1258 attr
.SecurityQualityOfService
= NULL
;
1260 status
= NtQueryAttributesFile( &attr
, &info
);
1261 RtlFreeUnicodeString( &nt_name
);
1263 if (status
== STATUS_SUCCESS
) return info
.FileAttributes
;
1265 /* NtQueryAttributesFile fails on devices, but GetFileAttributesW succeeds */
1266 if (RtlIsDosDeviceName_U( name
)) return FILE_ATTRIBUTE_ARCHIVE
;
1268 SetLastError( RtlNtStatusToDosError(status
) );
1269 return INVALID_FILE_ATTRIBUTES
;
1273 /**************************************************************************
1274 * GetFileAttributesExA (kernelbase.@)
1276 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileAttributesExA( LPCSTR name
, GET_FILEEX_INFO_LEVELS level
, void *ptr
)
1280 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return FALSE
;
1281 return GetFileAttributesExW( nameW
, level
, ptr
);
1285 /**************************************************************************
1286 * GetFileAttributesExW (kernelbase.@)
1288 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileAttributesExW( LPCWSTR name
, GET_FILEEX_INFO_LEVELS level
, void *ptr
)
1290 FILE_NETWORK_OPEN_INFORMATION info
;
1291 WIN32_FILE_ATTRIBUTE_DATA
*data
= ptr
;
1292 UNICODE_STRING nt_name
;
1293 OBJECT_ATTRIBUTES attr
;
1296 TRACE("%s %d %p\n", debugstr_w(name
), level
, ptr
);
1298 if (level
!= GetFileExInfoStandard
)
1300 SetLastError( ERROR_INVALID_PARAMETER
);
1304 if (!RtlDosPathNameToNtPathName_U( name
, &nt_name
, NULL
, NULL
))
1306 SetLastError( ERROR_PATH_NOT_FOUND
);
1310 attr
.Length
= sizeof(attr
);
1311 attr
.RootDirectory
= 0;
1312 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
1313 attr
.ObjectName
= &nt_name
;
1314 attr
.SecurityDescriptor
= NULL
;
1315 attr
.SecurityQualityOfService
= NULL
;
1317 status
= NtQueryFullAttributesFile( &attr
, &info
);
1318 RtlFreeUnicodeString( &nt_name
);
1319 if (!set_ntstatus( status
)) return FALSE
;
1321 data
->dwFileAttributes
= info
.FileAttributes
;
1322 data
->ftCreationTime
.dwLowDateTime
= info
.CreationTime
.u
.LowPart
;
1323 data
->ftCreationTime
.dwHighDateTime
= info
.CreationTime
.u
.HighPart
;
1324 data
->ftLastAccessTime
.dwLowDateTime
= info
.LastAccessTime
.u
.LowPart
;
1325 data
->ftLastAccessTime
.dwHighDateTime
= info
.LastAccessTime
.u
.HighPart
;
1326 data
->ftLastWriteTime
.dwLowDateTime
= info
.LastWriteTime
.u
.LowPart
;
1327 data
->ftLastWriteTime
.dwHighDateTime
= info
.LastWriteTime
.u
.HighPart
;
1328 data
->nFileSizeLow
= info
.EndOfFile
.u
.LowPart
;
1329 data
->nFileSizeHigh
= info
.EndOfFile
.u
.HighPart
;
1334 /***********************************************************************
1335 * GetFullPathNameA (kernelbase.@)
1337 DWORD WINAPI DECLSPEC_HOTPATCH
GetFullPathNameA( LPCSTR name
, DWORD len
, LPSTR buffer
, LPSTR
*lastpart
)
1340 WCHAR bufferW
[MAX_PATH
], *lastpartW
= NULL
;
1343 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return 0;
1345 ret
= GetFullPathNameW( nameW
, MAX_PATH
, bufferW
, &lastpartW
);
1350 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1353 ret
= copy_filename_WtoA( bufferW
, buffer
, len
);
1354 if (ret
< len
&& lastpart
)
1357 *lastpart
= buffer
+ file_name_WtoA( bufferW
, lastpartW
- bufferW
, NULL
, 0 );
1365 /***********************************************************************
1366 * GetFullPathNameW (kernelbase.@)
1368 DWORD WINAPI DECLSPEC_HOTPATCH
GetFullPathNameW( LPCWSTR name
, DWORD len
, LPWSTR buffer
, LPWSTR
*lastpart
)
1370 return RtlGetFullPathName_U( name
, len
* sizeof(WCHAR
), buffer
, lastpart
) / sizeof(WCHAR
);
1374 /***********************************************************************
1375 * GetLongPathNameA (kernelbase.@)
1377 DWORD WINAPI DECLSPEC_HOTPATCH
GetLongPathNameA( LPCSTR shortpath
, LPSTR longpath
, DWORD longlen
)
1380 WCHAR longpathW
[MAX_PATH
];
1383 TRACE( "%s\n", debugstr_a( shortpath
));
1385 if (!(shortpathW
= file_name_AtoW( shortpath
, FALSE
))) return 0;
1387 ret
= GetLongPathNameW( shortpathW
, longpathW
, MAX_PATH
);
1392 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1395 return copy_filename_WtoA( longpathW
, longpath
, longlen
);
1399 /***********************************************************************
1400 * GetLongPathNameW (kernelbase.@)
1402 DWORD WINAPI DECLSPEC_HOTPATCH
GetLongPathNameW( LPCWSTR shortpath
, LPWSTR longpath
, DWORD longlen
)
1404 WCHAR tmplongpath
[1024];
1405 DWORD sp
= 0, lp
= 0, tmplen
;
1406 WIN32_FIND_DATAW wfd
;
1407 UNICODE_STRING nameW
;
1411 TRACE("%s,%p,%u\n", debugstr_w(shortpath
), longpath
, longlen
);
1415 SetLastError( ERROR_INVALID_PARAMETER
);
1420 SetLastError( ERROR_PATH_NOT_FOUND
);
1424 if (shortpath
[0] == '\\' && shortpath
[1] == '\\')
1426 FIXME( "UNC pathname %s\n", debugstr_w(shortpath
) );
1427 tmplen
= lstrlenW( shortpath
);
1428 if (tmplen
< longlen
)
1430 if (longpath
!= shortpath
) lstrcpyW( longpath
, shortpath
);
1436 /* check for drive letter */
1437 if (shortpath
[0] != '/' && shortpath
[1] == ':' )
1439 tmplongpath
[0] = shortpath
[0];
1440 tmplongpath
[1] = ':';
1444 if (wcspbrk( shortpath
+ sp
, L
"*?" ))
1446 SetLastError( ERROR_INVALID_NAME
);
1450 while (shortpath
[sp
])
1452 /* check for path delimiters and reproduce them */
1453 if (shortpath
[sp
] == '\\' || shortpath
[sp
] == '/')
1455 tmplongpath
[lp
++] = shortpath
[sp
++];
1456 tmplongpath
[lp
] = 0; /* terminate string */
1460 for (p
= shortpath
+ sp
; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
1461 tmplen
= p
- (shortpath
+ sp
);
1462 lstrcpynW( tmplongpath
+ lp
, shortpath
+ sp
, tmplen
+ 1 );
1464 if (tmplongpath
[lp
] == '.')
1466 if (tmplen
== 1 || (tmplen
== 2 && tmplongpath
[lp
+ 1] == '.'))
1474 /* Check if the file exists */
1475 handle
= FindFirstFileW( tmplongpath
, &wfd
);
1476 if (handle
== INVALID_HANDLE_VALUE
)
1478 TRACE( "not found %s\n", debugstr_w( tmplongpath
));
1479 SetLastError ( ERROR_FILE_NOT_FOUND
);
1482 FindClose( handle
);
1484 /* Use the existing file name if it's a short name */
1485 RtlInitUnicodeString( &nameW
, tmplongpath
+ lp
);
1486 if (RtlIsNameLegalDOS8Dot3( &nameW
, NULL
, NULL
)) lstrcpyW( tmplongpath
+ lp
, wfd
.cFileName
);
1487 lp
+= lstrlenW( tmplongpath
+ lp
);
1490 tmplen
= lstrlenW( shortpath
) - 1;
1491 if ((shortpath
[tmplen
] == '/' || shortpath
[tmplen
] == '\\') &&
1492 (tmplongpath
[lp
- 1] != '/' && tmplongpath
[lp
- 1] != '\\'))
1493 tmplongpath
[lp
++] = shortpath
[tmplen
];
1494 tmplongpath
[lp
] = 0;
1496 tmplen
= lstrlenW( tmplongpath
) + 1;
1497 if (tmplen
<= longlen
)
1499 lstrcpyW( longpath
, tmplongpath
);
1500 TRACE("returning %s\n", debugstr_w( longpath
));
1501 tmplen
--; /* length without 0 */
1507 /***********************************************************************
1508 * GetShortPathNameW (kernelbase.@)
1510 DWORD WINAPI DECLSPEC_HOTPATCH
GetShortPathNameW( LPCWSTR longpath
, LPWSTR shortpath
, DWORD shortlen
)
1512 WIN32_FIND_DATAW wfd
;
1513 WCHAR
*tmpshortpath
;
1516 DWORD sp
= 0, lp
= 0, tmplen
, buf_len
;
1518 TRACE( "%s,%p,%u\n", debugstr_w(longpath
), shortpath
, shortlen
);
1522 SetLastError( ERROR_INVALID_PARAMETER
);
1527 SetLastError( ERROR_BAD_PATHNAME
);
1531 /* code below only removes characters from string, never adds, so this is
1532 * the largest buffer that tmpshortpath will need to have */
1533 buf_len
= lstrlenW(longpath
) + 1;
1534 tmpshortpath
= HeapAlloc( GetProcessHeap(), 0, buf_len
* sizeof(WCHAR
) );
1537 SetLastError( ERROR_OUTOFMEMORY
);
1541 if (longpath
[0] == '\\' && longpath
[1] == '\\' && longpath
[2] == '?' && longpath
[3] == '\\')
1543 memcpy( tmpshortpath
, longpath
, 4 * sizeof(WCHAR
) );
1547 if (wcspbrk( longpath
+ lp
, L
"*?" ))
1549 HeapFree( GetProcessHeap(), 0, tmpshortpath
);
1550 SetLastError( ERROR_INVALID_NAME
);
1554 /* check for drive letter */
1555 if (longpath
[lp
] != '/' && longpath
[lp
+ 1] == ':' )
1557 tmpshortpath
[sp
] = longpath
[lp
];
1558 tmpshortpath
[sp
+ 1] = ':';
1563 while (longpath
[lp
])
1565 /* check for path delimiters and reproduce them */
1566 if (longpath
[lp
] == '\\' || longpath
[lp
] == '/')
1568 tmpshortpath
[sp
++] = longpath
[lp
++];
1569 tmpshortpath
[sp
] = 0; /* terminate string */
1574 for (; *p
&& *p
!= '/' && *p
!= '\\'; p
++);
1575 tmplen
= p
- (longpath
+ lp
);
1576 lstrcpynW( tmpshortpath
+ sp
, longpath
+ lp
, tmplen
+ 1 );
1578 if (tmpshortpath
[sp
] == '.')
1580 if (tmplen
== 1 || (tmplen
== 2 && tmpshortpath
[sp
+ 1] == '.'))
1588 /* Check if the file exists and use the existing short file name */
1589 handle
= FindFirstFileW( tmpshortpath
, &wfd
);
1590 if (handle
== INVALID_HANDLE_VALUE
) goto notfound
;
1591 FindClose( handle
);
1593 /* In rare cases (like "a.abcd") short path may be longer than original path.
1594 * Make sure we have enough space in temp buffer. */
1595 if (wfd
.cAlternateFileName
[0] && tmplen
< lstrlenW(wfd
.cAlternateFileName
))
1598 buf_len
+= lstrlenW( wfd
.cAlternateFileName
) - tmplen
;
1599 new_buf
= HeapReAlloc( GetProcessHeap(), 0, tmpshortpath
, buf_len
* sizeof(WCHAR
) );
1602 HeapFree( GetProcessHeap(), 0, tmpshortpath
);
1603 SetLastError( ERROR_OUTOFMEMORY
);
1606 tmpshortpath
= new_buf
;
1609 lstrcpyW( tmpshortpath
+ sp
, wfd
.cAlternateFileName
[0] ? wfd
.cAlternateFileName
: wfd
.cFileName
);
1610 sp
+= lstrlenW( tmpshortpath
+ sp
);
1613 tmpshortpath
[sp
] = 0;
1615 tmplen
= lstrlenW( tmpshortpath
) + 1;
1616 if (tmplen
<= shortlen
)
1618 lstrcpyW( shortpath
, tmpshortpath
);
1619 TRACE( "returning %s\n", debugstr_w( shortpath
));
1620 tmplen
--; /* length without 0 */
1623 HeapFree( GetProcessHeap(), 0, tmpshortpath
);
1627 HeapFree( GetProcessHeap(), 0, tmpshortpath
);
1628 TRACE( "not found\n" );
1629 SetLastError( ERROR_FILE_NOT_FOUND
);
1634 /***********************************************************************
1635 * GetSystemDirectoryA (kernelbase.@)
1637 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemDirectoryA( LPSTR path
, UINT count
)
1639 return copy_filename_WtoA( system_dir
, path
, count
);
1643 /***********************************************************************
1644 * GetSystemDirectoryW (kernelbase.@)
1646 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemDirectoryW( LPWSTR path
, UINT count
)
1648 return copy_filename( system_dir
, path
, count
);
1652 /***********************************************************************
1653 * GetSystemWindowsDirectoryA (kernelbase.@)
1655 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemWindowsDirectoryA( LPSTR path
, UINT count
)
1657 return GetWindowsDirectoryA( path
, count
);
1661 /***********************************************************************
1662 * GetSystemWindowsDirectoryW (kernelbase.@)
1664 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemWindowsDirectoryW( LPWSTR path
, UINT count
)
1666 return GetWindowsDirectoryW( path
, count
);
1670 /***********************************************************************
1671 * GetSystemWow64DirectoryA (kernelbase.@)
1673 UINT WINAPI
/* DECLSPEC_HOTPATCH */ GetSystemWow64DirectoryA( LPSTR path
, UINT count
)
1675 if (!is_win64
&& !is_wow64
)
1677 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1680 return copy_filename_WtoA( get_machine_wow64_dir( IMAGE_FILE_MACHINE_I386
), path
, count
);
1684 /***********************************************************************
1685 * GetSystemWow64DirectoryW (kernelbase.@)
1687 UINT WINAPI
/* DECLSPEC_HOTPATCH */ GetSystemWow64DirectoryW( LPWSTR path
, UINT count
)
1689 if (!is_win64
&& !is_wow64
)
1691 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
1694 return copy_filename( get_machine_wow64_dir( IMAGE_FILE_MACHINE_I386
), path
, count
);
1698 /***********************************************************************
1699 * GetSystemWow64Directory2A (kernelbase.@)
1701 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemWow64Directory2A( LPSTR path
, UINT count
, WORD machine
)
1703 const WCHAR
*dir
= get_machine_wow64_dir( machine
);
1705 return dir
? copy_filename_WtoA( dir
, path
, count
) : 0;
1709 /***********************************************************************
1710 * GetSystemWow64Directory2W (kernelbase.@)
1712 UINT WINAPI DECLSPEC_HOTPATCH
GetSystemWow64Directory2W( LPWSTR path
, UINT count
, WORD machine
)
1714 const WCHAR
*dir
= get_machine_wow64_dir( machine
);
1716 return dir
? copy_filename( dir
, path
, count
) : 0;
1720 /***********************************************************************
1721 * GetTempFileNameA (kernelbase.@)
1723 UINT WINAPI DECLSPEC_HOTPATCH
GetTempFileNameA( LPCSTR path
, LPCSTR prefix
, UINT unique
, LPSTR buffer
)
1725 WCHAR
*pathW
, *prefixW
= NULL
;
1726 WCHAR bufferW
[MAX_PATH
];
1729 if (!(pathW
= file_name_AtoW( path
, FALSE
))) return 0;
1730 if (prefix
&& !(prefixW
= file_name_AtoW( prefix
, TRUE
))) return 0;
1732 ret
= GetTempFileNameW( pathW
, prefixW
, unique
, bufferW
);
1733 if (ret
) file_name_WtoA( bufferW
, -1, buffer
, MAX_PATH
);
1735 HeapFree( GetProcessHeap(), 0, prefixW
);
1740 /***********************************************************************
1741 * GetTempFileNameW (kernelbase.@)
1743 UINT WINAPI DECLSPEC_HOTPATCH
GetTempFileNameW( LPCWSTR path
, LPCWSTR prefix
, UINT unique
, LPWSTR buffer
)
1749 if (!path
|| !buffer
)
1751 SetLastError( ERROR_INVALID_PARAMETER
);
1755 /* ensure that the provided directory exists */
1756 attr
= GetFileAttributesW( path
);
1757 if (attr
== INVALID_FILE_ATTRIBUTES
|| !(attr
& FILE_ATTRIBUTE_DIRECTORY
))
1759 TRACE( "path not found %s\n", debugstr_w( path
));
1760 SetLastError( ERROR_DIRECTORY
);
1764 lstrcpyW( buffer
, path
);
1765 p
= buffer
+ lstrlenW(buffer
);
1767 /* add a \, if there isn't one */
1768 if ((p
== buffer
) || (p
[-1] != '\\')) *p
++ = '\\';
1770 if (prefix
) for (i
= 3; (i
> 0) && (*prefix
); i
--) *p
++ = *prefix
++;
1773 if (unique
) swprintf( p
, MAX_PATH
- (p
- buffer
), L
"%x.tmp", unique
);
1776 /* get a "random" unique number and try to create the file */
1778 UINT num
= NtGetTickCount() & 0xffff;
1781 /* avoid using the same name twice in a short interval */
1782 if (last
- num
< 10) num
= last
+ 1;
1787 swprintf( p
, MAX_PATH
- (p
- buffer
), L
"%x.tmp", unique
);
1788 handle
= CreateFileW( buffer
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, 0 );
1789 if (handle
!= INVALID_HANDLE_VALUE
)
1790 { /* We created it */
1791 CloseHandle( handle
);
1795 if (GetLastError() != ERROR_FILE_EXISTS
&& GetLastError() != ERROR_SHARING_VIOLATION
)
1796 break; /* No need to go on */
1797 if (!(++unique
& 0xffff)) unique
= 1;
1798 } while (unique
!= num
);
1800 TRACE( "returning %s\n", debugstr_w( buffer
));
1805 /***********************************************************************
1806 * GetTempPathA (kernelbase.@)
1808 DWORD WINAPI DECLSPEC_HOTPATCH
GetTempPathA( DWORD count
, LPSTR path
)
1810 WCHAR pathW
[MAX_PATH
];
1813 if (!(ret
= GetTempPathW( MAX_PATH
, pathW
))) return 0;
1816 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1819 return copy_filename_WtoA( pathW
, path
, count
);
1823 /***********************************************************************
1824 * GetTempPathW (kernelbase.@)
1826 DWORD WINAPI DECLSPEC_HOTPATCH
GetTempPathW( DWORD count
, LPWSTR path
)
1828 WCHAR tmp_path
[MAX_PATH
];
1831 if (!(ret
= GetEnvironmentVariableW( L
"TMP", tmp_path
, MAX_PATH
)) &&
1832 !(ret
= GetEnvironmentVariableW( L
"TEMP", tmp_path
, MAX_PATH
)) &&
1833 !(ret
= GetEnvironmentVariableW( L
"USERPROFILE", tmp_path
, MAX_PATH
)) &&
1834 !(ret
= GetWindowsDirectoryW( tmp_path
, MAX_PATH
)))
1839 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1842 ret
= GetFullPathNameW( tmp_path
, MAX_PATH
, tmp_path
, NULL
);
1845 if (ret
> MAX_PATH
- 2)
1847 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1850 if (tmp_path
[ret
-1] != '\\')
1852 tmp_path
[ret
++] = '\\';
1853 tmp_path
[ret
] = '\0';
1856 ret
++; /* add space for terminating 0 */
1859 lstrcpynW( path
, tmp_path
, count
);
1860 /* the remaining buffer must be zeroed up to 32766 bytes in XP or 32767
1861 * bytes after it, we will assume the > XP behavior for now */
1862 memset( path
+ ret
, 0, (min(count
, 32767) - ret
) * sizeof(WCHAR
) );
1863 ret
--; /* return length without 0 */
1867 /* the buffer must be cleared if contents will not fit */
1868 memset( path
, 0, count
* sizeof(WCHAR
) );
1871 TRACE( "returning %u, %s\n", ret
, debugstr_w( path
));
1876 /***********************************************************************
1877 * GetWindowsDirectoryA (kernelbase.@)
1879 UINT WINAPI DECLSPEC_HOTPATCH
GetWindowsDirectoryA( LPSTR path
, UINT count
)
1881 return copy_filename_WtoA( windows_dir
, path
, count
);
1885 /***********************************************************************
1886 * GetWindowsDirectoryW (kernelbase.@)
1888 UINT WINAPI DECLSPEC_HOTPATCH
GetWindowsDirectoryW( LPWSTR path
, UINT count
)
1890 return copy_filename( windows_dir
, path
, count
);
1894 /***********************************************************************
1895 * NeedCurrentDirectoryForExePathA (kernelbase.@)
1897 BOOL WINAPI DECLSPEC_HOTPATCH
NeedCurrentDirectoryForExePathA( LPCSTR name
)
1901 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return TRUE
;
1902 return NeedCurrentDirectoryForExePathW( nameW
);
1906 /***********************************************************************
1907 * NeedCurrentDirectoryForExePathW (kernelbase.@)
1909 BOOL WINAPI DECLSPEC_HOTPATCH
NeedCurrentDirectoryForExePathW( LPCWSTR name
)
1913 if (wcschr( name
, '\\' )) return TRUE
;
1914 /* check the existence of the variable, not value */
1915 return !GetEnvironmentVariableW( L
"NoDefaultCurrentDirectoryInExePath", &env_val
, 1 );
1919 /***********************************************************************
1920 * SearchPathA (kernelbase.@)
1922 DWORD WINAPI DECLSPEC_HOTPATCH
SearchPathA( LPCSTR path
, LPCSTR name
, LPCSTR ext
,
1923 DWORD buflen
, LPSTR buffer
, LPSTR
*lastpart
)
1925 WCHAR
*pathW
= NULL
, *nameW
, *extW
= NULL
;
1926 WCHAR bufferW
[MAX_PATH
];
1931 SetLastError( ERROR_INVALID_PARAMETER
);
1935 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return 0;
1936 if (path
&& !(pathW
= file_name_AtoW( path
, TRUE
))) return 0;
1937 if (ext
&& !(extW
= file_name_AtoW( ext
, TRUE
)))
1939 RtlFreeHeap( GetProcessHeap(), 0, pathW
);
1943 ret
= SearchPathW( pathW
, nameW
, extW
, MAX_PATH
, bufferW
, NULL
);
1945 RtlFreeHeap( GetProcessHeap(), 0, pathW
);
1946 RtlFreeHeap( GetProcessHeap(), 0, extW
);
1951 SetLastError( ERROR_FILENAME_EXCED_RANGE
);
1954 ret
= copy_filename_WtoA( bufferW
, buffer
, buflen
);
1955 if (buflen
> ret
&& lastpart
) *lastpart
= strrchr(buffer
, '\\') + 1;
1960 /***********************************************************************
1961 * SearchPathW (kernelbase.@)
1963 DWORD WINAPI DECLSPEC_HOTPATCH
SearchPathW( LPCWSTR path
, LPCWSTR name
, LPCWSTR ext
, DWORD buflen
,
1964 LPWSTR buffer
, LPWSTR
*lastpart
)
1969 if (!name
|| !name
[0])
1971 SetLastError( ERROR_INVALID_PARAMETER
);
1975 /* If the name contains an explicit path, ignore the path */
1977 if (contains_path( name
))
1979 /* try first without extension */
1980 if (RtlDoesFileExists_U( name
)) return GetFullPathNameW( name
, buflen
, buffer
, lastpart
);
1982 if ((name_ext
= append_ext( name
, ext
)))
1984 if (RtlDoesFileExists_U( name_ext
))
1985 ret
= GetFullPathNameW( name_ext
, buflen
, buffer
, lastpart
);
1986 RtlFreeHeap( GetProcessHeap(), 0, name_ext
);
1989 else if (path
&& path
[0]) /* search in the specified path */
1991 ret
= RtlDosSearchPath_U( path
, name
, ext
, buflen
* sizeof(WCHAR
),
1992 buffer
, lastpart
) / sizeof(WCHAR
);
1994 else /* search in active context and default path */
1996 WCHAR
*dll_path
= NULL
, *name_ext
= append_ext( name
, ext
);
1998 if (name_ext
) name
= name_ext
;
2000 /* When file is found with activation context no attempt is made
2001 to check if it's really exist, path is returned only basing on context info. */
2002 if (find_actctx_dllpath( name
, &dll_path
) == STATUS_SUCCESS
)
2004 ret
= lstrlenW( dll_path
) + lstrlenW( name
) + 1;
2006 /* count null termination char too */
2009 lstrcpyW( buffer
, dll_path
);
2010 lstrcatW( buffer
, name
);
2011 if (lastpart
) *lastpart
= buffer
+ lstrlenW( dll_path
);
2014 else if (lastpart
) *lastpart
= NULL
;
2015 RtlFreeHeap( GetProcessHeap(), 0, dll_path
);
2017 else if (!RtlGetSearchPath( &dll_path
))
2019 ret
= RtlDosSearchPath_U( dll_path
, name
, NULL
, buflen
* sizeof(WCHAR
),
2020 buffer
, lastpart
) / sizeof(WCHAR
);
2021 RtlReleasePath( dll_path
);
2023 RtlFreeHeap( GetProcessHeap(), 0, name_ext
);
2026 if (!ret
) SetLastError( ERROR_FILE_NOT_FOUND
);
2027 else TRACE( "found %s\n", debugstr_w(buffer
) );
2032 /***********************************************************************
2033 * SetCurrentDirectoryA (kernelbase.@)
2035 BOOL WINAPI DECLSPEC_HOTPATCH
SetCurrentDirectoryA( LPCSTR dir
)
2038 UNICODE_STRING strW
;
2040 if (!(dirW
= file_name_AtoW( dir
, FALSE
))) return FALSE
;
2041 RtlInitUnicodeString( &strW
, dirW
);
2042 return set_ntstatus( RtlSetCurrentDirectory_U( &strW
));
2046 /***********************************************************************
2047 * SetCurrentDirectoryW (kernelbase.@)
2049 BOOL WINAPI DECLSPEC_HOTPATCH
SetCurrentDirectoryW( LPCWSTR dir
)
2051 UNICODE_STRING dirW
;
2053 RtlInitUnicodeString( &dirW
, dir
);
2054 return set_ntstatus( RtlSetCurrentDirectory_U( &dirW
));
2058 /**************************************************************************
2059 * SetFileApisToANSI (kernelbase.@)
2061 void WINAPI DECLSPEC_HOTPATCH
SetFileApisToANSI(void)
2063 oem_file_apis
= FALSE
;
2067 /**************************************************************************
2068 * SetFileApisToOEM (kernelbase.@)
2070 void WINAPI DECLSPEC_HOTPATCH
SetFileApisToOEM(void)
2072 oem_file_apis
= TRUE
;
2076 /**************************************************************************
2077 * SetFileAttributesA (kernelbase.@)
2079 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileAttributesA( LPCSTR name
, DWORD attributes
)
2083 if (!(nameW
= file_name_AtoW( name
, FALSE
))) return FALSE
;
2084 return SetFileAttributesW( nameW
, attributes
);
2088 /**************************************************************************
2089 * SetFileAttributesW (kernelbase.@)
2091 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileAttributesW( LPCWSTR name
, DWORD attributes
)
2093 UNICODE_STRING nt_name
;
2094 OBJECT_ATTRIBUTES attr
;
2099 TRACE( "%s %x\n", debugstr_w(name
), attributes
);
2101 if (!RtlDosPathNameToNtPathName_U( name
, &nt_name
, NULL
, NULL
))
2103 SetLastError( ERROR_PATH_NOT_FOUND
);
2107 attr
.Length
= sizeof(attr
);
2108 attr
.RootDirectory
= 0;
2109 attr
.Attributes
= OBJ_CASE_INSENSITIVE
;
2110 attr
.ObjectName
= &nt_name
;
2111 attr
.SecurityDescriptor
= NULL
;
2112 attr
.SecurityQualityOfService
= NULL
;
2114 status
= NtOpenFile( &handle
, SYNCHRONIZE
, &attr
, &io
, 0, FILE_SYNCHRONOUS_IO_NONALERT
);
2115 RtlFreeUnicodeString( &nt_name
);
2117 if (status
== STATUS_SUCCESS
)
2119 FILE_BASIC_INFORMATION info
;
2121 memset( &info
, 0, sizeof(info
) );
2122 info
.FileAttributes
= attributes
| FILE_ATTRIBUTE_NORMAL
; /* make sure it's not zero */
2123 status
= NtSetInformationFile( handle
, &io
, &info
, sizeof(info
), FileBasicInformation
);
2126 return set_ntstatus( status
);
2130 /***********************************************************************
2131 * Wow64DisableWow64FsRedirection (kernelbase.@)
2133 BOOL WINAPI DECLSPEC_HOTPATCH
Wow64DisableWow64FsRedirection( PVOID
*old_value
)
2135 return set_ntstatus( RtlWow64EnableFsRedirectionEx( TRUE
, (ULONG
*)old_value
));
2139 /***********************************************************************
2140 * Wow64RevertWow64FsRedirection (kernelbase.@)
2142 BOOL WINAPI DECLSPEC_HOTPATCH
Wow64RevertWow64FsRedirection( PVOID old_value
)
2144 return set_ntstatus( RtlWow64EnableFsRedirection( !old_value
));
2148 /***********************************************************************
2149 * Operations on file handles
2150 ***********************************************************************/
2153 /***********************************************************************
2154 * CancelIo (kernelbase.@)
2156 BOOL WINAPI DECLSPEC_HOTPATCH
CancelIo( HANDLE handle
)
2160 NtCancelIoFile( handle
, &io
);
2161 return set_ntstatus( io
.u
.Status
);
2165 /***********************************************************************
2166 * CancelIoEx (kernelbase.@)
2168 BOOL WINAPI DECLSPEC_HOTPATCH
CancelIoEx( HANDLE handle
, LPOVERLAPPED overlapped
)
2172 NtCancelIoFileEx( handle
, (PIO_STATUS_BLOCK
)overlapped
, &io
);
2173 return set_ntstatus( io
.u
.Status
);
2177 /***********************************************************************
2178 * CancelSynchronousIo (kernelbase.@)
2180 BOOL WINAPI DECLSPEC_HOTPATCH
CancelSynchronousIo( HANDLE thread
)
2182 FIXME( "(%p): stub\n", thread
);
2183 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
2188 /***********************************************************************
2189 * FlushFileBuffers (kernelbase.@)
2191 BOOL WINAPI DECLSPEC_HOTPATCH
FlushFileBuffers( HANDLE file
)
2193 IO_STATUS_BLOCK iosb
;
2195 return set_ntstatus( NtFlushBuffersFile( file
, &iosb
));
2199 /***********************************************************************
2200 * GetFileInformationByHandle (kernelbase.@)
2202 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileInformationByHandle( HANDLE file
, BY_HANDLE_FILE_INFORMATION
*info
)
2204 FILE_ALL_INFORMATION all_info
;
2208 status
= NtQueryInformationFile( file
, &io
, &all_info
, sizeof(all_info
), FileAllInformation
);
2209 if (status
== STATUS_BUFFER_OVERFLOW
) status
= STATUS_SUCCESS
;
2210 if (!set_ntstatus( status
)) return FALSE
;
2212 info
->dwFileAttributes
= all_info
.BasicInformation
.FileAttributes
;
2213 info
->ftCreationTime
.dwHighDateTime
= all_info
.BasicInformation
.CreationTime
.u
.HighPart
;
2214 info
->ftCreationTime
.dwLowDateTime
= all_info
.BasicInformation
.CreationTime
.u
.LowPart
;
2215 info
->ftLastAccessTime
.dwHighDateTime
= all_info
.BasicInformation
.LastAccessTime
.u
.HighPart
;
2216 info
->ftLastAccessTime
.dwLowDateTime
= all_info
.BasicInformation
.LastAccessTime
.u
.LowPart
;
2217 info
->ftLastWriteTime
.dwHighDateTime
= all_info
.BasicInformation
.LastWriteTime
.u
.HighPart
;
2218 info
->ftLastWriteTime
.dwLowDateTime
= all_info
.BasicInformation
.LastWriteTime
.u
.LowPart
;
2219 info
->dwVolumeSerialNumber
= 0; /* FIXME */
2220 info
->nFileSizeHigh
= all_info
.StandardInformation
.EndOfFile
.u
.HighPart
;
2221 info
->nFileSizeLow
= all_info
.StandardInformation
.EndOfFile
.u
.LowPart
;
2222 info
->nNumberOfLinks
= all_info
.StandardInformation
.NumberOfLinks
;
2223 info
->nFileIndexHigh
= all_info
.InternalInformation
.IndexNumber
.u
.HighPart
;
2224 info
->nFileIndexLow
= all_info
.InternalInformation
.IndexNumber
.u
.LowPart
;
2229 /***********************************************************************
2230 * GetFileInformationByHandleEx (kernelbase.@)
2232 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileInformationByHandleEx( HANDLE handle
, FILE_INFO_BY_HANDLE_CLASS
class,
2233 LPVOID info
, DWORD size
)
2240 case FileStreamInfo
:
2241 case FileCompressionInfo
:
2242 case FileRemoteProtocolInfo
:
2243 case FileFullDirectoryInfo
:
2244 case FileFullDirectoryRestartInfo
:
2245 case FileStorageInfo
:
2246 case FileAlignmentInfo
:
2247 case FileIdExtdDirectoryInfo
:
2248 case FileIdExtdDirectoryRestartInfo
:
2249 FIXME( "%p, %u, %p, %u\n", handle
, class, info
, size
);
2250 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
2253 case FileAttributeTagInfo
:
2254 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileAttributeTagInformation
);
2258 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileBasicInformation
);
2261 case FileStandardInfo
:
2262 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileStandardInformation
);
2266 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileNameInformation
);
2270 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileIdInformation
);
2273 case FileIdBothDirectoryRestartInfo
:
2274 case FileIdBothDirectoryInfo
:
2275 status
= NtQueryDirectoryFile( handle
, NULL
, NULL
, NULL
, &io
, info
, size
,
2276 FileIdBothDirectoryInformation
, FALSE
, NULL
,
2277 (class == FileIdBothDirectoryRestartInfo
) );
2280 case FileRenameInfo
:
2281 case FileDispositionInfo
:
2282 case FileAllocationInfo
:
2283 case FileIoPriorityHintInfo
:
2284 case FileEndOfFileInfo
:
2286 SetLastError( ERROR_INVALID_PARAMETER
);
2289 return set_ntstatus( status
);
2293 /***********************************************************************
2294 * GetFileSize (kernelbase.@)
2296 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileSize( HANDLE file
, LPDWORD size_high
)
2300 if (!GetFileSizeEx( file
, &size
)) return INVALID_FILE_SIZE
;
2301 if (size_high
) *size_high
= size
.u
.HighPart
;
2302 if (size
.u
.LowPart
== INVALID_FILE_SIZE
) SetLastError( 0 );
2303 return size
.u
.LowPart
;
2307 /***********************************************************************
2308 * GetFileSizeEx (kernelbase.@)
2310 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileSizeEx( HANDLE file
, PLARGE_INTEGER size
)
2312 FILE_STANDARD_INFORMATION info
;
2315 if (is_console_handle( file
))
2317 SetLastError( ERROR_INVALID_HANDLE
);
2321 if (!set_ntstatus( NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileStandardInformation
)))
2324 *size
= info
.EndOfFile
;
2329 /***********************************************************************
2330 * GetFileTime (kernelbase.@)
2332 BOOL WINAPI DECLSPEC_HOTPATCH
GetFileTime( HANDLE file
, FILETIME
*creation
,
2333 FILETIME
*access
, FILETIME
*write
)
2335 FILE_BASIC_INFORMATION info
;
2338 if (!set_ntstatus( NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FileBasicInformation
)))
2343 creation
->dwHighDateTime
= info
.CreationTime
.u
.HighPart
;
2344 creation
->dwLowDateTime
= info
.CreationTime
.u
.LowPart
;
2348 access
->dwHighDateTime
= info
.LastAccessTime
.u
.HighPart
;
2349 access
->dwLowDateTime
= info
.LastAccessTime
.u
.LowPart
;
2353 write
->dwHighDateTime
= info
.LastWriteTime
.u
.HighPart
;
2354 write
->dwLowDateTime
= info
.LastWriteTime
.u
.LowPart
;
2360 /***********************************************************************
2361 * GetFileType (kernelbase.@)
2363 DWORD WINAPI DECLSPEC_HOTPATCH
GetFileType( HANDLE file
)
2365 FILE_FS_DEVICE_INFORMATION info
;
2368 if (file
== (HANDLE
)STD_INPUT_HANDLE
||
2369 file
== (HANDLE
)STD_OUTPUT_HANDLE
||
2370 file
== (HANDLE
)STD_ERROR_HANDLE
)
2371 file
= GetStdHandle( (DWORD_PTR
)file
);
2373 if (is_console_handle( file
)) return FILE_TYPE_CHAR
;
2375 if (!set_ntstatus( NtQueryVolumeInformationFile( file
, &io
, &info
, sizeof(info
),
2376 FileFsDeviceInformation
)))
2377 return FILE_TYPE_UNKNOWN
;
2379 switch (info
.DeviceType
)
2381 case FILE_DEVICE_NULL
:
2382 case FILE_DEVICE_SERIAL_PORT
:
2383 case FILE_DEVICE_PARALLEL_PORT
:
2384 case FILE_DEVICE_TAPE
:
2385 case FILE_DEVICE_UNKNOWN
:
2386 return FILE_TYPE_CHAR
;
2387 case FILE_DEVICE_NAMED_PIPE
:
2388 return FILE_TYPE_PIPE
;
2390 return FILE_TYPE_DISK
;
2395 /***********************************************************************
2396 * GetOverlappedResult (kernelbase.@)
2398 BOOL WINAPI DECLSPEC_HOTPATCH
GetOverlappedResult( HANDLE file
, LPOVERLAPPED overlapped
,
2399 LPDWORD result
, BOOL wait
)
2401 return GetOverlappedResultEx( file
, overlapped
, result
, wait
? INFINITE
: 0, FALSE
);
2405 /***********************************************************************
2406 * GetOverlappedResultEx (kernelbase.@)
2408 BOOL WINAPI DECLSPEC_HOTPATCH
GetOverlappedResultEx( HANDLE file
, OVERLAPPED
*overlapped
,
2409 DWORD
*result
, DWORD timeout
, BOOL alertable
)
2414 TRACE( "(%p %p %p %u %d)\n", file
, overlapped
, result
, timeout
, alertable
);
2416 status
= overlapped
->Internal
;
2417 if (status
== STATUS_PENDING
)
2421 SetLastError( ERROR_IO_INCOMPLETE
);
2424 ret
= WaitForSingleObjectEx( overlapped
->hEvent
? overlapped
->hEvent
: file
, timeout
, alertable
);
2425 if (ret
== WAIT_FAILED
)
2429 SetLastError( ret
);
2433 status
= overlapped
->Internal
;
2434 if (status
== STATUS_PENDING
) status
= STATUS_SUCCESS
;
2437 *result
= overlapped
->InternalHigh
;
2438 return set_ntstatus( status
);
2442 /**************************************************************************
2443 * LockFile (kernelbase.@)
2445 BOOL WINAPI DECLSPEC_HOTPATCH
LockFile( HANDLE file
, DWORD offset_low
, DWORD offset_high
,
2446 DWORD count_low
, DWORD count_high
)
2448 LARGE_INTEGER count
, offset
;
2450 TRACE( "%p %x%08x %x%08x\n", file
, offset_high
, offset_low
, count_high
, count_low
);
2452 count
.u
.LowPart
= count_low
;
2453 count
.u
.HighPart
= count_high
;
2454 offset
.u
.LowPart
= offset_low
;
2455 offset
.u
.HighPart
= offset_high
;
2456 return set_ntstatus( NtLockFile( file
, 0, NULL
, NULL
, NULL
, &offset
, &count
, NULL
, TRUE
, TRUE
));
2460 /**************************************************************************
2461 * LockFileEx (kernelbase.@)
2463 BOOL WINAPI DECLSPEC_HOTPATCH
LockFileEx( HANDLE file
, DWORD flags
, DWORD reserved
,
2464 DWORD count_low
, DWORD count_high
, LPOVERLAPPED overlapped
)
2466 LARGE_INTEGER count
, offset
;
2467 LPVOID cvalue
= NULL
;
2471 SetLastError( ERROR_INVALID_PARAMETER
);
2475 TRACE( "%p %x%08x %x%08x flags %x\n",
2476 file
, overlapped
->u
.s
.OffsetHigh
, overlapped
->u
.s
.Offset
, count_high
, count_low
, flags
);
2478 count
.u
.LowPart
= count_low
;
2479 count
.u
.HighPart
= count_high
;
2480 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
2481 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
2483 if (((ULONG_PTR
)overlapped
->hEvent
& 1) == 0) cvalue
= overlapped
;
2485 return set_ntstatus( NtLockFile( file
, overlapped
->hEvent
, NULL
, cvalue
,
2486 NULL
, &offset
, &count
, NULL
,
2487 flags
& LOCKFILE_FAIL_IMMEDIATELY
,
2488 flags
& LOCKFILE_EXCLUSIVE_LOCK
));
2492 /***********************************************************************
2493 * OpenFileById (kernelbase.@)
2495 HANDLE WINAPI DECLSPEC_HOTPATCH
OpenFileById( HANDLE handle
, LPFILE_ID_DESCRIPTOR id
, DWORD access
,
2496 DWORD share
, LPSECURITY_ATTRIBUTES sec_attr
, DWORD flags
)
2500 OBJECT_ATTRIBUTES attr
;
2502 UNICODE_STRING objectName
;
2506 SetLastError( ERROR_INVALID_PARAMETER
);
2507 return INVALID_HANDLE_VALUE
;
2510 options
= FILE_OPEN_BY_FILE_ID
;
2511 if (flags
& FILE_FLAG_BACKUP_SEMANTICS
)
2512 options
|= FILE_OPEN_FOR_BACKUP_INTENT
;
2514 options
|= FILE_NON_DIRECTORY_FILE
;
2515 if (flags
& FILE_FLAG_NO_BUFFERING
) options
|= FILE_NO_INTERMEDIATE_BUFFERING
;
2516 if (!(flags
& FILE_FLAG_OVERLAPPED
)) options
|= FILE_SYNCHRONOUS_IO_NONALERT
;
2517 if (flags
& FILE_FLAG_RANDOM_ACCESS
) options
|= FILE_RANDOM_ACCESS
;
2518 flags
&= FILE_ATTRIBUTE_VALID_FLAGS
;
2520 objectName
.Length
= sizeof(ULONGLONG
);
2521 objectName
.Buffer
= (WCHAR
*)&id
->u
.FileId
;
2522 attr
.Length
= sizeof(attr
);
2523 attr
.RootDirectory
= handle
;
2524 attr
.Attributes
= 0;
2525 attr
.ObjectName
= &objectName
;
2526 attr
.SecurityDescriptor
= sec_attr
? sec_attr
->lpSecurityDescriptor
: NULL
;
2527 attr
.SecurityQualityOfService
= NULL
;
2528 if (sec_attr
&& sec_attr
->bInheritHandle
) attr
.Attributes
|= OBJ_INHERIT
;
2530 if (!set_ntstatus( NtCreateFile( &result
, access
| SYNCHRONIZE
, &attr
, &io
, NULL
, flags
,
2531 share
, OPEN_EXISTING
, options
, NULL
, 0 )))
2532 return INVALID_HANDLE_VALUE
;
2537 /***********************************************************************
2538 * ReOpenFile (kernelbase.@)
2540 HANDLE WINAPI DECLSPEC_HOTPATCH
ReOpenFile( HANDLE handle
, DWORD access
, DWORD sharing
, DWORD attributes
)
2542 SECURITY_QUALITY_OF_SERVICE qos
;
2543 OBJECT_ATTRIBUTES attr
;
2544 UNICODE_STRING empty
= { 0 };
2549 TRACE("handle %p, access %#x, sharing %#x, attributes %#x.\n", handle
, access
, sharing
, attributes
);
2551 if (attributes
& 0x7ffff) /* FILE_ATTRIBUTE_* flags are invalid */
2553 SetLastError(ERROR_INVALID_PARAMETER
);
2554 return INVALID_HANDLE_VALUE
;
2557 if (attributes
& FILE_FLAG_DELETE_ON_CLOSE
)
2560 InitializeObjectAttributes( &attr
, &empty
, OBJ_CASE_INSENSITIVE
, handle
, NULL
);
2561 if (attributes
& SECURITY_SQOS_PRESENT
)
2563 qos
.Length
= sizeof(qos
);
2564 qos
.ImpersonationLevel
= (attributes
>> 16) & 0x3;
2565 qos
.ContextTrackingMode
= attributes
& SECURITY_CONTEXT_TRACKING
? SECURITY_DYNAMIC_TRACKING
: SECURITY_STATIC_TRACKING
;
2566 qos
.EffectiveOnly
= (attributes
& SECURITY_EFFECTIVE_ONLY
) != 0;
2567 attr
.SecurityQualityOfService
= &qos
;
2570 status
= NtCreateFile( &file
, access
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
, &attr
, &io
, NULL
,
2571 0, sharing
, FILE_OPEN
, get_nt_file_options( attributes
), NULL
, 0 );
2572 if (!set_ntstatus( status
))
2573 return INVALID_HANDLE_VALUE
;
2578 static void WINAPI
invoke_completion( void *context
, IO_STATUS_BLOCK
*io
, ULONG res
)
2580 LPOVERLAPPED_COMPLETION_ROUTINE completion
= context
;
2581 completion( io
->u
.Status
, io
->Information
, (LPOVERLAPPED
)io
);
2584 /****************************************************************************
2585 * ReadDirectoryChangesW (kernelbase.@)
2587 BOOL WINAPI DECLSPEC_HOTPATCH
ReadDirectoryChangesW( HANDLE handle
, LPVOID buffer
, DWORD len
,
2588 BOOL subtree
, DWORD filter
, LPDWORD returned
,
2589 LPOVERLAPPED overlapped
,
2590 LPOVERLAPPED_COMPLETION_ROUTINE completion
)
2592 OVERLAPPED ov
, *pov
;
2593 IO_STATUS_BLOCK
*ios
;
2595 LPVOID cvalue
= NULL
;
2597 TRACE( "%p %p %08x %d %08x %p %p %p\n",
2598 handle
, buffer
, len
, subtree
, filter
, returned
, overlapped
, completion
);
2602 memset( &ov
, 0, sizeof ov
);
2603 ov
.hEvent
= CreateEventW( NULL
, 0, 0, NULL
);
2609 if (completion
) cvalue
= completion
;
2610 else if (((ULONG_PTR
)overlapped
->hEvent
& 1) == 0) cvalue
= overlapped
;
2613 ios
= (PIO_STATUS_BLOCK
)pov
;
2614 ios
->u
.Status
= STATUS_PENDING
;
2616 status
= NtNotifyChangeDirectoryFile( handle
, completion
&& overlapped
? NULL
: pov
->hEvent
,
2617 completion
&& overlapped
? invoke_completion
: NULL
,
2618 cvalue
, ios
, buffer
, len
, filter
, subtree
);
2619 if (status
== STATUS_PENDING
)
2621 if (overlapped
) return TRUE
;
2622 WaitForSingleObjectEx( ov
.hEvent
, INFINITE
, TRUE
);
2623 if (returned
) *returned
= ios
->Information
;
2624 status
= ios
->u
.Status
;
2626 if (!overlapped
) CloseHandle( ov
.hEvent
);
2627 return set_ntstatus( status
);
2631 /***********************************************************************
2632 * ReadFile (kernelbase.@)
2634 BOOL WINAPI DECLSPEC_HOTPATCH
ReadFile( HANDLE file
, LPVOID buffer
, DWORD count
,
2635 LPDWORD result
, LPOVERLAPPED overlapped
)
2637 LARGE_INTEGER offset
;
2638 PLARGE_INTEGER poffset
= NULL
;
2639 IO_STATUS_BLOCK iosb
;
2640 PIO_STATUS_BLOCK io_status
= &iosb
;
2643 LPVOID cvalue
= NULL
;
2645 TRACE( "%p %p %d %p %p\n", file
, buffer
, count
, result
, overlapped
);
2647 if (result
) *result
= 0;
2651 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
2652 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
2654 event
= overlapped
->hEvent
;
2655 io_status
= (PIO_STATUS_BLOCK
)overlapped
;
2656 if (((ULONG_PTR
)event
& 1) == 0) cvalue
= overlapped
;
2658 else io_status
->Information
= 0;
2659 io_status
->u
.Status
= STATUS_PENDING
;
2661 status
= NtReadFile( file
, event
, NULL
, cvalue
, io_status
, buffer
, count
, poffset
, NULL
);
2663 if (status
== STATUS_PENDING
&& !overlapped
)
2665 WaitForSingleObject( file
, INFINITE
);
2666 status
= io_status
->u
.Status
;
2669 if (result
) *result
= overlapped
&& status
? 0 : io_status
->Information
;
2671 if (status
== STATUS_END_OF_FILE
)
2673 if (overlapped
!= NULL
)
2675 SetLastError( RtlNtStatusToDosError(status
) );
2679 else if (status
&& status
!= STATUS_TIMEOUT
)
2681 SetLastError( RtlNtStatusToDosError(status
) );
2688 /***********************************************************************
2689 * ReadFileEx (kernelbase.@)
2691 BOOL WINAPI DECLSPEC_HOTPATCH
ReadFileEx( HANDLE file
, LPVOID buffer
, DWORD count
, LPOVERLAPPED overlapped
,
2692 LPOVERLAPPED_COMPLETION_ROUTINE completion
)
2694 PIO_STATUS_BLOCK io
;
2695 LARGE_INTEGER offset
;
2698 TRACE( "(file=%p, buffer=%p, bytes=%u, ovl=%p, ovl_fn=%p)\n",
2699 file
, buffer
, count
, overlapped
, completion
);
2703 SetLastError( ERROR_INVALID_PARAMETER
);
2706 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
2707 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
2708 io
= (PIO_STATUS_BLOCK
)overlapped
;
2709 io
->u
.Status
= STATUS_PENDING
;
2710 io
->Information
= 0;
2712 status
= NtReadFile( file
, NULL
, read_write_apc
, completion
, io
, buffer
, count
, &offset
, NULL
);
2713 if (status
== STATUS_PENDING
) return TRUE
;
2714 return set_ntstatus( status
);
2718 /***********************************************************************
2719 * ReadFileScatter (kernelbase.@)
2721 BOOL WINAPI DECLSPEC_HOTPATCH
ReadFileScatter( HANDLE file
, FILE_SEGMENT_ELEMENT
*segments
, DWORD count
,
2722 LPDWORD reserved
, LPOVERLAPPED overlapped
)
2724 PIO_STATUS_BLOCK io
;
2725 LARGE_INTEGER offset
;
2726 void *cvalue
= NULL
;
2728 TRACE( "(%p %p %u %p)\n", file
, segments
, count
, overlapped
);
2730 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
2731 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
2732 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
2733 io
= (PIO_STATUS_BLOCK
)overlapped
;
2734 io
->u
.Status
= STATUS_PENDING
;
2735 io
->Information
= 0;
2737 return set_ntstatus( NtReadFileScatter( file
, overlapped
->hEvent
, NULL
, cvalue
, io
,
2738 segments
, count
, &offset
, NULL
));
2742 /**************************************************************************
2743 * SetEndOfFile (kernelbase.@)
2745 BOOL WINAPI DECLSPEC_HOTPATCH
SetEndOfFile( HANDLE file
)
2747 FILE_POSITION_INFORMATION pos
;
2748 FILE_END_OF_FILE_INFORMATION eof
;
2752 if (!(status
= NtQueryInformationFile( file
, &io
, &pos
, sizeof(pos
), FilePositionInformation
)))
2754 eof
.EndOfFile
= pos
.CurrentByteOffset
;
2755 status
= NtSetInformationFile( file
, &io
, &eof
, sizeof(eof
), FileEndOfFileInformation
);
2757 return set_ntstatus( status
);
2761 /***********************************************************************
2762 * SetFileInformationByHandle (kernelbase.@)
2764 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileInformationByHandle( HANDLE file
, FILE_INFO_BY_HANDLE_CLASS
class,
2765 void *info
, DWORD size
)
2770 TRACE( "%p %u %p %u\n", file
, class, info
, size
);
2775 case FileRenameInfo
:
2776 case FileAllocationInfo
:
2777 case FileEndOfFileInfo
:
2778 case FileStreamInfo
:
2779 case FileIdBothDirectoryInfo
:
2780 case FileIdBothDirectoryRestartInfo
:
2781 case FileFullDirectoryInfo
:
2782 case FileFullDirectoryRestartInfo
:
2783 case FileStorageInfo
:
2784 case FileAlignmentInfo
:
2786 case FileIdExtdDirectoryInfo
:
2787 case FileIdExtdDirectoryRestartInfo
:
2788 FIXME( "%p, %u, %p, %u\n", file
, class, info
, size
);
2789 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
2793 status
= NtSetInformationFile( file
, &io
, info
, size
, FileBasicInformation
);
2795 case FileDispositionInfo
:
2796 status
= NtSetInformationFile( file
, &io
, info
, size
, FileDispositionInformation
);
2798 case FileIoPriorityHintInfo
:
2799 status
= NtSetInformationFile( file
, &io
, info
, size
, FileIoPriorityHintInformation
);
2801 case FileStandardInfo
:
2802 case FileCompressionInfo
:
2803 case FileAttributeTagInfo
:
2804 case FileRemoteProtocolInfo
:
2806 SetLastError( ERROR_INVALID_PARAMETER
);
2809 return set_ntstatus( status
);
2813 /***********************************************************************
2814 * SetFilePointer (kernelbase.@)
2816 DWORD WINAPI DECLSPEC_HOTPATCH
SetFilePointer( HANDLE file
, LONG distance
, LONG
*highword
, DWORD method
)
2818 LARGE_INTEGER dist
, newpos
;
2822 dist
.u
.LowPart
= distance
;
2823 dist
.u
.HighPart
= *highword
;
2825 else dist
.QuadPart
= distance
;
2827 if (!SetFilePointerEx( file
, dist
, &newpos
, method
)) return INVALID_SET_FILE_POINTER
;
2829 if (highword
) *highword
= newpos
.u
.HighPart
;
2830 if (newpos
.u
.LowPart
== INVALID_SET_FILE_POINTER
) SetLastError( 0 );
2831 return newpos
.u
.LowPart
;
2835 /***********************************************************************
2836 * SetFilePointerEx (kernelbase.@)
2838 BOOL WINAPI DECLSPEC_HOTPATCH
SetFilePointerEx( HANDLE file
, LARGE_INTEGER distance
,
2839 LARGE_INTEGER
*newpos
, DWORD method
)
2843 FILE_POSITION_INFORMATION info
;
2844 FILE_END_OF_FILE_INFORMATION eof
;
2849 pos
= distance
.QuadPart
;
2852 if (NtQueryInformationFile( file
, &io
, &info
, sizeof(info
), FilePositionInformation
))
2854 pos
= info
.CurrentByteOffset
.QuadPart
+ distance
.QuadPart
;
2857 if (NtQueryInformationFile( file
, &io
, &eof
, sizeof(eof
), FileEndOfFileInformation
))
2859 pos
= eof
.EndOfFile
.QuadPart
+ distance
.QuadPart
;
2862 SetLastError( ERROR_INVALID_PARAMETER
);
2868 SetLastError( ERROR_NEGATIVE_SEEK
);
2872 info
.CurrentByteOffset
.QuadPart
= pos
;
2873 if (!NtSetInformationFile( file
, &io
, &info
, sizeof(info
), FilePositionInformation
))
2875 if (newpos
) newpos
->QuadPart
= pos
;
2880 return set_ntstatus( io
.u
.Status
);
2884 /***********************************************************************
2885 * SetFileTime (kernelbase.@)
2887 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileTime( HANDLE file
, const FILETIME
*ctime
,
2888 const FILETIME
*atime
, const FILETIME
*mtime
)
2890 FILE_BASIC_INFORMATION info
;
2893 memset( &info
, 0, sizeof(info
) );
2896 info
.CreationTime
.u
.HighPart
= ctime
->dwHighDateTime
;
2897 info
.CreationTime
.u
.LowPart
= ctime
->dwLowDateTime
;
2901 info
.LastAccessTime
.u
.HighPart
= atime
->dwHighDateTime
;
2902 info
.LastAccessTime
.u
.LowPart
= atime
->dwLowDateTime
;
2906 info
.LastWriteTime
.u
.HighPart
= mtime
->dwHighDateTime
;
2907 info
.LastWriteTime
.u
.LowPart
= mtime
->dwLowDateTime
;
2910 return set_ntstatus( NtSetInformationFile( file
, &io
, &info
, sizeof(info
), FileBasicInformation
));
2914 /***********************************************************************
2915 * SetFileValidData (kernelbase.@)
2917 BOOL WINAPI DECLSPEC_HOTPATCH
SetFileValidData( HANDLE file
, LONGLONG length
)
2919 FILE_VALID_DATA_LENGTH_INFORMATION info
;
2922 info
.ValidDataLength
.QuadPart
= length
;
2923 return set_ntstatus( NtSetInformationFile( file
, &io
, &info
, sizeof(info
),
2924 FileValidDataLengthInformation
));
2928 /**************************************************************************
2929 * UnlockFile (kernelbase.@)
2931 BOOL WINAPI DECLSPEC_HOTPATCH
UnlockFile( HANDLE file
, DWORD offset_low
, DWORD offset_high
,
2932 DWORD count_low
, DWORD count_high
)
2934 LARGE_INTEGER count
, offset
;
2936 count
.u
.LowPart
= count_low
;
2937 count
.u
.HighPart
= count_high
;
2938 offset
.u
.LowPart
= offset_low
;
2939 offset
.u
.HighPart
= offset_high
;
2940 return set_ntstatus( NtUnlockFile( file
, NULL
, &offset
, &count
, NULL
));
2944 /**************************************************************************
2945 * UnlockFileEx (kernelbase.@)
2947 BOOL WINAPI DECLSPEC_HOTPATCH
UnlockFileEx( HANDLE file
, DWORD reserved
,
2948 DWORD count_low
, DWORD count_high
, LPOVERLAPPED overlapped
)
2952 SetLastError( ERROR_INVALID_PARAMETER
);
2955 if (overlapped
->hEvent
) FIXME("Unimplemented overlapped operation\n");
2957 return UnlockFile( file
, overlapped
->u
.s
.Offset
, overlapped
->u
.s
.OffsetHigh
, count_low
, count_high
);
2961 /***********************************************************************
2962 * WriteFile (kernelbase.@)
2964 BOOL WINAPI DECLSPEC_HOTPATCH
WriteFile( HANDLE file
, LPCVOID buffer
, DWORD count
,
2965 LPDWORD result
, LPOVERLAPPED overlapped
)
2967 HANDLE event
= NULL
;
2968 LARGE_INTEGER offset
;
2969 PLARGE_INTEGER poffset
= NULL
;
2971 IO_STATUS_BLOCK iosb
;
2972 PIO_STATUS_BLOCK piosb
= &iosb
;
2973 LPVOID cvalue
= NULL
;
2975 TRACE( "%p %p %d %p %p\n", file
, buffer
, count
, result
, overlapped
);
2979 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
2980 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
2982 event
= overlapped
->hEvent
;
2983 piosb
= (PIO_STATUS_BLOCK
)overlapped
;
2984 if (((ULONG_PTR
)event
& 1) == 0) cvalue
= overlapped
;
2986 else piosb
->Information
= 0;
2987 piosb
->u
.Status
= STATUS_PENDING
;
2989 status
= NtWriteFile( file
, event
, NULL
, cvalue
, piosb
, buffer
, count
, poffset
, NULL
);
2991 if (status
== STATUS_PENDING
&& !overlapped
)
2993 WaitForSingleObject( file
, INFINITE
);
2994 status
= piosb
->u
.Status
;
2997 if (result
) *result
= overlapped
&& status
? 0 : piosb
->Information
;
2999 if (status
&& status
!= STATUS_TIMEOUT
)
3001 SetLastError( RtlNtStatusToDosError(status
) );
3008 /***********************************************************************
3009 * WriteFileEx (kernelbase.@)
3011 BOOL WINAPI DECLSPEC_HOTPATCH
WriteFileEx( HANDLE file
, LPCVOID buffer
,
3012 DWORD count
, LPOVERLAPPED overlapped
,
3013 LPOVERLAPPED_COMPLETION_ROUTINE completion
)
3015 LARGE_INTEGER offset
;
3017 PIO_STATUS_BLOCK io
;
3019 TRACE( "%p %p %d %p %p\n", file
, buffer
, count
, overlapped
, completion
);
3023 SetLastError( ERROR_INVALID_PARAMETER
);
3026 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3027 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3029 io
= (PIO_STATUS_BLOCK
)overlapped
;
3030 io
->u
.Status
= STATUS_PENDING
;
3031 io
->Information
= 0;
3033 status
= NtWriteFile( file
, NULL
, read_write_apc
, completion
, io
, buffer
, count
, &offset
, NULL
);
3034 if (status
== STATUS_PENDING
) return TRUE
;
3035 return set_ntstatus( status
);
3039 /***********************************************************************
3040 * WriteFileGather (kernelbase.@)
3042 BOOL WINAPI DECLSPEC_HOTPATCH
WriteFileGather( HANDLE file
, FILE_SEGMENT_ELEMENT
*segments
, DWORD count
,
3043 LPDWORD reserved
, LPOVERLAPPED overlapped
)
3045 PIO_STATUS_BLOCK io
;
3046 LARGE_INTEGER offset
;
3047 void *cvalue
= NULL
;
3049 TRACE( "%p %p %u %p\n", file
, segments
, count
, overlapped
);
3051 offset
.u
.LowPart
= overlapped
->u
.s
.Offset
;
3052 offset
.u
.HighPart
= overlapped
->u
.s
.OffsetHigh
;
3053 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
3054 io
= (PIO_STATUS_BLOCK
)overlapped
;
3055 io
->u
.Status
= STATUS_PENDING
;
3056 io
->Information
= 0;
3058 return set_ntstatus( NtWriteFileGather( file
, overlapped
->hEvent
, NULL
, cvalue
,
3059 io
, segments
, count
, &offset
, NULL
));
3063 /***********************************************************************
3064 * Operations on file times
3065 ***********************************************************************/
3068 /*********************************************************************
3069 * CompareFileTime (kernelbase.@)
3071 INT WINAPI DECLSPEC_HOTPATCH
CompareFileTime( const FILETIME
*x
, const FILETIME
*y
)
3073 if (!x
|| !y
) return -1;
3074 if (x
->dwHighDateTime
> y
->dwHighDateTime
) return 1;
3075 if (x
->dwHighDateTime
< y
->dwHighDateTime
) return -1;
3076 if (x
->dwLowDateTime
> y
->dwLowDateTime
) return 1;
3077 if (x
->dwLowDateTime
< y
->dwLowDateTime
) return -1;
3082 /*********************************************************************
3083 * FileTimeToLocalFileTime (kernelbase.@)
3085 BOOL WINAPI DECLSPEC_HOTPATCH
FileTimeToLocalFileTime( const FILETIME
*utc
, FILETIME
*local
)
3087 return set_ntstatus( RtlSystemTimeToLocalTime( (const LARGE_INTEGER
*)utc
, (LARGE_INTEGER
*)local
));
3091 /*********************************************************************
3092 * FileTimeToSystemTime (kernelbase.@)
3094 BOOL WINAPI DECLSPEC_HOTPATCH
FileTimeToSystemTime( const FILETIME
*ft
, SYSTEMTIME
*systime
)
3098 RtlTimeToTimeFields( (const LARGE_INTEGER
*)ft
, &tf
);
3099 systime
->wYear
= tf
.Year
;
3100 systime
->wMonth
= tf
.Month
;
3101 systime
->wDay
= tf
.Day
;
3102 systime
->wHour
= tf
.Hour
;
3103 systime
->wMinute
= tf
.Minute
;
3104 systime
->wSecond
= tf
.Second
;
3105 systime
->wMilliseconds
= tf
.Milliseconds
;
3106 systime
->wDayOfWeek
= tf
.Weekday
;
3111 /*********************************************************************
3112 * GetLocalTime (kernelbase.@)
3114 void WINAPI DECLSPEC_HOTPATCH
GetLocalTime( SYSTEMTIME
*systime
)
3116 LARGE_INTEGER ft
, ft2
;
3118 NtQuerySystemTime( &ft
);
3119 RtlSystemTimeToLocalTime( &ft
, &ft2
);
3120 FileTimeToSystemTime( (FILETIME
*)&ft2
, systime
);
3124 /*********************************************************************
3125 * GetSystemTime (kernelbase.@)
3127 void WINAPI DECLSPEC_HOTPATCH
GetSystemTime( SYSTEMTIME
*systime
)
3131 NtQuerySystemTime( &ft
);
3132 FileTimeToSystemTime( (FILETIME
*)&ft
, systime
);
3136 /***********************************************************************
3137 * GetSystemTimeAsFileTime (kernelbase.@)
3139 void WINAPI DECLSPEC_HOTPATCH
GetSystemTimeAsFileTime( FILETIME
*time
)
3141 NtQuerySystemTime( (LARGE_INTEGER
*)time
);
3145 /***********************************************************************
3146 * GetSystemTimePreciseAsFileTime (kernelbase.@)
3148 void WINAPI DECLSPEC_HOTPATCH
GetSystemTimePreciseAsFileTime( FILETIME
*time
)
3152 t
.QuadPart
= RtlGetSystemTimePrecise();
3153 time
->dwLowDateTime
= t
.u
.LowPart
;
3154 time
->dwHighDateTime
= t
.u
.HighPart
;
3158 /*********************************************************************
3159 * LocalFileTimeToFileTime (kernelbase.@)
3161 BOOL WINAPI DECLSPEC_HOTPATCH
LocalFileTimeToFileTime( const FILETIME
*local
, FILETIME
*utc
)
3163 return set_ntstatus( RtlLocalTimeToSystemTime( (const LARGE_INTEGER
*)local
, (LARGE_INTEGER
*)utc
));
3167 /***********************************************************************
3168 * SetLocalTime (kernelbase.@)
3170 BOOL WINAPI DECLSPEC_HOTPATCH
SetLocalTime( const SYSTEMTIME
*systime
)
3175 if (!SystemTimeToFileTime( systime
, &ft
)) return FALSE
;
3176 RtlLocalTimeToSystemTime( (LARGE_INTEGER
*)&ft
, &st
);
3177 return set_ntstatus( NtSetSystemTime( &st
, NULL
));
3181 /***********************************************************************
3182 * SetSystemTime (kernelbase.@)
3184 BOOL WINAPI DECLSPEC_HOTPATCH
SetSystemTime( const SYSTEMTIME
*systime
)
3188 if (!SystemTimeToFileTime( systime
, &ft
)) return FALSE
;
3189 return set_ntstatus( NtSetSystemTime( (LARGE_INTEGER
*)&ft
, NULL
));
3193 /*********************************************************************
3194 * SystemTimeToFileTime (kernelbase.@)
3196 BOOL WINAPI DECLSPEC_HOTPATCH
SystemTimeToFileTime( const SYSTEMTIME
*systime
, FILETIME
*ft
)
3200 tf
.Year
= systime
->wYear
;
3201 tf
.Month
= systime
->wMonth
;
3202 tf
.Day
= systime
->wDay
;
3203 tf
.Hour
= systime
->wHour
;
3204 tf
.Minute
= systime
->wMinute
;
3205 tf
.Second
= systime
->wSecond
;
3206 tf
.Milliseconds
= systime
->wMilliseconds
;
3207 if (RtlTimeFieldsToTime( &tf
, (LARGE_INTEGER
*)ft
)) return TRUE
;
3208 SetLastError( ERROR_INVALID_PARAMETER
);
3213 /***********************************************************************
3215 ***********************************************************************/
3218 static void dump_dcb( const DCB
*dcb
)
3220 TRACE( "size=%d rate=%d fParity=%d Parity=%d stopbits=%d %sIXON %sIXOFF CTS=%d RTS=%d DSR=%d DTR=%d %sCRTSCTS\n",
3221 dcb
->ByteSize
, dcb
->BaudRate
, dcb
->fParity
, dcb
->Parity
,
3222 (dcb
->StopBits
== ONESTOPBIT
) ? 1 : (dcb
->StopBits
== TWOSTOPBITS
) ? 2 : 0,
3223 dcb
->fOutX
? "" : "~", dcb
->fInX
? "" : "~",
3224 dcb
->fOutxCtsFlow
, dcb
->fRtsControl
, dcb
->fOutxDsrFlow
, dcb
->fDtrControl
,
3225 (dcb
->fOutxCtsFlow
|| dcb
->fRtsControl
== RTS_CONTROL_HANDSHAKE
) ? "" : "~" );
3228 /*****************************************************************************
3229 * ClearCommBreak (kernelbase.@)
3231 BOOL WINAPI DECLSPEC_HOTPATCH
ClearCommBreak( HANDLE handle
)
3233 return EscapeCommFunction( handle
, CLRBREAK
);
3237 /*****************************************************************************
3238 * ClearCommError (kernelbase.@)
3240 BOOL WINAPI DECLSPEC_HOTPATCH
ClearCommError( HANDLE handle
, DWORD
*errors
, COMSTAT
*stat
)
3244 if (!DeviceIoControl( handle
, IOCTL_SERIAL_GET_COMMSTATUS
, NULL
, 0, &ss
, sizeof(ss
), NULL
, NULL
))
3247 TRACE( "status %#x,%#x, in %u, out %u, eof %d, wait %d\n", ss
.Errors
, ss
.HoldReasons
,
3248 ss
.AmountInInQueue
, ss
.AmountInOutQueue
, ss
.EofReceived
, ss
.WaitForImmediate
);
3253 if (ss
.Errors
& SERIAL_ERROR_BREAK
) *errors
|= CE_BREAK
;
3254 if (ss
.Errors
& SERIAL_ERROR_FRAMING
) *errors
|= CE_FRAME
;
3255 if (ss
.Errors
& SERIAL_ERROR_OVERRUN
) *errors
|= CE_OVERRUN
;
3256 if (ss
.Errors
& SERIAL_ERROR_QUEUEOVERRUN
) *errors
|= CE_RXOVER
;
3257 if (ss
.Errors
& SERIAL_ERROR_PARITY
) *errors
|= CE_RXPARITY
;
3261 stat
->fCtsHold
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_CTS
);
3262 stat
->fDsrHold
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_DSR
);
3263 stat
->fRlsdHold
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_DCD
);
3264 stat
->fXoffHold
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_FOR_XON
);
3265 stat
->fXoffSent
= !!(ss
.HoldReasons
& SERIAL_TX_WAITING_XOFF_SENT
);
3266 stat
->fEof
= !!ss
.EofReceived
;
3267 stat
->fTxim
= !!ss
.WaitForImmediate
;
3268 stat
->cbInQue
= ss
.AmountInInQueue
;
3269 stat
->cbOutQue
= ss
.AmountInOutQueue
;
3275 /****************************************************************************
3276 * DeviceIoControl (kernelbase.@)
3278 BOOL WINAPI DECLSPEC_HOTPATCH
DeviceIoControl( HANDLE handle
, DWORD code
, void *in_buff
, DWORD in_count
,
3279 void *out_buff
, DWORD out_count
, DWORD
*returned
,
3280 OVERLAPPED
*overlapped
)
3282 IO_STATUS_BLOCK iosb
, *piosb
= &iosb
;
3283 void *cvalue
= NULL
;
3287 TRACE( "(%p,%x,%p,%d,%p,%d,%p,%p)\n",
3288 handle
, code
, in_buff
, in_count
, out_buff
, out_count
, returned
, overlapped
);
3292 piosb
= (IO_STATUS_BLOCK
*)overlapped
;
3293 if (!((ULONG_PTR
)overlapped
->hEvent
& 1)) cvalue
= overlapped
;
3294 event
= overlapped
->hEvent
;
3295 overlapped
->Internal
= STATUS_PENDING
;
3296 overlapped
->InternalHigh
= 0;
3299 if (HIWORD(code
) == FILE_DEVICE_FILE_SYSTEM
)
3300 status
= NtFsControlFile( handle
, event
, NULL
, cvalue
, piosb
, code
,
3301 in_buff
, in_count
, out_buff
, out_count
);
3303 status
= NtDeviceIoControlFile( handle
, event
, NULL
, cvalue
, piosb
, code
,
3304 in_buff
, in_count
, out_buff
, out_count
);
3306 if (returned
) *returned
= piosb
->Information
;
3307 return set_ntstatus( status
);
3311 /*****************************************************************************
3312 * EscapeCommFunction (kernelbase.@)
3314 BOOL WINAPI DECLSPEC_HOTPATCH
EscapeCommFunction( HANDLE handle
, DWORD func
)
3316 static const DWORD ioctls
[] =
3319 IOCTL_SERIAL_SET_XOFF
, /* SETXOFF */
3320 IOCTL_SERIAL_SET_XON
, /* SETXON */
3321 IOCTL_SERIAL_SET_RTS
, /* SETRTS */
3322 IOCTL_SERIAL_CLR_RTS
, /* CLRRTS */
3323 IOCTL_SERIAL_SET_DTR
, /* SETDTR */
3324 IOCTL_SERIAL_CLR_DTR
, /* CLRDTR */
3325 IOCTL_SERIAL_RESET_DEVICE
, /* RESETDEV */
3326 IOCTL_SERIAL_SET_BREAK_ON
, /* SETBREAK */
3327 IOCTL_SERIAL_SET_BREAK_OFF
/* CLRBREAK */
3330 if (func
>= ARRAY_SIZE(ioctls
) || !ioctls
[func
])
3332 SetLastError( ERROR_INVALID_PARAMETER
);
3335 return DeviceIoControl( handle
, ioctls
[func
], NULL
, 0, NULL
, 0, NULL
, NULL
);
3339 /***********************************************************************
3340 * GetCommConfig (kernelbase.@)
3342 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommConfig( HANDLE handle
, COMMCONFIG
*config
, DWORD
*size
)
3344 if (!config
) return FALSE
;
3346 TRACE( "(%p, %p, %p %u)\n", handle
, config
, size
, *size
);
3348 if (*size
< sizeof(COMMCONFIG
))
3350 *size
= sizeof(COMMCONFIG
);
3353 *size
= sizeof(COMMCONFIG
);
3354 config
->dwSize
= sizeof(COMMCONFIG
);
3355 config
->wVersion
= 1;
3356 config
->wReserved
= 0;
3357 config
->dwProviderSubType
= PST_RS232
;
3358 config
->dwProviderOffset
= 0;
3359 config
->dwProviderSize
= 0;
3360 return GetCommState( handle
, &config
->dcb
);
3364 /*****************************************************************************
3365 * GetCommMask (kernelbase.@)
3367 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommMask( HANDLE handle
, DWORD
*mask
)
3369 return DeviceIoControl( handle
, IOCTL_SERIAL_GET_WAIT_MASK
, NULL
, 0, mask
, sizeof(*mask
),
3374 /***********************************************************************
3375 * GetCommModemStatus (kernelbase.@)
3377 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommModemStatus( HANDLE handle
, DWORD
*status
)
3379 return DeviceIoControl( handle
, IOCTL_SERIAL_GET_MODEMSTATUS
, NULL
, 0, status
, sizeof(*status
),
3384 /***********************************************************************
3385 * GetCommProperties (kernelbase.@)
3387 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommProperties( HANDLE handle
, COMMPROP
*prop
)
3389 return DeviceIoControl( handle
, IOCTL_SERIAL_GET_PROPERTIES
, NULL
, 0, prop
, sizeof(*prop
), NULL
, NULL
);
3393 /*****************************************************************************
3394 * GetCommState (kernelbase.@)
3396 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommState( HANDLE handle
, DCB
*dcb
)
3398 SERIAL_BAUD_RATE sbr
;
3399 SERIAL_LINE_CONTROL slc
;
3400 SERIAL_HANDFLOW shf
;
3405 SetLastError( ERROR_INVALID_PARAMETER
);
3408 if (!DeviceIoControl(handle
, IOCTL_SERIAL_GET_BAUD_RATE
, NULL
, 0, &sbr
, sizeof(sbr
), NULL
, NULL
) ||
3409 !DeviceIoControl(handle
, IOCTL_SERIAL_GET_LINE_CONTROL
, NULL
, 0, &slc
, sizeof(slc
), NULL
, NULL
) ||
3410 !DeviceIoControl(handle
, IOCTL_SERIAL_GET_HANDFLOW
, NULL
, 0, &shf
, sizeof(shf
), NULL
, NULL
) ||
3411 !DeviceIoControl(handle
, IOCTL_SERIAL_GET_CHARS
, NULL
, 0, &sc
, sizeof(sc
), NULL
, NULL
))
3414 dcb
->DCBlength
= sizeof(*dcb
);
3415 dcb
->BaudRate
= sbr
.BaudRate
;
3416 /* yes, they seem no never be (re)set on NT */
3419 dcb
->fOutxCtsFlow
= !!(shf
.ControlHandShake
& SERIAL_CTS_HANDSHAKE
);
3420 dcb
->fOutxDsrFlow
= !!(shf
.ControlHandShake
& SERIAL_DSR_HANDSHAKE
);
3421 dcb
->fDsrSensitivity
= !!(shf
.ControlHandShake
& SERIAL_DSR_SENSITIVITY
);
3422 dcb
->fTXContinueOnXoff
= !!(shf
.FlowReplace
& SERIAL_XOFF_CONTINUE
);
3423 dcb
->fOutX
= !!(shf
.FlowReplace
& SERIAL_AUTO_TRANSMIT
);
3424 dcb
->fInX
= !!(shf
.FlowReplace
& SERIAL_AUTO_RECEIVE
);
3425 dcb
->fErrorChar
= !!(shf
.FlowReplace
& SERIAL_ERROR_CHAR
);
3426 dcb
->fNull
= !!(shf
.FlowReplace
& SERIAL_NULL_STRIPPING
);
3427 dcb
->fAbortOnError
= !!(shf
.ControlHandShake
& SERIAL_ERROR_ABORT
);
3428 dcb
->XonLim
= shf
.XonLimit
;
3429 dcb
->XoffLim
= shf
.XoffLimit
;
3430 dcb
->ByteSize
= slc
.WordLength
;
3431 dcb
->Parity
= slc
.Parity
;
3432 dcb
->StopBits
= slc
.StopBits
;
3433 dcb
->XonChar
= sc
.XonChar
;
3434 dcb
->XoffChar
= sc
.XoffChar
;
3435 dcb
->ErrorChar
= sc
.ErrorChar
;
3436 dcb
->EofChar
= sc
.EofChar
;
3437 dcb
->EvtChar
= sc
.EventChar
;
3439 switch (shf
.ControlHandShake
& (SERIAL_DTR_CONTROL
| SERIAL_DTR_HANDSHAKE
))
3441 case SERIAL_DTR_CONTROL
: dcb
->fDtrControl
= DTR_CONTROL_ENABLE
; break;
3442 case SERIAL_DTR_HANDSHAKE
: dcb
->fDtrControl
= DTR_CONTROL_HANDSHAKE
; break;
3443 default: dcb
->fDtrControl
= DTR_CONTROL_DISABLE
; break;
3445 switch (shf
.FlowReplace
& (SERIAL_RTS_CONTROL
| SERIAL_RTS_HANDSHAKE
))
3447 case SERIAL_RTS_CONTROL
: dcb
->fRtsControl
= RTS_CONTROL_ENABLE
; break;
3448 case SERIAL_RTS_HANDSHAKE
: dcb
->fRtsControl
= RTS_CONTROL_HANDSHAKE
; break;
3449 case SERIAL_RTS_CONTROL
| SERIAL_RTS_HANDSHAKE
:
3450 dcb
->fRtsControl
= RTS_CONTROL_TOGGLE
; break;
3451 default: dcb
->fRtsControl
= RTS_CONTROL_DISABLE
; break;
3458 /*****************************************************************************
3459 * GetCommTimeouts (kernelbase.@)
3461 BOOL WINAPI DECLSPEC_HOTPATCH
GetCommTimeouts( HANDLE handle
, COMMTIMEOUTS
*timeouts
)
3465 SetLastError( ERROR_INVALID_PARAMETER
);
3468 return DeviceIoControl( handle
, IOCTL_SERIAL_GET_TIMEOUTS
, NULL
, 0, timeouts
, sizeof(*timeouts
),
3472 /********************************************************************
3473 * PurgeComm (kernelbase.@)
3475 BOOL WINAPI DECLSPEC_HOTPATCH
PurgeComm(HANDLE handle
, DWORD flags
)
3477 return DeviceIoControl( handle
, IOCTL_SERIAL_PURGE
, &flags
, sizeof(flags
),
3478 NULL
, 0, NULL
, NULL
);
3482 /*****************************************************************************
3483 * SetCommBreak (kernelbase.@)
3485 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommBreak( HANDLE handle
)
3487 return EscapeCommFunction( handle
, SETBREAK
);
3491 /***********************************************************************
3492 * SetCommConfig (kernelbase.@)
3494 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommConfig( HANDLE handle
, COMMCONFIG
*config
, DWORD size
)
3496 TRACE( "(%p, %p, %u)\n", handle
, config
, size
);
3497 return SetCommState( handle
, &config
->dcb
);
3501 /*****************************************************************************
3502 * SetCommMask (kernelbase.@)
3504 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommMask( HANDLE handle
, DWORD mask
)
3506 return DeviceIoControl( handle
, IOCTL_SERIAL_SET_WAIT_MASK
, &mask
, sizeof(mask
),
3507 NULL
, 0, NULL
, NULL
);
3511 /*****************************************************************************
3512 * SetCommState (kernelbase.@)
3514 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommState( HANDLE handle
, DCB
*dcb
)
3516 SERIAL_BAUD_RATE sbr
;
3517 SERIAL_LINE_CONTROL slc
;
3518 SERIAL_HANDFLOW shf
;
3523 SetLastError( ERROR_INVALID_PARAMETER
);
3528 sbr
.BaudRate
= dcb
->BaudRate
;
3529 slc
.StopBits
= dcb
->StopBits
;
3530 slc
.Parity
= dcb
->Parity
;
3531 slc
.WordLength
= dcb
->ByteSize
;
3532 shf
.ControlHandShake
= 0;
3533 shf
.FlowReplace
= 0;
3534 if (dcb
->fOutxCtsFlow
) shf
.ControlHandShake
|= SERIAL_CTS_HANDSHAKE
;
3535 if (dcb
->fOutxDsrFlow
) shf
.ControlHandShake
|= SERIAL_DSR_HANDSHAKE
;
3536 switch (dcb
->fDtrControl
)
3538 case DTR_CONTROL_DISABLE
: break;
3539 case DTR_CONTROL_ENABLE
: shf
.ControlHandShake
|= SERIAL_DTR_CONTROL
; break;
3540 case DTR_CONTROL_HANDSHAKE
: shf
.ControlHandShake
|= SERIAL_DTR_HANDSHAKE
; break;
3542 SetLastError( ERROR_INVALID_PARAMETER
);
3545 switch (dcb
->fRtsControl
)
3547 case RTS_CONTROL_DISABLE
: break;
3548 case RTS_CONTROL_ENABLE
: shf
.FlowReplace
|= SERIAL_RTS_CONTROL
; break;
3549 case RTS_CONTROL_HANDSHAKE
: shf
.FlowReplace
|= SERIAL_RTS_HANDSHAKE
; break;
3550 case RTS_CONTROL_TOGGLE
: shf
.FlowReplace
|= SERIAL_RTS_CONTROL
| SERIAL_RTS_HANDSHAKE
; break;
3552 SetLastError( ERROR_INVALID_PARAMETER
);
3555 if (dcb
->fDsrSensitivity
) shf
.ControlHandShake
|= SERIAL_DSR_SENSITIVITY
;
3556 if (dcb
->fAbortOnError
) shf
.ControlHandShake
|= SERIAL_ERROR_ABORT
;
3557 if (dcb
->fErrorChar
) shf
.FlowReplace
|= SERIAL_ERROR_CHAR
;
3558 if (dcb
->fNull
) shf
.FlowReplace
|= SERIAL_NULL_STRIPPING
;
3559 if (dcb
->fTXContinueOnXoff
) shf
.FlowReplace
|= SERIAL_XOFF_CONTINUE
;
3560 if (dcb
->fOutX
) shf
.FlowReplace
|= SERIAL_AUTO_TRANSMIT
;
3561 if (dcb
->fInX
) shf
.FlowReplace
|= SERIAL_AUTO_RECEIVE
;
3562 shf
.XonLimit
= dcb
->XonLim
;
3563 shf
.XoffLimit
= dcb
->XoffLim
;
3564 sc
.EofChar
= dcb
->EofChar
;
3565 sc
.ErrorChar
= dcb
->ErrorChar
;
3567 sc
.EventChar
= dcb
->EvtChar
;
3568 sc
.XonChar
= dcb
->XonChar
;
3569 sc
.XoffChar
= dcb
->XoffChar
;
3571 /* note: change DTR/RTS lines after setting the comm attributes,
3572 * so flow control does not interfere.
3574 return (DeviceIoControl( handle
, IOCTL_SERIAL_SET_BAUD_RATE
, &sbr
, sizeof(sbr
), NULL
, 0, NULL
, NULL
) &&
3575 DeviceIoControl( handle
, IOCTL_SERIAL_SET_LINE_CONTROL
, &slc
, sizeof(slc
), NULL
, 0, NULL
, NULL
) &&
3576 DeviceIoControl( handle
, IOCTL_SERIAL_SET_HANDFLOW
, &shf
, sizeof(shf
), NULL
, 0, NULL
, NULL
) &&
3577 DeviceIoControl( handle
, IOCTL_SERIAL_SET_CHARS
, &sc
, sizeof(sc
), NULL
, 0, NULL
, NULL
));
3581 /*****************************************************************************
3582 * SetCommTimeouts (kernelbase.@)
3584 BOOL WINAPI DECLSPEC_HOTPATCH
SetCommTimeouts( HANDLE handle
, COMMTIMEOUTS
*timeouts
)
3588 SetLastError( ERROR_INVALID_PARAMETER
);
3591 return DeviceIoControl( handle
, IOCTL_SERIAL_SET_TIMEOUTS
, timeouts
, sizeof(*timeouts
),
3592 NULL
, 0, NULL
, NULL
);
3596 /*****************************************************************************
3597 * SetupComm (kernelbase.@)
3599 BOOL WINAPI DECLSPEC_HOTPATCH
SetupComm( HANDLE handle
, DWORD in_size
, DWORD out_size
)
3601 SERIAL_QUEUE_SIZE sqs
;
3603 sqs
.InSize
= in_size
;
3604 sqs
.OutSize
= out_size
;
3605 return DeviceIoControl( handle
, IOCTL_SERIAL_SET_QUEUE_SIZE
, &sqs
, sizeof(sqs
), NULL
, 0, NULL
, NULL
);
3609 /*****************************************************************************
3610 * TransmitCommChar (kernelbase.@)
3612 BOOL WINAPI DECLSPEC_HOTPATCH
TransmitCommChar( HANDLE handle
, CHAR ch
)
3614 return DeviceIoControl( handle
, IOCTL_SERIAL_IMMEDIATE_CHAR
, &ch
, sizeof(ch
), NULL
, 0, NULL
, NULL
);
3618 /***********************************************************************
3619 * WaitCommEvent (kernelbase.@)
3621 BOOL WINAPI DECLSPEC_HOTPATCH
WaitCommEvent( HANDLE handle
, DWORD
*events
, OVERLAPPED
*overlapped
)
3623 return DeviceIoControl( handle
, IOCTL_SERIAL_WAIT_ON_MASK
, NULL
, 0, events
, sizeof(*events
),