Added additional file functions and tests.
authorArmin Novak <armin.novak@thincast.com>
Wed, 9 Dec 2015 17:29:16 +0000 (18:29 +0100)
committerArmin Novak <armin.novak@thincast.com>
Wed, 9 Dec 2015 17:29:16 +0000 (18:29 +0100)
winpr/include/winpr/file.h
winpr/libwinpr/file/file.c
winpr/libwinpr/file/file.h [new file with mode: 0644]
winpr/libwinpr/file/generic.c
winpr/libwinpr/file/namedPipeClient.c
winpr/libwinpr/file/test/TestFileCreateFile.c
winpr/libwinpr/handle/handle.h
winpr/libwinpr/pipe/pipe.c

index afe8588..f0129e2 100644 (file)
 #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;
@@ -261,6 +268,8 @@ WINPR_API BOOL FlushFileBuffers(HANDLE hFile);
 
 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);
 
index 49d6a5d..a0f1976 100644 (file)
 #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)
 {
@@ -84,10 +77,81 @@ static BOOL FileCloseHandle(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)
 {
@@ -159,29 +223,347 @@ static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit
        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);
@@ -206,11 +588,10 @@ HANDLE GetStdHandle(DWORD nStdHandle)
                default:
                        return INVALID_HANDLE_VALUE;
        }
-       pFile = FileHandle_New();
+       pFile = FileHandle_New(fd);
        if (!pFile)
                return INVALID_HANDLE_VALUE;
 
-       pFile->fd = fd;
        return (HANDLE)pFile;
 }
 
@@ -239,7 +620,7 @@ HANDLE GetFileHandleForFileDescriptor(int fd)
        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;
diff --git a/winpr/libwinpr/file/file.h b/winpr/libwinpr/file/file.h
new file mode 100644 (file)
index 0000000..fc28793
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * 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 */
+
index 6a8a265..8719787 100644 (file)
@@ -65,6 +65,8 @@
 
 #include "../pipe/pipe.h"
 
+#include "file.h"
+
 /**
  * api-ms-win-core-file-l1-2-0.dll:
  *
@@ -195,6 +197,7 @@ static void _HandleCreatorsInit()
 #if defined __linux__ && !defined ANDROID
        ArrayList_Add(_HandleCreators, GetCommHandleCreator());
 #endif /* __linux__ && !defined ANDROID */
+       ArrayList_Add(_HandleCreators, GetFileHandleCreator());
 }
 
 
@@ -253,8 +256,9 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
 
                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;
                }
@@ -267,7 +271,17 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
 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)
@@ -279,7 +293,15 @@ 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,
@@ -304,22 +326,55 @@ 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,
@@ -336,68 +391,236 @@ 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
index d2aed74..b78f8eb 100644 (file)
@@ -111,7 +111,20 @@ static HANDLE_OPS ops = {
                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,
index 39b6a26..9628106 100644 (file)
@@ -2,9 +2,70 @@
 #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;
 }
index 7dd6200..d2669ba 100644 (file)
@@ -50,9 +50,33 @@ typedef BOOL (*pcCloseHandle)(HANDLE handle);
 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
 {
@@ -61,7 +85,20 @@ 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
index 28d9eed..02beb5d 100644 (file)
@@ -178,7 +178,20 @@ static HANDLE_OPS ops = {
                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 */
 };
 
 
@@ -409,6 +422,8 @@ static HANDLE_OPS namedOps = {
                NamedPipeGetFd,
                NULL, /* CleanupHandle */
                NamedPipeRead,
+               NULL,
+               NULL,
                NamedPipeWrite
 };