/*++ Copyright (c) 1997 Microsoft Corporation Module Name: basefile.c Abstract: Contains simple wrappers for commonly used file i/o functions. Author: Marc R. Whitten (marcw) 02-Sep-1999 Revision History: --*/ #include "pch.h" // // Includes // // None #define DBG_BASEFILE "File Utils" // // Strings // // None // // Constants // // None // // Macros // // None // // Types // // None // // Globals // // None // // Macro expansion list // // None // // Private function prototypes // // None // // Macro expansion definition // // None // // Code // BOOL WriteFileStringA ( IN HANDLE File, IN PCSTR String ) /*++ Routine Description: Writes a DBCS string to the specified file. Arguments: File - Specifies the file handle that was opened with write access. String - Specifies the nul-terminated string to write to the file. Return Value: TRUE if successful, FALSE if an error occurred. Call GetLastError for error condition. --*/ { DWORD DontCare; return WriteFile (File, String, ByteCountA (String), &DontCare, NULL); } BOOL WriteFileStringW ( IN HANDLE File, IN PCWSTR String ) /*++ Routine Description: Converts a UNICODE string to DBCS, then Writes it to the specified file. Arguments: File - Specifies the file handle that was opened with write access. String - Specifies the UNICODE nul-terminated string to convert and write to the file. Return Value: TRUE if successful, FALSE if an error occurred. Call GetLastError for error condition. --*/ { DWORD DontCare; PCSTR AnsiVersion; BOOL b; AnsiVersion = ConvertWtoA (String); if (!AnsiVersion) { return FALSE; } b = WriteFile (File, AnsiVersion, ByteCountA (AnsiVersion), &DontCare, NULL); FreeConvertedStr (AnsiVersion); return b; } BOOL DoesFileExistExA( IN PCSTR FileName, OUT PWIN32_FIND_DATAA FindData OPTIONAL ) /*++ Routine Description: Determine if a file exists and is accessible. Errormode is set (and then restored) so the user will not see any pop-ups. Arguments: FileName - supplies full path of file to check for existance. FindData - if specified, receives find data for the file. Return Value: TRUE if the file exists and is accessible. FALSE if not. GetLastError() returns extended error info. --*/ { WIN32_FIND_DATAA ourFindData; HANDLE FindHandle; UINT OldMode; DWORD Error; if (!FindData) { return GetFileAttributesA (FileName) != 0xffffffff; } OldMode = SetErrorMode(SEM_FAILCRITICALERRORS); FindHandle = FindFirstFileA(FileName, &ourFindData); if (FindHandle == INVALID_HANDLE_VALUE) { Error = GetLastError(); } else { FindClose(FindHandle); *FindData = ourFindData; Error = NO_ERROR; } SetErrorMode(OldMode); SetLastError(Error); return (Error == NO_ERROR); } BOOL DoesFileExistExW ( IN PCWSTR FileName, OUT PWIN32_FIND_DATAW FindData OPTIONAL ) /*++ Routine Description: Determine if a file exists and is accessible. Errormode is set (and then restored) so the user will not see any pop-ups. Arguments: FileName - supplies full path of file to check for existance. FindData - if specified, receives find data for the file. Return Value: TRUE if the file exists and is accessible. FALSE if not. GetLastError() returns extended error info. --*/ { WIN32_FIND_DATAW ourFindData; HANDLE FindHandle; UINT OldMode; DWORD Error; if (!FindData) { return GetFileAttributesW (FileName) != 0xffffffff; } OldMode = SetErrorMode(SEM_FAILCRITICALERRORS); FindHandle = FindFirstFileW(FileName,&ourFindData); if (FindHandle == INVALID_HANDLE_VALUE) { Error = GetLastError(); } else { FindClose(FindHandle); *FindData = ourFindData; Error = NO_ERROR; } SetErrorMode(OldMode); SetLastError(Error); return (Error == NO_ERROR); } /*++ Routine Description: PathIsDirectory determines if a path identifies an accessible directory. Arguments: PathSpec - Specifies the full path. Return Value: TRUE if the path identifies a directory. FALSE if not. GetLastError() returns extended error info. --*/ BOOL PathIsDirectoryA ( IN PCSTR PathSpec ) { DWORD attribs; MYASSERT (PathSpec); if (!PathSpec) { return FALSE; } attribs = GetFileAttributesA (PathSpec); return attribs != (DWORD)-1 && (attribs & FILE_ATTRIBUTE_DIRECTORY); } BOOL PathIsDirectoryW ( IN PCWSTR PathSpec ) { DWORD attribs; MYASSERT (PathSpec); if (!PathSpec) { return FALSE; } attribs = GetFileAttributesW (PathSpec); return attribs != (DWORD)-1 && (attribs & FILE_ATTRIBUTE_DIRECTORY); } PVOID MapFileIntoMemoryExA ( IN PCSTR FileName, OUT PHANDLE FileHandle, OUT PHANDLE MapHandle, IN BOOL WriteAccess ) /*++ Routine Description: MapFileIntoMemoryA and MapFileIntoMemoryW map a file into memory. It does that by opening the file, creating a mapping object and mapping opened file into created mapping object. It returnes the address where the file is mapped and also sets FileHandle and MapHandle variables to be used in order to unmap the file when work is done. Arguments: FileName - the name of the file to be mapped into memory FileHandle - will end keeping the file handle if the file was opened successfully MapHandle - will end keeping the mapping object handle if this object was created successfully Return Value: NULL if function fails, a valid memory address if successfull Comments: If the return value is NULL you should call UnmapFile to release all allocated resources --*/ { PVOID fileImage = NULL; //verify function parameters if ((FileHandle == NULL) || (MapHandle == NULL)) { return NULL; } //first thing. Try to open the file, read-only *FileHandle = CreateFileA ( FileName, WriteAccess?GENERIC_READ|GENERIC_WRITE:GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (*FileHandle == INVALID_HANDLE_VALUE) { return NULL; } //now try to create a mapping object, read-only *MapHandle = CreateFileMappingA (*FileHandle, NULL, WriteAccess?PAGE_READWRITE:PAGE_READONLY, 0, 0, NULL); if (*MapHandle == NULL) { return NULL; } //one more thing to do: map view of file fileImage = MapViewOfFile (*MapHandle, WriteAccess?FILE_MAP_WRITE:FILE_MAP_READ, 0, 0, 0); return fileImage; } PVOID MapFileIntoMemoryExW ( IN PCWSTR FileName, OUT PHANDLE FileHandle, OUT PHANDLE MapHandle, IN BOOL WriteAccess ) /*++ Routine Description: MapFileIntoMemoryA and MapFileIntoMemoryW map a file into memory. It does that by opening the file, creating a mapping object and mapping opened file into created mapping object. It returnes the address where the file is mapped and also sets FileHandle and MapHandle variables to be used in order to unmap the file when work is done. Arguments: FileName - the name of the file to be mapped into memory FileHandle - will end keeping the file handle if the file was opened successfully MapHandle - will end keeping the mapping object handle if this object was created successfully Return Value: NULL if function fails, a valid memory address if successfull Comments: If the return value is NULL you should call UnmapFile to release all allocated resources --*/ { PVOID fileImage = NULL; //verify function parameters if ((FileHandle == NULL) || (MapHandle == NULL)) { return NULL; } //first thing. Try to open the file, read-only *FileHandle = CreateFileW ( FileName, WriteAccess?GENERIC_READ|GENERIC_WRITE:GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (*FileHandle == INVALID_HANDLE_VALUE) { return NULL; } //now try to create a mapping object, read-only *MapHandle = CreateFileMappingW (*FileHandle, NULL, WriteAccess?PAGE_READWRITE:PAGE_READONLY, 0, 0, NULL); if (*MapHandle == NULL) { return NULL; } //one more thing to do: map view of file fileImage = MapViewOfFile (*MapHandle, WriteAccess?FILE_MAP_WRITE:FILE_MAP_READ, 0, 0, 0); return fileImage; } #if 0 BOOL UnmapFile ( IN PCVOID FileImage, IN HANDLE MapHandle, IN HANDLE FileHandle ) /*++ Routine Description: UnmapFile is used to release all resources allocated by MapFileIntoMemory. Arguments: FileImage - image of the mapped file as returned by MapFileIntoMemory MapHandle - handle of the mapping object as returned by MapFileIntoMemory FileHandle - handle of the file as returned by MapFileIntoMemory Return Value: TRUE if successfull, FALSE if not --*/ { BOOL result = TRUE; //if FileImage is a valid pointer then try to unmap file if (FileImage != NULL) { if (UnmapViewOfFile (FileImage) == 0) { result = FALSE; } } //if mapping object is valid then try to delete it if (MapHandle != NULL) { if (CloseHandle (MapHandle) == 0) { result = FALSE; } } //if file handle is valid then try to close the file if (FileHandle != INVALID_HANDLE_VALUE) { if (CloseHandle (FileHandle) == 0) { result = FALSE; } } return result; } #endif BOOL BfGetTempFileNameA ( OUT PSTR Buffer, IN UINT BufferTchars ) { CHAR tempPath[MAX_MBCHAR_PATH]; CHAR tempFile[MAX_MBCHAR_PATH]; UINT tchars; if (!GetTempPathA (ARRAYSIZE(tempPath), tempPath)) { return FALSE; } if (BufferTchars >= MAX_PATH) { if (!GetTempFileNameA (tempPath, "tmp", 0, Buffer)) { return FALSE; } } else { if (!GetTempFileNameA (tempPath, "tmp", 0, tempFile)) { return FALSE; } tchars = TcharCountA (tempFile); if (tchars > BufferTchars) { DEBUGMSG ((DBG_ERROR, "Can't get temp file name -- buffer too small")); return FALSE; } CopyMemory (Buffer, tempFile, tchars * sizeof (CHAR)); } return TRUE; } BOOL BfGetTempFileNameW ( OUT PWSTR Buffer, IN UINT BufferTchars ) { WCHAR tempPath[MAX_WCHAR_PATH]; WCHAR tempFile[MAX_WCHAR_PATH]; UINT tchars; if (!GetTempPathW (ARRAYSIZE(tempPath), tempPath)) { return FALSE; } if (BufferTchars >= MAX_PATH) { if (!GetTempFileNameW (tempPath, L"tmp", 0, Buffer)) { return FALSE; } } else { if (!GetTempFileNameW (tempPath, L"tmp", 0, tempFile)) { return FALSE; } tchars = TcharCountW (tempFile); if (tchars > BufferTchars) { DEBUGMSG ((DBG_ERROR, "Can't get temp file name -- buffer too small")); return FALSE; } CopyMemory (Buffer, tempFile, tchars * sizeof (WCHAR)); } return TRUE; } HANDLE BfGetTempFile ( VOID ) { CHAR tempFile[MAX_MBCHAR_PATH]; HANDLE file; if (!BfGetTempFileNameA (tempFile, ARRAYSIZE(tempFile))) { return NULL; } file = CreateFile ( tempFile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL ); if (file == INVALID_HANDLE_VALUE) { file = NULL; } return file; } BOOL BfSetFilePointer ( IN HANDLE File, IN LONGLONG Offset ) { LARGE_INTEGER li; li.QuadPart = Offset; li.LowPart = SetFilePointer (File, li.LowPart, &li.HighPart, FILE_BEGIN); if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) { li.QuadPart = -1; } return li.QuadPart != -1; } HANDLE BfOpenFileA ( IN PCSTR FileName ) { HANDLE handle; handle = CreateFileA ( FileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (handle == INVALID_HANDLE_VALUE) { handle = NULL; } return handle; } HANDLE BfOpenFileW ( IN PCWSTR FileName ) { HANDLE handle; handle = CreateFileW ( FileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (handle == INVALID_HANDLE_VALUE) { handle = NULL; } return handle; } HANDLE BfCreateFileA ( IN PCSTR FileName ) { HANDLE handle; handle = CreateFileA ( FileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (handle == INVALID_HANDLE_VALUE) { handle = NULL; } return handle; } HANDLE BfCreateFileW ( IN PCWSTR FileName ) { HANDLE handle; handle = CreateFileW ( FileName, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (handle == INVALID_HANDLE_VALUE) { handle = NULL; } return handle; } HANDLE BfCreateSharedFileA ( IN PCSTR FileName ) { HANDLE handle; handle = CreateFileA ( FileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (handle == INVALID_HANDLE_VALUE) { handle = NULL; } return handle; } HANDLE BfCreateSharedFileW ( IN PCWSTR FileName ) { HANDLE handle; handle = CreateFileW ( FileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (handle == INVALID_HANDLE_VALUE) { handle = NULL; } return handle; } BOOL BfSetSizeOfFile ( HANDLE File, LONGLONG Size ) { if (!BfSetFilePointer (File, Size)) { return FALSE; } return SetEndOfFile (File); } BOOL BfGoToEndOfFile ( IN HANDLE File, OUT PLONGLONG FileSize OPTIONAL ) { LARGE_INTEGER li; li.HighPart = 0; li.LowPart = SetFilePointer (File, 0, &li.HighPart, FILE_END); if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) { li.QuadPart = -1; } else if (FileSize) { *FileSize = li.QuadPart; } return li.QuadPart != -1; } BOOL BfGetFilePointer ( IN HANDLE File, OUT PLONGLONG FilePointer OPTIONAL ) { LARGE_INTEGER li; li.HighPart = 0; li.LowPart = SetFilePointer (File, 0, &li.HighPart, FILE_CURRENT); if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR) { li.QuadPart = -1; } else if (FilePointer) { *FilePointer = li.QuadPart; } return li.QuadPart != -1; } BOOL BfReadFile ( IN HANDLE File, OUT PBYTE Buffer, IN UINT BytesToRead ) { DWORD bytesRead; if (!ReadFile (File, Buffer, BytesToRead, &bytesRead, NULL)) { return FALSE; } return bytesRead == BytesToRead; } BOOL BfWriteFile ( IN HANDLE File, OUT PCBYTE Buffer, IN UINT BytesToWrite ) { DWORD bytesWritten; if (!WriteFile (File, Buffer, BytesToWrite, &bytesWritten, NULL)) { return FALSE; } return bytesWritten == BytesToWrite; } BOOL BfCreateDirectoryA ( IN PCSTR FullPath ) { PSTR pathCopy; PSTR p; BOOL b = TRUE; pathCopy = DuplicatePathStringA (FullPath, 0); // // Advance past first directory // if (pathCopy[1] == ':' && pathCopy[2] == '\\') { // // :\ case // p = _mbschr (&pathCopy[3], '\\'); } else if (pathCopy[0] == '\\' && pathCopy[1] == '\\') { // // UNC case // p = _mbschr (pathCopy + 2, '\\'); if (p) { p = _mbschr (p + 1, '\\'); if (p) { p++; } } } else { // // Relative dir case // p = _mbschr (pathCopy, '\\'); } // // Make all directories along the path // while (p) { *p = 0; b = CreateDirectoryA (pathCopy, NULL); if (!b && GetLastError() == ERROR_ALREADY_EXISTS) { b = TRUE; } if (!b) { break; } *p = '\\'; p = _mbschr (p + 1, '\\'); } // // At last, make the FullPath directory // if (b) { b = CreateDirectoryA (pathCopy, NULL); if (!b && GetLastError() == ERROR_ALREADY_EXISTS) { b = TRUE; } } FreePathStringA (pathCopy); return b; } BOOL BfCreateDirectoryW ( IN PCWSTR FullPath ) { PWSTR pathCopy; PWSTR p; BOOL b = TRUE; pathCopy = DuplicatePathStringW (FullPath, 0); // // Advance past first directory // if (pathCopy[1] == L':' && pathCopy[2] == L'\\') { // // :\ case // p = wcschr (&pathCopy[3], L'\\'); } else if (pathCopy[0] == L'\\' && pathCopy[1] == L'\\') { // // UNC case // p = wcschr (pathCopy + 2, L'\\'); if (p) { p = wcschr (p + 1, L'\\'); if (p) { p++; } } } else { // // Relative dir case // p = wcschr (pathCopy, L'\\'); } // // Make all directories along the path // while (p) { *p = 0; b = CreateDirectoryW (pathCopy, NULL); if (!b && GetLastError() == ERROR_ALREADY_EXISTS) { b = TRUE; } if (!b) { break; } *p = L'\\'; p = wcschr (p + 1, L'\\'); } // // At last, make the FullPath directory // if (b) { b = CreateDirectoryW (pathCopy, NULL); if (!b && GetLastError() == ERROR_ALREADY_EXISTS) { b = TRUE; } } FreePathStringW (pathCopy); return b; } LONGLONG BfGetFileSizeA ( IN PCSTR FileName ) { WIN32_FIND_DATAA fd; LONGLONG l; if (!DoesFileExistExA (FileName, &fd)) { return 0; } l = ((LONGLONG) fd.nFileSizeHigh << 32) | fd.nFileSizeLow; return l; } PSTR pGetFirstSegA ( IN PCSTR SrcFileName ) { if (SrcFileName [0] == '\\') { SrcFileName ++; if (SrcFileName [0] == '\\') { SrcFileName ++; } return (_mbschr (SrcFileName, '\\')); } else { return (_mbschr (SrcFileName, '\\')); } } BOOL pGetLongFileNameWorkerA ( IN PCSTR SrcFileName, IN PGROWBUFFER GrowBuf ) { PSTR beginSegPtr; PSTR endSegPtr; WIN32_FIND_DATAA findData; CHAR savedChar; beginSegPtr = pGetFirstSegA (SrcFileName); if (!beginSegPtr) { GbAppendStringA (GrowBuf, SrcFileName); return TRUE; } beginSegPtr = _mbsinc (beginSegPtr); GbAppendStringABA (GrowBuf, SrcFileName, beginSegPtr); while (beginSegPtr) { endSegPtr = _mbschr (beginSegPtr, '\\'); if (!endSegPtr) { endSegPtr = GetEndOfStringA (beginSegPtr); MYASSERT (endSegPtr); } savedChar = *endSegPtr; *endSegPtr = 0; if (DoesFileExistExA (SrcFileName, &findData)) { GbAppendStringA (GrowBuf, findData.cFileName); } else { GbAppendStringABA (GrowBuf, beginSegPtr, endSegPtr); } *endSegPtr = savedChar; if (savedChar) { beginSegPtr = _mbsinc (endSegPtr); GbAppendStringABA (GrowBuf, endSegPtr, beginSegPtr); } else { beginSegPtr = NULL; } } return TRUE; } PCSTR BfGetLongFileNameA ( IN PCSTR SrcFileName ) { GROWBUFFER growBuf = INIT_GROWBUFFER; PSTR srcFileName; PCSTR result = NULL; srcFileName = (PSTR)SanitizePathA (SrcFileName); if (pGetLongFileNameWorkerA (srcFileName, &growBuf)) { result = DuplicatePathStringA (growBuf.Buf, 0); GbFree (&growBuf); } FreePathStringA (srcFileName); return result; } BOOL BfGetLongFileNameExA ( IN PCSTR SrcFileName, IN PGROWBUFFER GrowBuff ) { PSTR srcFileName; BOOL result; srcFileName = (PSTR)SanitizePathA (SrcFileName); result = pGetLongFileNameWorkerA (srcFileName, GrowBuff); FreePathStringA (srcFileName); return result; } PWSTR pGetFirstSegW ( IN PCWSTR SrcFileName ) { if (SrcFileName [0] == L'\\') { SrcFileName ++; if (SrcFileName [0] == L'\\') { SrcFileName ++; } return (wcschr (SrcFileName, L'\\')); } else { return (wcschr (SrcFileName, L'\\')); } } BOOL pGetLongFileNameWorkerW ( IN PCWSTR SrcFileName, IN PGROWBUFFER GrowBuf ) { PWSTR beginSegPtr; PWSTR endSegPtr; WIN32_FIND_DATAW findData; WCHAR savedChar; beginSegPtr = pGetFirstSegW (SrcFileName); if (!beginSegPtr) { GbAppendStringW (GrowBuf, SrcFileName); return TRUE; } beginSegPtr ++; GbAppendStringABW (GrowBuf, SrcFileName, beginSegPtr); while (beginSegPtr) { endSegPtr = wcschr (beginSegPtr, L'\\'); if (!endSegPtr) { endSegPtr = GetEndOfStringW (beginSegPtr); MYASSERT (endSegPtr); } savedChar = *endSegPtr; *endSegPtr = 0; if (DoesFileExistExW (SrcFileName, &findData)) { GbAppendStringW (GrowBuf, findData.cFileName); } else { GbAppendStringABW (GrowBuf, beginSegPtr, endSegPtr); } *endSegPtr = savedChar; if (savedChar) { beginSegPtr = endSegPtr + 1; GbAppendStringABW (GrowBuf, endSegPtr, beginSegPtr); } else { beginSegPtr = NULL; } } return TRUE; } PCWSTR BfGetLongFileNameW ( IN PCWSTR SrcFileName ) { GROWBUFFER growBuf = INIT_GROWBUFFER; PWSTR srcFileName; PCWSTR result = NULL; srcFileName = (PWSTR)SanitizePathW (SrcFileName); if (pGetLongFileNameWorkerW (srcFileName, &growBuf)) { result = DuplicatePathStringW ((PCWSTR)growBuf.Buf, 0); GbFree (&growBuf); } FreePathStringW (srcFileName); return result; } BOOL BfGetLongFileNameExW ( IN PCWSTR SrcFileName, IN PGROWBUFFER GrowBuff ) { PWSTR srcFileName; BOOL result; srcFileName = (PWSTR)SanitizePathW (SrcFileName); result = pGetLongFileNameWorkerW (srcFileName, GrowBuff); FreePathStringW (srcFileName); return result; }