#define STD_OUTPUT_HANDLE (DWORD)-11
#define STD_ERROR_HANDLE (DWORD)-12
+#define FILE_BEGIN 0
+#define FILE_CURRENT 1
+#define FILE_END 2
+
+#define LOCKFILE_FAIL_IMMEDIATELY 1
+#define LOCKFILE_EXCLUSIVE_LOCK 2
+
typedef union _FILE_SEGMENT_ELEMENT
{
PVOID64 Buffer;
WINPR_API BOOL SetEndOfFile(HANDLE hFile);
+WINPR_API DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
+
WINPR_API DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove,
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
#define TAG WINPR_TAG("file")
#include <winpr/wlog.h>
+#include <winpr/string.h>
-#include "../handle/handle.h"
+#include "file.h"
#include <errno.h>
#include <fcntl.h>
-
-struct winpr_file
-{
- WINPR_HANDLE_DEF();
-
- int fd;
-};
-
-typedef struct winpr_file WINPR_FILE;
+#include <sys/file.h>
static BOOL FileIsHandled(HANDLE handle)
{
}
}
- free(handle);
+ free(file->lpFileName);
+ free(file);
return TRUE;
}
+static BOOL FileSetEndOfFile(HANDLE hFile)
+{
+ WINPR_FILE* pFile = (WINPR_FILE*) hFile;
+ DWORD lowSize, highSize;
+ off_t size;
+
+ if (!hFile)
+ return FALSE;
+
+ lowSize = GetFileSize(hFile, &highSize);
+ if (lowSize == INVALID_FILE_SIZE)
+ return FALSE;
+
+ size = lowSize | ((off_t)highSize << 32);
+ if (ftruncate(pFile->fd, size) < 0)
+ {
+ WLog_ERR(TAG, "ftruncate %d failed with %s [%08X]",
+ pFile->fd, strerror(errno), errno);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static DWORD FileSetFilePointer(HANDLE hFile, LONG lDistanceToMove,
+ PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
+{
+ WINPR_FILE* pFile = (WINPR_FILE*) hFile;
+ long offset = lDistanceToMove;
+ int whence;
+ FILE* fp;
+
+ if (!hFile)
+ return INVALID_SET_FILE_POINTER;
+
+ fp = fdopen(pFile->fd, "w");
+
+ if (!fp)
+ {
+ WLog_ERR(TAG, "fdopen(%d) failed with %s [%08X]", pFile->fd,
+ strerror(errno), errno);
+ return INVALID_SET_FILE_POINTER;
+ }
+
+ switch(dwMoveMethod)
+ {
+ case FILE_BEGIN:
+ whence = SEEK_SET;
+ break;
+ case FILE_END:
+ whence = SEEK_END;
+ break;
+ case FILE_CURRENT:
+ whence = SEEK_CUR;
+ break;
+ default:
+ return INVALID_SET_FILE_POINTER;
+ }
+
+ if (fseek(fp, offset, whence))
+ {
+ WLog_ERR(TAG, "fseek(%d) failed with %s [%08X]", pFile->fd,
+ strerror(errno), errno);
+ return INVALID_SET_FILE_POINTER;
+ }
+
+ return ftell(fp);
+}
+
static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
{
return TRUE;
}
+static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh)
+{
+ WINPR_FILE* file;
+ FILE* fp;
+ long cur, size;
+
+ if (!Object)
+ return 0;
+
+ file = (WINPR_FILE *)Object;
+ fp = fdopen(file->fd, "r");
+
+ if (!fp)
+ {
+ WLog_ERR(TAG, "fdopen(%d) failed with %s [%08X]", file->fd,
+ strerror(errno), errno);
+ return INVALID_FILE_SIZE;
+ }
+
+ cur = ftell(fp);
+
+ if (cur < 0)
+ {
+ WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd,
+ strerror(errno), errno);
+ return INVALID_FILE_SIZE;
+ }
+
+ if (fseek(fp, 0, SEEK_END) != 0)
+ {
+ WLog_ERR(TAG, "fseek(%d) failed with %s [%08X]", file->fd,
+ strerror(errno), errno);
+ return INVALID_FILE_SIZE;
+ }
+
+ size = ftell(fp);
+
+ if (size < 0)
+ {
+ WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd,
+ strerror(errno), errno);
+ return INVALID_FILE_SIZE;
+ }
+
+ if (fseek(fp, cur, SEEK_SET) != 0)
+ {
+ WLog_ERR(TAG, "ftell(%d) failed with %s [%08X]", file->fd,
+ strerror(errno), errno);
+ return INVALID_FILE_SIZE;
+ }
+
+ if (lpFileSizeHigh)
+ *lpFileSizeHigh = 0;
+
+ return size;
+}
+
+static BOOL FileLockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
+ DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
+ LPOVERLAPPED lpOverlapped)
+ {
+ int lock;
+ WINPR_FILE* pFile = (WINPR_FILE*)hFile;
+
+ if (!hFile)
+ return FALSE;
+
+ if (pFile->bLocked)
+ {
+ WLog_ERR(TAG, "File %d already locked!", pFile->fd);
+ return FALSE;
+ }
+
+ if (lpOverlapped)
+ {
+ WLog_ERR(TAG, "lpOverlapped not implemented!");
+ return FALSE;
+ }
+
+ if (dwFlags & LOCKFILE_EXCLUSIVE_LOCK)
+ lock = LOCK_EX;
+ else
+ lock = LOCK_SH;
+
+ if (dwFlags & LOCKFILE_FAIL_IMMEDIATELY)
+ lock |= LOCK_NB;
+
+ if (flock(pFile->fd, lock) < 0)
+ {
+ WLog_ERR(TAG, "flock failed with %s [%08X]",
+ strerror(errno), errno);
+ return FALSE;
+ }
+
+ pFile->bLocked = TRUE;
+
+ return TRUE;
+}
+
+static BOOL FileUnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
+ DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
+{
+ WINPR_FILE* pFile = (WINPR_FILE*)hFile;
+
+ if (!hFile)
+ return FALSE;
+
+ if (!pFile->bLocked)
+ {
+ WLog_ERR(TAG, "File %d is not locked!", pFile->fd);
+ return FALSE;
+ }
+
+ if (flock(pFile->fd, LOCK_UN) < 0)
+ {
+ WLog_ERR(TAG, "flock(LOCK_UN) %d failed with %s [%08X]",
+ pFile->fd, strerror(errno), errno);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
+ DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped)
+{
+ WINPR_FILE* pFile = (WINPR_FILE*)hFile;
+
+ if (!hFile)
+ return FALSE;
+
+ if (!pFile->bLocked)
+ {
+ WLog_ERR(TAG, "File %d is not locked!", pFile->fd);
+ return FALSE;
+ }
+
+ if (lpOverlapped)
+ {
+ WLog_ERR(TAG, "lpOverlapped not implemented!");
+ return FALSE;
+ }
+
+ if (flock(pFile->fd, LOCK_UN) < 0)
+ {
+ WLog_ERR(TAG, "flock(LOCK_UN) %d failed with %s [%08X]",
+ pFile->fd, strerror(errno), errno);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static HANDLE_OPS fileOps = {
+ FileIsHandled,
+ FileCloseHandle,
+ FileGetFd,
+ NULL, /* CleanupHandle */
+ FileRead,
+ NULL, /* FileReadEx */
+ NULL, /* FileReadScatter */
+ FileWrite,
+ NULL, /* FileWriteEx */
+ NULL, /* FileWriteGather */
+ FileGetFileSize,
+ NULL, /* FlushFileBuffers */
+ FileSetEndOfFile,
+ FileSetFilePointer,
+ NULL, /* SetFilePointerEx */
+ NULL, /* FileLockFile */
+ FileLockFileEx,
+ FileUnlockFile,
+ FileUnlockFileEx
+};
+
+static HANDLE_OPS pipeOps = {
+ FileIsHandled,
+ FileCloseHandle,
+ FileGetFd,
+ NULL, /* CleanupHandle */
+ FileRead,
+ NULL, /* FileReadEx */
+ NULL, /* FileReadScatter */
+ FileWrite,
+ NULL, /* FileWriteEx */
+ NULL, /* FileWriteGather */
+ NULL, /* FileGetFileSize */
+ NULL, /* FlushFileBuffers */
+ NULL, /* FileSetEndOfFile */
+ NULL, /* FileSetFilePointer */
+ NULL, /* SetFilePointerEx */
+ NULL, /* FileLockFile */
+ NULL, /* FileLockFileEx */
+ NULL, /* FileUnlockFile */
+ NULL /* FileUnlockFileEx */
-static HANDLE_OPS ops = {
- FileIsHandled,
- FileCloseHandle,
- FileGetFd,
- NULL, /* CleanupHandle */
- FileRead,
- FileWrite
};
-static WINPR_FILE *FileHandle_New()
+
+static const char* FileGetMode(DWORD dwDesiredAccess, DWORD dwCreationDisposition, BOOL* create)
+{
+ BOOL writeable = dwDesiredAccess & GENERIC_WRITE;
+
+ switch(dwCreationDisposition)
+ {
+ case CREATE_ALWAYS:
+ *create = TRUE;
+ return (writeable) ? "wb+" : "rwb";
+ case CREATE_NEW:
+ *create = TRUE;
+ return "wb+";
+ case OPEN_ALWAYS:
+ *create = TRUE;
+ return "rb+";
+ case OPEN_EXISTING:
+ *create = FALSE;
+ return "rb+";
+ case TRUNCATE_EXISTING:
+ *create = FALSE;
+ return "wb+";
+ default:
+ *create = FALSE;
+ return "";
+ }
+}
+
+static HANDLE FileCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
+{
+ WINPR_FILE* pFile;
+ BOOL create;
+ const char* mode = FileGetMode(dwDesiredAccess, dwCreationDisposition, &create);
+ int lock;
+
+ pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE));
+ if (!pFile)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
+ pFile->ops = &fileOps;
+
+ pFile->lpFileName = _strdup(lpFileName);
+ if (!pFile->lpFileName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ free(pFile);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ pFile->dwOpenMode = dwDesiredAccess;
+ pFile->dwShareMode = dwShareMode;
+ pFile->dwFlagsAndAttributes = dwFlagsAndAttributes;
+ pFile->lpSecurityAttributes = lpSecurityAttributes;
+ pFile->dwCreationDisposition = dwCreationDisposition;
+ pFile->hTemplateFile = hTemplateFile;
+
+ if (create)
+ {
+ FILE* fp = fopen(pFile->lpFileName, "ab");
+ if (!fp)
+ {
+ free(pFile->lpFileName);
+ free(pFile);
+ return INVALID_HANDLE_VALUE;
+ }
+ fclose(fp);
+ }
+
+ {
+ FILE* fp = fopen(pFile->lpFileName, mode);
+ pFile->fd = fileno(fp);
+ }
+ if (pFile->fd < 0)
+ {
+ WLog_ERR(TAG, "Failed to open file %s with mode %s",
+ pFile->lpFileName, mode);
+
+ free(pFile->lpFileName);
+ free(pFile);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (dwShareMode & FILE_SHARE_READ)
+ lock = LOCK_SH;
+ if (dwShareMode & FILE_SHARE_WRITE)
+ lock = LOCK_EX;
+
+ if (dwShareMode & (FILE_SHARE_READ | FILE_SHARE_WRITE))
+ {
+ if (flock(pFile->fd, lock) < 0)
+ {
+ WLog_ERR(TAG, "flock failed with %s [%08X]",
+ strerror(errno), errno);
+ close(pFile->fd);
+ free(pFile->lpFileName);
+ free(pFile);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ pFile->bLocked = TRUE;
+ }
+
+ return pFile;
+}
+
+BOOL IsFileDevice(LPCTSTR lpDeviceName)
+{
+ return TRUE;
+}
+
+HANDLE_CREATOR _FileHandleCreator =
+{
+ IsFileDevice,
+ FileCreateFileA
+};
+
+HANDLE_CREATOR *GetFileHandleCreator(void)
+{
+ return &_FileHandleCreator;
+}
+
+
+static WINPR_FILE *FileHandle_New(int fd)
{
WINPR_FILE *pFile;
HANDLE hFile;
+ char name[MAX_PATH];
+ _snprintf(name, sizeof(name), "pipe_device_%d", fd);
pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE));
if (!pFile)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
- pFile->fd = -1;
- pFile->ops = &ops;
+ pFile->fd = fd;
+ pFile->ops = &pipeOps;
+ pFile->lpFileName = _strdup(name);
hFile = (HANDLE) pFile;
WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
default:
return INVALID_HANDLE_VALUE;
}
- pFile = FileHandle_New();
+ pFile = FileHandle_New(fd);
if (!pFile)
return INVALID_HANDLE_VALUE;
- pFile->fd = fd;
return (HANDLE)pFile;
}
if (fcntl(fd, F_GETFD) == -1 && errno == EBADF)
return INVALID_HANDLE_VALUE;
- pFile = FileHandle_New();
+ pFile = FileHandle_New(fd);
if (!pFile)
return INVALID_HANDLE_VALUE;
pFile->fd = fd;
--- /dev/null
+/**
+ * WinPR: Windows Portable Runtime
+ * File Functions
+ *
+ * Copyright 2015 Armin Novak <armin.novak@thincast.com>
+ * Copyright 2015 Thincast Technologies GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WINPR_FILE_PRIV_H
+#define WINPR_FILE_PRIV_H
+
+#include <winpr/winpr.h>
+#include <winpr/wtypes.h>
+
+#include <winpr/nt.h>
+#include <winpr/io.h>
+#include <winpr/error.h>
+
+#ifndef _WIN32
+
+#include <stdio.h>
+#include "../handle/handle.h"
+
+struct winpr_file
+{
+ WINPR_HANDLE_DEF();
+
+ int fd;
+
+ char* lpFileName;
+
+ DWORD dwOpenMode;
+ DWORD dwShareMode;
+ DWORD dwFlagsAndAttributes;
+
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes;
+ DWORD dwCreationDisposition;
+ HANDLE hTemplateFile;
+
+ BOOL bLocked;
+};
+typedef struct winpr_file WINPR_FILE;
+
+HANDLE_CREATOR *GetFileHandleCreator(void);
+
+#endif /* _WIN32 */
+
+#endif /* WINPR_FILE_PRIV_H */
+
#include "../pipe/pipe.h"
+#include "file.h"
+
/**
* api-ms-win-core-file-l1-2-0.dll:
*
#if defined __linux__ && !defined ANDROID
ArrayList_Add(_HandleCreators, GetCommHandleCreator());
#endif /* __linux__ && !defined ANDROID */
+ ArrayList_Add(_HandleCreators, GetFileHandleCreator());
}
if (creator && creator->IsHandled(lpFileName))
{
- HANDLE newHandle = creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
- dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
+ HANDLE newHandle = creator->CreateFileA(lpFileName, dwDesiredAccess,
+ dwShareMode, lpSecurityAttributes, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile);
ArrayList_Unlock(_HandleCreators);
return newHandle;
}
HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
- return NULL;
+ LPSTR lpFileNameA = NULL;
+ HANDLE hdl;
+
+ if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL))
+ return NULL;
+
+ hdl= CreateFileA(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
+ dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
+ free (lpFileNameA);
+
+ return hdl;
}
BOOL DeleteFileA(LPCSTR lpFileName)
BOOL DeleteFileW(LPCWSTR lpFileName)
{
- return TRUE;
+ LPSTR lpFileNameA = NULL;
+ BOOL rc = FALSE;
+
+ if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL))
+ return FALSE;
+ rc = DeleteFileA(lpFileNameA);
+ free (lpFileNameA);
+
+ return rc;
}
BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
handle = (WINPR_HANDLE *)hFile;
if (handle->ops->ReadFile)
- return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
+ return handle->ops->ReadFile(handle, lpBuffer, nNumberOfBytesToRead,
+ lpNumberOfBytesRead, lpOverlapped);
WLog_ERR(TAG, "ReadFile operation not implemented");
return FALSE;
}
BOOL ReadFileEx(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
- LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+ LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->ReadFileEx)
+ return handle->ops->ReadFileEx(handle, lpBuffer, nNumberOfBytesToRead,
+ lpOverlapped, lpCompletionRoutine);
+
+ WLog_ERR(TAG, "ReadFileEx operation not implemented");
+ return FALSE;
+
return TRUE;
}
BOOL ReadFileScatter(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[],
- DWORD nNumberOfBytesToRead, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
+ DWORD nNumberOfBytesToRead, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->ReadFileScatter)
+ return handle->ops->ReadFileScatter(handle, aSegmentArray, nNumberOfBytesToRead,
+ lpReserved, lpOverlapped);
+
+ WLog_ERR(TAG, "ReadFileScatter operation not implemented");
+ return FALSE;
}
BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
handle = (WINPR_HANDLE *)hFile;
if (handle->ops->WriteFile)
- return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
+ return handle->ops->WriteFile(handle, lpBuffer, nNumberOfBytesToWrite,
+ lpNumberOfBytesWritten, lpOverlapped);
- WLog_ERR(TAG, "ReadFile operation not implemented");
+ WLog_ERR(TAG, "WriteFile operation not implemented");
return FALSE;
}
BOOL WriteFileEx(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
- LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
+ LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->WriteFileEx)
+ return handle->ops->WriteFileEx(handle, lpBuffer, nNumberOfBytesToWrite,
+ lpOverlapped, lpCompletionRoutine);
+
+ WLog_ERR(TAG, "WriteFileEx operation not implemented");
+ return FALSE;
}
BOOL WriteFileGather(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[],
- DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
+ DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->WriteFileGather)
+ return handle->ops->WriteFileGather(handle, aSegmentArray, nNumberOfBytesToWrite,
+ lpReserved, lpOverlapped);
+
+ WLog_ERR(TAG, "WriteFileGather operation not implemented");
+ return FALSE;
}
BOOL FlushFileBuffers(HANDLE hFile)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->FlushFileBuffers)
+ return handle->ops->FlushFileBuffers(handle);
+
+ WLog_ERR(TAG, "FlushFileBuffers operation not implemented");
+ return FALSE;
}
BOOL SetEndOfFile(HANDLE hFile)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->SetEndOfFile)
+ return handle->ops->SetEndOfFile(handle);
+
+ WLog_ERR(TAG, "SetEndOfFile operation not implemented");
+ return FALSE;
+}
+
+DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
+{
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->GetFileSize)
+ return handle->ops->GetFileSize(handle, lpFileSizeHigh);
+
+ WLog_ERR(TAG, "GetFileSize operation not implemented");
+ return 0;
}
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove,
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->SetFilePointer)
+ return handle->ops->SetFilePointer(handle, lDistanceToMove,
+ lpDistanceToMoveHigh, dwMoveMethod);
+
+ WLog_ERR(TAG, "SetFilePointer operation not implemented");
+ return 0;
}
BOOL SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
- PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
+ PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->SetFilePointerEx)
+ return handle->ops->SetFilePointerEx(handle, liDistanceToMove,
+ lpNewFilePointer, dwMoveMethod);
+
+ WLog_ERR(TAG, "SetFilePointerEx operation not implemented");
+ return 0;
}
BOOL LockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->LockFile)
+ return handle->ops->LockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
+ nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh);
+
+ WLog_ERR(TAG, "LockFile operation not implemented");
+ return FALSE;
}
BOOL LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
- DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped)
+ DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->LockFileEx)
+ return handle->ops->LockFileEx(handle, dwFlags, dwReserved,
+ nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, lpOverlapped);
+
+ WLog_ERR(TAG, "LockFileEx operation not implemented");
+ return FALSE;
}
BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->UnlockFile)
+ return handle->ops->UnlockFile(handle, dwFileOffsetLow, dwFileOffsetHigh,
+ nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh);
+
+ WLog_ERR(TAG, "UnLockFile operation not implemented");
+ return FALSE;
}
BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped)
{
- return TRUE;
+ ULONG Type;
+ WINPR_HANDLE *handle;
+
+ if (hFile == INVALID_HANDLE_VALUE)
+ return FALSE;
+
+ if (!winpr_Handle_GetInfo(hFile, &Type, &handle))
+ return FALSE;
+
+ handle = (WINPR_HANDLE *)hFile;
+ if (handle->ops->UnlockFileEx)
+ return handle->ops->UnlockFileEx(handle, dwReserved,
+ nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh, lpOverlapped);
+
+ WLog_ERR(TAG, "UnLockFileEx operation not implemented");
+ return FALSE;
}
struct _WIN32_FILE_SEARCH
NamedPipeClientGetFd,
NULL, /* CleanupHandle */
NamedPipeRead,
- NamedPipeWrite
+ NULL, /* FileReadEx */
+ NULL, /* FileReadScatter */
+ NamedPipeWrite,
+ NULL, /* FileWriteEx */
+ NULL, /* FileWriteGather */
+ NULL, /* FileGetFileSize */
+ NULL, /* FlushFileBuffers */
+ NULL, /* FileSetEndOfFile */
+ NULL, /* FileSetFilePointer */
+ NULL, /* SetFilePointerEx */
+ NULL, /* FileLockFile */
+ NULL, /* FileLockFileEx */
+ NULL, /* FileUnlockFile */
+ NULL /* FileUnlockFileEx */
};
static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
#include <stdio.h>
#include <winpr/crt.h>
#include <winpr/file.h>
+#include <winpr/path.h>
#include <winpr/windows.h>
int TestFileCreateFile(int argc, char* argv[])
{
- return 0;
+ HANDLE handle;
+ HRESULT hr;
+ DWORD written;
+ const char buffer[] = "Some random text\r\njust want it done.";
+ char cmp[sizeof(buffer)];
+ LPSTR name = GetKnownSubPath(KNOWN_PATH_TEMP, "CreateFile.testfile");
+
+ int rc = 0;
+
+ if (!name)
+ return -1;
+
+ /* On windows we would need '\\' or '/' as seperator.
+ * Single '\' do not work. */
+ hr = PathCchConvertStyleA(name, strlen(name), PATH_STYLE_UNIX);
+ if (FAILED(hr))
+ rc = -1;
+
+ handle = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 0, NULL,
+ CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (!handle)
+ {
+ free(name);
+ return -1;
+ }
+
+ if (!PathFileExistsA(name))
+ rc = -1;
+
+ if (!WriteFile(handle, buffer, sizeof(buffer), &written, NULL))
+ rc = -1;
+
+ if (written != sizeof(buffer))
+ rc = -1;
+
+ written = SetFilePointer(handle, 0, NULL, FILE_BEGIN);
+
+ if (written != 0)
+ rc = -1;
+
+ if (!ReadFile(handle, cmp, sizeof(cmp), &written, NULL))
+ rc = -1;
+
+ if (written != sizeof(cmp))
+ rc = -1;
+
+ if (memcmp(buffer, cmp, sizeof(buffer)))
+ rc = -1;
+
+ if (!CloseHandle(handle))
+ rc = -1;
+
+ if (!DeleteFileA(name))
+ rc = -1;
+
+ if (PathFileExistsA(name))
+ rc = -1;
+
+ free(name);
+
+ return rc;
}
typedef int (*pcGetFd)(HANDLE handle);
typedef DWORD (*pcCleanupHandle)(HANDLE handle);
typedef BOOL (*pcReadFile)(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
- LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
+ LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
+typedef BOOL (*pcReadFileEx)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
+ LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
+typedef BOOL (*pcReadFileScatter)(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[],
+ DWORD nNumberOfBytesToRead, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped);
typedef BOOL (*pcWriteFile)(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
- LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
+ LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
+typedef BOOL (*pcWriteFileEx)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
+ LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
+typedef BOOL (*pcWriteFileGather)(HANDLE hFile, FILE_SEGMENT_ELEMENT aSegmentArray[],
+ DWORD nNumberOfBytesToWrite, LPDWORD lpReserved, LPOVERLAPPED lpOverlapped);
+typedef DWORD (*pcGetFileSize)(HANDLE handle, LPDWORD lpFileSizeHigh);
+typedef BOOL (*pcFlushFileBuffers)(HANDLE hFile);
+typedef BOOL (*pcSetEndOfFile)(HANDLE handle);
+typedef DWORD(*pcSetFilePointer)(HANDLE handle, LONG lDistanceToMove,
+ PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
+typedef BOOL (*pcSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
+ PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
+typedef BOOL (*pcLockFile)(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
+ DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh);
+typedef BOOL (*pcLockFileEx)(HANDLE hFile, DWORD dwFlags, DWORD dwReserved,
+ DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
+ LPOVERLAPPED lpOverlapped);
+typedef BOOL (*pcUnlockFile)(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,
+ DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh);
+typedef BOOL (*pcUnlockFileEx)(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow,
+ DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped);
typedef struct _HANDLE_OPS
{
pcGetFd GetFd;
pcCleanupHandle CleanupHandle;
pcReadFile ReadFile;
+ pcReadFileEx ReadFileEx;
+ pcReadFileScatter ReadFileScatter;
pcWriteFile WriteFile;
+ pcWriteFileEx WriteFileEx;
+ pcWriteFileGather WriteFileGather;
+ pcGetFileSize GetFileSize;
+ pcFlushFileBuffers FlushFileBuffers;
+ pcSetEndOfFile SetEndOfFile;
+ pcSetFilePointer SetFilePointer;
+ pcSetFilePointerEx SetFilePointerEx;
+ pcLockFile LockFile;
+ pcLockFileEx LockFileEx;
+ pcUnlockFile UnlockFile;
+ pcUnlockFileEx UnlockFileEx;
} HANDLE_OPS;
struct winpr_handle
PipeGetFd,
NULL, /* CleanupHandle */
PipeRead,
- PipeWrite
+ NULL, /* FileReadEx */
+ NULL, /* FileReadScatter */
+ PipeWrite,
+ NULL, /* FileWriteEx */
+ NULL, /* FileWriteGather */
+ NULL, /* FileGetFileSize */
+ NULL, /* FlushFileBuffers */
+ NULL, /* FileSetEndOfFile */
+ NULL, /* FileSetFilePointer */
+ NULL, /* SetFilePointerEx */
+ NULL, /* FileLockFile */
+ NULL, /* FileLockFileEx */
+ NULL, /* FileUnlockFile */
+ NULL /* FileUnlockFileEx */
};
NamedPipeGetFd,
NULL, /* CleanupHandle */
NamedPipeRead,
+ NULL,
+ NULL,
NamedPipeWrite
};