mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 08:54:38 +09:00
Merge pull request #2816 from akallabeth/known_hosts_locking
Known hosts locking
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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__)
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
61
winpr/libwinpr/file/file.h
Normal file
61
winpr/libwinpr/file/file.h
Normal 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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user