📄 file.c
字号:
/* $Id: file.c 21880 2006-05-10 17:47:44Z ion $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/kernel32/file/file.c
* PURPOSE: Directory functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
* GetTempFileName is modified from WINE [ Alexandre Juiliard ]
* UPDATE HISTORY:
* Created 01/11/98
*/
/* INCLUDES *****************************************************************/
/* File contains Vista Semantics */
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#include <k32.h>
#define NDEBUG
#include "../include/debug.h"
/* GLOBALS ******************************************************************/
BOOL bIsFileApiAnsi = TRUE; // set the file api to ansi or oem
/* FUNCTIONS ****************************************************************/
PWCHAR
FilenameA2W(LPCSTR NameA, BOOL alloc)
{
ANSI_STRING str;
UNICODE_STRING strW;
PUNICODE_STRING pstrW;
NTSTATUS Status;
ASSERT(NtCurrentTeb()->StaticUnicodeString.Buffer == NtCurrentTeb()->StaticUnicodeBuffer);
ASSERT(NtCurrentTeb()->StaticUnicodeString.MaximumLength == sizeof(NtCurrentTeb()->StaticUnicodeBuffer));
RtlInitAnsiString(&str, NameA);
pstrW = alloc ? &strW : &NtCurrentTeb()->StaticUnicodeString;
if (bIsFileApiAnsi)
Status= RtlAnsiStringToUnicodeString( pstrW, &str, alloc );
else
Status= RtlOemStringToUnicodeString( pstrW, &str, alloc );
if (NT_SUCCESS(Status))
return pstrW->Buffer;
if (Status== STATUS_BUFFER_OVERFLOW)
SetLastError( ERROR_FILENAME_EXCED_RANGE );
else
SetLastErrorByStatus(Status);
return NULL;
}
/*
No copy/conversion is done if the dest. buffer is too small.
Returns:
Success: number of TCHARS copied into dest. buffer NOT including nullterm
Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
*/
DWORD
FilenameU2A_FitOrFail(
LPSTR DestA,
INT destLen, /* buffer size in TCHARS incl. nullchar */
PUNICODE_STRING SourceU
)
{
DWORD ret;
ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU);
/* ret incl. nullchar */
if (DestA && (INT)ret <= destLen)
{
ANSI_STRING str;
str.Buffer = DestA;
str.MaximumLength = destLen;
if (bIsFileApiAnsi)
RtlUnicodeStringToAnsiString(&str, SourceU, FALSE );
else
RtlUnicodeStringToOemString(&str, SourceU, FALSE );
ret = str.Length; /* SUCCESS: length without terminating 0 */
}
return ret;
}
/*
No copy/conversion is done if the dest. buffer is too small.
Returns:
Success: number of TCHARS copied into dest. buffer NOT including nullterm
Fail: size of buffer in TCHARS required to hold the converted filename, including nullterm
*/
DWORD
FilenameW2A_FitOrFail(
LPSTR DestA,
INT destLen, /* buffer size in TCHARS incl. nullchar */
LPCWSTR SourceW,
INT sourceLen /* buffer size in TCHARS incl. nullchar */
)
{
UNICODE_STRING strW;
if (sourceLen < 0) sourceLen = wcslen(SourceW) + 1;
strW.Buffer = (PWCHAR)SourceW;
strW.MaximumLength = sourceLen * sizeof(WCHAR);
strW.Length = strW.MaximumLength - sizeof(WCHAR);
return FilenameU2A_FitOrFail(DestA, destLen, &strW);
}
/*
Return: num. TCHARS copied into dest including nullterm
*/
DWORD
FilenameA2W_N(
LPWSTR dest,
INT destlen, /* buffer size in TCHARS incl. nullchar */
LPCSTR src,
INT srclen /* buffer size in TCHARS incl. nullchar */
)
{
DWORD ret;
if (srclen < 0) srclen = strlen( src ) + 1;
if (bIsFileApiAnsi)
RtlMultiByteToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
else
RtlOemToUnicodeN( dest, destlen* sizeof(WCHAR), &ret, (LPSTR)src, srclen );
if (ret) dest[(ret/sizeof(WCHAR))-1]=0;
return ret/sizeof(WCHAR);
}
/*
Return: num. TCHARS copied into dest including nullterm
*/
DWORD
FilenameW2A_N(
LPSTR dest,
INT destlen, /* buffer size in TCHARS incl. nullchar */
LPCWSTR src,
INT srclen /* buffer size in TCHARS incl. nullchar */
)
{
DWORD ret;
if (srclen < 0) srclen = wcslen( src ) + 1;
if (bIsFileApiAnsi)
RtlUnicodeToMultiByteN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR));
else
RtlUnicodeToOemN( dest, destlen, &ret, (LPWSTR) src, srclen * sizeof(WCHAR) );
if (ret) dest[ret-1]=0;
return ret;
}
/*
* @implemented
*/
VOID
STDCALL
SetFileApisToOEM(VOID)
{
/* Set the correct Base Api */
Basep8BitStringToUnicodeString = (PRTL_CONVERT_STRING)RtlOemStringToUnicodeString;
/* FIXME: Old, deprecated way */
bIsFileApiAnsi = FALSE;
}
/*
* @implemented
*/
VOID
STDCALL
SetFileApisToANSI(VOID)
{
/* Set the correct Base Api */
Basep8BitStringToUnicodeString = RtlAnsiStringToUnicodeString;
/* FIXME: Old, deprecated way */
bIsFileApiAnsi = TRUE;
}
/*
* @implemented
*/
BOOL STDCALL
AreFileApisANSI(VOID)
{
return bIsFileApiAnsi;
}
/*
* @implemented
*/
HFILE STDCALL
OpenFile(LPCSTR lpFileName,
LPOFSTRUCT lpReOpenBuff,
UINT uStyle)
{
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING FileNameString;
UNICODE_STRING FileNameU;
ANSI_STRING FileName;
WCHAR PathNameW[MAX_PATH];
HANDLE FileHandle = NULL;
NTSTATUS errCode;
PWCHAR FilePart;
ULONG Len;
DPRINT("OpenFile('%s', lpReOpenBuff %x, uStyle %x)\n", lpFileName, lpReOpenBuff, uStyle);
if (lpReOpenBuff == NULL)
{
return FALSE;
}
if ((uStyle & OF_CREATE) == OF_CREATE)
{
DWORD Sharing;
switch (uStyle & 0x70)
{
case OF_SHARE_EXCLUSIVE: Sharing = 0; break;
case OF_SHARE_DENY_WRITE: Sharing = FILE_SHARE_READ; break;
case OF_SHARE_DENY_READ: Sharing = FILE_SHARE_WRITE; break;
case OF_SHARE_DENY_NONE:
case OF_SHARE_COMPAT:
default:
Sharing = FILE_SHARE_READ | FILE_SHARE_WRITE;
}
return (HFILE) CreateFileA (lpFileName,
GENERIC_READ | GENERIC_WRITE,
Sharing,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0);
}
RtlInitAnsiString (&FileName, (LPSTR)lpFileName);
/* convert ansi (or oem) string to unicode */
if (bIsFileApiAnsi)
RtlAnsiStringToUnicodeString (&FileNameU, &FileName, TRUE);
else
RtlOemStringToUnicodeString (&FileNameU, &FileName, TRUE);
Len = SearchPathW (NULL,
FileNameU.Buffer,
NULL,
OFS_MAXPATHNAME,
PathNameW,
&FilePart);
RtlFreeUnicodeString(&FileNameU);
if (Len == 0 || Len > OFS_MAXPATHNAME)
{
return (HFILE)INVALID_HANDLE_VALUE;
}
FileName.Buffer = lpReOpenBuff->szPathName;
FileName.Length = 0;
FileName.MaximumLength = OFS_MAXPATHNAME;
RtlInitUnicodeString(&FileNameU, PathNameW);
/* convert unicode string to ansi (or oem) */
if (bIsFileApiAnsi)
RtlUnicodeStringToAnsiString (&FileName, &FileNameU, FALSE);
else
RtlUnicodeStringToOemString (&FileName, &FileNameU, FALSE);
if (!RtlDosPathNameToNtPathName_U (PathNameW,
&FileNameString,
NULL,
NULL))
{
return (HFILE)INVALID_HANDLE_VALUE;
}
// FILE_SHARE_READ
// FILE_NO_INTERMEDIATE_BUFFERING
if ((uStyle & OF_PARSE) == OF_PARSE)
{
RtlFreeHeap(RtlGetProcessHeap(),
0,
FileNameString.Buffer);
return (HFILE)NULL;
}
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory = NULL;
ObjectAttributes.ObjectName = &FileNameString;
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT;
ObjectAttributes.SecurityDescriptor = NULL;
ObjectAttributes.SecurityQualityOfService = NULL;
errCode = NtOpenFile (&FileHandle,
GENERIC_READ|SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ,
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
RtlFreeHeap(RtlGetProcessHeap(),
0,
FileNameString.Buffer);
lpReOpenBuff->nErrCode = RtlNtStatusToDosError(errCode);
if (!NT_SUCCESS(errCode))
{
SetLastErrorByStatus (errCode);
return (HFILE)INVALID_HANDLE_VALUE;
}
return (HFILE)FileHandle;
}
/*
* @implemented
*/
BOOL STDCALL
FlushFileBuffers(HANDLE hFile)
{
NTSTATUS errCode;
IO_STATUS_BLOCK IoStatusBlock;
if (IsConsoleHandle(hFile))
{
return FALSE;
}
errCode = NtFlushBuffersFile(hFile,
&IoStatusBlock);
if (!NT_SUCCESS(errCode))
{
SetLastErrorByStatus(errCode);
return(FALSE);
}
return(TRUE);
}
/*
* @implemented
*/
DWORD STDCALL
SetFilePointer(HANDLE hFile,
LONG lDistanceToMove,
PLONG lpDistanceToMoveHigh,
DWORD dwMoveMethod)
{
FILE_POSITION_INFORMATION FilePosition;
FILE_STANDARD_INFORMATION FileStandard;
NTSTATUS errCode;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER Distance;
DPRINT("SetFilePointer(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n",
hFile,lDistanceToMove,dwMoveMethod);
if(IsConsoleHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return -1;
}
Distance.u.LowPart = lDistanceToMove;
if (lpDistanceToMoveHigh)
{
Distance.u.HighPart = *lpDistanceToMoveHigh;
}
else if (lDistanceToMove >= 0)
{
Distance.u.HighPart = 0;
}
else
{
Distance.u.HighPart = -1;
}
switch(dwMoveMethod)
{
case FILE_CURRENT:
NtQueryInformationFile(hFile,
&IoStatusBlock,
&FilePosition,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation);
FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart;
break;
case FILE_END:
NtQueryInformationFile(hFile,
&IoStatusBlock,
&FileStandard,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
FilePosition.CurrentByteOffset.QuadPart =
FileStandard.EndOfFile.QuadPart + Distance.QuadPart;
break;
case FILE_BEGIN:
FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart;
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
if(FilePosition.CurrentByteOffset.QuadPart < 0)
{
SetLastError(ERROR_NEGATIVE_SEEK);
return -1;
}
errCode = NtSetInformationFile(hFile,
&IoStatusBlock,
&FilePosition,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation);
if (!NT_SUCCESS(errCode))
{
SetLastErrorByStatus(errCode);
return -1;
}
if (lpDistanceToMoveHigh != NULL)
{
*lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart;
}
return FilePosition.CurrentByteOffset.u.LowPart;
}
/*
* @implemented
*/
BOOL
STDCALL
SetFilePointerEx(HANDLE hFile,
LARGE_INTEGER liDistanceToMove,
PLARGE_INTEGER lpNewFilePointer,
DWORD dwMoveMethod)
{
FILE_POSITION_INFORMATION FilePosition;
FILE_STANDARD_INFORMATION FileStandard;
NTSTATUS errCode;
IO_STATUS_BLOCK IoStatusBlock;
if(IsConsoleHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
switch(dwMoveMethod)
{
case FILE_CURRENT:
NtQueryInformationFile(hFile,
&IoStatusBlock,
&FilePosition,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation);
FilePosition.CurrentByteOffset.QuadPart += liDistanceToMove.QuadPart;
break;
case FILE_END:
NtQueryInformationFile(hFile,
&IoStatusBlock,
&FileStandard,
sizeof(FILE_STANDARD_INFORMATION),
FileStandardInformation);
FilePosition.CurrentByteOffset.QuadPart =
FileStandard.EndOfFile.QuadPart + liDistanceToMove.QuadPart;
break;
case FILE_BEGIN:
FilePosition.CurrentByteOffset.QuadPart = liDistanceToMove.QuadPart;
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if(FilePosition.CurrentByteOffset.QuadPart < 0)
{
SetLastError(ERROR_NEGATIVE_SEEK);
return FALSE;
}
errCode = NtSetInformationFile(hFile,
&IoStatusBlock,
&FilePosition,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation);
if (!NT_SUCCESS(errCode))
{
SetLastErrorByStatus(errCode);
return FALSE;
}
if (lpNewFilePointer)
{
*lpNewFilePointer = FilePosition.CurrentByteOffset;
}
return TRUE;
}
/*
* @implemented
*/
DWORD STDCALL
GetFileType(HANDLE hFile)
{
FILE_FS_DEVICE_INFORMATION DeviceInfo;
IO_STATUS_BLOCK StatusBlock;
NTSTATUS Status;
/* Get real handle */
switch ((ULONG)hFile)
{
case STD_INPUT_HANDLE:
hFile = NtCurrentPeb()->ProcessParameters->StandardInput;
break;
case STD_OUTPUT_HANDLE:
hFile = NtCurrentPeb()->ProcessParameters->StandardOutput;
break;
case STD_ERROR_HANDLE:
hFile = NtCurrentPeb()->ProcessParameters->StandardError;
break;
}
/* Check for console handle */
if (IsConsoleHandle(hFile))
{
if (VerifyConsoleIoHandle(hFile))
return FILE_TYPE_CHAR;
}
Status = NtQueryVolumeInformationFile(hFile,
&StatusBlock,
&DeviceInfo,
sizeof(FILE_FS_DEVICE_INFORMATION),
FileFsDeviceInformation);
if (!NT_SUCCESS(Status))
{
SetLastErrorByStatus(Status);
return FILE_TYPE_UNKNOWN;
}
switch (DeviceInfo.DeviceType)
{
case FILE_DEVICE_CD_ROM:
case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
case FILE_DEVICE_CONTROLLER:
case FILE_DEVICE_DATALINK:
case FILE_DEVICE_DFS:
case FILE_DEVICE_DISK:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -