drive_file.h
drive_main.c)
-if(WIN32)
- set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}
- statvfs.c
- statvfs.h
- dirent.h)
-endif()
-
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry")
+++ /dev/null
-/*****************************************************************************
- * dirent.h - dirent API for Microsoft Visual Studio
- *
- * Copyright (C) 2006 Toni Ronkko
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * ``Software''), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Mar 15, 2011, Toni Ronkko
- * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
- *
- * Aug 11, 2010, Toni Ronkko
- * Added d_type and d_namlen fields to dirent structure. The former is
- * especially useful for determining whether directory entry represents a
- * file or a directory. For more information, see
- * http://www.delorie.com/gnu/docs/glibc/libc_270.html
- *
- * Aug 11, 2010, Toni Ronkko
- * Improved conformance to the standards. For example, errno is now set
- * properly on failure and assert() is never used. Thanks to Peter Brockam
- * for suggestions.
- *
- * Aug 11, 2010, Toni Ronkko
- * Fixed a bug in rewinddir(): when using relative directory names, change
- * of working directory no longer causes rewinddir() to fail.
- *
- * Dec 15, 2009, John Cunningham
- * Added rewinddir member function
- *
- * Jan 18, 2008, Toni Ronkko
- * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
- * between multi-byte and unicode representations. This makes the
- * code simpler and also allows the code to be compiled under MingW. Thanks
- * to Azriel Fasten for the suggestion.
- *
- * Mar 4, 2007, Toni Ronkko
- * Bug fix: due to the strncpy_s() function this file only compiled in
- * Visual Studio 2005. Using the new string functions only when the
- * compiler version allows.
- *
- * Nov 2, 2006, Toni Ronkko
- * Major update: removed support for Watcom C, MS-DOS and Turbo C to
- * simplify the file, updated the code to compile cleanly on Visual
- * Studio 2005 with both unicode and multi-byte character strings,
- * removed rewinddir() as it had a bug.
- *
- * Aug 20, 2006, Toni Ronkko
- * Removed all remarks about MSVC 1.0, which is antiqued now. Simplified
- * comments by removing SGML tags.
- *
- * May 14 2002, Toni Ronkko
- * Embedded the function definitions directly to the header so that no
- * source modules need to be included in the Visual Studio project. Removed
- * all the dependencies to other projects so that this very header can be
- * used independently.
- *
- * May 28 1998, Toni Ronkko
- * First version.
- *****************************************************************************/
-#ifndef DIRENT_H
-#define DIRENT_H
-
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-/* Entries missing from MSVC 6.0 */
-#if !defined(FILE_ATTRIBUTE_DEVICE)
-# define FILE_ATTRIBUTE_DEVICE 0x40
-#endif
-
-/* File type and permission flags for stat() */
-#if defined(_MSC_VER) && !defined(S_IREAD)
-# define S_IFMT _S_IFMT /* file type mask */
-# define S_IFDIR _S_IFDIR /* directory */
-# define S_IFCHR _S_IFCHR /* character device */
-# define S_IFFIFO _S_IFFIFO /* pipe */
-# define S_IFREG _S_IFREG /* regular file */
-# define S_IREAD _S_IREAD /* read permission */
-# define S_IWRITE _S_IWRITE /* write permission */
-# define S_IEXEC _S_IEXEC /* execute permission */
-#endif
-#define S_IFBLK 0 /* block device */
-#define S_IFLNK 0 /* link */
-#define S_IFSOCK 0 /* socket */
-
-#if defined(_MSC_VER)
-# define S_IRUSR S_IREAD /* read, user */
-# define S_IWUSR S_IWRITE /* write, user */
-# define S_IXUSR 0 /* execute, user */
-# define S_IRGRP 0 /* read, group */
-# define S_IWGRP 0 /* write, group */
-# define S_IXGRP 0 /* execute, group */
-# define S_IROTH 0 /* read, others */
-# define S_IWOTH 0 /* write, others */
-# define S_IXOTH 0 /* execute, others */
-#endif
-
-/* Indicates that d_type field is available in dirent structure */
-#define _DIRENT_HAVE_D_TYPE
-
-/* File type flags for d_type */
-#define DT_UNKNOWN 0
-#define DT_REG S_IFREG
-#define DT_DIR S_IFDIR
-#define DT_FIFO S_IFFIFO
-#define DT_SOCK S_IFSOCK
-#define DT_CHR S_IFCHR
-#define DT_BLK S_IFBLK
-
-/* Macros for converting between st_mode and d_type */
-#define IFTODT(mode) ((mode) & S_IFMT)
-#define DTTOIF(type) (type)
-
-/*
- * File type macros. Note that block devices, sockets and links cannot be
- * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
- * only defined for compatibility. These macros should always return FALSE
- * on Windows.
- */
-#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
-#define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
-#define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
-#define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-typedef struct dirent
-{
- char d_name[MAX_PATH + 1]; /* File name */
- size_t d_namlen; /* Length of name without \0 */
- int d_type; /* File type */
-} dirent;
-
-
-typedef struct DIR
-{
- dirent curentry; /* Current directory entry */
- WIN32_FIND_DATAA find_data; /* Private file data */
- int cached; /* True if data is valid */
- HANDLE search_handle; /* Win32 search handle */
- char patt[MAX_PATH + 3]; /* Initial directory name */
-} DIR;
-
-
-/* Forward declarations */
-static DIR *opendir(const char *dirname);
-static struct dirent *readdir(DIR *dirp);
-static int closedir(DIR *dirp);
-static void rewinddir(DIR* dirp);
-
-
-/* Use the new safe string functions introduced in Visual Studio 2005 */
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-# define DIRENT_STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE)
-#else
-# define DIRENT_STRNCPY(dest,src,size) strncpy((dest),(src),(size))
-#endif
-
-/* Set errno variable */
-#if defined(_MSC_VER)
-#define DIRENT_SET_ERRNO(x) _set_errno (x)
-#else
-#define DIRENT_SET_ERRNO(x) (errno = (x))
-#endif
-
-
-/*****************************************************************************
- * Open directory stream DIRNAME for read and return a pointer to the
- * internal working area that is used to retrieve individual directory
- * entries.
- */
-static DIR *opendir(const char *dirname)
-{
- DIR *dirp;
-
- /* ensure that the resulting search pattern will be a valid file name */
- if (dirname == NULL) {
- DIRENT_SET_ERRNO (ENOENT);
- return NULL;
- }
- if (strlen (dirname) + 3 >= MAX_PATH) {
- DIRENT_SET_ERRNO (ENAMETOOLONG);
- return NULL;
- }
-
- /* construct new DIR structure */
- dirp = (DIR*) malloc (sizeof (struct DIR));
- if (dirp != NULL) {
- int error;
-
- /*
- * Convert relative directory name to an absolute one. This
- * allows rewinddir() to function correctly when the current working
- * directory is changed between opendir() and rewinddir().
- */
- if (GetFullPathNameA(dirname, MAX_PATH, dirp->patt, NULL)) {
- char *p;
-
- /* append the search pattern "\\*\0" to the directory name */
- p = strchr (dirp->patt, '\0');
- if (dirp->patt < p && *(p-1) != '\\' && *(p-1) != ':') {
- *p++ = '\\';
- }
- *p++ = '*';
- *p = '\0';
-
- /* open directory stream and retrieve the first entry */
- dirp->search_handle = FindFirstFileA(dirp->patt, &dirp->find_data);
- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
- /* a directory entry is now waiting in memory */
- dirp->cached = 1;
- error = 0;
- } else {
- /* search pattern is not a directory name? */
- DIRENT_SET_ERRNO (ENOENT);
- error = 1;
- }
- } else {
- /* buffer too small */
- DIRENT_SET_ERRNO (ENOMEM);
- error = 1;
- }
-
- if (error) {
- free (dirp);
- dirp = NULL;
- }
- }
-
- return dirp;
-}
-
-
-/*****************************************************************************
- * Read a directory entry, and return a pointer to a dirent structure
- * containing the name of the entry in d_name field. Individual directory
- * entries returned by this very function include regular files,
- * sub-directories, pseudo-directories "." and "..", but also volume labels,
- * hidden files and system files may be returned.
- */
-static struct dirent *readdir(DIR *dirp)
-{
- DWORD attr;
- if (dirp == NULL) {
- /* directory stream did not open */
- DIRENT_SET_ERRNO (EBADF);
- return NULL;
- }
-
- /* get next directory entry */
- if (dirp->cached != 0) {
- /* a valid directory entry already in memory */
- dirp->cached = 0;
- } else {
- /* get the next directory entry from stream */
- if (dirp->search_handle == INVALID_HANDLE_VALUE) {
- return NULL;
- }
- if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) {
- /* the very last entry has been processed or an error occurred */
- FindClose (dirp->search_handle);
- dirp->search_handle = INVALID_HANDLE_VALUE;
- return NULL;
- }
- }
-
- /* copy as a multibyte character string */
- DIRENT_STRNCPY ( dirp->curentry.d_name,
- dirp->find_data.cFileName,
- sizeof(dirp->curentry.d_name) );
- dirp->curentry.d_name[MAX_PATH] = '\0';
-
- /* compute the length of name */
- dirp->curentry.d_namlen = strlen (dirp->curentry.d_name);
-
- /* determine file type */
- attr = dirp->find_data.dwFileAttributes;
- if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
- dirp->curentry.d_type = DT_CHR;
- } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
- dirp->curentry.d_type = DT_DIR;
- } else {
- dirp->curentry.d_type = DT_REG;
- }
- return &dirp->curentry;
-}
-
-
-/*****************************************************************************
- * Close directory stream opened by opendir() function. Close of the
- * directory stream invalidates the DIR structure as well as any previously
- * read directory entry.
- */
-static int closedir(DIR *dirp)
-{
- if (dirp == NULL) {
- /* invalid directory stream */
- DIRENT_SET_ERRNO (EBADF);
- return -1;
- }
-
- /* release search handle */
- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
- FindClose (dirp->search_handle);
- dirp->search_handle = INVALID_HANDLE_VALUE;
- }
-
- /* release directory structure */
- free (dirp);
- return 0;
-}
-
-
-/*****************************************************************************
- * Resets the position of the directory stream to which dirp refers to the
- * beginning of the directory. It also causes the directory stream to refer
- * to the current state of the corresponding directory, as a call to opendir()
- * would have done. If dirp does not refer to a directory stream, the effect
- * is undefined.
- */
-static void rewinddir(DIR* dirp)
-{
- if (dirp != NULL) {
- /* release search handle */
- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
- FindClose (dirp->search_handle);
- }
-
- /* open new search handle and retrieve the first entry */
- dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
- if (dirp->search_handle != INVALID_HANDLE_VALUE) {
- /* a directory entry is now waiting in memory */
- dirp->cached = 1;
- } else {
- /* failed to re-open directory: no directory entry in memory */
- dirp->cached = 0;
- }
- }
-}
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif /*DIRENT_H*/
#include <winpr/path.h>
#include <winpr/file.h>
#include <winpr/stream.h>
+#include <winpr/shell.h>
#include <freerdp/channels/rdpdr.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-#define __USE_GNU /* for O_PATH */
-#include <fcntl.h>
-#undef __USE_GNU
-#endif
-
-#ifdef _WIN32
-#pragma comment(lib, "Shlwapi.lib")
-#include <Shlwapi.h>
-#else
-#include <winpr/path.h>
-#endif
-
#include "drive_file.h"
#ifdef _WIN32
#pragma warning(disable: 4244)
#endif
-static void drive_file_fix_path(char* path)
+#ifdef WITH_DEBUG_RDPDR
+#define DEBUG_WSTR(msg, wstr) do { LPSTR lpstr; ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &lpstr, 0, NULL, NULL); WLog_DBG(TAG, msg, lpstr); free(lpstr); } while (0)
+#else
+#define DEBUG_WSTR(msg, wstr) do { } while (0)
+#endif
+
+
+static void drive_file_fix_path(WCHAR* path)
{
- size_t i;
- size_t length = strlen(path);
+ int i;
+ int length;
+ length = (int) _wcslen(path);
for (i = 0; i < length; i++)
{
path[length - 1] = '\0';
}
-static char* drive_file_combine_fullpath(const char* base_path, const char* path)
+static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path,
+ UINT32 PathLength)
{
- char* fullpath;
+ WCHAR* fullpath;
+ UINT32 base_path_length;
if (!base_path || !path)
return NULL;
- fullpath = (char*) malloc(strlen(base_path) + strlen(path) + 1);
+ base_path_length = _wcslen(base_path) * 2;
+ fullpath = (WCHAR*)calloc(1, base_path_length + PathLength + sizeof(WCHAR));
if (!fullpath)
{
return NULL;
}
- strcpy(fullpath, base_path);
- strcat(fullpath, path);
+ CopyMemory(fullpath, base_path, base_path_length);
+ CopyMemory((char*)fullpath + base_path_length, path, PathLength);
drive_file_fix_path(fullpath);
return fullpath;
}
-static BOOL drive_file_remove_dir(const char* path)
+static BOOL drive_file_remove_dir(const WCHAR* path)
{
- DIR* dir;
- char* p;
- struct STAT st;
- struct dirent* pdirent;
+ WIN32_FIND_DATAW findFileData;
BOOL ret = TRUE;
+ INT len;
+ HANDLE dir;
+ WCHAR* fullpath;
+ WCHAR* path_slash;
+ UINT32 base_path_length;
+ base_path_length = _wcslen(path) * 2;
+ path_slash = (WCHAR*)calloc(1, base_path_length + sizeof(WCHAR) * 3);
+
+ if (!path_slash)
+ {
+ WLog_ERR(TAG, "malloc failed!");
+ return FALSE;
+ }
if (!path)
return FALSE;
- dir = opendir(path);
+ CopyMemory(path_slash, path, base_path_length);
+ path_slash[base_path_length / 2] = '/';
+ path_slash[base_path_length / 2 + 1] = '*';
+ DEBUG_WSTR("Search in %s", path_slash);
+ dir = FindFirstFileW(path_slash, &findFileData);
+ path_slash[base_path_length / 2 + 1] = 0;
- if (dir == NULL)
+ if (dir == INVALID_HANDLE_VALUE)
+ {
+ free(path_slash);
return FALSE;
+ }
- pdirent = readdir(dir);
-
- while (pdirent)
+ do
{
- if (strcmp(pdirent->d_name, ".") == 0 || strcmp(pdirent->d_name, "..") == 0)
- {
- pdirent = readdir(dir);
- continue;
- }
-
- p = (char*) malloc(strlen(path) + strlen(pdirent->d_name) + 2);
+ len = _wcslen(findFileData.cFileName);
- if (!p)
+ if ((len == 1 && findFileData.cFileName[0] == '.') || (len == 2 &&
+ findFileData.cFileName[0] == '.' && findFileData.cFileName[1] == '.'))
{
- WLog_ERR(TAG, "malloc failed!");
- return FALSE;
+ continue;
}
- sprintf(p, "%s/%s", path, pdirent->d_name);
+ fullpath = drive_file_combine_fullpath(path_slash, findFileData.cFileName, len * 2);
+ DEBUG_WSTR("Delete %s", fullpath);
- if (STAT(p, &st) != 0)
- {
- ret = FALSE;
- }
- else if (S_ISDIR(st.st_mode))
+ if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
- ret = drive_file_remove_dir(p);
- }
- else if (unlink(p) < 0)
- {
- ret = FALSE;
+ ret = drive_file_remove_dir(fullpath);
}
else
{
- ret = TRUE;
+ ret = DeleteFileW(fullpath);
}
- free(p);
+ free(fullpath);
if (!ret)
break;
-
- pdirent = readdir(dir);
}
+ while (ret && FindNextFileW(dir, &findFileData) != 0);
- closedir(dir);
+ FindClose(dir);
if (ret)
{
- if (rmdir(path) < 0)
+ if (!RemoveDirectoryW(path))
{
ret = FALSE;
}
}
+ free(path_slash);
return ret;
}
-static void drive_file_set_fullpath(DRIVE_FILE* file, char* fullpath)
+static void drive_file_set_fullpath(DRIVE_FILE* file, WCHAR* fullpath)
{
free(file->fullpath);
file->fullpath = fullpath;
- file->filename = strrchr(file->fullpath, '/');
+ file->filename = _wcsrchr(file->fullpath, 0x5c);
if (file->filename == NULL)
file->filename = file->fullpath;
file->filename += 1;
}
-static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 CreateDisposition,
- UINT32 CreateOptions)
+BOOL drive_file_init(DRIVE_FILE* file)
{
- struct STAT st;
- BOOL exists;
-#ifdef WIN32
- const static int mode = _S_IREAD | _S_IWRITE ;
-#else
- const static int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
- BOOL largeFile = FALSE;
-#endif
- int oflag = 0;
+ UINT CreateDisposition = 0;
+ DWORD dwAttr = GetFileAttributesW(file->fullpath);
- if (STAT(file->fullpath, &st) == 0)
+ if (dwAttr != INVALID_FILE_ATTRIBUTES)
{
- file->is_dir = (S_ISDIR(st.st_mode) ? TRUE : FALSE);
+ /* The file exists */
+ file->is_dir = (dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0;
- if (!file->is_dir && !S_ISREG(st.st_mode))
+ if (file->is_dir)
{
- file->err = EPERM;
- return TRUE;
- }
-
-#ifndef WIN32
+ if (file->CreateDisposition == FILE_CREATE)
+ {
+ SetLastError(ERROR_ALREADY_EXISTS);
+ return FALSE;
+ }
- if (st.st_size > (unsigned long) 0x07FFFFFFF)
- largeFile = TRUE;
+ if (file->CreateOptions & FILE_NON_DIRECTORY_FILE)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
-#endif
- exists = TRUE;
+ return TRUE;
+ }
+ else
+ {
+ if (file->CreateOptions & FILE_DIRECTORY_FILE)
+ {
+ SetLastError(ERROR_DIRECTORY);
+ return FALSE;
+ }
+ }
}
else
{
- file->is_dir = ((CreateOptions & FILE_DIRECTORY_FILE) ? TRUE : FALSE);
+ file->is_dir = ((file->CreateOptions & FILE_DIRECTORY_FILE) ? TRUE : FALSE);
if (file->is_dir)
{
/* Should only create the directory if the disposition allows for it */
- if ((CreateDisposition == FILE_OPEN_IF) || (CreateDisposition == FILE_CREATE))
+ if ((file->CreateDisposition == FILE_OPEN_IF) || (file->CreateDisposition == FILE_CREATE))
{
- if (mkdir(file->fullpath, mode) != 0)
+ if (CreateDirectoryW(file->fullpath, NULL) != 0)
{
- file->err = errno;
return TRUE;
}
}
- }
- exists = FALSE;
- }
-
- if (file->is_dir)
- {
- file->dir = opendir(file->fullpath);
-
- if (file->dir == NULL)
- {
- file->err = errno;
- return TRUE;
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ return FALSE;
}
}
- else
+
+ if (file->file_handle == INVALID_HANDLE_VALUE)
{
- switch (CreateDisposition)
+ switch (file->CreateDisposition)
{
- case FILE_SUPERSEDE:
- oflag = O_TRUNC | O_CREAT;
+ case FILE_SUPERSEDE: /* If the file already exists, replace it with the given file. If it does not, create the given file. */
+ CreateDisposition = CREATE_ALWAYS;
break;
- case FILE_OPEN:
+ case FILE_OPEN: /* If the file already exists, open it instead of creating a new file. If it does not, fail the request and do not create a new file. */
+ CreateDisposition = OPEN_EXISTING;
break;
- case FILE_CREATE:
- oflag = O_CREAT | O_EXCL;
+ case FILE_CREATE: /* If the file already exists, fail the request and do not create or open the given file. If it does not, create the given file. */
+ CreateDisposition = CREATE_NEW;
break;
- case FILE_OPEN_IF:
- oflag = O_CREAT;
+ case FILE_OPEN_IF: /* If the file already exists, open it. If it does not, create the given file. */
+ CreateDisposition = OPEN_ALWAYS;
break;
- case FILE_OVERWRITE:
- oflag = O_TRUNC;
+ case FILE_OVERWRITE: /* If the file already exists, open it and overwrite it. If it does not, fail the request. */
+ CreateDisposition = TRUNCATE_EXISTING;
break;
- case FILE_OVERWRITE_IF:
- oflag = O_TRUNC | O_CREAT;
+ case FILE_OVERWRITE_IF: /* If the file already exists, open it and overwrite it. If it does not, create the given file. */
+ CreateDisposition = CREATE_ALWAYS;
break;
default:
break;
}
- if ((CreateOptions & FILE_DELETE_ON_CLOSE) && (DesiredAccess & DELETE))
- {
- file->delete_pending = TRUE;
- }
-
- if ((DesiredAccess & GENERIC_ALL)
- || (DesiredAccess & GENERIC_WRITE)
- || (DesiredAccess & FILE_WRITE_DATA)
- || (DesiredAccess & FILE_APPEND_DATA))
- {
- oflag |= O_RDWR;
- }
- else
- {
- oflag |= O_RDONLY;
- }
-
#ifndef WIN32
-
- if (largeFile)
- {
- oflag |= O_LARGEFILE;
- }
-
-#else
- oflag |= O_BINARY;
+ file->SharedAccess = 0;
#endif
- file->fd = OPEN(file->fullpath, oflag, mode);
+ file->file_handle = CreateFileW(file->fullpath, file->DesiredAccess,
+ file->SharedAccess, NULL, CreateDisposition,
+ file->FileAttributes, NULL);
+ }
- if (file->fd == -1)
+ if (file->file_handle == INVALID_HANDLE_VALUE)
+ {
+ /* Get the error message, if any. */
+ DWORD errorMessageID = GetLastError();
+
+ if (errorMessageID != 0)
{
- file->err = errno;
- return TRUE;
+#ifdef WIN32
+ LPSTR messageBuffer = NULL;
+ size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
+ WLog_ERR(TAG, "Error in drive_file_init: %s %s", messageBuffer, file->fullpath);
+ /* Free the buffer. */
+ LocalFree(messageBuffer);
+#endif
}
}
- return TRUE;
+ return file->file_handle != INVALID_HANDLE_VALUE;
}
-DRIVE_FILE* drive_file_new(const char* base_path, const char* path, UINT32 id,
- UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions)
+DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id,
+ UINT32 DesiredAccess, UINT32 CreateDisposition,
+ UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess)
{
DRIVE_FILE* file;
file = (DRIVE_FILE*) calloc(1, sizeof(DRIVE_FILE));
return NULL;
}
+ file->file_handle = INVALID_HANDLE_VALUE;
+ file->find_handle = INVALID_HANDLE_VALUE;
file->id = id;
- file->basepath = (char*) base_path;
- drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path));
- file->fd = -1;
-
- if (!drive_file_init(file, DesiredAccess, CreateDisposition, CreateOptions))
+ file->basepath = (WCHAR*) base_path;
+ file->FileAttributes = FileAttributes;
+ file->DesiredAccess = DesiredAccess;
+ file->CreateDisposition = CreateDisposition;
+ file->CreateOptions = CreateOptions;
+ file->SharedAccess = SharedAccess;
+ drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathLength));
+
+ if (!drive_file_init(file))
{
drive_file_free(file);
return NULL;
}
-#if defined(__linux__) && defined(O_PATH)
-
- if (file->fd < 0 && file->err == EACCES)
- {
- /**
- * We have no access permissions for the file or directory but if the
- * peer is only interested in reading the object's attributes we can try
- * to obtain a file descriptor who's only purpose is to perform
- * operations that act purely at the file descriptor level.
- * See open(2)
- **/
- {
- if ((file->fd = OPEN(file->fullpath, O_PATH)) >= 0)
- {
- file->err = 0;
- }
- }
- }
-
-#endif
return file;
}
-void drive_file_free(DRIVE_FILE* file)
+BOOL drive_file_free(DRIVE_FILE* file)
{
if (!file)
return;
- if (file->fd != -1)
- close(file->fd);
+ if (file->file_handle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(file->file_handle);
+ file->file_handle = INVALID_HANDLE_VALUE;
+ }
- if (file->dir != NULL)
- closedir(file->dir);
+ if (file->find_handle != INVALID_HANDLE_VALUE)
+ {
+ FindClose(file->find_handle);
+ file->find_handle = INVALID_HANDLE_VALUE;
+ }
if (file->delete_pending)
{
if (file->is_dir)
drive_file_remove_dir(file->fullpath);
- else
- unlink(file->fullpath);
+ else if (!DeleteFileW(file->fullpath))
+ {
+ free(file->fullpath);
+ free(file);
+ return FALSE;
+ }
}
- free(file->pattern);
+ DEBUG_WSTR("Free %s", file->fullpath);
free(file->fullpath);
free(file);
+ return TRUE;
}
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset)
if (!file)
return FALSE;
- if (file->is_dir || file->fd == -1)
- return FALSE;
-
- if (LSEEK(file->fd, Offset, SEEK_SET) == (off_t) - 1)
- return FALSE;
-
- return TRUE;
+ LONG lDistHigh = Offset >> 32;
+ DEBUG_WSTR("Seek %s", file->fullpath);
+ DWORD dwPtrLow = SetFilePointer(file->file_handle, Offset & 0xFFFFFFFF, &lDistHigh, FILE_BEGIN);
+ return dwPtrLow != INVALID_SET_FILE_POINTER;
}
BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length)
{
- ssize_t r;
+ UINT32 read;
if (!file || !buffer || !Length)
return FALSE;
- if (file->is_dir || file->fd == -1)
- return FALSE;
-
- r = read(file->fd, buffer, *Length);
+ DEBUG_WSTR("Read file %s", file->fullpath);
- if (r < 0)
- return FALSE;
+ if (ReadFile(file->file_handle, buffer, *Length, &read, NULL))
+ {
+ *Length = read;
+ return TRUE;
+ }
- *Length = (UINT32) r;
- return TRUE;
+ return FALSE;
}
BOOL drive_file_write(DRIVE_FILE* file, BYTE* buffer, UINT32 Length)
{
- ssize_t r;
+ UINT32 written;
if (!file || !buffer)
return FALSE;
- if (file->is_dir || file->fd == -1)
- return FALSE;
+ DEBUG_WSTR("Write file %s", file->fullpath);
while (Length > 0)
{
- r = write(file->fd, buffer, Length);
-
- if (r == -1)
+ if (!WriteFile(file->file_handle, buffer, Length, &written, NULL))
return FALSE;
- Length -= r;
- buffer += r;
+ Length -= written;
+ buffer += written;
}
return TRUE;
BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, wStream* output)
{
- struct STAT st;
+ WIN32_FIND_DATAW findFileData;
+ HANDLE hFind;
+ DEBUG_WSTR("FindFirstFile %s", file->fullpath);
if (!file || !output)
return FALSE;
- if (STAT(file->fullpath, &st) != 0)
+ if ((hFind = FindFirstFileW(file->fullpath, &findFileData)) == INVALID_HANDLE_VALUE)
{
- Stream_Write_UINT32(output, 0); /* Length */
- return FALSE;
+#ifdef WIN32
+ ZeroMemory(&findFileData, sizeof(findFileData));
+ findFileData.dwFileAttributes = GetFileAttributesW(file->fullpath);
+
+ if (findFileData.dwFileAttributes == INVALID_FILE_ATTRIBUTES)
+ {
+ goto out_fail;
+ }
+
+#else
+ goto out_fail;
+#endif
}
+ FindClose(hFind);
+
switch (FsInformationClass)
{
case FileBasicInformation:
goto out_fail;
Stream_Write_UINT32(output, 36); /* Length */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */
- Stream_Write_UINT32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
+ Stream_Write_UINT32(output, findFileData.ftCreationTime.dwLowDateTime); /* CreationTime */
+ Stream_Write_UINT32(output, findFileData.ftCreationTime.dwHighDateTime); /* CreationTime */
+ Stream_Write_UINT32(output, findFileData.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
+ Stream_Write_UINT32(output, findFileData.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
+ Stream_Write_UINT32(output, findFileData.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
+ Stream_Write_UINT32(output, findFileData.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
+ Stream_Write_UINT32(output, findFileData.ftLastWriteTime.dwLowDateTime); /* ChangeTime */
+ Stream_Write_UINT32(output, findFileData.ftLastWriteTime.dwHighDateTime); /* ChangeTime */
+ Stream_Write_UINT32(output, findFileData.dwFileAttributes); /* FileAttributes */
/* Reserved(4), MUST NOT be added! */
break;
goto out_fail;
Stream_Write_UINT32(output, 22); /* Length */
- Stream_Write_UINT64(output, st.st_size); /* AllocationSize */
- Stream_Write_UINT64(output, st.st_size); /* EndOfFile */
- Stream_Write_UINT32(output, st.st_nlink); /* NumberOfLinks */
+ Stream_Write_UINT32(output, findFileData.nFileSizeLow); /* AllocationSize */
+ Stream_Write_UINT32(output, findFileData.nFileSizeHigh); /* AllocationSize */
+ Stream_Write_UINT32(output, findFileData.nFileSizeLow); /* EndOfFile */
+ Stream_Write_UINT32(output, findFileData.nFileSizeHigh); /* EndOfFile */
+ Stream_Write_UINT32(output, 0); /* NumberOfLinks */
Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); /* DeletePending */
- Stream_Write_UINT8(output, file->is_dir ? 1 : 0); /* Directory */
+ Stream_Write_UINT8(output, findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? TRUE :
+ FALSE); /* Directory */
/* Reserved(2), MUST NOT be added! */
break;
goto out_fail;
Stream_Write_UINT32(output, 8); /* Length */
- Stream_Write_UINT32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
+ Stream_Write_UINT32(output, findFileData.dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, 0); /* ReparseTag */
break;
default:
/* Unhandled FsInformationClass */
- Stream_Write_UINT32(output, 0); /* Length */
- return FALSE;
+ goto out_fail;
}
return TRUE;
return FALSE;
}
-int dir_empty(const char* path)
-{
-#ifdef _WIN32
- return PathIsDirectoryEmptyA(path);
-#else
- struct dirent* dp;
- int empty = 1;
- DIR* dir = opendir(path);
-
- if (dir == NULL) //Not a directory or doesn't exist
- return 1;
-
- while ((dp = readdir(dir)) != NULL)
- {
- if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
- continue; /* Skip . and .. */
-
- empty = 0;
- break;
- }
-
- closedir(dir);
- return empty;
-#endif
-}
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length,
wStream* input)
{
- char* s = NULL;
INT64 size;
- int status;
- char* fullpath;
+ WCHAR* fullpath;
ULARGE_INTEGER liCreationTime;
ULARGE_INTEGER liLastAccessTime;
ULARGE_INTEGER liLastWriteTime;
FILETIME* pftLastWriteTime = NULL;
UINT32 FileAttributes;
UINT32 FileNameLength;
- HANDLE hFd;
LARGE_INTEGER liSize;
+ UINT8 delete_pending;
+ UINT8 ReplaceIfExists;
+ DWORD attr;
if (!file || !input)
return FALSE;
Stream_Read_UINT64(input, liChangeTime.QuadPart);
Stream_Read_UINT32(input, FileAttributes);
- if (!PathFileExistsA(file->fullpath))
+ if (!PathFileExistsW(file->fullpath))
return FALSE;
- hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (hFd == INVALID_HANDLE_VALUE)
+ if (file->file_handle == INVALID_HANDLE_VALUE)
{
WLog_ERR(TAG, "Unable to create file %s", file->fullpath);
return FALSE;
pftLastWriteTime = &ftLastWriteTime;
}
- if (!SetFileTime(hFd, pftCreationTime, pftLastAccessTime, pftLastWriteTime))
+ DEBUG_WSTR("SetFileTime %s", file->fullpath);
+
+ if (!SetFileTime(file->file_handle, pftCreationTime, pftLastAccessTime, pftLastWriteTime))
{
- WLog_ERR(TAG, "Unable to set file time on %s", file->fullpath);
- CloseHandle(hFd);
+ WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath);
return FALSE;
}
- CloseHandle(hFd);
+ SetFileAttributesW(file->fullpath, FileAttributes);
break;
case FileEndOfFileInformation:
case FileAllocationInformation:
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
Stream_Read_INT64(input, size);
- hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFd == INVALID_HANDLE_VALUE)
+ if (file->file_handle == INVALID_HANDLE_VALUE)
{
WLog_ERR(TAG, "Unable to truncate %s to %"PRId64"", file->fullpath, size);
return FALSE;
}
- liSize.QuadPart = size;
+ if (SetFilePointer(file->file_handle, liSize.LowPart, &liSize.HighPart,
+ FILE_BEGIN) == INVALID_SET_FILE_POINTER)
+ {
+ WLog_ERR(TAG, "Unable to truncate %s to %d (%d)", file->fullpath, size, GetLastError());
+ return FALSE;
+ }
+
+ DEBUG_WSTR("Truncate %s", file->fullpath);
- if (SetFilePointer(hFd, liSize.LowPart, &liSize.HighPart, FILE_BEGIN) == 0)
+ if (SetEndOfFile(file->file_handle) == 0)
{
- WLog_ERR(TAG, "Unable to truncate %s to %"PRId64"", file->fullpath, size);
- CloseHandle(hFd);
+ WLog_ERR(TAG, "Unable to truncate %s to %d (%d)", file->fullpath, size, GetLastError());
return FALSE;
}
- CloseHandle(hFd);
break;
case FileDispositionInformation:
/* http://msdn.microsoft.com/en-us/library/cc232098.aspx */
/* http://msdn.microsoft.com/en-us/library/cc241371.aspx */
- if (file->is_dir && !dir_empty(file->fullpath))
- break;
+ if (file->is_dir && !PathIsDirectoryEmptyW(file->fullpath))
+ break; // TODO: SetLastError ???
if (Length)
- Stream_Read_UINT8(input, file->delete_pending);
+ Stream_Read_UINT8(input, delete_pending);
else
- file->delete_pending = 1;
+ delete_pending = 1;
+
+ if (delete_pending)
+ {
+ DEBUG_WSTR("SetDeletePending %s", file->fullpath);
+ attr = GetFileAttributesW(file->fullpath);
+
+ if (attr & FILE_ATTRIBUTE_READONLY)
+ {
+ SetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ }
+ file->delete_pending = delete_pending;
break;
case FileRenameInformation:
/* http://msdn.microsoft.com/en-us/library/cc232085.aspx */
- Stream_Seek_UINT8(input); /* ReplaceIfExists */
+ Stream_Read_UINT8(input, ReplaceIfExists);
Stream_Seek_UINT8(input); /* RootDirectory */
Stream_Read_UINT32(input, FileNameLength);
- status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(input),
- FileNameLength / 2, &s, 0, NULL, NULL);
-
- if (status < 1)
- if (!(s = (char*) calloc(1, 1)))
- {
- WLog_ERR(TAG, "calloc failed!");
- return FALSE;
- }
-
- fullpath = drive_file_combine_fullpath(file->basepath, s);
+ fullpath = drive_file_combine_fullpath(file->basepath, (WCHAR*)Stream_Pointer(input),
+ FileNameLength);
if (!fullpath)
{
WLog_ERR(TAG, "drive_file_combine_fullpath failed!");
- free(s);
return FALSE;
}
- free(s);
#ifdef _WIN32
-
- if (file->fd)
- close(file->fd);
+ if (file->file_handle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(file->file_handle);
+ file->file_handle = INVALID_HANDLE_VALUE;
+ }
#endif
+ DEBUG_WSTR("MoveFileExW %s", file->fullpath);
- if (rename(file->fullpath, fullpath) == 0)
+ if (MoveFileExW(file->fullpath, fullpath,
+ MOVEFILE_COPY_ALLOWED | (ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0)))
{
drive_file_set_fullpath(file, fullpath);
#ifdef _WIN32
return FALSE;
}
+#ifdef _WIN32
+ drive_file_init(file);
+#endif
break;
default:
}
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
- const char* path, wStream* output)
+ const WCHAR* path, UINT32 PathLength, wStream* output)
{
int length;
BOOL ret;
WCHAR* ent_path;
- struct STAT st;
- struct dirent* ent;
if (!file || !path || !output)
return FALSE;
- if (!file->dir)
- {
- Stream_Write_UINT32(output, 0); /* Length */
- Stream_Write_UINT8(output, 0); /* Padding */
- return FALSE;
- }
-
if (InitialQuery != 0)
{
- rewinddir(file->dir);
- free(file->pattern);
+ /* release search handle */
+ if (file->find_handle != INVALID_HANDLE_VALUE)
+ FindClose(file->find_handle);
- if (path[0])
- {
- if (!(file->pattern = _strdup(strrchr(path, '\\') + 1)))
- {
- WLog_ERR(TAG, "_strdup failed!");
- return FALSE;
- }
- }
- else
- file->pattern = NULL;
- }
+ ent_path = drive_file_combine_fullpath(file->basepath, path, PathLength);
+ /* open new search handle and retrieve the first entry */
+ file->find_handle = FindFirstFileW(ent_path, &file->find_data);
+ free(ent_path);
- if (file->pattern)
- {
- do
- {
- ent = readdir(file->dir);
-
- if (ent == NULL)
- continue;
-
- if (FilePatternMatchA(ent->d_name, file->pattern))
- break;
- }
- while (ent);
- }
- else
- {
- ent = readdir(file->dir);
+ if (file->find_handle == INVALID_HANDLE_VALUE)
+ goto out_fail;
}
+ else if (!FindNextFileW(file->find_handle, &file->find_data))
+ goto out_fail;
- if (!ent)
- {
- Stream_Write_UINT32(output, 0); /* Length */
- Stream_Write_UINT8(output, 0); /* Padding */
- return FALSE;
- }
-
- memset(&st, 0, sizeof(struct STAT));
- ent_path = (WCHAR*) malloc(strlen(file->fullpath) + strlen(ent->d_name) + 2);
-
- if (!ent_path)
- {
- WLog_ERR(TAG, "malloc failed!");
- return FALSE;
- }
-
- sprintf((char*) ent_path, "%s/%s", file->fullpath, ent->d_name);
-
- if (STAT((char*) ent_path, &st) != 0)
- {
- }
-
- free(ent_path);
- ent_path = NULL;
- length = ConvertToUnicode(sys_code_page, 0, ent->d_name, -1, &ent_path, 0) * 2;
- ret = TRUE;
+ length = _wcslen(file->find_data.cFileName) * 2;
switch (FsInformationClass)
{
Stream_Write_UINT32(output, 64 + length); /* Length */
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
Stream_Write_UINT32(output, 0); /* FileIndex */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */
- Stream_Write_UINT64(output, st.st_size); /* EndOfFile */
- Stream_Write_UINT64(output, st.st_size); /* AllocationSize */
- Stream_Write_UINT32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
+ Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */
+ Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */
+ Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, length); /* FileNameLength */
- Stream_Write(output, ent_path, length);
+ Stream_Write(output, file->find_data.cFileName, length);
break;
case FileFullDirectoryInformation:
Stream_Write_UINT32(output, 68 + length); /* Length */
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
Stream_Write_UINT32(output, 0); /* FileIndex */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */
- Stream_Write_UINT64(output, st.st_size); /* EndOfFile */
- Stream_Write_UINT64(output, st.st_size); /* AllocationSize */
- Stream_Write_UINT32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
+ Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */
+ Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */
+ Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, length); /* FileNameLength */
Stream_Write_UINT32(output, 0); /* EaSize */
- Stream_Write(output, ent_path, length);
+ Stream_Write(output, file->find_data.cFileName, length);
break;
case FileBothDirectoryInformation:
Stream_Write_UINT32(output, 93 + length); /* Length */
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
Stream_Write_UINT32(output, 0); /* FileIndex */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* CreationTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_atime)); /* LastAccessTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_mtime)); /* LastWriteTime */
- Stream_Write_UINT64(output, FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* ChangeTime */
- Stream_Write_UINT64(output, st.st_size); /* EndOfFile */
- Stream_Write_UINT64(output, st.st_size); /* AllocationSize */
- Stream_Write_UINT32(output, FILE_ATTR_SYSTEM_TO_RDP(file, st)); /* FileAttributes */
+ Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */
+ Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */
+ Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */
+ Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */
+ Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, length); /* FileNameLength */
Stream_Write_UINT32(output, 0); /* EaSize */
Stream_Write_UINT8(output, 0); /* ShortNameLength */
/* Reserved(1), MUST NOT be added! */
Stream_Zero(output, 24); /* ShortName */
- Stream_Write(output, ent_path, length);
+ Stream_Write(output, file->find_data.cFileName, length);
break;
case FileNamesInformation:
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
Stream_Write_UINT32(output, 0); /* FileIndex */
Stream_Write_UINT32(output, length); /* FileNameLength */
- Stream_Write(output, ent_path, length);
+ Stream_Write(output, file->find_data.cFileName, length);
break;
default:
/* Unhandled FsInformationClass */
- Stream_Write_UINT32(output, 0); /* Length */
- Stream_Write_UINT8(output, 0); /* Padding */
- ret = FALSE;
- break;
+ goto out_fail;
}
- free(ent_path);
- return ret;
+ return TRUE;
out_fail:
- free(ent_path);
Stream_Write_UINT32(output, 0); /* Length */
Stream_Write_UINT8(output, 0); /* Padding */
return FALSE;
#include <sys/stat.h>
#include <freerdp/channels/log.h>
-#ifdef _WIN32
-#include <direct.h>
-#include <io.h>
-#include "dirent.h"
-#include "statvfs.h"
-#else
-#include <dirent.h>
-#ifdef ANDROID
-#include <sys/vfs.h>
-#else
-#include <sys/statvfs.h>
-#endif
-#endif
-
-#ifdef _WIN32
-#define STAT __stat64
-#define OPEN _open
-#define close _close
-#define read _read
-#define write _write
-#define LSEEK _lseeki64
-#define FSTAT _fstat64
-#define STATVFS statvfs
-#define mkdir(a,b) _mkdir(a)
-#define rmdir _rmdir
-#define unlink(a) _unlink(a)
-#define ftruncate(a,b) _chsize(a,b)
-
-typedef UINT32 ssize_t;
-typedef UINT32 mode_t;
-
-#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
-#define STAT stat
-#define OPEN open
-#define LSEEK lseek
-#define FSTAT fstat
-#define STATVFS statvfs
-#define O_LARGEFILE 0
-#elif defined(ANDROID)
-#define STAT stat
-#define OPEN open
-#define LSEEK lseek
-#define FSTAT fstat
-#define STATVFS statfs
-#else
-#define STAT stat64
-#define OPEN open64
-#define LSEEK lseek64
-#define FSTAT fstat64
-#define STATVFS statvfs64
-#endif
-
-#define EPOCH_DIFF 11644473600LL
-
-#define FILE_TIME_SYSTEM_TO_RDP(_t) \
- (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL)
-
-#define FILE_ATTR_SYSTEM_TO_RDP(_f, _st) ( \
- (S_ISDIR(_st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY : 0) | \
- (_f->filename[0] == '.' ? FILE_ATTRIBUTE_HIDDEN : 0) | \
- (_f->delete_pending ? FILE_ATTRIBUTE_TEMPORARY : 0) | \
- (st.st_mode & S_IWUSR ? 0 : FILE_ATTRIBUTE_READONLY))
-
#define TAG CHANNELS_TAG("drive.client")
typedef struct _DRIVE_FILE DRIVE_FILE;
{
UINT32 id;
BOOL is_dir;
- int fd;
- int err;
- DIR* dir;
- char* basepath;
- char* fullpath;
- char* filename;
- char* pattern;
+ HANDLE file_handle;
+ HANDLE find_handle;
+ WIN32_FIND_DATAW find_data;
+ WCHAR* basepath;
+ WCHAR* fullpath;
+ WCHAR* filename;
BOOL delete_pending;
+ UINT32 FileAttributes;
+ UINT32 SharedAccess;
+ UINT32 DesiredAccess;
+ UINT32 CreateDisposition;
+ UINT32 CreateOptions;
};
-DRIVE_FILE* drive_file_new(const char* base_path, const char* path, UINT32 id,
- UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions);
-void drive_file_free(DRIVE_FILE* file);
+DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id,
+ UINT32 DesiredAccess, UINT32 CreateDisposition,
+ UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess);
+BOOL drive_file_free(DRIVE_FILE* file);
+BOOL drive_file_open(DRIVE_FILE* file);
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset);
BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length);
BOOL drive_file_write(DRIVE_FILE* file, BYTE* buffer, UINT32 Length);
BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, wStream* output);
-BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input);
+BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length,
+ wStream* input);
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
- const char* path, wStream* output);
-int dir_empty(const char *path);
+ const WCHAR* path, UINT32 PathLength, wStream* output);
extern UINT sys_code_page;
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
+ * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <winpr/crt.h>
#include <winpr/path.h>
+#include <winpr/file.h>
#include <winpr/string.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/environment.h>
#include <winpr/interlocked.h>
#include <winpr/collections.h>
+#include <winpr/shell.h>
#include <freerdp/channels/rdpdr.h>
{
DEVICE device;
- char* path;
+ WCHAR* path;
+ UINT32 PathLength;
wListDictionary* files;
HANDLE thread;
rdpContext* rdpcontext;
};
-static UINT32 drive_map_posix_err(int fs_errno)
+static DWORD drive_map_windows_err(DWORD fs_errno)
{
- UINT32 rc;
+ DWORD rc;
/* try to return NTSTATUS version of error code */
switch (fs_errno)
{
- case EPERM:
- case EACCES:
+ case STATUS_SUCCESS:
+ rc = STATUS_SUCCESS;
+ break;
+
+ case ERROR_ACCESS_DENIED:
+ case ERROR_SHARING_VIOLATION:
rc = STATUS_ACCESS_DENIED;
break;
- case ENOENT:
+ case ERROR_FILE_NOT_FOUND:
rc = STATUS_NO_SUCH_FILE;
break;
- case EBUSY:
+ case ERROR_BUSY_DRIVE:
rc = STATUS_DEVICE_BUSY;
break;
- case EEXIST:
+ case ERROR_FILE_EXISTS:
+ case ERROR_ALREADY_EXISTS:
rc = STATUS_OBJECT_NAME_COLLISION;
break;
- case EISDIR:
- rc = STATUS_FILE_IS_A_DIRECTORY;
+ case ERROR_INVALID_NAME:
+ rc = STATUS_NO_SUCH_FILE;
+ break;
+
+ case ERROR_INVALID_HANDLE:
+ rc = STATUS_INVALID_HANDLE;
+ break;
+
+ case ERROR_NO_MORE_FILES:
+ rc = STATUS_NO_MORE_FILES;
+ break;
+
+ case ERROR_DIRECTORY:
+ rc = STATUS_NOT_A_DIRECTORY;
+ break;
+
+ case ERROR_PATH_NOT_FOUND:
+ rc = STATUS_OBJECT_PATH_NOT_FOUND;
break;
default:
rc = STATUS_UNSUCCESSFUL;
+ WLog_ERR(TAG, "Error code not found: %d", fs_errno);
break;
}
*/
static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp)
{
- int status;
void* key;
UINT32 FileId;
DRIVE_FILE* file;
BYTE Information;
+ UINT32 FileAttributes;
+ UINT32 SharedAccess;
UINT32 DesiredAccess;
UINT32 CreateDisposition;
UINT32 CreateOptions;
UINT32 PathLength;
- char* path = NULL;
+ const WCHAR* path;
Stream_Read_UINT32(irp->input, DesiredAccess);
- Stream_Seek(irp->input,
- 16); /* AllocationSize(8), FileAttributes(4), SharedAccess(4) */
+ Stream_Seek(irp->input, 8); /* AllocationSize(8) */
+ Stream_Read_UINT32(irp->input, FileAttributes);
+ Stream_Read_UINT32(irp->input, SharedAccess);
Stream_Read_UINT32(irp->input, CreateDisposition);
Stream_Read_UINT32(irp->input, CreateOptions);
Stream_Read_UINT32(irp->input, PathLength);
- status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
- PathLength / 2, &path, 0, NULL, NULL);
-
- if (status < 1)
- {
- path = (char*) calloc(1, 1);
-
- if (!path)
- {
- WLog_ERR(TAG, "calloc failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
- }
-
+ path = (WCHAR*) Stream_Pointer(irp->input);
FileId = irp->devman->id_sequence++;
- file = drive_file_new(drive->path, path, FileId,
- DesiredAccess, CreateDisposition, CreateOptions);
+ file = drive_file_new(drive->path, path, PathLength, FileId, DesiredAccess, CreateDisposition,
+ CreateOptions, FileAttributes, SharedAccess);
if (!file)
{
- irp->IoStatus = STATUS_UNSUCCESSFUL;
+ irp->IoStatus = drive_map_windows_err(GetLastError());
FileId = 0;
Information = 0;
}
- else if (file->err)
- {
- FileId = 0;
- Information = 0;
- /* map errno to windows result */
- irp->IoStatus = drive_map_posix_err(file->err);
- drive_file_free(file);
- }
else
{
key = (void*)(size_t) file->id;
if (!ListDictionary_Add(drive->files, key, file))
{
WLog_ERR(TAG, "ListDictionary_Add failed!");
- free(path);
return ERROR_INTERNAL_ERROR;
}
Stream_Write_UINT32(irp->output, FileId);
Stream_Write_UINT8(irp->output, Information);
- free(path);
return irp->Complete(irp);
}
else
{
ListDictionary_Remove(drive->files, key);
- drive_file_free(file);
+
+ if (drive_file_free(file))
+ irp->IoStatus = STATUS_SUCCESS;
+ else
+ irp->IoStatus = drive_map_windows_err(GetLastError());
}
Stream_Zero(irp->output, 5); /* Padding(5) */
}
else if (!drive_file_seek(file, Offset))
{
- irp->IoStatus = STATUS_UNSUCCESSFUL;
+ irp->IoStatus = drive_map_windows_err(GetLastError());
Length = 0;
}
else
if (!drive_file_read(file, buffer, &Length))
{
- irp->IoStatus = STATUS_UNSUCCESSFUL;
+ irp->IoStatus = drive_map_windows_err(GetLastError());
free(buffer);
buffer = NULL;
Length = 0;
}
else if (!drive_file_seek(file, Offset))
{
- irp->IoStatus = STATUS_UNSUCCESSFUL;
+ irp->IoStatus = drive_map_windows_err(GetLastError());
Length = 0;
}
else if (!drive_file_write(file, Stream_Pointer(irp->input), Length))
{
- irp->IoStatus = STATUS_UNSUCCESSFUL;
+ irp->IoStatus = drive_map_windows_err(GetLastError());
Length = 0;
}
}
else if (!drive_file_query_information(file, FsInformationClass, irp->output))
{
- irp->IoStatus = STATUS_UNSUCCESSFUL;
+ irp->IoStatus = drive_map_windows_err(GetLastError());
}
return irp->Complete(irp);
else if (!drive_file_set_information(file, FsInformationClass, Length,
irp->input))
{
- irp->IoStatus = STATUS_UNSUCCESSFUL;
+ irp->IoStatus = drive_map_windows_err(GetLastError());
}
- if (file && file->is_dir && !dir_empty(file->fullpath))
+ if (file && file->is_dir && !PathIsDirectoryEmptyW(file->fullpath))
irp->IoStatus = STATUS_DIRECTORY_NOT_EMPTY;
Stream_Write_UINT32(irp->output, Length);
return irp->Complete(irp);
}
+
/**
* Function description
*
{
UINT32 FsInformationClass;
wStream* output = irp->output;
- struct STATVFS svfst;
- struct STAT st;
char* volumeLabel = {"FREERDP"};
char* diskType = {"FAT32"};
WCHAR* outStr = NULL;
int length;
+ DWORD lpSectorsPerCluster;
+ DWORD lpBytesPerSector;
+ DWORD lpNumberOfFreeClusters;
+ DWORD lpTotalNumberOfClusters;
+ WIN32_FILE_ATTRIBUTE_DATA wfad;
Stream_Read_UINT32(irp->input, FsInformationClass);
- STATVFS(drive->path, &svfst);
- STAT(drive->path, &st);
+ GetDiskFreeSpaceW(drive->path, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters,
+ &lpTotalNumberOfClusters);
switch (FsInformationClass)
{
return CHANNEL_RC_NO_MEMORY;
}
- Stream_Write_UINT64(output,
- FILE_TIME_SYSTEM_TO_RDP(st.st_ctime)); /* VolumeCreationTime */
-#ifdef ANDROID
- Stream_Write_UINT32(output, svfst.f_fsid.__val[0]); /* VolumeSerialNumber */
-#else
- Stream_Write_UINT32(output, svfst.f_fsid); /* VolumeSerialNumber */
-#endif
+ GetFileAttributesExW(drive->path, GetFileExInfoStandard, &wfad);
+ Stream_Write_UINT32(output, wfad.ftCreationTime.dwLowDateTime); /* VolumeCreationTime */
+ Stream_Write_UINT32(output, wfad.ftCreationTime.dwHighDateTime); /* VolumeCreationTime */
+ Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff); /* VolumeSerialNumber */
Stream_Write_UINT32(output, length); /* VolumeLabelLength */
Stream_Write_UINT8(output, 0); /* SupportsObjects */
/* Reserved(1), MUST NOT be added! */
return CHANNEL_RC_NO_MEMORY;
}
- Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */
- Stream_Write_UINT64(output, svfst.f_bavail); /* AvailableAllocationUnits */
- Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */
- Stream_Write_UINT32(output, svfst.f_bsize); /* BytesPerSector */
+ Stream_Write_UINT64(output, lpTotalNumberOfClusters); /* TotalAllocationUnits */
+ Stream_Write_UINT64(output, lpNumberOfFreeClusters); /* AvailableAllocationUnits */
+ Stream_Write_UINT32(output, lpSectorsPerCluster); /* SectorsPerAllocationUnit */
+ Stream_Write_UINT32(output, lpBytesPerSector); /* BytesPerSector */
break;
case FileFsAttributeInformation:
FILE_CASE_SENSITIVE_SEARCH |
FILE_CASE_PRESERVED_NAMES |
FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
-#ifdef ANDROID
- Stream_Write_UINT32(output, 255); /* MaximumComponentNameLength */
-#else
- Stream_Write_UINT32(output,
- svfst.f_namemax/*510*/); /* MaximumComponentNameLength */
-#endif
+ Stream_Write_UINT32(output, MAX_PATH); /* MaximumComponentNameLength */
Stream_Write_UINT32(output, length); /* FileSystemNameLength */
Stream_Write(output, outStr, length); /* FileSystemName (Unicode) */
free(outStr);
return CHANNEL_RC_NO_MEMORY;
}
- Stream_Write_UINT64(output, svfst.f_blocks); /* TotalAllocationUnits */
- Stream_Write_UINT64(output,
- svfst.f_bavail); /* CallerAvailableAllocationUnits */
- Stream_Write_UINT64(output, svfst.f_bfree); /* AvailableAllocationUnits */
- Stream_Write_UINT32(output, 1); /* SectorsPerAllocationUnit */
- Stream_Write_UINT32(output, svfst.f_bsize); /* BytesPerSector */
+ Stream_Write_UINT64(output, lpTotalNumberOfClusters); /* TotalAllocationUnits */
+ Stream_Write_UINT64(output, lpNumberOfFreeClusters); /* CallerAvailableAllocationUnits */
+ Stream_Write_UINT64(output, lpNumberOfFreeClusters); /* AvailableAllocationUnits */
+ Stream_Write_UINT32(output, lpSectorsPerCluster); /* SectorsPerAllocationUnit */
+ Stream_Write_UINT32(output, lpBytesPerSector); /* BytesPerSector */
break;
case FileFsDeviceInformation:
*/
static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp)
{
- char* path = NULL;
- int status;
+ const WCHAR* path;
DRIVE_FILE* file;
BYTE InitialQuery;
UINT32 PathLength;
Stream_Read_UINT8(irp->input, InitialQuery);
Stream_Read_UINT32(irp->input, PathLength);
Stream_Seek(irp->input, 23); /* Padding */
- status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input),
- PathLength / 2, &path, 0, NULL, NULL);
-
- if (status < 1)
- if (!(path = (char*) calloc(1, 1)))
- {
- WLog_ERR(TAG, "calloc failed!");
- return CHANNEL_RC_NO_MEMORY;
- }
+ path = (WCHAR*) Stream_Pointer(irp->input);
file = drive_get_file_by_id(drive, irp->FileId);
if (file == NULL)
irp->IoStatus = STATUS_UNSUCCESSFUL;
Stream_Write_UINT32(irp->output, 0); /* Length */
}
- else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery,
- path, irp->output))
+ else if (!drive_file_query_directory(file, FsInformationClass, InitialQuery, path, PathLength,
+ irp->output))
{
- irp->IoStatus = STATUS_NO_MORE_FILES;
+ irp->IoStatus = drive_map_windows_err(GetLastError());
}
- free(path);
return irp->Complete(irp);
}
}
if (error && drive->rdpcontext)
- setChannelError(drive->rdpcontext, error,
- "drive_thread_func reported an error");
+ setChannelError(drive->rdpcontext, error, "drive_thread_func reported an error");
ExitThread((DWORD)error);
return NULL;
for (i = 0; i <= length; i++)
Stream_Write_UINT8(drive->device.data, name[i] < 0 ? '_' : name[i]);
- drive->path = path;
+ ConvertToUnicode(sys_code_page, 0, path, -1, &drive->path, 0);
drive->files = ListDictionary_New(TRUE);
if (!drive->files)
goto out_error;
}
- ListDictionary_ValueObject(drive->files)->fnObjectFree =
- (OBJECT_FREE_FN) drive_file_free;
+ ListDictionary_ValueObject(drive->files)->fnObjectFree = (OBJECT_FREE_FN) drive_file_free;
drive->IrpQueue = MessageQueue_New(NULL);
if (!drive->IrpQueue)
goto out_error;
}
- if (!(drive->thread = CreateThread(NULL, 0,
- (LPTHREAD_START_ROUTINE) drive_thread_func, drive, CREATE_SUSPENDED, NULL)))
+ if (!(drive->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_thread_func, drive,
+ CREATE_SUSPENDED, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
goto out_error;
+++ /dev/null
-/**
- * FreeRDP: A Remote Desktop Protocol Implementation
- * statvfs emulation for Windows
- *
- * Copyright 2012 Gerald Richter
- * Copyright 2016 Inuvika Inc.
- * Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
- *
- * 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.
- */
-
-#include <string.h>
-#include <malloc.h>
-
-#include <winpr/crt.h>
-#include <winpr/windows.h>
-
-#include "statvfs.h"
-
-int statvfs(const char *path, struct statvfs *buf)
-{
- BOOL res;
- int len;
- LPWSTR unicodestr = NULL;
- DWORD lpSectorsPerCluster;
- DWORD lpBytesPerSector;
- DWORD lpNumberOfFreeClusters;
- DWORD lpTotalNumberOfClusters;
-
- len = ConvertToUnicode(CP_ACP, 0, path, -1, &unicodestr, 0);
- if (len <= 0)
- return -1;
-
- res = GetDiskFreeSpaceW(unicodestr, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters, &lpTotalNumberOfClusters);
- free(unicodestr);
-
- buf->f_bsize = lpBytesPerSector; /* file system block size */
- buf->f_frsize = 0; /* fragment size */
- buf->f_blocks = lpTotalNumberOfClusters; /* size of fs in f_frsize units */
- buf->f_bfree = lpNumberOfFreeClusters; /* # free blocks */
- buf->f_bavail = lpNumberOfFreeClusters; /* # free blocks for unprivileged users */
- buf->f_files = 0; /* # inodes */
- buf->f_ffree = 0; /* # free inodes */
- buf->f_favail = 0; /* # free inodes for unprivileged users */
- buf->f_fsid = lpNumberOfFreeClusters & 0xffff; /* file system ID */
- buf->f_flag = 0; /* mount flags */
- buf->f_namemax = 250; /* maximum filename length */
-
- return res;
-}
+++ /dev/null
-/**
- * FreeRDP: A Remote Desktop Protocol Implementation
- * statvfs emulation for windows
- *
- * Copyright 2012 Gerald Richter
- *
- * 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 RDPDR_DISK_STATVFS_H
-#define RDPDR_DISK_STATVFS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef unsigned long long fsblkcnt_t;
-typedef unsigned long long fsfilcnt_t;
-
-struct statvfs {
- unsigned long f_bsize; /* file system block size */
- unsigned long f_frsize; /* fragment size */
- fsblkcnt_t f_blocks; /* size of fs in f_frsize units */
- fsblkcnt_t f_bfree; /* # free blocks */
- fsblkcnt_t f_bavail; /* # free blocks for unprivileged users */
- fsfilcnt_t f_files; /* # inodes */
- fsfilcnt_t f_ffree; /* # free inodes */
- fsfilcnt_t f_favail; /* # free inodes for unprivileged users */
- unsigned long f_fsid; /* file system ID */
- unsigned long f_flag; /* mount flags */
- unsigned long f_namemax; /* maximum filename length */
-};
-
-int statvfs(const char *path, struct statvfs *buf);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* RDPDR_DISK_STATVFS_H */
set (WITH_DEBUG_RDP OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RDPEI OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_REDIR OFF CACHE BOOL "enable debug")
+set (WITH_DEBUG_RDPDR OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RFX OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_SCARD OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_SND OFF CACHE BOOL "enable debug")
option(WITH_DEBUG_RDP "Print RDP debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_RDPEI "Print input virtual channel debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_REDIR "Redirection debug messages" ${DEFAULT_DEBUG_OPTION})
+option(WITH_DEBUG_RDPDR "Rdpdr debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_RFX "Print RemoteFX debug messages." ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_SCARD "Print smartcard debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_SND "Print rdpsnd debug messages" ${DEFAULT_DEBUG_OPTION})
#cmakedefine WITH_DEBUG_RAIL
#cmakedefine WITH_DEBUG_RDP
#cmakedefine WITH_DEBUG_REDIR
+#cmakedefine WITH_DEBUG_RDPDR
#cmakedefine WITH_DEBUG_RFX
#cmakedefine WITH_DEBUG_SCARD
#cmakedefine WITH_DEBUG_SND