|
|
|
@ -22,6 +22,7 @@
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif /* HAVE_CONFIG_H */
|
|
|
|
|
|
|
|
|
|
#include <winpr/crt.h>
|
|
|
|
|
#include <winpr/file.h>
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
@ -704,6 +705,119 @@ BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle)
|
|
|
|
|
|
|
|
|
|
#ifdef _UWP
|
|
|
|
|
|
|
|
|
|
HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
|
|
|
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
|
|
|
|
|
{
|
|
|
|
|
HANDLE hFile;
|
|
|
|
|
CREATEFILE2_EXTENDED_PARAMETERS params;
|
|
|
|
|
|
|
|
|
|
ZeroMemory(¶ms, sizeof(CREATEFILE2_EXTENDED_PARAMETERS));
|
|
|
|
|
|
|
|
|
|
params.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
|
|
|
|
|
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) params.dwFileFlags |= FILE_FLAG_BACKUP_SEMANTICS;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) params.dwFileFlags |= FILE_FLAG_DELETE_ON_CLOSE;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING) params.dwFileFlags |= FILE_FLAG_NO_BUFFERING;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL) params.dwFileFlags |= FILE_FLAG_OPEN_NO_RECALL;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT) params.dwFileFlags |= FILE_FLAG_OPEN_REPARSE_POINT;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REQUIRING_OPLOCK) params.dwFileFlags |= FILE_FLAG_OPEN_REQUIRING_OPLOCK;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED) params.dwFileFlags |= FILE_FLAG_OVERLAPPED;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS) params.dwFileFlags |= FILE_FLAG_POSIX_SEMANTICS;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS) params.dwFileFlags |= FILE_FLAG_RANDOM_ACCESS;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_SESSION_AWARE) params.dwFileFlags |= FILE_FLAG_SESSION_AWARE;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN) params.dwFileFlags |= FILE_FLAG_SEQUENTIAL_SCAN;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH) params.dwFileFlags |= FILE_FLAG_WRITE_THROUGH;
|
|
|
|
|
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_ARCHIVE) params.dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_COMPRESSED) params.dwFileAttributes |= FILE_ATTRIBUTE_COMPRESSED;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_DEVICE) params.dwFileAttributes |= FILE_ATTRIBUTE_DEVICE;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_DIRECTORY) params.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_ENCRYPTED) params.dwFileAttributes |= FILE_ATTRIBUTE_ENCRYPTED;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_HIDDEN) params.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) params.dwFileAttributes |= FILE_ATTRIBUTE_INTEGRITY_STREAM;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NORMAL) params.dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) params.dwFileAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) params.dwFileAttributes |= FILE_ATTRIBUTE_NO_SCRUB_DATA;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_OFFLINE) params.dwFileAttributes |= FILE_ATTRIBUTE_OFFLINE;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_READONLY) params.dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_REPARSE_POINT) params.dwFileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_SPARSE_FILE) params.dwFileAttributes |= FILE_ATTRIBUTE_SPARSE_FILE;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_SYSTEM) params.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_TEMPORARY) params.dwFileAttributes |= FILE_ATTRIBUTE_TEMPORARY;
|
|
|
|
|
if (dwFlagsAndAttributes & FILE_ATTRIBUTE_VIRTUAL) params.dwFileAttributes |= FILE_ATTRIBUTE_VIRTUAL;
|
|
|
|
|
|
|
|
|
|
if (dwFlagsAndAttributes & SECURITY_ANONYMOUS) params.dwSecurityQosFlags |= SECURITY_ANONYMOUS;
|
|
|
|
|
if (dwFlagsAndAttributes & SECURITY_CONTEXT_TRACKING) params.dwSecurityQosFlags |= SECURITY_CONTEXT_TRACKING;
|
|
|
|
|
if (dwFlagsAndAttributes & SECURITY_DELEGATION) params.dwSecurityQosFlags |= SECURITY_DELEGATION;
|
|
|
|
|
if (dwFlagsAndAttributes & SECURITY_EFFECTIVE_ONLY) params.dwSecurityQosFlags |= SECURITY_EFFECTIVE_ONLY;
|
|
|
|
|
if (dwFlagsAndAttributes & SECURITY_IDENTIFICATION) params.dwSecurityQosFlags |= SECURITY_IDENTIFICATION;
|
|
|
|
|
if (dwFlagsAndAttributes & SECURITY_IMPERSONATION) params.dwSecurityQosFlags |= SECURITY_IMPERSONATION;
|
|
|
|
|
|
|
|
|
|
params.lpSecurityAttributes = lpSecurityAttributes;
|
|
|
|
|
params.hTemplateFile = hTemplateFile;
|
|
|
|
|
|
|
|
|
|
hFile = CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, ¶ms);
|
|
|
|
|
|
|
|
|
|
return hFile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
|
|
|
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
|
|
|
|
|
{
|
|
|
|
|
HANDLE hFile;
|
|
|
|
|
WCHAR* lpFileNameW = NULL;
|
|
|
|
|
|
|
|
|
|
ConvertToUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameW, 0);
|
|
|
|
|
|
|
|
|
|
if (!lpFileNameW)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
hFile = CreateFileW(lpFileNameW, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
|
|
|
|
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
|
|
|
|
|
|
|
|
|
free(lpFileNameW);
|
|
|
|
|
|
|
|
|
|
return hFile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
|
|
|
|
|
{
|
|
|
|
|
BOOL status;
|
|
|
|
|
LARGE_INTEGER fileSize = { 0, 0 };
|
|
|
|
|
|
|
|
|
|
if (!lpFileSizeHigh)
|
|
|
|
|
return INVALID_FILE_SIZE;
|
|
|
|
|
|
|
|
|
|
status = GetFileSizeEx(hFile, &fileSize);
|
|
|
|
|
|
|
|
|
|
if (!status)
|
|
|
|
|
return INVALID_FILE_SIZE;
|
|
|
|
|
|
|
|
|
|
*lpFileSizeHigh = fileSize.HighPart;
|
|
|
|
|
|
|
|
|
|
return fileSize.LowPart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove,
|
|
|
|
|
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
|
|
|
|
|
{
|
|
|
|
|
BOOL status;
|
|
|
|
|
LARGE_INTEGER liDistanceToMove = { 0, 0 };
|
|
|
|
|
LARGE_INTEGER liNewFilePointer = { 0, 0 };
|
|
|
|
|
|
|
|
|
|
liDistanceToMove.LowPart = lDistanceToMove;
|
|
|
|
|
|
|
|
|
|
status = SetFilePointerEx(hFile, liDistanceToMove, &liNewFilePointer, dwMoveMethod);
|
|
|
|
|
|
|
|
|
|
if (!status)
|
|
|
|
|
return INVALID_SET_FILE_POINTER;
|
|
|
|
|
|
|
|
|
|
if (lpDistanceToMoveHigh)
|
|
|
|
|
*lpDistanceToMoveHigh = liNewFilePointer.HighPart;
|
|
|
|
|
|
|
|
|
|
return liNewFilePointer.LowPart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
|
|
|
|
|
{
|
|
|
|
|
return FindFirstFileExA(lpFileName, FindExInfoStandard, lpFindFileData, FindExSearchNameMatch, NULL, 0);
|
|
|
|
@ -714,6 +828,106 @@ HANDLE FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData)
|
|
|
|
|
return FindFirstFileExW(lpFileName, FindExInfoStandard, lpFindFileData, FindExSearchNameMatch, NULL, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart)
|
|
|
|
|
{
|
|
|
|
|
DWORD dwStatus;
|
|
|
|
|
WCHAR* lpFileNameW = NULL;
|
|
|
|
|
WCHAR* lpBufferW = NULL;
|
|
|
|
|
WCHAR* lpFilePartW = NULL;
|
|
|
|
|
DWORD nBufferLengthW = nBufferLength * 2;
|
|
|
|
|
|
|
|
|
|
if (!lpFileName || (nBufferLength < 1))
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
ConvertToUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameW, 0);
|
|
|
|
|
|
|
|
|
|
if (!lpFileNameW)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
lpBufferW = (WCHAR*) malloc(nBufferLengthW);
|
|
|
|
|
|
|
|
|
|
if (!lpBufferW)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
dwStatus = GetFullPathNameW(lpFileNameW, nBufferLengthW, lpBufferW, &lpFilePartW);
|
|
|
|
|
|
|
|
|
|
ConvertFromUnicode(CP_UTF8, 0, lpBufferW, nBufferLengthW, &lpBuffer, nBufferLength, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
if (lpFilePart)
|
|
|
|
|
lpFilePart = lpBuffer + (lpFilePartW - lpBufferW);
|
|
|
|
|
|
|
|
|
|
free(lpFileNameW);
|
|
|
|
|
free(lpBufferW);
|
|
|
|
|
|
|
|
|
|
return dwStatus * 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
|
|
|
|
|
LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
|
|
|
|
|
{
|
|
|
|
|
BOOL status;
|
|
|
|
|
ULARGE_INTEGER FreeBytesAvailableToCaller = { 0, 0 };
|
|
|
|
|
ULARGE_INTEGER TotalNumberOfBytes = { 0, 0 };
|
|
|
|
|
ULARGE_INTEGER TotalNumberOfFreeBytes = { 0, 0 };
|
|
|
|
|
|
|
|
|
|
status = GetDiskFreeSpaceExA(lpRootPathName, &FreeBytesAvailableToCaller,
|
|
|
|
|
&TotalNumberOfBytes, &TotalNumberOfFreeBytes);
|
|
|
|
|
|
|
|
|
|
if (!status)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
*lpBytesPerSector = 1;
|
|
|
|
|
*lpSectorsPerCluster = TotalNumberOfBytes.LowPart;
|
|
|
|
|
*lpNumberOfFreeClusters = FreeBytesAvailableToCaller.LowPart;
|
|
|
|
|
*lpTotalNumberOfClusters = TotalNumberOfFreeBytes.LowPart;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL GetDiskFreeSpaceW(LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
|
|
|
|
|
LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
|
|
|
|
|
{
|
|
|
|
|
BOOL status;
|
|
|
|
|
ULARGE_INTEGER FreeBytesAvailableToCaller = { 0, 0 };
|
|
|
|
|
ULARGE_INTEGER TotalNumberOfBytes = { 0, 0 };
|
|
|
|
|
ULARGE_INTEGER TotalNumberOfFreeBytes = { 0, 0 };
|
|
|
|
|
|
|
|
|
|
status = GetDiskFreeSpaceExW(lpRootPathName, &FreeBytesAvailableToCaller,
|
|
|
|
|
&TotalNumberOfBytes, &TotalNumberOfFreeBytes);
|
|
|
|
|
|
|
|
|
|
if (!status)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
*lpBytesPerSector = 1;
|
|
|
|
|
*lpSectorsPerCluster = TotalNumberOfBytes.LowPart;
|
|
|
|
|
*lpNumberOfFreeClusters = FreeBytesAvailableToCaller.LowPart;
|
|
|
|
|
*lpTotalNumberOfClusters = TotalNumberOfFreeBytes.LowPart;
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
|
|
|
|
|
{
|
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD GetLogicalDriveStringsW(DWORD nBufferLength, LPWSTR lpBuffer)
|
|
|
|
|
{
|
|
|
|
|
SetLastError(ERROR_INVALID_FUNCTION);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
|
|
|
|
|
{
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UINT GetACP(void)
|
|
|
|
|
{
|
|
|
|
|
return CP_UTF8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* Extended API */
|
|
|
|
|