Blame winpr/libwinpr/file/file.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * File Functions
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2015 Thincast Technologies GmbH
Packit 1fb8d4
 * Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
Packit 1fb8d4
 * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif /* HAVE_CONFIG_H */
Packit 1fb8d4
Packit 1fb8d4
#if defined(__FreeBSD_kernel__) && defined(__GLIBC__)
Packit 1fb8d4
#define _GNU_SOURCE
Packit 1fb8d4
#define KFREEBSD
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/wtypes.h>
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/file.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef _WIN32
Packit 1fb8d4
Packit 1fb8d4
#include <io.h>
Packit 1fb8d4
Packit 1fb8d4
#else /* _WIN32 */
Packit 1fb8d4
Packit 1fb8d4
#include "../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("file")
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/wlog.h>
Packit 1fb8d4
#include <winpr/string.h>
Packit 1fb8d4
Packit 1fb8d4
#include "file.h"
Packit 1fb8d4
#include <errno.h>
Packit 1fb8d4
#include <fcntl.h>
Packit 1fb8d4
#include <sys/file.h>
Packit 1fb8d4
#include <sys/stat.h>
Packit 1fb8d4
#include <sys/time.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef ANDROID
Packit 1fb8d4
#include <sys/vfs.h>
Packit 1fb8d4
#else
Packit 1fb8d4
#include <sys/statvfs.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
static BOOL FileIsHandled(HANDLE handle)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_FILE* pFile = (WINPR_FILE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!pFile || (pFile->Type != HANDLE_TYPE_FILE))
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_INVALID_HANDLE);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int FileGetFd(HANDLE handle)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_FILE* file = (WINPR_FILE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!FileIsHandled(handle))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return fileno(file->fp);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL FileCloseHandle(HANDLE handle)
Packit Service 5a9772
{
Packit Service 5a9772
	WINPR_FILE* file = (WINPR_FILE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!FileIsHandled(handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (file->fp)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* Don't close stdin/stdout/stderr */
Packit 1fb8d4
		if (fileno(file->fp) > 2)
Packit 1fb8d4
		{
Packit 1fb8d4
			fclose(file->fp);
Packit 1fb8d4
			file->fp = NULL;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	free(file->lpFileName);
Packit 1fb8d4
	free(file);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL FileSetEndOfFile(HANDLE hFile)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_FILE* pFile = (WINPR_FILE*)hFile;
Packit 1fb8d4
	INT64 size;
Packit 1fb8d4
Packit 1fb8d4
	if (!hFile)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	size = _ftelli64(pFile->fp);
Packit 1fb8d4
Packit 1fb8d4
	if (ftruncate(fileno(pFile->fp), size) < 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "ftruncate %s failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		SetLastError(map_posix_err(errno));
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
Packit Service 5a9772
                                DWORD dwMoveMethod)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_FILE* pFile = (WINPR_FILE*)hFile;
Packit 1fb8d4
	INT64 offset;
Packit 1fb8d4
	int whence;
Packit 1fb8d4
Packit 1fb8d4
	if (!hFile)
Packit 1fb8d4
		return INVALID_SET_FILE_POINTER;
Packit 1fb8d4
Packit 1fb8d4
	/* If there is a high part, the sign is contained in that
Packit 1fb8d4
	 * and the low integer must be interpreted as unsigned. */
Packit 1fb8d4
	if (lpDistanceToMoveHigh)
Packit 1fb8d4
	{
Packit 1fb8d4
		offset = (INT64)(((UINT64)*lpDistanceToMoveHigh << 32U) | (UINT64)lDistanceToMove);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit Service 5a9772
		offset = lDistanceToMove;
Packit 1fb8d4
Packit Service 5a9772
	switch (dwMoveMethod)
Packit 1fb8d4
	{
Packit Service 5a9772
		case FILE_BEGIN:
Packit Service 5a9772
			whence = SEEK_SET;
Packit Service 5a9772
			break;
Packit Service 5a9772
		case FILE_END:
Packit Service 5a9772
			whence = SEEK_END;
Packit Service 5a9772
			break;
Packit Service 5a9772
		case FILE_CURRENT:
Packit Service 5a9772
			whence = SEEK_CUR;
Packit Service 5a9772
			break;
Packit Service 5a9772
		default:
Packit Service 5a9772
			return INVALID_SET_FILE_POINTER;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (_fseeki64(pFile->fp, offset, whence))
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		return INVALID_SET_FILE_POINTER;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return _ftelli64(pFile->fp);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL FileSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
Packit Service 5a9772
                                 PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_FILE* pFile = (WINPR_FILE*)hFile;
Packit 1fb8d4
	int whence;
Packit 1fb8d4
Packit 1fb8d4
	if (!hFile)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	switch (dwMoveMethod)
Packit 1fb8d4
	{
Packit Service 5a9772
		case FILE_BEGIN:
Packit Service 5a9772
			whence = SEEK_SET;
Packit Service 5a9772
			break;
Packit Service 5a9772
		case FILE_END:
Packit Service 5a9772
			whence = SEEK_END;
Packit Service 5a9772
			break;
Packit Service 5a9772
		case FILE_CURRENT:
Packit Service 5a9772
			whence = SEEK_CUR;
Packit Service 5a9772
			break;
Packit Service 5a9772
		default:
Packit Service 5a9772
			return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (_fseeki64(pFile->fp, liDistanceToMove.QuadPart, whence))
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (lpNewFilePointer)
Packit 1fb8d4
		lpNewFilePointer->QuadPart = _ftelli64(pFile->fp);
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
Packit Service 5a9772
                     LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t io_status;
Packit 1fb8d4
	WINPR_FILE* file;
Packit 1fb8d4
	BOOL status = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!Object)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	file = (WINPR_FILE*)Object;
Packit 1fb8d4
	clearerr(file->fp);
Packit 1fb8d4
	io_status = fread(lpBuffer, 1, nNumberOfBytesToRead, file->fp);
Packit 1fb8d4
Packit 1fb8d4
	if (io_status == 0 && ferror(file->fp))
Packit 1fb8d4
	{
Packit 1fb8d4
		status = FALSE;
Packit 1fb8d4
Packit 1fb8d4
		switch (errno)
Packit 1fb8d4
		{
Packit 1fb8d4
			case EWOULDBLOCK:
Packit 1fb8d4
				SetLastError(ERROR_NO_DATA);
Packit 1fb8d4
				break;
Packit 1fb8d4
			default:
Packit 1fb8d4
				SetLastError(map_posix_err(errno));
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (lpNumberOfBytesRead)
Packit 1fb8d4
		*lpNumberOfBytesRead = io_status;
Packit 1fb8d4
Packit 1fb8d4
	return status;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
Packit Service 5a9772
                      LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t io_status;
Packit 1fb8d4
	WINPR_FILE* file;
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!Object)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	file = (WINPR_FILE*)Object;
Packit 1fb8d4
Packit 1fb8d4
	clearerr(file->fp);
Packit 1fb8d4
	io_status = fwrite(lpBuffer, 1, nNumberOfBytesToWrite, file->fp);
Packit 1fb8d4
	if (io_status == 0 && ferror(file->fp))
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(map_posix_err(errno));
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	*lpNumberOfBytesWritten = io_status;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_FILE* file;
Packit 1fb8d4
	INT64 cur, size;
Packit 1fb8d4
Packit 1fb8d4
	if (!Object)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit Service 5a9772
	file = (WINPR_FILE*)Object;
Packit 1fb8d4
Packit 1fb8d4
	cur = _ftelli64(file->fp);
Packit 1fb8d4
Packit 1fb8d4
	if (cur < 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		return INVALID_FILE_SIZE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (_fseeki64(file->fp, 0, SEEK_END) != 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "_fseeki64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		return INVALID_FILE_SIZE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	size = _ftelli64(file->fp);
Packit 1fb8d4
Packit 1fb8d4
	if (size < 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		return INVALID_FILE_SIZE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (_fseeki64(file->fp, cur, SEEK_SET) != 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "_ftelli64(%s) failed with %s [0x%08X]", file->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		return INVALID_FILE_SIZE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (lpFileSizeHigh)
Packit 1fb8d4
		*lpFileSizeHigh = 0;
Packit 1fb8d4
Packit 1fb8d4
	return size;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
Packit Service 5a9772
                           DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
Packit Service 5a9772
                           LPOVERLAPPED lpOverlapped)
Packit Service 5a9772
{
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
	struct flock lock;
Packit 1fb8d4
	int lckcmd;
Packit 1fb8d4
#else
Packit 1fb8d4
	int lock;
Packit 1fb8d4
#endif
Packit 1fb8d4
	WINPR_FILE* pFile = (WINPR_FILE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!hFile)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (pFile->bLocked)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "File %s already locked!", pFile->lpFileName);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
	lock.l_start = 0;
Packit 1fb8d4
	lock.l_len = 0;
Packit 1fb8d4
	lock.l_whence = SEEK_SET;
Packit 1fb8d4
Packit 1fb8d4
	if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)
Packit 1fb8d4
		lock.l_type = F_WRLCK;
Packit 1fb8d4
	else
Packit 1fb8d4
		lock.l_type = F_WRLCK;
Packit 1fb8d4
Packit 1fb8d4
	if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY)
Packit 1fb8d4
		lckcmd = F_SETLK;
Packit 1fb8d4
	else
Packit 1fb8d4
		lckcmd = F_SETLKW;
Packit 1fb8d4
Packit Service 5a9772
	if (fcntl(fileno(pFile->fp), lckcmd, &lock) == -1)
Packit Service 5a9772
	{
Packit Service 5a9772
		WLog_ERR(TAG, "F_SETLK failed with %s [0x%08X]", strerror(errno), errno);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
#else
Packit 1fb8d4
	if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)
Packit 1fb8d4
		lock = LOCK_EX;
Packit 1fb8d4
	else
Packit 1fb8d4
		lock = LOCK_SH;
Packit 1fb8d4
Packit 1fb8d4
	if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY)
Packit 1fb8d4
		lock |= LOCK_NB;
Packit 1fb8d4
Packit 1fb8d4
	if (flock(fileno(pFile->fp), lock) < 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "flock failed with %s [0x%08X]", strerror(errno), errno);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	pFile->bLocked = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
Packit Service 5a9772
                           DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_FILE* pFile = (WINPR_FILE*)hFile;
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
	struct flock lock;
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (!hFile)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!pFile->bLocked)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "File %s is not locked!", pFile->lpFileName);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
	lock.l_start = 0;
Packit 1fb8d4
	lock.l_len = 0;
Packit 1fb8d4
	lock.l_whence = SEEK_SET;
Packit 1fb8d4
	lock.l_type = F_UNLCK;
Packit 1fb8d4
	if (fcntl(fileno(pFile->fp), F_GETLK, &lock) == -1)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "F_UNLCK on %s failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#else
Packit 1fb8d4
	if (flock(fileno(pFile->fp), LOCK_UN) < 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [0x%08X]", pFile->lpFileName,
Packit Service 5a9772
		         strerror(errno), errno);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
Packit Service 5a9772
                             DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_FILE* pFile = (WINPR_FILE*)hFile;
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
	struct flock lock;
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (lpOverlapped)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the lpOverlapped parameter", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!hFile)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!pFile->bLocked)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "File %s is not locked!", pFile->lpFileName);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
	lock.l_start = 0;
Packit 1fb8d4
	lock.l_len = 0;
Packit 1fb8d4
	lock.l_whence = SEEK_SET;
Packit 1fb8d4
	lock.l_type = F_UNLCK;
Packit 1fb8d4
	if (fcntl(fileno(pFile->fp), F_GETLK, &lock) == -1)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "F_UNLCK on %s failed with %s [0x%08X]", pFile->lpFileName, strerror(errno),
Packit Service 5a9772
		         errno);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
#else
Packit 1fb8d4
	if (flock(fileno(pFile->fp), LOCK_UN) < 0)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [0x%08X]", pFile->lpFileName,
Packit Service 5a9772
		         strerror(errno), errno);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static UINT64 FileTimeToUS(const FILETIME* ft)
Packit 1fb8d4
{
Packit 1fb8d4
	const UINT64 EPOCH_DIFF = 11644473600ULL * 1000000ULL;
Packit Service 5a9772
	UINT64 tmp = ((UINT64)ft->dwHighDateTime) << 32 | ft->dwLowDateTime;
Packit 1fb8d4
	tmp /= 10; /* 100ns steps to 1us step */
Packit 1fb8d4
	tmp -= EPOCH_DIFF;
Packit 1fb8d4
	return tmp;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
Packit 1fb8d4
                            const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime)
Packit 1fb8d4
{
Packit 1fb8d4
	int rc;
Packit 1fb8d4
#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD)
Packit 1fb8d4
	struct stat buf;
Packit 1fb8d4
	/* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */
Packit 1fb8d4
	struct timeval timevals[2];
Packit 1fb8d4
#else
Packit 1fb8d4
	struct timespec times[2]; /* last access, last modification */
Packit 1fb8d4
#endif
Packit 1fb8d4
	WINPR_FILE* pFile = (WINPR_FILE*)hFile;
Packit 1fb8d4
Packit 1fb8d4
	if (!hFile)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD)
Packit 1fb8d4
	rc = fstat(fileno(pFile->fp), &buf;;
Packit 1fb8d4
Packit 1fb8d4
	if (rc < 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (!lpLastAccessTime)
Packit 1fb8d4
	{
Packit 1fb8d4
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
Packit 1fb8d4
		timevals[0].tv_sec = buf.st_atime;
Packit 1fb8d4
#ifdef _POSIX_SOURCE
Packit 1fb8d4
		TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atim);
Packit 1fb8d4
#else
Packit 1fb8d4
		TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atimespec);
Packit 1fb8d4
#endif
Packit 1fb8d4
#elif defined(ANDROID)
Packit 1fb8d4
		timevals[0].tv_sec = buf.st_atime;
Packit 1fb8d4
		timevals[0].tv_usec = buf.st_atimensec / 1000UL;
Packit 1fb8d4
#else
Packit 1fb8d4
		times[0].tv_sec = UTIME_OMIT;
Packit 1fb8d4
		times[0].tv_nsec = UTIME_OMIT;
Packit 1fb8d4
#endif
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT64 tmp = FileTimeToUS(lpLastAccessTime);
Packit 1fb8d4
#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
Packit 1fb8d4
		timevals[0].tv_sec = tmp / 1000000ULL;
Packit 1fb8d4
		timevals[0].tv_usec = tmp % 1000000ULL;
Packit 1fb8d4
#else
Packit 1fb8d4
		times[0].tv_sec = tmp / 1000000ULL;
Packit 1fb8d4
		times[0].tv_nsec = (tmp % 1000000ULL) * 1000ULL;
Packit 1fb8d4
#endif
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!lpLastWriteTime)
Packit 1fb8d4
	{
Packit 1fb8d4
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
Packit 1fb8d4
		timevals[1].tv_sec = buf.st_mtime;
Packit 1fb8d4
#ifdef _POSIX_SOURCE
Packit 1fb8d4
		TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtim);
Packit 1fb8d4
#else
Packit 1fb8d4
		TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtimespec);
Packit 1fb8d4
#endif
Packit 1fb8d4
#elif defined(ANDROID)
Packit 1fb8d4
		timevals[1].tv_sec = buf.st_mtime;
Packit 1fb8d4
		timevals[1].tv_usec = buf.st_mtimensec / 1000UL;
Packit 1fb8d4
#else
Packit 1fb8d4
		times[1].tv_sec = UTIME_OMIT;
Packit 1fb8d4
		times[1].tv_nsec = UTIME_OMIT;
Packit 1fb8d4
#endif
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		UINT64 tmp = FileTimeToUS(lpLastWriteTime);
Packit 1fb8d4
#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
Packit 1fb8d4
		timevals[1].tv_sec = tmp / 1000000ULL;
Packit 1fb8d4
		timevals[1].tv_usec = tmp % 1000000ULL;
Packit 1fb8d4
#else
Packit 1fb8d4
		times[1].tv_sec = tmp / 1000000ULL;
Packit 1fb8d4
		times[1].tv_nsec = (tmp % 1000000ULL) * 1000ULL;
Packit 1fb8d4
#endif
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	// TODO: Creation time can not be handled!
Packit 1fb8d4
#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
Packit 1fb8d4
	rc = utimes(pFile->lpFileName, timevals);
Packit 1fb8d4
#else
Packit 1fb8d4
	rc = futimens(fileno(pFile->fp), times);
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (rc != 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static HANDLE_OPS fileOps = { FileIsHandled,
Packit Service 5a9772
	                          FileCloseHandle,
Packit Service 5a9772
	                          FileGetFd,
Packit Service 5a9772
	                          NULL, /* CleanupHandle */
Packit Service 5a9772
	                          FileRead,
Packit Service 5a9772
	                          NULL, /* FileReadEx */
Packit Service 5a9772
	                          NULL, /* FileReadScatter */
Packit Service 5a9772
	                          FileWrite,
Packit Service 5a9772
	                          NULL, /* FileWriteEx */
Packit Service 5a9772
	                          NULL, /* FileWriteGather */
Packit Service 5a9772
	                          FileGetFileSize,
Packit Service 5a9772
	                          NULL, /*  FlushFileBuffers */
Packit Service 5a9772
	                          FileSetEndOfFile,
Packit Service 5a9772
	                          FileSetFilePointer,
Packit Service 5a9772
	                          FileSetFilePointerEx,
Packit Service 5a9772
	                          NULL, /* FileLockFile */
Packit Service 5a9772
	                          FileLockFileEx,
Packit Service 5a9772
	                          FileUnlockFile,
Packit Service 5a9772
	                          FileUnlockFileEx,
Packit Service 5a9772
	                          FileSetFileTime };
Packit 1fb8d4
Packit 1fb8d4
static HANDLE_OPS shmOps = {
Packit Service 5a9772
	FileIsHandled, FileCloseHandle,
Packit Service 5a9772
	FileGetFd,     NULL, /* CleanupHandle */
Packit Service 5a9772
	FileRead,      NULL, /* FileReadEx */
Packit Service 5a9772
	NULL,                /* FileReadScatter */
Packit Service 5a9772
	FileWrite,     NULL, /* FileWriteEx */
Packit Service 5a9772
	NULL,                /* FileWriteGather */
Packit Service 5a9772
	NULL,                /* FileGetFileSize */
Packit Service 5a9772
	NULL,                /*  FlushFileBuffers */
Packit Service 5a9772
	NULL,                /* FileSetEndOfFile */
Packit Service 5a9772
	NULL,                /* FileSetFilePointer */
Packit Service 5a9772
	NULL,                /* SetFilePointerEx */
Packit Service 5a9772
	NULL,                /* FileLockFile */
Packit Service 5a9772
	NULL,                /* FileLockFileEx */
Packit Service 5a9772
	NULL,                /* FileUnlockFile */
Packit Service 5a9772
	NULL,                /* FileUnlockFileEx */
Packit Service 5a9772
	NULL                 /* FileSetFileTime */
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static const char* FileGetMode(DWORD dwDesiredAccess, DWORD dwCreationDisposition, BOOL* create)
Packit 1fb8d4
{
Packit Service 5a9772
	BOOL writeable = (dwDesiredAccess & (GENERIC_WRITE | FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0;
Packit 1fb8d4
Packit Service 5a9772
	switch (dwCreationDisposition)
Packit 1fb8d4
	{
Packit Service 5a9772
		case CREATE_ALWAYS:
Packit Service 5a9772
			*create = TRUE;
Packit Service 5a9772
			return (writeable) ? "wb+" : "rwb";
Packit Service 5a9772
		case CREATE_NEW:
Packit Service 5a9772
			*create = TRUE;
Packit Service 5a9772
			return "wb+";
Packit Service 5a9772
		case OPEN_ALWAYS:
Packit Service 5a9772
			*create = TRUE;
Packit Service 5a9772
			return "rb+";
Packit Service 5a9772
		case OPEN_EXISTING:
Packit Service 5a9772
			*create = FALSE;
Packit Service 5a9772
			return (writeable) ? "rb+" : "rb";
Packit Service 5a9772
		case TRUNCATE_EXISTING:
Packit Service 5a9772
			*create = FALSE;
Packit Service 5a9772
			return "wb+";
Packit Service 5a9772
		default:
Packit Service 5a9772
			*create = FALSE;
Packit Service 5a9772
			return "";
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
UINT32 map_posix_err(int fs_errno)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 rc;
Packit 1fb8d4
Packit 1fb8d4
	/* try to return NTSTATUS version of error code */
Packit 1fb8d4
Packit 1fb8d4
	switch (fs_errno)
Packit 1fb8d4
	{
Packit 1fb8d4
		case 0:
Packit 1fb8d4
			rc = STATUS_SUCCESS;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case ENOTCONN:
Packit 1fb8d4
		case ENODEV:
Packit 1fb8d4
		case ENOTDIR:
Packit 1fb8d4
		case ENXIO:
Packit 1fb8d4
			rc = ERROR_FILE_NOT_FOUND;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case EROFS:
Packit 1fb8d4
		case EPERM:
Packit 1fb8d4
		case EACCES:
Packit 1fb8d4
			rc = ERROR_ACCESS_DENIED;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case ENOENT:
Packit 1fb8d4
			rc = ERROR_FILE_NOT_FOUND;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case EBUSY:
Packit 1fb8d4
			rc = ERROR_BUSY_DRIVE;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case EEXIST:
Packit Service 5a9772
			rc = ERROR_FILE_EXISTS;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case EISDIR:
Packit 1fb8d4
			rc = STATUS_FILE_IS_A_DIRECTORY;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case ENOTEMPTY:
Packit 1fb8d4
			rc = STATUS_DIRECTORY_NOT_EMPTY;
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit Service 5a9772
			WLog_ERR(TAG, "Missing ERRNO mapping %s [%d]", strerror(fs_errno), fs_errno);
Packit 1fb8d4
			rc = STATUS_UNSUCCESSFUL;
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit Service 5a9772
Packit 1fb8d4
	return rc;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
Packit Service 5a9772
                              LPSECURITY_ATTRIBUTES lpSecurityAttributes,
Packit Service 5a9772
                              DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
Packit Service 5a9772
                              HANDLE hTemplateFile)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_FILE* pFile;
Packit 1fb8d4
	BOOL create;
Packit 1fb8d4
	const char* mode = FileGetMode(dwDesiredAccess, dwCreationDisposition, &create);
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
	struct flock lock;
Packit 1fb8d4
#else
Packit 1fb8d4
	int lock = 0;
Packit 1fb8d4
#endif
Packit 1fb8d4
	FILE* fp = NULL;
Packit 1fb8d4
	struct stat st;
Packit 1fb8d4
Packit 1fb8d4
	if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	pFile = (WINPR_FILE*)calloc(1, sizeof(WINPR_FILE));
Packit 1fb8d4
	if (!pFile)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
Packit 1fb8d4
	pFile->ops = &fileOps;
Packit 1fb8d4
Packit 1fb8d4
	pFile->lpFileName = _strdup(lpFileName);
Packit 1fb8d4
	if (!pFile->lpFileName)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		free(pFile);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pFile->dwOpenMode = dwDesiredAccess;
Packit 1fb8d4
	pFile->dwShareMode = dwShareMode;
Packit 1fb8d4
	pFile->dwFlagsAndAttributes = dwFlagsAndAttributes;
Packit 1fb8d4
	pFile->lpSecurityAttributes = lpSecurityAttributes;
Packit 1fb8d4
	pFile->dwCreationDisposition = dwCreationDisposition;
Packit 1fb8d4
	pFile->hTemplateFile = hTemplateFile;
Packit 1fb8d4
Packit 1fb8d4
	if (create)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (dwCreationDisposition == CREATE_NEW)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (stat(pFile->lpFileName, &st) == 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				SetLastError(ERROR_FILE_EXISTS);
Packit 1fb8d4
				free(pFile->lpFileName);
Packit 1fb8d4
				free(pFile);
Packit 1fb8d4
				return INVALID_HANDLE_VALUE;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		fp = fopen(pFile->lpFileName, "ab");
Packit 1fb8d4
		if (!fp)
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(map_posix_err(errno));
Packit 1fb8d4
			free(pFile->lpFileName);
Packit 1fb8d4
			free(pFile);
Packit 1fb8d4
			return INVALID_HANDLE_VALUE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		fp = freopen(pFile->lpFileName, mode, fp);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		if (stat(pFile->lpFileName, &st) != 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(map_posix_err(errno));
Packit 1fb8d4
			free(pFile->lpFileName);
Packit 1fb8d4
			free(pFile);
Packit 1fb8d4
			return INVALID_HANDLE_VALUE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		/* FIFO (named pipe) would block the following fopen
Packit 1fb8d4
		 * call if not connected. This renders the channel unusable,
Packit 1fb8d4
		 * therefore abort early. */
Packit 1fb8d4
		if (S_ISFIFO(st.st_mode))
Packit 1fb8d4
		{
Packit 1fb8d4
			SetLastError(ERROR_FILE_NOT_FOUND);
Packit 1fb8d4
			free(pFile->lpFileName);
Packit 1fb8d4
			free(pFile);
Packit 1fb8d4
			return INVALID_HANDLE_VALUE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (NULL == fp)
Packit 1fb8d4
		fp = fopen(pFile->lpFileName, mode);
Packit 1fb8d4
Packit 1fb8d4
	pFile->fp = fp;
Packit 1fb8d4
	if (!pFile->fp)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* This case can occur when trying to open a
Packit 1fb8d4
		 * not existing file without create flag. */
Packit 1fb8d4
		SetLastError(map_posix_err(errno));
Packit 1fb8d4
		free(pFile->lpFileName);
Packit 1fb8d4
		free(pFile);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	setvbuf(fp, NULL, _IONBF, 0);
Packit 1fb8d4
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
	lock.l_start = 0;
Packit 1fb8d4
	lock.l_len = 0;
Packit 1fb8d4
	lock.l_whence = SEEK_SET;
Packit 1fb8d4
Packit 1fb8d4
	if (dwShareMode & FILE_SHARE_READ)
Packit 1fb8d4
		lock.l_type = F_RDLCK;
Packit 1fb8d4
	if (dwShareMode & FILE_SHARE_WRITE)
Packit 1fb8d4
		lock.l_type = F_RDLCK;
Packit 1fb8d4
#else
Packit 1fb8d4
	if (dwShareMode & FILE_SHARE_READ)
Packit 1fb8d4
		lock = LOCK_SH;
Packit 1fb8d4
	if (dwShareMode & FILE_SHARE_WRITE)
Packit 1fb8d4
		lock = LOCK_EX;
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	if (dwShareMode & (FILE_SHARE_READ | FILE_SHARE_WRITE))
Packit 1fb8d4
	{
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
		if (fcntl(fileno(pFile->fp), F_SETLKW, &lock) == -1)
Packit 1fb8d4
#else
Packit 1fb8d4
		if (flock(fileno(pFile->fp), lock) < 0)
Packit 1fb8d4
#endif
Packit 1fb8d4
		{
Packit 1fb8d4
#ifdef __sun
Packit 1fb8d4
			WLog_ERR(TAG, "F_SETLKW failed with %s [0x%08X]",
Packit 1fb8d4
#else
Packit 1fb8d4
			WLog_ERR(TAG, "flock failed with %s [0x%08X]",
Packit 1fb8d4
#endif
Packit Service 5a9772
			         strerror(errno), errno);
Packit 1fb8d4
			SetLastError(map_posix_err(errno));
Packit 1fb8d4
			FileCloseHandle(pFile);
Packit 1fb8d4
			return INVALID_HANDLE_VALUE;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		pFile->bLocked = TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	if (fstat(fileno(pFile->fp), &st) == 0 && dwFlagsAndAttributes & FILE_ATTRIBUTE_READONLY)
Packit 1fb8d4
	{
Packit Service 5a9772
		st.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
Packit Service 5a9772
		fchmod(fileno(pFile->fp), st.st_mode);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	SetLastError(STATUS_SUCCESS);
Packit 1fb8d4
	return pFile;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL IsFileDevice(LPCTSTR lpDeviceName)
Packit 1fb8d4
{
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
HANDLE_CREATOR _FileHandleCreator = { IsFileDevice, FileCreateFileA };
Packit 1fb8d4
Packit Service 5a9772
HANDLE_CREATOR* GetFileHandleCreator(void)
Packit 1fb8d4
{
Packit 1fb8d4
	return &_FileHandleCreator;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static WINPR_FILE* FileHandle_New(FILE* fp)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_FILE* pFile;
Packit 1fb8d4
	char name[MAX_PATH];
Packit 1fb8d4
Packit 1fb8d4
	_snprintf(name, sizeof(name), "device_%d", fileno(fp));
Packit Service 5a9772
	pFile = (WINPR_FILE*)calloc(1, sizeof(WINPR_FILE));
Packit 1fb8d4
	if (!pFile)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
	pFile->fp = fp;
Packit 1fb8d4
	pFile->ops = &shmOps;
Packit 1fb8d4
	pFile->lpFileName = _strdup(name);
Packit 1fb8d4
Packit 1fb8d4
	WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
Packit 1fb8d4
	return pFile;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE GetStdHandle(DWORD nStdHandle)
Packit 1fb8d4
{
Packit 1fb8d4
	FILE* fp;
Packit Service 5a9772
	WINPR_FILE* pFile;
Packit 1fb8d4
Packit 1fb8d4
	switch (nStdHandle)
Packit 1fb8d4
	{
Packit 1fb8d4
		case STD_INPUT_HANDLE:
Packit 1fb8d4
			fp = stdin;
Packit 1fb8d4
			break;
Packit 1fb8d4
		case STD_OUTPUT_HANDLE:
Packit 1fb8d4
			fp = stdout;
Packit 1fb8d4
			break;
Packit 1fb8d4
		case STD_ERROR_HANDLE:
Packit 1fb8d4
			fp = stderr;
Packit 1fb8d4
			break;
Packit 1fb8d4
		default:
Packit 1fb8d4
			return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
	pFile = FileHandle_New(fp);
Packit 1fb8d4
	if (!pFile)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	return (HANDLE)pFile;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
Packit 1fb8d4
{
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle)
Packit 1fb8d4
{
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
Packit Service 5a9772
                       LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
Packit 1fb8d4
{
Packit 1fb8d4
#if defined(ANDROID)
Packit 1fb8d4
#define STATVFS statfs
Packit 1fb8d4
#else
Packit 1fb8d4
#define STATVFS statvfs
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	struct STATVFS svfst;
Packit 1fb8d4
	STATVFS(lpRootPathName, &svfst);
Packit 1fb8d4
	*lpSectorsPerCluster = svfst.f_frsize;
Packit 1fb8d4
	*lpBytesPerSector = 1;
Packit 1fb8d4
	*lpNumberOfFreeClusters = svfst.f_bavail;
Packit 1fb8d4
	*lpTotalNumberOfClusters = svfst.f_blocks;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL GetDiskFreeSpaceW(LPCWSTR lpwRootPathName, LPDWORD lpSectorsPerCluster,
Packit Service 5a9772
                       LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
Packit Service 5a9772
                       LPDWORD lpTotalNumberOfClusters)
Packit 1fb8d4
{
Packit 1fb8d4
	LPSTR lpRootPathName;
Packit 1fb8d4
	BOOL ret;
Packit 1fb8d4
Packit 1fb8d4
	if (ConvertFromUnicode(CP_UTF8, 0, lpwRootPathName, -1, &lpRootPathName, 0, NULL, NULL) <= 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
	ret = GetDiskFreeSpaceA(lpRootPathName, lpSectorsPerCluster, lpBytesPerSector,
Packit Service 5a9772
	                        lpNumberOfFreeClusters, lpTotalNumberOfClusters);
Packit 1fb8d4
	free(lpRootPathName);
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/**
Packit 1fb8d4
 * Check if a file name component is valid.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Some file names are not valid on Windows. See "Naming Files, Paths, and Namespaces":
Packit 1fb8d4
 * https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
Packit 1fb8d4
 */
Packit 1fb8d4
BOOL ValidFileNameComponent(LPCWSTR lpFileName)
Packit 1fb8d4
{
Packit 1fb8d4
	LPCWSTR c = NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFileName)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	/* CON */
Packit 1fb8d4
	if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'C' || lpFileName[0] == L'c')) &&
Packit 1fb8d4
	    (lpFileName[1] != L'\0' && (lpFileName[1] == L'O' || lpFileName[1] == L'o')) &&
Packit 1fb8d4
	    (lpFileName[2] != L'\0' && (lpFileName[2] == L'N' || lpFileName[2] == L'n')) &&
Packit 1fb8d4
	    (lpFileName[3] == L'\0'))
Packit 1fb8d4
	{
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* PRN */
Packit 1fb8d4
	if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'P' || lpFileName[0] == L'p')) &&
Packit 1fb8d4
	    (lpFileName[1] != L'\0' && (lpFileName[1] == L'R' || lpFileName[1] == L'r')) &&
Packit 1fb8d4
	    (lpFileName[2] != L'\0' && (lpFileName[2] == L'N' || lpFileName[2] == L'n')) &&
Packit 1fb8d4
	    (lpFileName[3] == L'\0'))
Packit 1fb8d4
	{
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* AUX */
Packit 1fb8d4
	if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'A' || lpFileName[0] == L'a')) &&
Packit 1fb8d4
	    (lpFileName[1] != L'\0' && (lpFileName[1] == L'U' || lpFileName[1] == L'u')) &&
Packit 1fb8d4
	    (lpFileName[2] != L'\0' && (lpFileName[2] == L'X' || lpFileName[2] == L'x')) &&
Packit 1fb8d4
	    (lpFileName[3] == L'\0'))
Packit 1fb8d4
	{
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* NUL */
Packit 1fb8d4
	if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'N' || lpFileName[0] == L'n')) &&
Packit 1fb8d4
	    (lpFileName[1] != L'\0' && (lpFileName[1] == L'U' || lpFileName[1] == L'u')) &&
Packit 1fb8d4
	    (lpFileName[2] != L'\0' && (lpFileName[2] == L'L' || lpFileName[2] == L'l')) &&
Packit 1fb8d4
	    (lpFileName[3] == L'\0'))
Packit 1fb8d4
	{
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* LPT0-9 */
Packit 1fb8d4
	if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'L' || lpFileName[0] == L'l')) &&
Packit 1fb8d4
	    (lpFileName[1] != L'\0' && (lpFileName[1] == L'P' || lpFileName[1] == L'p')) &&
Packit 1fb8d4
	    (lpFileName[2] != L'\0' && (lpFileName[2] == L'T' || lpFileName[2] == L't')) &&
Packit 1fb8d4
	    (lpFileName[3] != L'\0' && (L'0' <= lpFileName[3] && lpFileName[3] <= L'9')) &&
Packit 1fb8d4
	    (lpFileName[4] == L'\0'))
Packit 1fb8d4
	{
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* COM0-9 */
Packit 1fb8d4
	if ((lpFileName[0] != L'\0' && (lpFileName[0] == L'C' || lpFileName[0] == L'c')) &&
Packit 1fb8d4
	    (lpFileName[1] != L'\0' && (lpFileName[1] == L'O' || lpFileName[1] == L'o')) &&
Packit 1fb8d4
	    (lpFileName[2] != L'\0' && (lpFileName[2] == L'M' || lpFileName[2] == L'm')) &&
Packit 1fb8d4
	    (lpFileName[3] != L'\0' && (L'0' <= lpFileName[3] && lpFileName[3] <= L'9')) &&
Packit 1fb8d4
	    (lpFileName[4] == L'\0'))
Packit 1fb8d4
	{
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	/* Reserved characters */
Packit 1fb8d4
	for (c = lpFileName; *c; c++)
Packit 1fb8d4
	{
Packit Service 5a9772
		if ((*c == L'<') || (*c == L'>') || (*c == L':') || (*c == L'"') || (*c == L'/') ||
Packit Service 5a9772
		    (*c == L'\\') || (*c == L'|') || (*c == L'?') || (*c == L'*'))
Packit 1fb8d4
		{
Packit 1fb8d4
			return FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif /* _WIN32 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef _UWP
Packit 1fb8d4
Packit Service 5a9772
HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
Packit Service 5a9772
                   LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
Packit Service 5a9772
                   DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
Packit 1fb8d4
{
Packit 1fb8d4
	HANDLE hFile;
Packit 1fb8d4
	CREATEFILE2_EXTENDED_PARAMETERS params;
Packit 1fb8d4
Packit 1fb8d4
	ZeroMemory(&params, sizeof(CREATEFILE2_EXTENDED_PARAMETERS));
Packit 1fb8d4
Packit 1fb8d4
	params.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
Packit 1fb8d4
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_BACKUP_SEMANTICS;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_DELETE_ON_CLOSE;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_NO_BUFFERING;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_OPEN_NO_RECALL;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_OPEN_REPARSE_POINT;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_OPEN_REQUIRING_OPLOCK)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_OPEN_REQUIRING_OPLOCK;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_OVERLAPPED;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_POSIX_SEMANTICS;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_RANDOM_ACCESS;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_SESSION_AWARE)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_SESSION_AWARE;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_SEQUENTIAL_SCAN;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_FLAG_WRITE_THROUGH)
Packit Service 5a9772
		params.dwFileFlags |= FILE_FLAG_WRITE_THROUGH;
Packit Service 5a9772
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_ARCHIVE)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_COMPRESSED)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_COMPRESSED;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_DEVICE)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_DEVICE;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_DIRECTORY)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_ENCRYPTED)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_ENCRYPTED;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_HIDDEN)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_INTEGRITY_STREAM;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NORMAL)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_NORMAL;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_NO_SCRUB_DATA;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_OFFLINE)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_OFFLINE;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_READONLY)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_REPARSE_POINT;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_SPARSE_FILE)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_SPARSE_FILE;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_SYSTEM)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_TEMPORARY)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_TEMPORARY;
Packit Service 5a9772
	if (dwFlagsAndAttributes & FILE_ATTRIBUTE_VIRTUAL)
Packit Service 5a9772
		params.dwFileAttributes |= FILE_ATTRIBUTE_VIRTUAL;
Packit Service 5a9772
Packit Service 5a9772
	if (dwFlagsAndAttributes & SECURITY_ANONYMOUS)
Packit Service 5a9772
		params.dwSecurityQosFlags |= SECURITY_ANONYMOUS;
Packit Service 5a9772
	if (dwFlagsAndAttributes & SECURITY_CONTEXT_TRACKING)
Packit Service 5a9772
		params.dwSecurityQosFlags |= SECURITY_CONTEXT_TRACKING;
Packit Service 5a9772
	if (dwFlagsAndAttributes & SECURITY_DELEGATION)
Packit Service 5a9772
		params.dwSecurityQosFlags |= SECURITY_DELEGATION;
Packit Service 5a9772
	if (dwFlagsAndAttributes & SECURITY_EFFECTIVE_ONLY)
Packit Service 5a9772
		params.dwSecurityQosFlags |= SECURITY_EFFECTIVE_ONLY;
Packit Service 5a9772
	if (dwFlagsAndAttributes & SECURITY_IDENTIFICATION)
Packit Service 5a9772
		params.dwSecurityQosFlags |= SECURITY_IDENTIFICATION;
Packit Service 5a9772
	if (dwFlagsAndAttributes & SECURITY_IMPERSONATION)
Packit Service 5a9772
		params.dwSecurityQosFlags |= SECURITY_IMPERSONATION;
Packit 1fb8d4
Packit 1fb8d4
	params.lpSecurityAttributes = lpSecurityAttributes;
Packit 1fb8d4
	params.hTemplateFile = hTemplateFile;
Packit 1fb8d4
Packit 1fb8d4
	hFile = CreateFile2(lpFileName, dwDesiredAccess, dwShareMode, dwCreationDisposition, &params);
Packit 1fb8d4
Packit 1fb8d4
	return hFile;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
Packit Service 5a9772
                   LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
Packit Service 5a9772
                   DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
Packit 1fb8d4
{
Packit 1fb8d4
	HANDLE hFile;
Packit 1fb8d4
	WCHAR* lpFileNameW = NULL;
Packit 1fb8d4
Packit 1fb8d4
	ConvertToUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameW, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFileNameW)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	hFile = CreateFileW(lpFileNameW, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
Packit Service 5a9772
	                    dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
Packit 1fb8d4
Packit 1fb8d4
	free(lpFileNameW);
Packit 1fb8d4
Packit 1fb8d4
	return hFile;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL status;
Packit 1fb8d4
	LARGE_INTEGER fileSize = { 0, 0 };
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFileSizeHigh)
Packit 1fb8d4
		return INVALID_FILE_SIZE;
Packit 1fb8d4
Packit 1fb8d4
	status = GetFileSizeEx(hFile, &fileSize);
Packit 1fb8d4
Packit 1fb8d4
	if (!status)
Packit 1fb8d4
		return INVALID_FILE_SIZE;
Packit 1fb8d4
Packit 1fb8d4
	*lpFileSizeHigh = fileSize.HighPart;
Packit 1fb8d4
Packit 1fb8d4
	return fileSize.LowPart;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
Packit Service 5a9772
                     DWORD dwMoveMethod)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL status;
Packit 1fb8d4
	LARGE_INTEGER liDistanceToMove = { 0, 0 };
Packit 1fb8d4
	LARGE_INTEGER liNewFilePointer = { 0, 0 };
Packit 1fb8d4
Packit 1fb8d4
	liDistanceToMove.LowPart = lDistanceToMove;
Packit 1fb8d4
Packit 1fb8d4
	status = SetFilePointerEx(hFile, liDistanceToMove, &liNewFilePointer, dwMoveMethod);
Packit 1fb8d4
Packit 1fb8d4
	if (!status)
Packit 1fb8d4
		return INVALID_SET_FILE_POINTER;
Packit 1fb8d4
Packit 1fb8d4
	if (lpDistanceToMoveHigh)
Packit 1fb8d4
		*lpDistanceToMoveHigh = liNewFilePointer.HighPart;
Packit 1fb8d4
Packit 1fb8d4
	return liNewFilePointer.LowPart;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
Packit 1fb8d4
{
Packit Service 5a9772
	return FindFirstFileExA(lpFileName, FindExInfoStandard, lpFindFileData, FindExSearchNameMatch,
Packit Service 5a9772
	                        NULL, 0);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData)
Packit 1fb8d4
{
Packit Service 5a9772
	return FindFirstFileExW(lpFileName, FindExInfoStandard, lpFindFileData, FindExSearchNameMatch,
Packit Service 5a9772
	                        NULL, 0);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DWORD GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart)
Packit 1fb8d4
{
Packit 1fb8d4
	DWORD dwStatus;
Packit 1fb8d4
	WCHAR* lpFileNameW = NULL;
Packit 1fb8d4
	WCHAR* lpBufferW = NULL;
Packit 1fb8d4
	WCHAR* lpFilePartW = NULL;
Packit 1fb8d4
	DWORD nBufferLengthW = nBufferLength * 2;
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFileName || (nBufferLength < 1))
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	ConvertToUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameW, 0);
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFileNameW)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit Service 5a9772
	lpBufferW = (WCHAR*)malloc(nBufferLengthW);
Packit 1fb8d4
Packit 1fb8d4
	if (!lpBufferW)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	dwStatus = GetFullPathNameW(lpFileNameW, nBufferLengthW, lpBufferW, &lpFilePartW);
Packit 1fb8d4
Packit 1fb8d4
	ConvertFromUnicode(CP_UTF8, 0, lpBufferW, nBufferLengthW, &lpBuffer, nBufferLength, NULL, NULL);
Packit 1fb8d4
Packit 1fb8d4
	if (lpFilePart)
Packit 1fb8d4
		lpFilePart = lpBuffer + (lpFilePartW - lpBufferW);
Packit 1fb8d4
Packit 1fb8d4
	free(lpFileNameW);
Packit 1fb8d4
	free(lpBufferW);
Packit 1fb8d4
Packit 1fb8d4
	return dwStatus * 2;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
BOOL GetDiskFreeSpaceA(LPCSTR lpRootPathName, LPDWORD lpSectorsPerCluster, LPDWORD lpBytesPerSector,
Packit Service 5a9772
                       LPDWORD lpNumberOfFreeClusters, LPDWORD lpTotalNumberOfClusters)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL status;
Packit 1fb8d4
	ULARGE_INTEGER FreeBytesAvailableToCaller = { 0, 0 };
Packit 1fb8d4
	ULARGE_INTEGER TotalNumberOfBytes = { 0, 0 };
Packit 1fb8d4
	ULARGE_INTEGER TotalNumberOfFreeBytes = { 0, 0 };
Packit 1fb8d4
Packit Service 5a9772
	status = GetDiskFreeSpaceExA(lpRootPathName, &FreeBytesAvailableToCaller, &TotalNumberOfBytes,
Packit Service 5a9772
	                             &TotalNumberOfFreeBytes);
Packit 1fb8d4
Packit 1fb8d4
	if (!status)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	*lpBytesPerSector = 1;
Packit 1fb8d4
	*lpSectorsPerCluster = TotalNumberOfBytes.LowPart;
Packit 1fb8d4
	*lpNumberOfFreeClusters = FreeBytesAvailableToCaller.LowPart;
Packit 1fb8d4
	*lpTotalNumberOfClusters = TotalNumberOfFreeBytes.LowPart;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL GetDiskFreeSpaceW(LPCWSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
Packit Service 5a9772
                       LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
Packit Service 5a9772
                       LPDWORD lpTotalNumberOfClusters)
Packit 1fb8d4
{
Packit 1fb8d4
	BOOL status;
Packit 1fb8d4
	ULARGE_INTEGER FreeBytesAvailableToCaller = { 0, 0 };
Packit 1fb8d4
	ULARGE_INTEGER TotalNumberOfBytes = { 0, 0 };
Packit 1fb8d4
	ULARGE_INTEGER TotalNumberOfFreeBytes = { 0, 0 };
Packit 1fb8d4
Packit Service 5a9772
	status = GetDiskFreeSpaceExW(lpRootPathName, &FreeBytesAvailableToCaller, &TotalNumberOfBytes,
Packit Service 5a9772
	                             &TotalNumberOfFreeBytes);
Packit 1fb8d4
Packit 1fb8d4
	if (!status)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	*lpBytesPerSector = 1;
Packit 1fb8d4
	*lpSectorsPerCluster = TotalNumberOfBytes.LowPart;
Packit 1fb8d4
	*lpNumberOfFreeClusters = FreeBytesAvailableToCaller.LowPart;
Packit 1fb8d4
	*lpTotalNumberOfClusters = TotalNumberOfFreeBytes.LowPart;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DWORD GetLogicalDriveStringsA(DWORD nBufferLength, LPSTR lpBuffer)
Packit 1fb8d4
{
Packit 1fb8d4
	SetLastError(ERROR_INVALID_FUNCTION);
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
DWORD GetLogicalDriveStringsW(DWORD nBufferLength, LPWSTR lpBuffer)
Packit 1fb8d4
{
Packit 1fb8d4
	SetLastError(ERROR_INVALID_FUNCTION);
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL PathIsDirectoryEmptyA(LPCSTR pszPath)
Packit 1fb8d4
{
Packit 1fb8d4
	return FALSE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
UINT GetACP(void)
Packit 1fb8d4
{
Packit 1fb8d4
	return CP_UTF8;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
/* Extended API */
Packit 1fb8d4
Packit 1fb8d4
#ifdef _WIN32
Packit 1fb8d4
#include <io.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
HANDLE GetFileHandleForFileDescriptor(int fd)
Packit 1fb8d4
{
Packit 1fb8d4
#ifdef _WIN32
Packit 1fb8d4
	return (HANDLE)_get_osfhandle(fd);
Packit Service 5a9772
#else  /* _WIN32 */
Packit Service 5a9772
	WINPR_FILE* pFile;
Packit 1fb8d4
	FILE* fp;
Packit 1fb8d4
	int flags;
Packit 1fb8d4
Packit 1fb8d4
	/* Make sure it's a valid fd */
Packit 1fb8d4
	if (fcntl(fd, F_GETFD) == -1 && errno == EBADF)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	flags = fcntl(fd, F_GETFL);
Packit 1fb8d4
	if (flags == -1)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	if (flags & O_WRONLY)
Packit 1fb8d4
		fp = fdopen(fd, "wb");
Packit 1fb8d4
	else
Packit 1fb8d4
		fp = fdopen(fd, "rb");
Packit 1fb8d4
Packit 1fb8d4
	if (!fp)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	setvbuf(fp, NULL, _IONBF, 0);
Packit 1fb8d4
Packit 1fb8d4
	pFile = FileHandle_New(fp);
Packit 1fb8d4
	if (!pFile)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	return (HANDLE)pFile;
Packit 1fb8d4
#endif /* _WIN32 */
Packit 1fb8d4
}