Merge pull request #2816 from akallabeth/known_hosts_locking

Known hosts locking
This commit is contained in:
Bernhard Miklautz
2015-12-16 19:03:15 +01:00
12 changed files with 1041 additions and 190 deletions

View File

@@ -116,63 +116,55 @@ fail:
static int certificate_data_match_legacy(rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data)
{
FILE* fp;
HANDLE fp;
int match = 1;
char* data;
char* mdata;
char* pline;
char* hostname;
long size;
DWORD lowSize, highSize;
UINT64 size;
size_t length;
DWORD read;
fp = fopen(certificate_store->legacy_file, "rb");
if (!fp)
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
PathCchConvertStyleA(certificate_store->legacy_file, strlen(certificate_store->legacy_file), PATH_STYLE_UNIX);
fp = CreateFileA(certificate_store->legacy_file, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fp == INVALID_HANDLE_VALUE)
return match;
if (fseek(fp, 0, SEEK_END) < 0)
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
{
WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
certificate_store->legacy_file, strerror(errno), errno);
fclose(fp);
return match;
}
if ((size = ftell(fp)) < 0)
{
WLog_ERR(TAG, "ftell(%s) returned %s [%08X]",
certificate_store->legacy_file, strerror(errno), errno);
fclose(fp);
return match;
}
if (fseek(fp, 0, SEEK_SET) < 0)
{
WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
certificate_store->legacy_file, strerror(errno), errno);
fclose(fp);
WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]",
certificate_store->legacy_file, strerror(errno), GetLastError());
CloseHandle(fp);
return match;
}
size = (UINT64)lowSize | ((UINT64)highSize << 32);
if (size < 1)
{
fclose(fp);
CloseHandle(fp);
return match;
}
mdata = (char*) malloc(size + 2);
if (!mdata)
{
fclose(fp);
CloseHandle(fp);
return match;
}
data = mdata;
if (fread(data, size, 1, fp) != 1)
if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
{
free(data);
fclose(fp);
CloseHandle(fp);
return match;
}
fclose(fp);
CloseHandle(fp);
data[size] = '\n';
data[size + 1] = '\0';
@@ -243,67 +235,59 @@ static int certificate_data_match_raw(rdpCertificateStore* certificate_store,
char** fprint)
{
BOOL found = FALSE;
FILE* fp;
HANDLE fp;
size_t length;
char* data;
char* mdata;
char* pline;
int match = 1;
long int size;
DWORD lowSize, highSize;
UINT64 size;
char* hostname = NULL;
char* subject = NULL;
char* issuer = NULL;
char* fingerprint = NULL;
unsigned short port = 0;
DWORD read;
fp = fopen(certificate_store->file, "rb");
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
fp = CreateFileA(certificate_store->file, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_NORMAL, NULL);
if (!fp)
if (fp == INVALID_HANDLE_VALUE)
return match;
if (fseek(fp, 0, SEEK_END) < 0)
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
{
WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
return match;
}
if ((size = ftell(fp)) < 0)
{
WLog_ERR(TAG, "ftell(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
return match;
}
if (fseek(fp, 0, SEEK_SET) < 0)
{
WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]",
certificate_store->legacy_file, strerror(errno), GetLastError());
CloseHandle(fp);
return match;
}
size = (UINT64)lowSize | ((UINT64)highSize << 32);
if (size < 1)
{
fclose(fp);
CloseHandle(fp);
return match;
}
mdata = (char*) malloc(size + 2);
if (!mdata)
{
fclose(fp);
CloseHandle(fp);
return match;
}
data = mdata;
if (fread(data, size, 1, fp) != 1)
if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
{
fclose(fp);
free(data);
CloseHandle(fp);
return match;
}
fclose(fp);
CloseHandle(fp);
data[size] = '\n';
data[size + 1] = '\0';
@@ -371,40 +355,36 @@ int certificate_data_match(rdpCertificateStore* certificate_store,
BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data)
{
FILE* fp;
HANDLE fp;
BOOL rc = FALSE;
size_t length;
char* data;
char* sdata;
char* pline;
long int size;
UINT64 size;
DWORD read, written;
DWORD lowSize, highSize;
fp = fopen(certificate_store->file, "rb");
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
fp = CreateFileA(certificate_store->file, GENERIC_READ | GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!fp)
if (fp == INVALID_HANDLE_VALUE)
return FALSE;
/* Read the current contents of the file. */
if (fseek(fp, 0, SEEK_END) < 0)
if ((lowSize = GetFileSize(fp, &highSize)) == INVALID_FILE_SIZE)
{
WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
WLog_ERR(TAG, "GetFileSize(%s) returned %s [%08X]",
certificate_store->legacy_file, strerror(errno), GetLastError());
CloseHandle(fp);
return FALSE;
}
size = (UINT64)lowSize | ((UINT64)highSize << 32);
if ((size = ftell(fp)) < 0)
if (size < 1)
{
WLog_ERR(TAG, "ftell(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
return FALSE;
}
if (fseek(fp, 0, SEEK_SET) < 0)
{
WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
CloseHandle(fp);
return FALSE;
}
@@ -415,22 +395,28 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
return FALSE;
}
if (fread(data, size, 1, fp) != 1)
if (!ReadFile(fp, data, size, &read, NULL) || (read != size))
{
fclose(fp);
free(data);
CloseHandle(fp);
return FALSE;
}
fclose(fp);
fp = fopen(certificate_store->file, "wb");
if (fp == NULL)
if (SetFilePointer(fp, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
WLog_ERR(TAG, "freopen(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
WLog_ERR(TAG, "SetFilePointer(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), GetLastError());
free(data);
CloseHandle(fp);
return FALSE;
}
if (!SetEndOfFile(fp))
{
WLog_ERR(TAG, "SetEndOfFile(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), GetLastError());
free(data);
CloseHandle(fp);
return FALSE;
}
@@ -451,6 +437,7 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
char* fingerprint = NULL;
char* subject = NULL;
char* issuer = NULL;
char* tdata;
if (!certificate_split_line(pline, &hostname, &port, &subject, &issuer, &fingerprint))
WLog_WARN(TAG, "Skipping invalid %s entry %s!",
@@ -464,26 +451,44 @@ BOOL certificate_data_replace(rdpCertificateStore* certificate_store,
fingerprint = certificate_data->fingerprint;
rc = TRUE;
}
if (fprintf(fp, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer) < 0)
size = _snprintf(NULL, 0, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer);
tdata = malloc(size + 1);
if (!tdata)
{
WLog_ERR(TAG, "fprintf(%s) returned %s [%08X]",
WLog_ERR(TAG, "malloc(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
free(data);
CloseHandle(fp);
return FALSE;
}
if (_snprintf(tdata, size + 1, "%s %hu %s %s %s\n", hostname, port, fingerprint, subject, issuer) != size)
{
WLog_ERR(TAG, "_snprintf(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
free(tdata);
free(data);
CloseHandle(fp);
return FALSE;
}
if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size))
{
WLog_ERR(TAG, "WriteFile(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
free(tdata);
free(data);
CloseHandle(fp);
return FALSE;
}
free(tdata);
}
}
pline = StrSep(&sdata, "\r\n");
}
if (fflush(fp) != 0)
{
WLog_WARN(TAG, "fflush(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
}
fclose(fp);
CloseHandle(fp);
free(data);
return rc;
@@ -533,39 +538,60 @@ BOOL certificate_split_line(char* line, char** host, UINT16* port, char** subjec
BOOL certificate_data_print(rdpCertificateStore* certificate_store, rdpCertificateData* certificate_data)
{
FILE* fp;
HANDLE fp;
char* tdata;
UINT64 size;
DWORD written;
/* reopen in append mode */
fp = fopen(certificate_store->file, "ab");
/* Assure POSIX style paths, CreateFile expects either '/' or '\\' */
PathCchConvertStyleA(certificate_store->file, strlen(certificate_store->file), PATH_STYLE_UNIX);
fp = CreateFileA(certificate_store->file, GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!fp)
if (fp == INVALID_HANDLE_VALUE)
return FALSE;
if (fseek(fp, 0, SEEK_END) < 0)
if (SetFilePointer(fp, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER)
{
WLog_ERR(TAG, "fseek(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
WLog_ERR(TAG, "SetFilePointer(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), GetLastError());
CloseHandle(fp);
return FALSE;
}
if (fprintf(fp, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port,
size = _snprintf(NULL, 0, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port,
certificate_data->fingerprint, certificate_data->subject,
certificate_data->issuer) < 0)
certificate_data->issuer);
tdata = malloc(size + 1);
if (!tdata)
{
WLog_ERR(TAG, "fprintf(%s) returned %s [%08X]",
WLog_ERR(TAG, "malloc(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
fclose(fp);
CloseHandle(fp);
return FALSE;
}
if (fflush(fp) != 0)
if (_snprintf(tdata, size + 1, "%s %hu %s %s %s\n", certificate_data->hostname, certificate_data->port,
certificate_data->fingerprint, certificate_data->subject,
certificate_data->issuer) != size)
{
WLog_WARN(TAG, "fflush(%s) returned %s [%08X]",
WLog_ERR(TAG, "_snprintf(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
free(tdata);
CloseHandle(fp);
return FALSE;
}
if (!WriteFile(fp, tdata, size, &written, NULL) || (written != size))
{
WLog_ERR(TAG, "WriteFile(%s) returned %s [%08X]",
certificate_store->file, strerror(errno), errno);
free(tdata);
CloseHandle(fp);
return FALSE;
}
free(tdata);
fclose(fp);
CloseHandle(fp);
return TRUE;
}

View File

@@ -32,6 +32,7 @@ WINPR_API void* winpr_backtrace(DWORD size);
WINPR_API void winpr_backtrace_free(void* buffer);
WINPR_API char** winpr_backtrace_symbols(void* buffer, size_t* used);
WINPR_API void winpr_backtrace_symbols_fd(void* buffer, int fd);
WINPR_API char* winpr_strerror(DWORD dw, char* dmsg, size_t size);
#ifdef __cplusplus
}

View File

@@ -165,6 +165,13 @@
#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);

View File

@@ -153,6 +153,7 @@ WINPR_API int lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2);
#endif
#define sprintf_s snprintf
#define _snprintf snprintf
#define _scprintf(_fmt, ...) snprintf(NULL, 0, _fmt, ## __VA_ARGS__)
#define _scprintf(_fmt, ...) snprintf(NULL, 0, _fmt, ## __VA_ARGS__)

View File

@@ -30,19 +30,12 @@
#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)
{
@@ -64,7 +57,7 @@ static int FileGetFd(HANDLE handle)
if (!FileIsHandled(handle))
return -1;
return file->fd;
return fileno(file->fp);
}
static BOOL FileCloseHandle(HANDLE handle) {
@@ -73,25 +66,80 @@ static BOOL FileCloseHandle(HANDLE handle) {
if (!FileIsHandled(handle))
return FALSE;
if (file->fd != -1)
if (file->fp)
{
/* Don't close stdin/stdout/stderr */
if (file->fd > 2)
if (fileno(file->fp) > 2)
{
close(file->fd);
file->fd = -1;
fclose(file->fp);
file->fp = NULL;
}
}
free(handle);
free(file->lpFileName);
free(file);
return TRUE;
}
static BOOL FileSetEndOfFile(HANDLE hFile)
{
WINPR_FILE* pFile = (WINPR_FILE*) hFile;
off_t size;
if (!hFile)
return FALSE;
size = ftell(pFile->fp);
if (ftruncate(fileno(pFile->fp), size) < 0)
{
WLog_ERR(TAG, "ftruncate %s failed with %s [%08X]",
pFile->lpFileName, 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;
if (!hFile)
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(pFile->fp, offset, whence))
{
WLog_ERR(TAG, "fseek(%s) failed with %s [%08X]", pFile->lpFileName,
strerror(errno), errno);
return INVALID_SET_FILE_POINTER;
}
return ftell(pFile->fp);
}
static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
{
int io_status;
size_t io_status;
WINPR_FILE* file;
BOOL status = TRUE;
@@ -105,13 +153,9 @@ static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
}
file = (WINPR_FILE *)Object;
do
{
io_status = read(file->fd, lpBuffer, nNumberOfBytesToRead);
}
while ((io_status < 0) && (errno == EINTR));
io_status = fread(lpBuffer, nNumberOfBytesToRead, 1, file->fp);
if (io_status < 0)
if (io_status != 1)
{
status = FALSE;
@@ -124,7 +168,7 @@ static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
}
if (lpNumberOfBytesRead)
*lpNumberOfBytesRead = io_status;
*lpNumberOfBytesRead = nNumberOfBytesToRead;
return status;
}
@@ -132,7 +176,7 @@ static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
{
int io_status;
size_t io_status;
WINPR_FILE* file;
if (!Object)
@@ -146,71 +190,377 @@ static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrit
file = (WINPR_FILE *)Object;
do
{
io_status = write(file->fd, lpBuffer, nNumberOfBytesToWrite);
}
while ((io_status < 0) && (errno == EINTR));
io_status = fwrite(lpBuffer, nNumberOfBytesToWrite, 1, file->fp);
if (io_status != 1)
return FALSE;
if ((io_status < 0) && (errno == EWOULDBLOCK))
io_status = 0;
*lpNumberOfBytesWritten = io_status;
*lpNumberOfBytesWritten = nNumberOfBytesToWrite;
return TRUE;
}
static DWORD FileGetFileSize(HANDLE Object, LPDWORD lpFileSizeHigh)
{
WINPR_FILE* file;
long cur, size;
static HANDLE_OPS ops = {
FileIsHandled,
FileCloseHandle,
FileGetFd,
NULL, /* CleanupHandle */
FileRead,
FileWrite
if (!Object)
return 0;
file = (WINPR_FILE *)Object;
cur = ftell(file->fp);
if (cur < 0)
{
WLog_ERR(TAG, "ftell(%s) failed with %s [%08X]", file->lpFileName,
strerror(errno), errno);
return INVALID_FILE_SIZE;
}
if (fseek(file->fp, 0, SEEK_END) != 0)
{
WLog_ERR(TAG, "fseek(%s) failed with %s [%08X]", file->lpFileName,
strerror(errno), errno);
return INVALID_FILE_SIZE;
}
size = ftell(file->fp);
if (size < 0)
{
WLog_ERR(TAG, "ftell(%s) failed with %s [%08X]", file->lpFileName,
strerror(errno), errno);
return INVALID_FILE_SIZE;
}
if (fseek(file->fp, cur, SEEK_SET) != 0)
{
WLog_ERR(TAG, "ftell(%s) failed with %s [%08X]", file->lpFileName,
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 %s already locked!", pFile->lpFileName);
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(fileno(pFile->fp), 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 %s is not locked!", pFile->lpFileName);
return FALSE;
}
if (flock(fileno(pFile->fp), LOCK_UN) < 0)
{
WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [%08X]",
pFile->lpFileName, 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 %s is not locked!", pFile->lpFileName);
return FALSE;
}
if (lpOverlapped)
{
WLog_ERR(TAG, "lpOverlapped not implemented!");
return FALSE;
}
if (flock(fileno(pFile->fp), LOCK_UN) < 0)
{
WLog_ERR(TAG, "flock(LOCK_UN) %s failed with %s [%08X]",
pFile->lpFileName, 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 WINPR_FILE *FileHandle_New()
static HANDLE_OPS shmOps = {
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 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;
FILE* fp = NULL;
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)
{
fp = fopen(pFile->lpFileName, "ab");
if (!fp)
{
free(pFile->lpFileName);
free(pFile);
return INVALID_HANDLE_VALUE;
}
fp = freopen(pFile->lpFileName, mode, fp);
}
if (NULL == fp)
fp = fopen(pFile->lpFileName, mode);
pFile->fp = fp;
if (!pFile->fp)
{
/* This case can occur when trying to open a
* not existing file without create flag. */
free(pFile->lpFileName);
free(pFile);
return INVALID_HANDLE_VALUE;
}
setvbuf(fp, NULL, _IONBF, 0);
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(fileno(pFile->fp), lock) < 0)
{
WLog_ERR(TAG, "flock failed with %s [%08X]",
strerror(errno), errno);
FileCloseHandle(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(FILE* fp)
{
WINPR_FILE *pFile;
HANDLE hFile;
char name[MAX_PATH];
_snprintf(name, sizeof(name), "device_%d", fileno(fp));
pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE));
if (!pFile)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
pFile->fd = -1;
pFile->ops = &ops;
pFile->fp = fp;
pFile->ops = &shmOps;
pFile->lpFileName = _strdup(name);
hFile = (HANDLE) pFile;
WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
return pFile;
}
HANDLE GetStdHandle(DWORD nStdHandle)
{
int fd;
FILE* fp;
WINPR_FILE *pFile;
switch (nStdHandle)
{
case STD_INPUT_HANDLE:
fd = STDIN_FILENO;
fp = stdin;
break;
case STD_OUTPUT_HANDLE:
fd = STDOUT_FILENO;
fp = stdout;
break;
case STD_ERROR_HANDLE:
fd = STDERR_FILENO;
fp = stderr;
break;
default:
return INVALID_HANDLE_VALUE;
}
pFile = FileHandle_New();
pFile = FileHandle_New(fp);
if (!pFile)
return INVALID_HANDLE_VALUE;
pFile->fd = fd;
return (HANDLE)pFile;
}
@@ -234,16 +584,33 @@ HANDLE GetFileHandleForFileDescriptor(int fd)
return (HANDLE)_get_osfhandle(fd);
#else /* WIN32 */
WINPR_FILE *pFile;
FILE* fp;
int flags;
/* Make sure it's a valid fd */
if (fcntl(fd, F_GETFD) == -1 && errno == EBADF)
return INVALID_HANDLE_VALUE;
pFile = FileHandle_New();
flags = fcntl(fd, F_GETFL);
if (flags == -1)
return INVALID_HANDLE_VALUE;
if (flags & O_WRONLY)
fp = fdopen(fd, "wb");
else
fp = fdopen(fd, "rb");
if (!fp)
return INVALID_HANDLE_VALUE;
setvbuf(fp, NULL, _IONBF, 0);
pFile = FileHandle_New(fp);
if (!pFile)
return INVALID_HANDLE_VALUE;
pFile->fd = fd;
return (HANDLE)pFile;
#endif /* WIN32 */
}

View File

@@ -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();
FILE* fp;
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 */

View 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

View 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,

View File

@@ -2,9 +2,81 @@
#include <stdio.h>
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/path.h>
#include <winpr/handle.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, 5, NULL, FILE_BEGIN);
if (written != 5)
rc = -1;
written = SetFilePointer(handle, 0, NULL, FILE_CURRENT);
if (written != 5)
rc = -1;
written = SetFilePointer(handle, -5, NULL, FILE_CURRENT);
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;
}

View 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

View 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
};

View File

@@ -471,3 +471,29 @@ void winpr_log_backtrace(const char* tag, DWORD level, DWORD size)
winpr_backtrace_free(stack);
}
char* winpr_strerror(DWORD dw, char* dmsg, size_t size) {
#if defined(_WIN32)
LPTSTR msg = NULL;
DWORD rc;
rc = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dw, 0, (LPTSTR)&msg, 0, NULL);
if (rc) {
#if defined(UNICODE)
WideCharToMultiByte(CP_ACP, 0, msg, rc, dmsg, size - 1, NULL, NULL);
#else /* defined(UNICODE) */
memcpy(dmsg, msg, min(rc, size - 1));
#endif /* defined(UNICODE) */
dmsg[min(rc, size - 1)] = 0;
LocalFree(msg);
} else {
_snprintf(dmsg, size, "FAILURE: %08X", GetLastError());
}
#else /* defined(_WIN32) */
_snprintf(dmsg, size, "%s", strerror(dw));
#endif /* defined(_WIN32) */
return dmsg;
}