2011-08-07 07:21:42 +04:00
|
|
|
/**
|
2012-10-09 05:00:07 +04:00
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2011-08-07 07:21:42 +04:00
|
|
|
* File System Virtual Channel
|
|
|
|
*
|
2012-10-09 05:00:07 +04:00
|
|
|
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
2011-08-07 07:21:42 +04:00
|
|
|
* Copyright 2010-2011 Vic Lee
|
2012-10-09 05:00:07 +04:00
|
|
|
* Copyright 2012 Gerald Richter
|
2015-06-03 16:33:59 +03:00
|
|
|
* Copyright 2015 Thincast Technologies GmbH
|
|
|
|
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
2016-01-07 22:04:10 +03:00
|
|
|
* Copyright 2016 Inuvika Inc.
|
|
|
|
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
|
2017-02-20 20:31:58 +03:00
|
|
|
* Copyright 2017 Armin Novak <armin.novak@thincast.com>
|
|
|
|
* Copyright 2017 Thincast Technologies GmbH
|
2011-08-07 07:21:42 +04:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2022-02-16 13:20:38 +03:00
|
|
|
#include <freerdp/config.h>
|
2012-08-15 01:09:01 +04:00
|
|
|
|
2011-10-19 17:43:04 +04:00
|
|
|
#include <errno.h>
|
2011-08-07 07:21:42 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <time.h>
|
2012-09-24 02:41:07 +04:00
|
|
|
|
2017-03-15 20:28:27 +03:00
|
|
|
#include <winpr/wtypes.h>
|
2012-10-07 18:21:54 +04:00
|
|
|
#include <winpr/crt.h>
|
2023-07-26 10:38:57 +03:00
|
|
|
#include <winpr/string.h>
|
2016-03-29 23:03:15 +03:00
|
|
|
#include <winpr/path.h>
|
2012-11-04 07:54:54 +04:00
|
|
|
#include <winpr/file.h>
|
2013-03-22 00:45:25 +04:00
|
|
|
#include <winpr/stream.h>
|
2013-10-17 23:56:56 +04:00
|
|
|
|
2012-10-09 05:00:07 +04:00
|
|
|
#include <freerdp/channels/rdpdr.h>
|
2011-08-07 07:21:42 +04:00
|
|
|
|
2012-11-03 03:59:07 +04:00
|
|
|
#include "drive_file.h"
|
2011-08-07 07:21:42 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
#ifdef WITH_DEBUG_RDPDR
|
2022-10-28 09:09:27 +03:00
|
|
|
#define DEBUG_WSTR(msg, wstr) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
char lpstr[1024] = { 0 }; \
|
|
|
|
ConvertWCharToUtf8(wstr, lpstr, ARRAYSIZE(lpstr)); \
|
|
|
|
WLog_DBG(TAG, msg, lpstr); \
|
2019-11-06 17:24:51 +03:00
|
|
|
} while (0)
|
2016-12-01 00:48:33 +03:00
|
|
|
#else
|
2019-11-06 17:24:51 +03:00
|
|
|
#define DEBUG_WSTR(msg, wstr) \
|
|
|
|
do \
|
|
|
|
{ \
|
|
|
|
} while (0)
|
2016-12-01 00:48:33 +03:00
|
|
|
#endif
|
|
|
|
|
2022-10-24 11:41:55 +03:00
|
|
|
static BOOL drive_file_fix_path(WCHAR* path, size_t length)
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2022-10-24 11:41:55 +03:00
|
|
|
if ((length == 0) || (length > UINT32_MAX))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
WINPR_ASSERT(path);
|
2012-10-07 01:49:56 +04:00
|
|
|
|
2024-01-30 12:25:38 +03:00
|
|
|
for (size_t i = 0; i < length; i++)
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2017-05-17 17:17:16 +03:00
|
|
|
if (path[i] == L'\\')
|
|
|
|
path[i] = L'/';
|
2011-08-07 07:21:42 +04:00
|
|
|
}
|
2012-10-07 01:49:56 +04:00
|
|
|
|
|
|
|
#ifdef WIN32
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2017-05-17 17:17:16 +03:00
|
|
|
if ((length == 3) && (path[1] == L':') && (path[2] == L'/'))
|
2022-10-24 11:41:55 +03:00
|
|
|
return FALSE;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2012-10-07 01:49:56 +04:00
|
|
|
#else
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2017-05-17 17:17:16 +03:00
|
|
|
if ((length == 1) && (path[0] == L'/'))
|
2022-10-24 11:41:55 +03:00
|
|
|
return FALSE;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2012-10-07 01:49:56 +04:00
|
|
|
#endif
|
|
|
|
|
2017-05-17 17:17:16 +03:00
|
|
|
if ((length > 0) && (path[length - 1] == L'/'))
|
|
|
|
path[length - 1] = L'\0';
|
2022-10-24 11:41:55 +03:00
|
|
|
|
|
|
|
return TRUE;
|
2011-08-07 20:37:31 +04:00
|
|
|
}
|
|
|
|
|
2024-07-01 10:48:23 +03:00
|
|
|
static BOOL contains_dotdot(const WCHAR* path, size_t base_length, size_t path_length)
|
|
|
|
{
|
|
|
|
WCHAR dotdotbuffer[6] = { 0 };
|
|
|
|
const WCHAR* dotdot = InitializeConstWCharFromUtf8("..", dotdotbuffer, ARRAYSIZE(dotdotbuffer));
|
|
|
|
const WCHAR* tst = path;
|
|
|
|
|
2024-08-21 10:20:25 +03:00
|
|
|
if (path_length < 2)
|
|
|
|
return FALSE;
|
|
|
|
|
2024-07-01 10:48:23 +03:00
|
|
|
do
|
|
|
|
{
|
|
|
|
tst = _wcsstr(tst, dotdot);
|
|
|
|
if (!tst)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Filter .. sequences in file or directory names */
|
|
|
|
if ((base_length == 0) || (*(tst - 1) == L'/') || (*(tst - 1) == L'\\'))
|
|
|
|
{
|
|
|
|
if (tst + 2 < path + path_length)
|
|
|
|
{
|
|
|
|
if ((tst[2] == '/') || (tst[2] == '\\'))
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tst += 2;
|
|
|
|
} while (TRUE);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path,
|
2022-10-24 11:41:55 +03:00
|
|
|
size_t PathWCharLength)
|
2011-08-07 20:37:31 +04:00
|
|
|
{
|
2022-10-24 11:41:55 +03:00
|
|
|
BOOL ok = FALSE;
|
|
|
|
WCHAR* fullpath = NULL;
|
2011-08-07 20:37:31 +04:00
|
|
|
|
2022-10-24 11:41:55 +03:00
|
|
|
if (!base_path || (!path && (PathWCharLength > 0)))
|
|
|
|
goto fail;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2022-10-24 11:41:55 +03:00
|
|
|
const size_t base_path_length = _wcsnlen(base_path, MAX_PATH);
|
2024-08-21 10:20:25 +03:00
|
|
|
const size_t length = base_path_length + PathWCharLength + 1;
|
2022-10-24 11:41:55 +03:00
|
|
|
fullpath = (WCHAR*)calloc(length, sizeof(WCHAR));
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2015-06-03 16:33:59 +03:00
|
|
|
if (!fullpath)
|
2022-10-24 11:41:55 +03:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
CopyMemory(fullpath, base_path, base_path_length * sizeof(WCHAR));
|
|
|
|
if (path)
|
|
|
|
CopyMemory(&fullpath[base_path_length], path, PathWCharLength * sizeof(WCHAR));
|
|
|
|
|
|
|
|
if (!drive_file_fix_path(fullpath, length))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Ensure the path does not contain sequences like '..' */
|
2024-07-01 10:48:23 +03:00
|
|
|
if (contains_dotdot(&fullpath[base_path_length], base_path_length, PathWCharLength))
|
2015-06-03 16:33:59 +03:00
|
|
|
{
|
2022-10-24 11:41:55 +03:00
|
|
|
char abuffer[MAX_PATH] = { 0 };
|
2022-10-28 09:09:27 +03:00
|
|
|
ConvertWCharToUtf8(&fullpath[base_path_length], abuffer, ARRAYSIZE(abuffer));
|
2022-10-24 11:41:55 +03:00
|
|
|
|
|
|
|
WLog_WARN(TAG, "[rdpdr] received invalid file path '%s' from server, aborting!",
|
|
|
|
&abuffer[base_path_length]);
|
|
|
|
goto fail;
|
2015-06-03 16:33:59 +03:00
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2022-10-24 11:41:55 +03:00
|
|
|
ok = TRUE;
|
|
|
|
fail:
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
free(fullpath);
|
|
|
|
fullpath = NULL;
|
|
|
|
}
|
2011-08-07 07:21:42 +04:00
|
|
|
return fullpath;
|
|
|
|
}
|
|
|
|
|
2017-07-17 13:31:13 +03:00
|
|
|
static BOOL drive_file_set_fullpath(DRIVE_FILE* file, WCHAR* fullpath)
|
2011-08-07 20:23:36 +04:00
|
|
|
{
|
2017-07-17 13:31:13 +03:00
|
|
|
if (!file || !fullpath)
|
|
|
|
return FALSE;
|
|
|
|
|
2023-07-26 10:38:57 +03:00
|
|
|
const size_t len = _wcslen(fullpath);
|
2012-10-09 07:21:26 +04:00
|
|
|
free(file->fullpath);
|
2023-07-26 10:38:57 +03:00
|
|
|
file->fullpath = NULL;
|
2023-07-26 11:45:05 +03:00
|
|
|
|
2023-07-26 10:38:57 +03:00
|
|
|
if (len == 0)
|
|
|
|
return TRUE;
|
|
|
|
|
2011-08-07 20:23:36 +04:00
|
|
|
file->fullpath = fullpath;
|
2012-10-02 18:57:39 +04:00
|
|
|
|
2023-07-26 10:38:57 +03:00
|
|
|
const WCHAR sep[] = { PathGetSeparatorW(PATH_STYLE_NATIVE), '\0' };
|
|
|
|
WCHAR* filename = _wcsrchr(file->fullpath, *sep);
|
2023-08-02 14:27:32 +03:00
|
|
|
if (filename && _wcsncmp(filename, sep, ARRAYSIZE(sep)) == 0)
|
2023-07-26 10:38:57 +03:00
|
|
|
*filename = '\0';
|
2017-07-17 13:31:13 +03:00
|
|
|
|
|
|
|
return TRUE;
|
2011-08-07 20:23:36 +04:00
|
|
|
}
|
|
|
|
|
2017-07-17 13:31:13 +03:00
|
|
|
static BOOL drive_file_init(DRIVE_FILE* file)
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
UINT CreateDisposition = 0;
|
|
|
|
DWORD dwAttr = GetFileAttributesW(file->fullpath);
|
2011-08-07 07:21:42 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (dwAttr != INVALID_FILE_ATTRIBUTES)
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
/* The file exists */
|
|
|
|
file->is_dir = (dwAttr & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->is_dir)
|
2014-09-02 17:42:44 +04:00
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->CreateDisposition == FILE_CREATE)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_ALREADY_EXISTS);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->CreateOptions & FILE_NON_DIRECTORY_FILE)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_ACCESS_DENIED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (file->CreateOptions & FILE_DIRECTORY_FILE)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_DIRECTORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2011-08-07 07:21:42 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
file->is_dir = ((file->CreateOptions & FILE_DIRECTORY_FILE) ? TRUE : FALSE);
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 07:21:42 +04:00
|
|
|
if (file->is_dir)
|
|
|
|
{
|
2012-11-04 07:54:54 +04:00
|
|
|
/* Should only create the directory if the disposition allows for it */
|
2019-11-06 17:24:51 +03:00
|
|
|
if ((file->CreateDisposition == FILE_OPEN_IF) ||
|
|
|
|
(file->CreateDisposition == FILE_CREATE))
|
2011-10-19 17:43:04 +04:00
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
if (CreateDirectoryW(file->fullpath, NULL) != 0)
|
2012-11-04 07:54:54 +04:00
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|
2011-10-19 17:43:04 +04:00
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
SetLastError(ERROR_FILE_NOT_FOUND);
|
|
|
|
return FALSE;
|
2011-10-19 17:43:04 +04:00
|
|
|
}
|
2011-08-07 07:21:42 +04:00
|
|
|
}
|
2016-12-01 00:48:33 +03:00
|
|
|
|
|
|
|
if (file->file_handle == INVALID_HANDLE_VALUE)
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
switch (file->CreateDisposition)
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
case FILE_SUPERSEDE: /* If the file already exists, replace it with the given file. If
|
|
|
|
it does not, create the given file. */
|
2016-12-01 00:48:33 +03:00
|
|
|
CreateDisposition = CREATE_ALWAYS;
|
2011-08-07 07:21:42 +04:00
|
|
|
break;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
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. */
|
2016-12-01 00:48:33 +03:00
|
|
|
CreateDisposition = OPEN_EXISTING;
|
2011-08-07 07:21:42 +04:00
|
|
|
break;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
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. */
|
2016-12-01 00:48:33 +03:00
|
|
|
CreateDisposition = CREATE_NEW;
|
2011-08-07 07:21:42 +04:00
|
|
|
break;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
case FILE_OPEN_IF: /* If the file already exists, open it. If it does not, create the
|
|
|
|
given file. */
|
2016-12-01 00:48:33 +03:00
|
|
|
CreateDisposition = OPEN_ALWAYS;
|
2011-08-07 07:21:42 +04:00
|
|
|
break;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
case FILE_OVERWRITE: /* If the file already exists, open it and overwrite it. If it does
|
|
|
|
not, fail the request. */
|
2016-12-01 00:48:33 +03:00
|
|
|
CreateDisposition = TRUNCATE_EXISTING;
|
2011-08-07 07:21:42 +04:00
|
|
|
break;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
case FILE_OVERWRITE_IF: /* If the file already exists, open it and overwrite it. If it
|
|
|
|
does not, create the given file. */
|
2016-12-01 00:48:33 +03:00
|
|
|
CreateDisposition = CREATE_ALWAYS;
|
2011-08-07 07:21:42 +04:00
|
|
|
break;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 07:21:42 +04:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2011-12-31 23:03:00 +04:00
|
|
|
|
2012-03-09 14:53:32 +04:00
|
|
|
#ifndef WIN32
|
2016-12-01 00:48:33 +03:00
|
|
|
file->SharedAccess = 0;
|
2012-03-09 14:53:32 +04:00
|
|
|
#endif
|
2019-11-06 17:24:51 +03:00
|
|
|
file->file_handle = CreateFileW(file->fullpath, file->DesiredAccess, file->SharedAccess,
|
|
|
|
NULL, CreateDisposition, file->FileAttributes, NULL);
|
2016-12-01 00:48:33 +03:00
|
|
|
}
|
2012-11-04 07:54:54 +04:00
|
|
|
|
2019-10-01 15:04:10 +03:00
|
|
|
#ifdef WIN32
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->file_handle == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
/* Get the error message, if any. */
|
|
|
|
DWORD errorMessageID = GetLastError();
|
|
|
|
|
|
|
|
if (errorMessageID != 0)
|
2011-10-19 17:43:04 +04:00
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
LPSTR messageBuffer = NULL;
|
2019-11-06 17:24:51 +03:00
|
|
|
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);
|
2016-12-01 00:48:33 +03:00
|
|
|
WLog_ERR(TAG, "Error in drive_file_init: %s %s", messageBuffer, file->fullpath);
|
|
|
|
/* Free the buffer. */
|
|
|
|
LocalFree(messageBuffer);
|
2019-10-01 15:04:10 +03:00
|
|
|
/* restore original error code */
|
|
|
|
SetLastError(errorMessageID);
|
2011-10-19 17:43:04 +04:00
|
|
|
}
|
2011-08-07 07:21:42 +04:00
|
|
|
}
|
2019-10-01 15:04:10 +03:00
|
|
|
#endif
|
2011-08-07 07:21:42 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
return file->file_handle != INVALID_HANDLE_VALUE;
|
2011-08-07 07:21:42 +04:00
|
|
|
}
|
|
|
|
|
2022-10-24 11:41:55 +03:00
|
|
|
DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathWCharLength,
|
|
|
|
UINT32 id, UINT32 DesiredAccess, UINT32 CreateDisposition,
|
|
|
|
UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess)
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
DRIVE_FILE* file = NULL;
|
2017-07-17 13:31:13 +03:00
|
|
|
|
2022-10-24 11:41:55 +03:00
|
|
|
if (!base_path || (!path && (PathWCharLength > 0)))
|
2017-07-17 13:31:13 +03:00
|
|
|
return NULL;
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
file = (DRIVE_FILE*)calloc(1, sizeof(DRIVE_FILE));
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2015-06-03 16:33:59 +03:00
|
|
|
if (!file)
|
|
|
|
{
|
|
|
|
WLog_ERR(TAG, "calloc failed!");
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-11-22 05:21:08 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
file->file_handle = INVALID_HANDLE_VALUE;
|
|
|
|
file->find_handle = INVALID_HANDLE_VALUE;
|
2011-08-07 07:21:42 +04:00
|
|
|
file->id = id;
|
2019-01-24 12:33:59 +03:00
|
|
|
file->basepath = base_path;
|
2016-12-01 00:48:33 +03:00
|
|
|
file->FileAttributes = FileAttributes;
|
|
|
|
file->DesiredAccess = DesiredAccess;
|
|
|
|
file->CreateDisposition = CreateDisposition;
|
|
|
|
file->CreateOptions = CreateOptions;
|
|
|
|
file->SharedAccess = SharedAccess;
|
2022-10-24 11:41:55 +03:00
|
|
|
drive_file_set_fullpath(file, drive_file_combine_fullpath(base_path, path, PathWCharLength));
|
2016-12-01 00:48:33 +03:00
|
|
|
|
|
|
|
if (!drive_file_init(file))
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2019-10-01 15:04:10 +03:00
|
|
|
DWORD lastError = GetLastError();
|
2012-11-03 03:59:07 +04:00
|
|
|
drive_file_free(file);
|
2019-10-01 15:04:10 +03:00
|
|
|
SetLastError(lastError);
|
2011-08-07 07:21:42 +04:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
BOOL drive_file_free(DRIVE_FILE* file)
|
2011-08-07 07:21:42 +04:00
|
|
|
{
|
2017-07-17 13:31:13 +03:00
|
|
|
BOOL rc = FALSE;
|
2018-08-13 14:23:52 +03:00
|
|
|
|
2017-02-20 20:31:58 +03:00
|
|
|
if (!file)
|
2017-03-14 20:48:10 +03:00
|
|
|
return FALSE;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->file_handle != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
CloseHandle(file->file_handle);
|
|
|
|
file->file_handle = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
2012-11-04 07:54:54 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->find_handle != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
FindClose(file->find_handle);
|
|
|
|
file->find_handle = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
2011-08-07 07:21:42 +04:00
|
|
|
|
|
|
|
if (file->delete_pending)
|
|
|
|
{
|
|
|
|
if (file->is_dir)
|
2016-12-01 00:48:33 +03:00
|
|
|
{
|
2023-07-25 16:25:00 +03:00
|
|
|
if (!winpr_RemoveDirectory_RecursiveW(file->fullpath))
|
2017-07-17 13:31:13 +03:00
|
|
|
goto fail;
|
2016-12-01 00:48:33 +03:00
|
|
|
}
|
2017-07-17 13:31:13 +03:00
|
|
|
else if (!DeleteFileW(file->fullpath))
|
|
|
|
goto fail;
|
2011-08-07 07:21:42 +04:00
|
|
|
}
|
|
|
|
|
2017-07-17 13:31:13 +03:00
|
|
|
rc = TRUE;
|
|
|
|
fail:
|
2016-12-01 00:48:33 +03:00
|
|
|
DEBUG_WSTR("Free %s", file->fullpath);
|
2012-10-09 07:21:26 +04:00
|
|
|
free(file->fullpath);
|
|
|
|
free(file);
|
2017-07-17 13:31:13 +03:00
|
|
|
return rc;
|
2011-08-07 07:21:42 +04:00
|
|
|
}
|
2011-08-07 09:11:52 +04:00
|
|
|
|
2012-11-03 03:59:07 +04:00
|
|
|
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset)
|
2011-08-07 09:11:52 +04:00
|
|
|
{
|
2017-08-08 11:52:11 +03:00
|
|
|
LARGE_INTEGER loffset;
|
2017-03-15 20:28:27 +03:00
|
|
|
|
2017-02-20 20:31:58 +03:00
|
|
|
if (!file)
|
|
|
|
return FALSE;
|
|
|
|
|
2019-01-24 12:33:59 +03:00
|
|
|
if (Offset > INT64_MAX)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
loffset.QuadPart = (LONGLONG)Offset;
|
2017-08-08 11:52:11 +03:00
|
|
|
return SetFilePointerEx(file->file_handle, loffset, NULL, FILE_BEGIN);
|
2011-08-07 09:11:52 +04:00
|
|
|
}
|
|
|
|
|
2012-11-03 03:59:07 +04:00
|
|
|
BOOL drive_file_read(DRIVE_FILE* file, BYTE* buffer, UINT32* Length)
|
2011-08-07 09:11:52 +04:00
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
DWORD read = 0;
|
2011-08-07 09:11:52 +04:00
|
|
|
|
2017-02-20 20:31:58 +03:00
|
|
|
if (!file || !buffer || !Length)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
DEBUG_WSTR("Read file %s", file->fullpath);
|
2012-11-04 07:54:54 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (ReadFile(file->file_handle, buffer, *Length, &read, NULL))
|
|
|
|
{
|
|
|
|
*Length = read;
|
|
|
|
return TRUE;
|
|
|
|
}
|
2012-11-04 07:54:54 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
return FALSE;
|
2011-08-07 09:11:52 +04:00
|
|
|
}
|
|
|
|
|
2023-06-07 16:38:21 +03:00
|
|
|
BOOL drive_file_write(DRIVE_FILE* file, const BYTE* buffer, UINT32 Length)
|
2011-08-07 09:11:52 +04:00
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
DWORD written = 0;
|
2011-08-07 09:11:52 +04:00
|
|
|
|
2017-02-20 20:31:58 +03:00
|
|
|
if (!file || !buffer)
|
|
|
|
return FALSE;
|
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
DEBUG_WSTR("Write file %s", file->fullpath);
|
2011-08-07 09:11:52 +04:00
|
|
|
|
|
|
|
while (Length > 0)
|
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
if (!WriteFile(file->file_handle, buffer, Length, &written, NULL))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2012-11-04 07:54:54 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
Length -= written;
|
|
|
|
buffer += written;
|
2011-08-07 09:11:52 +04:00
|
|
|
}
|
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
return TRUE;
|
2011-08-07 09:11:52 +04:00
|
|
|
}
|
2011-08-07 11:17:06 +04:00
|
|
|
|
2022-11-03 13:47:59 +03:00
|
|
|
static BOOL drive_file_query_from_handle_information(const DRIVE_FILE* file,
|
|
|
|
const BY_HANDLE_FILE_INFORMATION* info,
|
|
|
|
UINT32 FsInformationClass, wStream* output)
|
2011-08-07 11:17:06 +04:00
|
|
|
{
|
2022-11-03 13:47:59 +03:00
|
|
|
switch (FsInformationClass)
|
|
|
|
{
|
|
|
|
case FileBasicInformation:
|
2011-08-07 11:17:06 +04:00
|
|
|
|
2022-11-03 13:47:59 +03:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
|
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 36))
|
|
|
|
return FALSE;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2022-11-03 13:47:59 +03:00
|
|
|
Stream_Write_UINT32(output, 36); /* Length */
|
|
|
|
Stream_Write_UINT32(output, info->ftCreationTime.dwLowDateTime); /* CreationTime */
|
|
|
|
Stream_Write_UINT32(output, info->ftCreationTime.dwHighDateTime); /* CreationTime */
|
|
|
|
Stream_Write_UINT32(output, info->ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
|
|
|
|
Stream_Write_UINT32(output, info->ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
|
|
|
|
Stream_Write_UINT32(output, info->ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
|
|
|
|
Stream_Write_UINT32(output, info->ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
|
|
|
|
Stream_Write_UINT32(output, info->ftLastWriteTime.dwLowDateTime); /* ChangeTime */
|
|
|
|
Stream_Write_UINT32(output, info->ftLastWriteTime.dwHighDateTime); /* ChangeTime */
|
|
|
|
Stream_Write_UINT32(output, info->dwFileAttributes); /* FileAttributes */
|
|
|
|
/* Reserved(4), MUST NOT be added! */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FileStandardInformation:
|
|
|
|
|
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232088.aspx */
|
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 22))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
Stream_Write_UINT32(output, 22); /* Length */
|
|
|
|
Stream_Write_UINT32(output, info->nFileSizeLow); /* AllocationSize */
|
|
|
|
Stream_Write_UINT32(output, info->nFileSizeHigh); /* AllocationSize */
|
|
|
|
Stream_Write_UINT32(output, info->nFileSizeLow); /* EndOfFile */
|
|
|
|
Stream_Write_UINT32(output, info->nFileSizeHigh); /* EndOfFile */
|
|
|
|
Stream_Write_UINT32(output, info->nNumberOfLinks); /* NumberOfLinks */
|
|
|
|
Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); /* DeletePending */
|
|
|
|
Stream_Write_UINT8(output, info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
|
|
|
|
? TRUE
|
|
|
|
: FALSE); /* Directory */
|
|
|
|
/* Reserved(2), MUST NOT be added! */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FileAttributeTagInformation:
|
|
|
|
|
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232093.aspx */
|
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 8))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
Stream_Write_UINT32(output, 8); /* Length */
|
|
|
|
Stream_Write_UINT32(output, info->dwFileAttributes); /* FileAttributes */
|
|
|
|
Stream_Write_UINT32(output, 0); /* ReparseTag */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* Unhandled FsInformationClass */
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2016-12-01 00:48:33 +03:00
|
|
|
|
2022-11-03 13:47:59 +03:00
|
|
|
static BOOL drive_file_query_from_attributes(const DRIVE_FILE* file,
|
|
|
|
const WIN32_FILE_ATTRIBUTE_DATA* attrib,
|
|
|
|
UINT32 FsInformationClass, wStream* output)
|
|
|
|
{
|
2011-08-07 11:17:06 +04:00
|
|
|
switch (FsInformationClass)
|
|
|
|
{
|
|
|
|
case FileBasicInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 11:17:06 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 36))
|
2022-11-03 13:47:59 +03:00
|
|
|
return FALSE;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2022-11-03 13:47:59 +03:00
|
|
|
Stream_Write_UINT32(output, 36); /* Length */
|
|
|
|
Stream_Write_UINT32(output, attrib->ftCreationTime.dwLowDateTime); /* CreationTime */
|
|
|
|
Stream_Write_UINT32(output, attrib->ftCreationTime.dwHighDateTime); /* CreationTime */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output,
|
2022-11-03 13:47:59 +03:00
|
|
|
attrib->ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output,
|
2022-11-03 13:47:59 +03:00
|
|
|
attrib->ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
|
|
|
|
Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
|
|
|
|
Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
|
|
|
|
Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwLowDateTime); /* ChangeTime */
|
|
|
|
Stream_Write_UINT32(output, attrib->ftLastWriteTime.dwHighDateTime); /* ChangeTime */
|
|
|
|
Stream_Write_UINT32(output, attrib->dwFileAttributes); /* FileAttributes */
|
2011-08-07 15:24:29 +04:00
|
|
|
/* Reserved(4), MUST NOT be added! */
|
2011-08-07 11:17:06 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FileStandardInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 11:17:06 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232088.aspx */
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 22))
|
2022-11-03 13:47:59 +03:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
Stream_Write_UINT32(output, 22); /* Length */
|
|
|
|
Stream_Write_UINT32(output, attrib->nFileSizeLow); /* AllocationSize */
|
|
|
|
Stream_Write_UINT32(output, attrib->nFileSizeHigh); /* AllocationSize */
|
|
|
|
Stream_Write_UINT32(output, attrib->nFileSizeLow); /* EndOfFile */
|
|
|
|
Stream_Write_UINT32(output, attrib->nFileSizeHigh); /* EndOfFile */
|
|
|
|
Stream_Write_UINT32(output, 0); /* NumberOfLinks */
|
|
|
|
Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); /* DeletePending */
|
|
|
|
Stream_Write_UINT8(output, attrib->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
|
2019-11-06 17:24:51 +03:00
|
|
|
? TRUE
|
|
|
|
: FALSE); /* Directory */
|
2011-08-07 15:24:29 +04:00
|
|
|
/* Reserved(2), MUST NOT be added! */
|
2011-08-07 11:17:06 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FileAttributeTagInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 11:17:06 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232093.aspx */
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 8))
|
2022-11-03 13:47:59 +03:00
|
|
|
return FALSE;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2022-11-03 13:47:59 +03:00
|
|
|
Stream_Write_UINT32(output, 8); /* Length */
|
|
|
|
Stream_Write_UINT32(output, attrib->dwFileAttributes); /* FileAttributes */
|
|
|
|
Stream_Write_UINT32(output, 0); /* ReparseTag */
|
2011-08-07 11:17:06 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2015-03-26 19:09:47 +03:00
|
|
|
/* Unhandled FsInformationClass */
|
2022-11-03 13:47:59 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, wStream* output)
|
|
|
|
{
|
|
|
|
BY_HANDLE_FILE_INFORMATION fileInformation = { 0 };
|
2024-01-23 18:49:54 +03:00
|
|
|
BOOL status = 0;
|
|
|
|
HANDLE hFile = NULL;
|
2022-11-03 13:47:59 +03:00
|
|
|
|
|
|
|
if (!file || !output)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
hFile = CreateFileW(file->fullpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING,
|
|
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (hFile != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
status = GetFileInformationByHandle(hFile, &fileInformation);
|
|
|
|
CloseHandle(hFile);
|
|
|
|
if (!status)
|
|
|
|
goto out_fail;
|
|
|
|
|
|
|
|
if (!drive_file_query_from_handle_information(file, &fileInformation, FsInformationClass,
|
|
|
|
output))
|
2016-12-01 00:48:33 +03:00
|
|
|
goto out_fail;
|
2022-11-03 13:47:59 +03:00
|
|
|
|
|
|
|
return TRUE;
|
2011-08-07 11:17:06 +04:00
|
|
|
}
|
2015-03-26 19:09:47 +03:00
|
|
|
|
2022-11-03 13:47:59 +03:00
|
|
|
/* If we failed before (i.e. if information for a drive is queried) fall back to
|
|
|
|
* GetFileAttributesExW */
|
|
|
|
WIN32_FILE_ATTRIBUTE_DATA fileAttributes = { 0 };
|
|
|
|
if (!GetFileAttributesExW(file->fullpath, GetFileExInfoStandard, &fileAttributes))
|
|
|
|
goto out_fail;
|
|
|
|
|
|
|
|
if (!drive_file_query_from_attributes(file, &fileAttributes, FsInformationClass, output))
|
|
|
|
goto out_fail;
|
|
|
|
|
2017-02-20 20:31:58 +03:00
|
|
|
return TRUE;
|
2015-03-26 19:09:47 +03:00
|
|
|
out_fail:
|
|
|
|
Stream_Write_UINT32(output, 0); /* Length */
|
|
|
|
return FALSE;
|
2011-08-07 11:17:06 +04:00
|
|
|
}
|
2011-08-07 15:24:29 +04:00
|
|
|
|
2017-02-20 20:31:58 +03:00
|
|
|
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length,
|
|
|
|
wStream* input)
|
2011-08-07 20:23:36 +04:00
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
INT64 size = 0;
|
|
|
|
WCHAR* fullpath = NULL;
|
2016-02-26 21:19:21 +03:00
|
|
|
ULARGE_INTEGER liCreationTime;
|
|
|
|
ULARGE_INTEGER liLastAccessTime;
|
|
|
|
ULARGE_INTEGER liLastWriteTime;
|
|
|
|
ULARGE_INTEGER liChangeTime;
|
|
|
|
FILETIME ftCreationTime;
|
|
|
|
FILETIME ftLastAccessTime;
|
|
|
|
FILETIME ftLastWriteTime;
|
|
|
|
FILETIME* pftCreationTime = NULL;
|
|
|
|
FILETIME* pftLastAccessTime = NULL;
|
|
|
|
FILETIME* pftLastWriteTime = NULL;
|
2024-01-23 18:49:54 +03:00
|
|
|
UINT32 FileAttributes = 0;
|
|
|
|
UINT32 FileNameLength = 0;
|
2016-01-07 22:04:10 +03:00
|
|
|
LARGE_INTEGER liSize;
|
2024-01-23 18:49:54 +03:00
|
|
|
UINT8 delete_pending = 0;
|
|
|
|
UINT8 ReplaceIfExists = 0;
|
|
|
|
DWORD attr = 0;
|
2011-08-07 20:23:36 +04:00
|
|
|
|
2017-02-20 20:31:58 +03:00
|
|
|
if (!file || !input)
|
|
|
|
return FALSE;
|
2012-10-16 21:31:16 +04:00
|
|
|
|
2011-08-07 20:23:36 +04:00
|
|
|
switch (FsInformationClass)
|
|
|
|
{
|
|
|
|
case FileBasicInformation:
|
2022-04-19 15:29:17 +03:00
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, input, 36))
|
2017-10-02 22:28:02 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2011-08-07 20:23:36 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
|
2016-02-26 21:19:21 +03:00
|
|
|
Stream_Read_UINT64(input, liCreationTime.QuadPart);
|
|
|
|
Stream_Read_UINT64(input, liLastAccessTime.QuadPart);
|
|
|
|
Stream_Read_UINT64(input, liLastWriteTime.QuadPart);
|
|
|
|
Stream_Read_UINT64(input, liChangeTime.QuadPart);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(input, FileAttributes);
|
2011-08-07 20:23:36 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (!PathFileExistsW(file->fullpath))
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->file_handle == INVALID_HANDLE_VALUE)
|
2011-08-07 20:23:36 +04:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "Unable to set file time %s (%" PRId32 ")", file->fullpath,
|
|
|
|
GetLastError());
|
2016-02-26 21:19:21 +03:00
|
|
|
return FALSE;
|
2011-08-07 20:23:36 +04:00
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-02-26 21:19:21 +03:00
|
|
|
if (liCreationTime.QuadPart != 0)
|
|
|
|
{
|
2019-11-25 15:05:09 +03:00
|
|
|
ftCreationTime.dwHighDateTime = liCreationTime.u.HighPart;
|
|
|
|
ftCreationTime.dwLowDateTime = liCreationTime.u.LowPart;
|
2016-02-26 21:19:21 +03:00
|
|
|
pftCreationTime = &ftCreationTime;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-02-26 21:19:21 +03:00
|
|
|
if (liLastAccessTime.QuadPart != 0)
|
|
|
|
{
|
2019-11-25 15:05:09 +03:00
|
|
|
ftLastAccessTime.dwHighDateTime = liLastAccessTime.u.HighPart;
|
|
|
|
ftLastAccessTime.dwLowDateTime = liLastAccessTime.u.LowPart;
|
2016-02-26 21:19:21 +03:00
|
|
|
pftLastAccessTime = &ftLastAccessTime;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-02-26 21:19:21 +03:00
|
|
|
if (liLastWriteTime.QuadPart != 0)
|
|
|
|
{
|
2019-11-25 15:05:09 +03:00
|
|
|
ftLastWriteTime.dwHighDateTime = liLastWriteTime.u.HighPart;
|
|
|
|
ftLastWriteTime.dwLowDateTime = liLastWriteTime.u.LowPart;
|
2016-02-26 21:19:21 +03:00
|
|
|
pftLastWriteTime = &ftLastWriteTime;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-02-26 21:19:21 +03:00
|
|
|
if (liChangeTime.QuadPart != 0 && liChangeTime.QuadPart > liLastWriteTime.QuadPart)
|
|
|
|
{
|
2019-11-25 15:05:09 +03:00
|
|
|
ftLastWriteTime.dwHighDateTime = liChangeTime.u.HighPart;
|
|
|
|
ftLastWriteTime.dwLowDateTime = liChangeTime.u.LowPart;
|
2016-02-26 21:19:21 +03:00
|
|
|
pftLastWriteTime = &ftLastWriteTime;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
DEBUG_WSTR("SetFileTime %s", file->fullpath);
|
|
|
|
|
2019-03-29 17:45:38 +03:00
|
|
|
SetFileAttributesW(file->fullpath, FileAttributes);
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!SetFileTime(file->file_handle, pftCreationTime, pftLastAccessTime,
|
|
|
|
pftLastWriteTime))
|
2016-02-26 21:19:21 +03:00
|
|
|
{
|
2017-03-18 00:05:21 +03:00
|
|
|
WLog_ERR(TAG, "Unable to set file time to %s", file->fullpath);
|
2016-02-26 21:19:21 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2014-02-12 07:34:33 +04:00
|
|
|
break;
|
2011-08-07 20:23:36 +04:00
|
|
|
|
|
|
|
case FileEndOfFileInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
|
2011-08-07 20:23:36 +04:00
|
|
|
case FileAllocationInformation:
|
2022-04-19 15:29:17 +03:00
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, input, 8))
|
2017-10-02 22:28:02 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2011-08-07 20:23:36 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
|
2016-01-07 22:04:10 +03:00
|
|
|
Stream_Read_INT64(input, size);
|
2016-02-26 21:19:21 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->file_handle == INVALID_HANDLE_VALUE)
|
2016-01-07 22:04:10 +03:00
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "Unable to truncate %s to %" PRId64 " (%" PRId32 ")", file->fullpath,
|
|
|
|
size, GetLastError());
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2016-01-07 22:04:10 +03:00
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-01-14 16:54:33 +03:00
|
|
|
liSize.QuadPart = size;
|
|
|
|
|
2017-08-08 11:52:11 +03:00
|
|
|
if (!SetFilePointerEx(file->file_handle, liSize, NULL, FILE_BEGIN))
|
2016-12-01 00:48:33 +03:00
|
|
|
{
|
2022-09-29 15:55:27 +03:00
|
|
|
WLog_ERR(TAG, "Unable to truncate %s to %" PRId64 " (%" PRId32 ")", file->fullpath,
|
|
|
|
size, GetLastError());
|
2016-12-01 00:48:33 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG_WSTR("Truncate %s", file->fullpath);
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (SetEndOfFile(file->file_handle) == 0)
|
2016-02-26 21:19:21 +03:00
|
|
|
{
|
2022-09-29 15:55:27 +03:00
|
|
|
WLog_ERR(TAG, "Unable to truncate %s to %" PRId64 " (%" PRId32 ")", file->fullpath,
|
|
|
|
size, GetLastError());
|
2016-02-26 21:19:21 +03:00
|
|
|
return FALSE;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 20:23:36 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FileDispositionInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 20:23:36 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232098.aspx */
|
2011-12-31 23:03:00 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc241371.aspx */
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->is_dir && !PathIsDirectoryEmptyW(file->fullpath))
|
2017-03-27 21:11:54 +03:00
|
|
|
break; /* TODO: SetLastError ??? */
|
2014-08-18 12:00:34 +04:00
|
|
|
|
2011-12-31 23:03:00 +04:00
|
|
|
if (Length)
|
2017-10-02 22:28:02 +03:00
|
|
|
{
|
2022-04-19 15:29:17 +03:00
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, input, 1))
|
2017-10-02 22:28:02 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Read_UINT8(input, delete_pending);
|
2017-10-02 22:28:02 +03:00
|
|
|
}
|
2011-12-31 23:03:00 +04:00
|
|
|
else
|
2016-12-01 00:48:33 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
file->delete_pending = delete_pending;
|
2011-08-07 20:23:36 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FileRenameInformation:
|
2022-04-19 15:29:17 +03:00
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, input, 6))
|
2017-10-02 22:28:02 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2011-08-07 20:23:36 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232085.aspx */
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Read_UINT8(input, ReplaceIfExists);
|
2013-05-09 00:27:21 +04:00
|
|
|
Stream_Seek_UINT8(input); /* RootDirectory */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Read_UINT32(input, FileNameLength);
|
2017-10-02 22:28:02 +03:00
|
|
|
|
2022-04-19 15:29:17 +03:00
|
|
|
if (!Stream_CheckAndLogRequiredLength(TAG, input, FileNameLength))
|
2017-10-02 22:28:02 +03:00
|
|
|
return FALSE;
|
|
|
|
|
2023-06-07 16:38:21 +03:00
|
|
|
fullpath = drive_file_combine_fullpath(file->basepath, Stream_ConstPointer(input),
|
2022-10-24 11:41:55 +03:00
|
|
|
FileNameLength / sizeof(WCHAR));
|
2018-08-13 14:23:52 +03:00
|
|
|
|
2015-06-03 16:33:59 +03:00
|
|
|
if (!fullpath)
|
|
|
|
return FALSE;
|
2011-08-07 20:23:36 +04:00
|
|
|
|
2014-02-12 14:13:42 +04:00
|
|
|
#ifdef _WIN32
|
2017-03-15 20:28:27 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->file_handle != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
CloseHandle(file->file_handle);
|
|
|
|
file->file_handle = INVALID_HANDLE_VALUE;
|
|
|
|
}
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2014-02-12 14:13:42 +04:00
|
|
|
#endif
|
2016-12-01 00:48:33 +03:00
|
|
|
DEBUG_WSTR("MoveFileExW %s", file->fullpath);
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (MoveFileExW(file->fullpath, fullpath,
|
2019-11-06 17:24:51 +03:00
|
|
|
MOVEFILE_COPY_ALLOWED |
|
|
|
|
(ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0)))
|
2011-08-07 20:23:36 +04:00
|
|
|
{
|
2017-07-17 13:31:13 +03:00
|
|
|
if (!drive_file_set_fullpath(file, fullpath))
|
|
|
|
return FALSE;
|
2011-08-07 20:23:36 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
free(fullpath);
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2011-08-07 20:23:36 +04:00
|
|
|
}
|
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
#ifdef _WIN32
|
|
|
|
drive_file_init(file);
|
|
|
|
#endif
|
2011-08-07 20:23:36 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-10-09 10:31:28 +04:00
|
|
|
return FALSE;
|
2011-08-07 20:23:36 +04:00
|
|
|
}
|
2011-11-25 20:24:47 +04:00
|
|
|
|
2012-10-09 10:31:28 +04:00
|
|
|
return TRUE;
|
2011-08-07 20:23:36 +04:00
|
|
|
}
|
|
|
|
|
2012-11-03 03:59:07 +04:00
|
|
|
BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYTE InitialQuery,
|
2022-10-24 11:41:55 +03:00
|
|
|
const WCHAR* path, UINT32 PathWCharLength, wStream* output)
|
2011-08-07 15:24:29 +04:00
|
|
|
{
|
2024-01-23 18:49:54 +03:00
|
|
|
size_t length = 0;
|
|
|
|
WCHAR* ent_path = NULL;
|
2011-08-07 15:24:29 +04:00
|
|
|
|
2017-02-20 20:31:58 +03:00
|
|
|
if (!file || !path || !output)
|
|
|
|
return FALSE;
|
|
|
|
|
2011-08-07 15:24:29 +04:00
|
|
|
if (InitialQuery != 0)
|
|
|
|
{
|
2016-12-01 00:48:33 +03:00
|
|
|
/* release search handle */
|
|
|
|
if (file->find_handle != INVALID_HANDLE_VALUE)
|
|
|
|
FindClose(file->find_handle);
|
2011-12-06 07:04:27 +04:00
|
|
|
|
2022-10-24 11:41:55 +03:00
|
|
|
ent_path = drive_file_combine_fullpath(file->basepath, path, PathWCharLength);
|
2016-12-01 00:48:33 +03:00
|
|
|
/* open new search handle and retrieve the first entry */
|
|
|
|
file->find_handle = FindFirstFileW(ent_path, &file->find_data);
|
|
|
|
free(ent_path);
|
2011-12-06 07:04:27 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
if (file->find_handle == INVALID_HANDLE_VALUE)
|
|
|
|
goto out_fail;
|
2011-08-07 15:24:29 +04:00
|
|
|
}
|
2016-12-01 00:48:33 +03:00
|
|
|
else if (!FindNextFileW(file->find_handle, &file->find_data))
|
|
|
|
goto out_fail;
|
2011-08-07 15:24:29 +04:00
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
length = _wcslen(file->find_data.cFileName) * 2;
|
2012-09-24 03:49:13 +04:00
|
|
|
|
2011-08-07 15:24:29 +04:00
|
|
|
switch (FsInformationClass)
|
|
|
|
{
|
|
|
|
case FileDirectoryInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 15:24:29 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232097.aspx */
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 64 + length))
|
2015-03-26 19:09:47 +03:00
|
|
|
goto out_fail;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-01-24 12:33:59 +03:00
|
|
|
if (length > UINT32_MAX - 64)
|
|
|
|
goto out_fail;
|
|
|
|
|
|
|
|
Stream_Write_UINT32(output, (UINT32)(64 + length)); /* Length */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
|
|
|
|
Stream_Write_UINT32(output, 0); /* FileIndex */
|
|
|
|
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 */
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Write(output, file->find_data.cFileName, length);
|
2011-08-07 15:24:29 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FileFullDirectoryInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 15:24:29 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232068.aspx */
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 68 + length))
|
2015-03-26 19:09:47 +03:00
|
|
|
goto out_fail;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-01-24 12:33:59 +03:00
|
|
|
if (length > UINT32_MAX - 68)
|
|
|
|
goto out_fail;
|
|
|
|
|
|
|
|
Stream_Write_UINT32(output, (UINT32)(68 + length)); /* Length */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
|
|
|
|
Stream_Write_UINT32(output, 0); /* FileIndex */
|
|
|
|
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 */
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
|
|
|
|
Stream_Write_UINT32(output, 0); /* EaSize */
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Write(output, file->find_data.cFileName, length);
|
2011-08-07 15:24:29 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FileBothDirectoryInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 15:24:29 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232095.aspx */
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 93 + length))
|
2015-03-26 19:09:47 +03:00
|
|
|
goto out_fail;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-01-24 12:33:59 +03:00
|
|
|
if (length > UINT32_MAX - 93)
|
|
|
|
goto out_fail;
|
|
|
|
|
|
|
|
Stream_Write_UINT32(output, (UINT32)(93 + length)); /* Length */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
|
|
|
|
Stream_Write_UINT32(output, 0); /* FileIndex */
|
|
|
|
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 */
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
|
|
|
|
Stream_Write_UINT32(output, 0); /* EaSize */
|
|
|
|
Stream_Write_UINT8(output, 0); /* ShortNameLength */
|
2011-08-07 15:24:29 +04:00
|
|
|
/* Reserved(1), MUST NOT be added! */
|
2013-05-09 00:27:21 +04:00
|
|
|
Stream_Zero(output, 24); /* ShortName */
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Write(output, file->find_data.cFileName, length);
|
2011-08-07 15:24:29 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FileNamesInformation:
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2011-08-07 15:24:29 +04:00
|
|
|
/* http://msdn.microsoft.com/en-us/library/cc232077.aspx */
|
2015-03-30 18:15:45 +03:00
|
|
|
if (!Stream_EnsureRemainingCapacity(output, 4 + 12 + length))
|
2015-03-26 19:09:47 +03:00
|
|
|
goto out_fail;
|
2017-02-20 20:31:58 +03:00
|
|
|
|
2019-01-24 12:33:59 +03:00
|
|
|
if (length > UINT32_MAX - 12)
|
|
|
|
goto out_fail;
|
|
|
|
|
|
|
|
Stream_Write_UINT32(output, (UINT32)(12 + length)); /* Length */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
|
|
|
|
Stream_Write_UINT32(output, 0); /* FileIndex */
|
|
|
|
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
|
2016-12-01 00:48:33 +03:00
|
|
|
Stream_Write(output, file->find_data.cFileName, length);
|
2011-08-07 15:24:29 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_ERR(TAG, "unhandled FsInformationClass %" PRIu32, FsInformationClass);
|
2015-03-26 19:09:47 +03:00
|
|
|
/* Unhandled FsInformationClass */
|
2016-12-01 00:48:33 +03:00
|
|
|
goto out_fail;
|
2011-08-07 15:24:29 +04:00
|
|
|
}
|
|
|
|
|
2016-12-01 00:48:33 +03:00
|
|
|
return TRUE;
|
2015-03-26 19:09:47 +03:00
|
|
|
out_fail:
|
|
|
|
Stream_Write_UINT32(output, 0); /* Length */
|
2019-11-06 17:24:51 +03:00
|
|
|
Stream_Write_UINT8(output, 0); /* Padding */
|
2015-03-26 19:09:47 +03:00
|
|
|
return FALSE;
|
2011-08-07 15:24:29 +04:00
|
|
|
}
|