mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
09ab9de32c | |||
75620332c7 | |||
47aa53c70a | |||
c343253718 | |||
6764269a49 | |||
41d69d7186 | |||
f6e6660362 | |||
61027daf6e | |||
9ae9b8ff2c | |||
74bb51ae07 | |||
332ba48203 | |||
0d7f13abeb | |||
e88a7742df | |||
c7b3312cf6 | |||
c0fa5696d7 | |||
43af829d46 | |||
9c1a7fb40b | |||
dd907a44ad | |||
df4c19c113 | |||
deaf475861 | |||
bda0477a79 |
38
Changelog.md
38
Changelog.md
@ -1,6 +1,44 @@
|
||||
# Changelog
|
||||
|
||||
|
||||
## v1.11B3 (2022+ARM64 Beta3)
|
||||
|
||||
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||
|
||||
- [NEW] A new file system operation has been added to the FUSE API:
|
||||
|
||||
```C
|
||||
int (*getpath)(const char *path, char *buf, size_t size,
|
||||
struct fuse_file_info *fi);
|
||||
```
|
||||
|
||||
The `getpath` operation allows a case-insensitive file system to report the correct case of a file path. For example, `getpath` can be used to report that the actual path of a file opened as `/PATH/TO/FILE` is really `/Path/To/File`. This capability is important for some Windows file system scenarios and can sometimes result in a performance improvement.
|
||||
|
||||
- [NEW] New `ntptfs` sample file system. This is a production quality pass through file system and should be used instead of the original `passthrough` file system that was developed for education purposes only.
|
||||
|
||||
- [NEW] Many performance improvements:
|
||||
|
||||
- A new `PostDispositionForDirOnly` setting has been added to `FSP_FSCTL_VOLUME_PARAMS`. This allows a file system to declare that it does not want to see `SetInformation/Disposition` requests for files (such requests will still be sent for directories, because a file system is supposed to check if a directory is empty before deletion). This makes file (not directory) deletion faster. This optimization should be safe to enable for most file systems. FUSE file systems get this optimization for free.
|
||||
|
||||
- The FSD now implements "fast I/O" reads and writes. Fast I/O is a technique for doing I/O without using IRP's (I/O Request Packets) and can only work for file systems using the cache manager (`FileInfoTimeout==-1`). This results in significant improvement in read/write scenarios.
|
||||
|
||||
- The FSD now implements "fast I/O" for "transact" messages. Transact messages are used in the communication protocol between the kernel-mode FSD and the user-mode file system. Fast I/O speeds this communication protocol by as much as 10% in some scenarios. (Fast I/O for transact messages is enabled only when using the new `FSP_IOCTL_TRANSACT` control code, but does not require any other special configuration to be enabled.)
|
||||
|
||||
- The FSD per directory cache limit has been increased from 16K to 64K. This should allow for more directory data to be maintained in kernel and reduce round-trips to the user mode file system.
|
||||
|
||||
- The user mode directory buffering mechanism (`FspFileSystemAcquireDirectoryBuffer`) has been improved. The mechanism uses the quick-sort algorithm internally which can exhibit bad performance when sorting already sorted data. The quick-sort algorithm has been improved with the use use of median of three partitioning, which alleviates this problem.
|
||||
|
||||
- [FIX] The WinFsp Network Provider now implements `NPGetUniversalName`. This fixes problems with some apps (e.g. Photos app).
|
||||
|
||||
- [FIX] WinFsp-FUSE now supports Azure AD accounts when specifying the `-o uid=-1` option. In addition a new option `-o uidmap=UID:SID` allows the specification of arbitrary UID<->SID or UID<->UserName mappings.
|
||||
|
||||
- [FIX] All executables (`*.exe,*.dll,*.sys`) in the WinFsp installation `bin` folder are now signed.
|
||||
|
||||
- [FIX] The default value for the registry setting `DistinctPermsForSameOwnerGroup` has been changed from 0 to 1.
|
||||
|
||||
- [BUILD] Product configuration (`MyProductName`, etc.) is done by the file `build.version.props` located in `build\VStudio`. This file was previously named `version.properties`.
|
||||
|
||||
|
||||
## v1.11B2 (2022+ARM64 Beta2)
|
||||
|
||||
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
<MyCanonicalVersion>1.11</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2022+ARM64 Beta2</MyProductVersion>
|
||||
<MyProductVersion>2022+ARM64 Beta3</MyProductVersion>
|
||||
<MyProductStage>Beta</MyProductStage>
|
||||
|
||||
<MyCrossCert>DigiCert High Assurance EV Root CA.crt</MyCrossCert>
|
||||
|
@ -48,6 +48,7 @@
|
||||
<ClInclude Include="..\..\src\shared\um\minimal.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\dll\debug.c" />
|
||||
<ClCompile Include="..\..\src\dll\dirbuf.c" />
|
||||
<ClCompile Include="..\..\src\dll\eventlog.c" />
|
||||
<ClCompile Include="..\..\src\dll\fuse3\fuse2to3.c" />
|
||||
@ -64,7 +65,7 @@
|
||||
<ClCompile Include="..\..\src\dll\mount.c" />
|
||||
<ClCompile Include="..\..\src\dll\np.c" />
|
||||
<ClCompile Include="..\..\src\dll\security.c" />
|
||||
<ClCompile Include="..\..\src\dll\debug.c" />
|
||||
<ClCompile Include="..\..\src\dll\debuglog.c" />
|
||||
<ClCompile Include="..\..\src\dll\fsctl.c" />
|
||||
<ClCompile Include="..\..\src\dll\fsop.c" />
|
||||
<ClCompile Include="..\..\src\dll\library.c" />
|
||||
|
@ -94,7 +94,7 @@
|
||||
<ClCompile Include="..\..\src\dll\library.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\debug.c">
|
||||
<ClCompile Include="..\..\src\dll\debuglog.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\ntstatus.c">
|
||||
@ -172,6 +172,9 @@
|
||||
<ClCompile Include="..\..\src\dll\ldap.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\debug.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def">
|
||||
|
@ -48,25 +48,51 @@ void tlib_add_test_opt(const char *name, void (*fn)(void))
|
||||
add_test_to_list(name, fn, 1, &test_tail);
|
||||
}
|
||||
|
||||
struct hook
|
||||
{
|
||||
void (*fn)(const char *name, void (*fn)(void), int v);
|
||||
struct hook *next;
|
||||
};
|
||||
static struct hook hook_sentinel = { .next = &hook_sentinel };
|
||||
static struct hook *hook_tail = &hook_sentinel;
|
||||
static void add_hook_to_list(void (*fn)(void), struct hook **tail)
|
||||
{
|
||||
struct hook *hook = calloc(1, sizeof *hook);
|
||||
hook->fn = fn;
|
||||
hook->next = (*tail)->next;
|
||||
(*tail)->next = hook;
|
||||
(*tail) = hook;
|
||||
}
|
||||
void tlib_add_hook(void (*fn)(const char *name, void (*fn)(void), int v))
|
||||
{
|
||||
add_hook_to_list(fn, &hook_tail);
|
||||
}
|
||||
|
||||
static FILE *tlib_out, *tlib_err;
|
||||
static jmp_buf test_jmp_buf, *test_jmp;
|
||||
static char assert_buf[256];
|
||||
static void test_printf(const char *fmt, ...);
|
||||
static double run_test(struct test *test)
|
||||
{
|
||||
double res;
|
||||
for (struct hook *hook = hook_tail->next->next; 0 != hook->fn; hook = hook->next)
|
||||
hook->fn(test->name, test->fn, +1);
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
unsigned long __stdcall timeGetTime(void);
|
||||
unsigned long t0 = timeGetTime();
|
||||
test->fn();
|
||||
unsigned long t1 = timeGetTime();
|
||||
return (t1 - t0) / 1000.0;
|
||||
res = (t1 - t0) / 1000.0;
|
||||
#else
|
||||
time_t t0 = time(0);
|
||||
test->fn();
|
||||
time_t t1 = time(0);
|
||||
return difftime(t1, t0);
|
||||
res = difftime(t1, t0);
|
||||
#endif
|
||||
for (struct hook *hook = hook_tail->next->next; 0 != hook->fn; hook = hook->next)
|
||||
hook->fn(test->name, test->fn, -1);
|
||||
return res;
|
||||
}
|
||||
static void do_test_default(struct test *test, int testno)
|
||||
{
|
||||
|
@ -65,6 +65,23 @@ void tlib_add_test_suite(const char *name, void (*fn)(void));
|
||||
void tlib_add_test(const char *name, void (*fn)(void));
|
||||
void tlib_add_test_opt(const char *name, void (*fn)(void));
|
||||
|
||||
/**
|
||||
* Register a test hook to be run before and after every test.
|
||||
*
|
||||
* Test hooks are functions with prototype
|
||||
* <code>void testhook(const char *name, void (*fn)(void), int v)</code>.
|
||||
* The parameter v specifies that a test is about to be executed (v is +1)
|
||||
* or it was just executed (v is -1).
|
||||
*/
|
||||
#define TESTHOOK(fn)\
|
||||
do\
|
||||
{\
|
||||
void fn(const char *name, void (*fn)(void), int v);\
|
||||
tlib_add_hook(fn);\
|
||||
} while (0)
|
||||
|
||||
void tlib_add_hook(void (*fn)(const char *name, void (*fn)(void), int v));
|
||||
|
||||
/**
|
||||
* Printf function.
|
||||
*
|
||||
|
@ -94,6 +94,9 @@ extern "C" {
|
||||
#define FSP_FUSE_NOTIFY_CHFLAGS 0x0080
|
||||
#define FSP_FUSE_NOTIFY_TRUNCATE 0x0100
|
||||
|
||||
/* getpath extension */
|
||||
#define FSP_FUSE_HAS_GETPATH 1
|
||||
|
||||
struct fuse_file_info
|
||||
{
|
||||
int flags;
|
||||
|
@ -97,8 +97,12 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'L', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_TRANSACT \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'T', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_IOCTL_TRANSACT \
|
||||
CTL_CODE(0x8000 | ('F'<<8) | 'W', 0x800 + 'T', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_TRANSACT_BATCH \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 't', METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
|
||||
#define FSP_IOCTL_TRANSACT_BATCH \
|
||||
CTL_CODE(0x8000 | ('F'<<8) | 'W', 0x800 + 't', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_STOP \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'S', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_STOP0 \
|
||||
@ -109,6 +113,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
||||
/* fsctl internal device codes (usable only in-kernel) */
|
||||
#define FSP_FSCTL_TRANSACT_INTERNAL \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'I', METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define FSP_IOCTL_TRANSACT_INTERNAL \
|
||||
CTL_CODE(0x8000 | ('F'<<8) | 'W', 0x800 + 'I', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
/* fsvol device codes */
|
||||
#define FSP_FSCTL_QUERY_WINFSP \
|
||||
|
@ -1835,6 +1835,7 @@ NTSTATUS FspAccessCheck(FSP_FILE_SYSTEM *FileSystem,
|
||||
/*
|
||||
* POSIX Interop
|
||||
*/
|
||||
FSP_API NTSTATUS FspPosixSetUidMap(UINT32 Uid[], PSID Sid[], ULONG Count);
|
||||
FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid);
|
||||
FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid);
|
||||
FSP_API VOID FspDeleteSid(PSID Sid, NTSTATUS (*CreateFunc)());
|
||||
|
881
src/dll/debug.c
881
src/dll/debug.c
@ -20,871 +20,22 @@
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <sddl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static HANDLE FspDebugLogHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
FSP_API VOID FspDebugLogSetHandle(HANDLE Handle)
|
||||
#if !defined(NDEBUG)
|
||||
ULONG DebugRandom(VOID)
|
||||
{
|
||||
FspDebugLogHandle = Handle;
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLog(const char *format, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
/* DbgPrint has a 512 byte limit, but wvsprintf is only safe with a 1024 byte buffer */
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
wvsprintfA(buf, format, ap);
|
||||
va_end(ap);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
if (INVALID_HANDLE_VALUE != FspDebugLogHandle)
|
||||
{
|
||||
DWORD bytes;
|
||||
WriteFile(FspDebugLogHandle, buf, lstrlenA(buf), &bytes, 0);
|
||||
}
|
||||
else
|
||||
OutputDebugStringA(buf);
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||
{
|
||||
char *Sddl;
|
||||
|
||||
if (0 == SecurityDescriptor)
|
||||
FspDebugLog(format, "null security descriptor");
|
||||
else if (ConvertSecurityDescriptorToStringSecurityDescriptorA(SecurityDescriptor,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0))
|
||||
{
|
||||
FspDebugLog(format, Sddl);
|
||||
LocalFree(Sddl);
|
||||
}
|
||||
else
|
||||
FspDebugLog(format, "invalid security descriptor");
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogSid(const char *format, PSID Sid)
|
||||
{
|
||||
char *S;
|
||||
|
||||
if (0 == Sid)
|
||||
FspDebugLog(format, "null SID");
|
||||
else if (ConvertSidToStringSidA(Sid, &S))
|
||||
{
|
||||
FspDebugLog(format, S);
|
||||
LocalFree(S);
|
||||
}
|
||||
else
|
||||
FspDebugLog(format, "invalid SID");
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime)
|
||||
{
|
||||
SYSTEMTIME SystemTime;
|
||||
char buf[32];
|
||||
|
||||
if (FileTimeToSystemTime(FileTime, &SystemTime))
|
||||
{
|
||||
wsprintfA(buf, "%04hu-%02hu-%02huT%02hu:%02hu:%02hu.%03huZ",
|
||||
SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay,
|
||||
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond,
|
||||
SystemTime.wMilliseconds);
|
||||
FspDebugLog(format, buf);
|
||||
}
|
||||
else
|
||||
FspDebugLog(format, "invalid file time");
|
||||
}
|
||||
|
||||
#define MAKE_UINT32_PAIR(v) \
|
||||
((PLARGE_INTEGER)&(v))->HighPart, ((PLARGE_INTEGER)&(v))->LowPart
|
||||
|
||||
static const char *FspDebugLogDispositionString(UINT32 CreateOptions)
|
||||
{
|
||||
switch ((CreateOptions >> 24) & 0xff)
|
||||
{
|
||||
case FILE_CREATE:
|
||||
return "FILE_CREATE";
|
||||
case FILE_OPEN:
|
||||
return "FILE_OPEN";
|
||||
case FILE_OPEN_IF:
|
||||
return "FILE_OPEN_IF";
|
||||
case FILE_OVERWRITE:
|
||||
return "FILE_OVERWRITE";
|
||||
case FILE_SUPERSEDE:
|
||||
return "FILE_SUPERSEDE";
|
||||
case FILE_OVERWRITE_IF:
|
||||
return "FILE_OVERWRITE_IF";
|
||||
default:
|
||||
return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *FspDebugLogUserContextString(UINT64 UserContext, UINT64 UserContext2, char *Buf)
|
||||
{
|
||||
wsprintfA(Buf, 0 == UserContext2 ? "%p" : "%p:%p", (PVOID)UserContext, (PVOID)UserContext2);
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogFileTimeString(UINT64 FileTime, char *Buf)
|
||||
{
|
||||
SYSTEMTIME SystemTime;
|
||||
|
||||
if (0 == FileTime)
|
||||
lstrcpyA(Buf, "0");
|
||||
else if (FileTimeToSystemTime((PFILETIME)&FileTime, &SystemTime))
|
||||
{
|
||||
wsprintfA(Buf, "%04hu-%02hu-%02huT%02hu:%02hu:%02hu.%03huZ",
|
||||
SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay,
|
||||
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond,
|
||||
SystemTime.wMilliseconds);
|
||||
}
|
||||
else
|
||||
lstrcpyA(Buf, "INVALID");
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogFileInfoString(FSP_FSCTL_FILE_INFO *FileInfo, char *Buf)
|
||||
{
|
||||
char CreationTimeBuf[32], LastAccessTimeBuf[32], LastWriteTimeBuf[32], ChangeTimeBuf[32];
|
||||
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"FileAttributes=%lx, "
|
||||
"ReparseTag=%lx, "
|
||||
"AllocationSize=%lx:%lx, "
|
||||
"FileSize=%lx:%lx, "
|
||||
"CreationTime=%s, "
|
||||
"LastAccessTime=%s, "
|
||||
"LastWriteTime=%s, "
|
||||
"ChangeTime=%s, "
|
||||
"IndexNumber=%lx:%lx"
|
||||
"}",
|
||||
FileInfo->FileAttributes,
|
||||
FileInfo->ReparseTag,
|
||||
MAKE_UINT32_PAIR(FileInfo->AllocationSize),
|
||||
MAKE_UINT32_PAIR(FileInfo->FileSize),
|
||||
FspDebugLogFileTimeString(FileInfo->CreationTime, CreationTimeBuf),
|
||||
FspDebugLogFileTimeString(FileInfo->LastAccessTime, LastAccessTimeBuf),
|
||||
FspDebugLogFileTimeString(FileInfo->LastWriteTime, LastWriteTimeBuf),
|
||||
FspDebugLogFileTimeString(FileInfo->ChangeTime, ChangeTimeBuf),
|
||||
MAKE_UINT32_PAIR(FileInfo->IndexNumber));
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogVolumeInfoString(FSP_FSCTL_VOLUME_INFO *VolumeInfo, char *Buf)
|
||||
{
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"TotalSize=%lx:%lx, "
|
||||
"FreeSize=%lx:%lx, "
|
||||
"VolumeLabel=\"%.32S\""
|
||||
"}",
|
||||
MAKE_UINT32_PAIR(VolumeInfo->TotalSize),
|
||||
MAKE_UINT32_PAIR(VolumeInfo->FreeSize),
|
||||
&VolumeInfo->VolumeLabel);
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogWideCharBufferString(PVOID WideCharBuf, ULONG Length, char *Buf)
|
||||
{
|
||||
WCHAR TempWideCharBuf[64 + 1];
|
||||
|
||||
if (Length > sizeof TempWideCharBuf - sizeof(WCHAR))
|
||||
Length = sizeof TempWideCharBuf - sizeof(WCHAR);
|
||||
|
||||
memcpy(TempWideCharBuf, WideCharBuf, Length);
|
||||
TempWideCharBuf[Length / sizeof(WCHAR)] = L'\0';
|
||||
|
||||
wsprintfA(Buf, "%.64S", TempWideCharBuf);
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogReparseDataString(PVOID ReparseData0, char *Buf)
|
||||
{
|
||||
union
|
||||
{
|
||||
PREPARSE_DATA_BUFFER D;
|
||||
PREPARSE_GUID_DATA_BUFFER G;
|
||||
} ReparseData;
|
||||
char SubstituteName[64 + 1], PrintName[64 + 1];
|
||||
|
||||
ReparseData.D = ReparseData0;
|
||||
if (0 == ReparseData.D->ReparseDataLength)
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=%#lx, "
|
||||
"ReparseDataLength=%hu"
|
||||
"}",
|
||||
ReparseData.D->ReparseTag, ReparseData.D->ReparseDataLength);
|
||||
else if (IO_REPARSE_TAG_MOUNT_POINT == ReparseData.D->ReparseTag)
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=IO_REPARSE_TAG_MOUNT_POINT, "
|
||||
"SubstituteName=\"%s\", "
|
||||
"PrintName=\"%s\""
|
||||
"}",
|
||||
FspDebugLogWideCharBufferString(
|
||||
ReparseData.D->MountPointReparseBuffer.PathBuffer +
|
||||
ReparseData.D->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
|
||||
ReparseData.D->MountPointReparseBuffer.SubstituteNameLength,
|
||||
SubstituteName),
|
||||
FspDebugLogWideCharBufferString(
|
||||
ReparseData.D->MountPointReparseBuffer.PathBuffer +
|
||||
ReparseData.D->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR),
|
||||
ReparseData.D->MountPointReparseBuffer.PrintNameLength,
|
||||
PrintName));
|
||||
else if (IO_REPARSE_TAG_SYMLINK == ReparseData.D->ReparseTag)
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=IO_REPARSE_TAG_SYMLINK, "
|
||||
"SubstituteName=\"%s\", "
|
||||
"PrintName=\"%s\", "
|
||||
"Flags=%u"
|
||||
"}",
|
||||
FspDebugLogWideCharBufferString(
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.PathBuffer +
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.SubstituteNameLength,
|
||||
SubstituteName),
|
||||
FspDebugLogWideCharBufferString(
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.PathBuffer +
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR),
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.PrintNameLength,
|
||||
PrintName),
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.Flags);
|
||||
else if (IsReparseTagMicrosoft(ReparseData.D->ReparseTag))
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=%#lx, "
|
||||
"ReparseDataLength=%hu"
|
||||
"}",
|
||||
ReparseData.D->ReparseTag, ReparseData.D->ReparseDataLength);
|
||||
else
|
||||
#define Guid ReparseData.G->ReparseGuid
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=%#lx, "
|
||||
"ReparseDataLength=%hu, "
|
||||
"ReparseGuid={%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"
|
||||
"}",
|
||||
ReparseData.G->ReparseTag, ReparseData.G->ReparseDataLength,
|
||||
Guid.Data1, Guid.Data2, Guid.Data3,
|
||||
Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
|
||||
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
|
||||
#undef Guid
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static VOID FspDebugLogRequestVoid(FSP_FSCTL_TRANSACT_REQ *Request, const char *Name)
|
||||
{
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint, Name);
|
||||
}
|
||||
|
||||
static VOID FspDebugLogResponseStatus(FSP_FSCTL_TRANSACT_RSP *Response, const char *Name)
|
||||
{
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<%s IoStatus=%lx[%ld]\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint, Name,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information);
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
||||
{
|
||||
char UserContextBuf[40];
|
||||
char CreationTimeBuf[32], LastAccessTimeBuf[32], LastWriteTimeBuf[32];
|
||||
char InfoBuf[256];
|
||||
char *Sddl = 0;
|
||||
|
||||
switch (Request->Kind)
|
||||
{
|
||||
case FspFsctlTransactReservedKind:
|
||||
FspDebugLogRequestVoid(Request, "RESERVED");
|
||||
break;
|
||||
case FspFsctlTransactCreateKind:
|
||||
if (0 != Request->Req.Create.SecurityDescriptor.Offset)
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorA(
|
||||
Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0);
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Create [%c%c%c%c%c%c] \"%S\", "
|
||||
"%s, CreateOptions=%lx, FileAttributes=%lx, Security=%s%s%s, "
|
||||
"AllocationSize=%lx:%lx, "
|
||||
"AccessToken=%p[PID=%lx], DesiredAccess=%lx, GrantedAccess=%lx, "
|
||||
"ShareAccess=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->Req.Create.UserMode ? 'U' : 'K',
|
||||
Request->Req.Create.HasTraversePrivilege ? 'T' : '-',
|
||||
Request->Req.Create.HasBackupPrivilege ? 'B' : '-',
|
||||
Request->Req.Create.HasRestorePrivilege ? 'R' : '-',
|
||||
Request->Req.Create.OpenTargetDirectory ? 'D' : '-',
|
||||
Request->Req.Create.CaseSensitive ? 'C' : '-',
|
||||
(PWSTR)Request->Buffer,
|
||||
FspDebugLogDispositionString(Request->Req.Create.CreateOptions),
|
||||
Request->Req.Create.CreateOptions & 0xffffff,
|
||||
Request->Req.Create.FileAttributes,
|
||||
Sddl ? "\"" : "",
|
||||
Sddl ? Sddl : "NULL",
|
||||
Sddl ? "\"" : "",
|
||||
MAKE_UINT32_PAIR(Request->Req.Create.AllocationSize),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(Request->Req.Create.AccessToken),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(Request->Req.Create.AccessToken),
|
||||
Request->Req.Create.DesiredAccess,
|
||||
Request->Req.Create.GrantedAccess,
|
||||
Request->Req.Create.ShareAccess);
|
||||
LocalFree(Sddl);
|
||||
break;
|
||||
case FspFsctlTransactOverwriteKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Overwrite%s %s%S%s%s, "
|
||||
"FileAttributes=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->Req.Overwrite.Supersede ? " [Supersede]" : "",
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Overwrite.UserContext, Request->Req.Overwrite.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.Overwrite.FileAttributes);
|
||||
break;
|
||||
case FspFsctlTransactCleanupKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Cleanup%s %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->Req.Cleanup.Delete ? " [Delete]" : "",
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Cleanup.UserContext, Request->Req.Cleanup.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactCloseKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Close %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Close.UserContext, Request->Req.Close.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactReadKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Read %s%S%s%s, "
|
||||
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Read.UserContext, Request->Req.Read.UserContext2,
|
||||
UserContextBuf),
|
||||
(PVOID)Request->Req.Read.Address,
|
||||
MAKE_UINT32_PAIR(Request->Req.Read.Offset),
|
||||
Request->Req.Read.Length,
|
||||
Request->Req.Read.Key);
|
||||
break;
|
||||
case FspFsctlTransactWriteKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Write%s %s%S%s%s, "
|
||||
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->Req.Write.ConstrainedIo ? " [C]" : "",
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Write.UserContext, Request->Req.Write.UserContext2,
|
||||
UserContextBuf),
|
||||
(PVOID)Request->Req.Write.Address,
|
||||
MAKE_UINT32_PAIR(Request->Req.Write.Offset),
|
||||
Request->Req.Write.Length,
|
||||
Request->Req.Write.Key);
|
||||
break;
|
||||
case FspFsctlTransactQueryInformationKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryInformation %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.QueryInformation.UserContext, Request->Req.QueryInformation.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactSetInformationKind:
|
||||
switch (Request->Req.SetInformation.FileInformationClass)
|
||||
{
|
||||
case 4/*FileBasicInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Basic] %s%S%s%s, "
|
||||
"FileAttributes=%lx, CreationTime=%s, LastAccessTime=%s, LastWriteTime=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.SetInformation.Info.Basic.FileAttributes,
|
||||
FspDebugLogFileTimeString(Request->Req.SetInformation.Info.Basic.CreationTime,
|
||||
CreationTimeBuf),
|
||||
FspDebugLogFileTimeString(Request->Req.SetInformation.Info.Basic.LastAccessTime,
|
||||
LastAccessTimeBuf),
|
||||
FspDebugLogFileTimeString(Request->Req.SetInformation.Info.Basic.LastWriteTime,
|
||||
LastWriteTimeBuf));
|
||||
break;
|
||||
case 19/*FileAllocationInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Allocation] %s%S%s%s, "
|
||||
"AllocationSize=%lx:%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
MAKE_UINT32_PAIR(Request->Req.SetInformation.Info.Allocation.AllocationSize));
|
||||
break;
|
||||
case 20/*FileEndOfFileInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [EndOfFile] %s%S%s%s, "
|
||||
"FileSize = %lx:%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
MAKE_UINT32_PAIR(Request->Req.SetInformation.Info.EndOfFile.FileSize));
|
||||
break;
|
||||
case 13/*FileDispositionInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Disposition] %s%S%s%s, "
|
||||
"%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.SetInformation.Info.Disposition.Delete ? "Delete" : "Undelete");
|
||||
break;
|
||||
case 64/*FileDispositionInformationEx*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [DispositionEx] %s%S%s%s, "
|
||||
"Flags=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.SetInformation.Info.DispositionEx.Flags);
|
||||
break;
|
||||
case 10/*FileRenameInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Rename] %s%S%s%s, "
|
||||
"NewFileName=\"%S\", AccessToken=%p[PID=%lx]\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
(PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(Request->Req.SetInformation.Info.Rename.AccessToken),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(Request->Req.SetInformation.Info.Rename.AccessToken));
|
||||
break;
|
||||
case 65/*FileRenameInformationEx*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [RenameEx] %s%S%s%s, "
|
||||
"NewFileName=\"%S\", AccessToken=%p[PID=%lx], Flags=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
(PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(Request->Req.SetInformation.Info.Rename.AccessToken),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(Request->Req.SetInformation.Info.Rename.AccessToken),
|
||||
Request->Req.SetInformation.Info.RenameEx.Flags);
|
||||
break;
|
||||
default:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [INVALID] %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactQueryEaKind:
|
||||
FspDebugLogRequestVoid(Request, "QUERYEA");
|
||||
break;
|
||||
case FspFsctlTransactSetEaKind:
|
||||
FspDebugLogRequestVoid(Request, "SETEA");
|
||||
break;
|
||||
case FspFsctlTransactFlushBuffersKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>FlushBuffers %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.FlushBuffers.UserContext, Request->Req.FlushBuffers.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactQueryVolumeInformationKind:
|
||||
FspDebugLogRequestVoid(Request, "QueryVolumeInformation");
|
||||
break;
|
||||
case FspFsctlTransactSetVolumeInformationKind:
|
||||
switch (Request->Req.SetVolumeInformation.FsInformationClass)
|
||||
{
|
||||
case 2/*FileFsLabelInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [FsLabel] "
|
||||
"Label=\"%S\"\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
(PWSTR)Request->Buffer);
|
||||
break;
|
||||
default:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [INVALID]\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactQueryDirectoryKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryDirectory %s%S%s%s, "
|
||||
"Address=%p, Length=%ld, Pattern=%s%S%s, Marker=%s%S%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.QueryDirectory.UserContext, Request->Req.QueryDirectory.UserContext2,
|
||||
UserContextBuf),
|
||||
(PVOID)Request->Req.QueryDirectory.Address,
|
||||
Request->Req.QueryDirectory.Length,
|
||||
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
||||
Request->Req.QueryDirectory.Pattern.Size ?
|
||||
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : L"NULL",
|
||||
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
||||
Request->Req.QueryDirectory.Marker.Size ? "\"" : "",
|
||||
Request->Req.QueryDirectory.Marker.Size ?
|
||||
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : L"NULL",
|
||||
Request->Req.QueryDirectory.Marker.Size ? "\"" : "");
|
||||
break;
|
||||
case FspFsctlTransactFileSystemControlKind:
|
||||
switch (Request->Req.FileSystemControl.FsControlCode)
|
||||
{
|
||||
case FSCTL_GET_REPARSE_POINT:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [FSCTL_GET_REPARSE_POINT] %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.FileSystemControl.UserContext, Request->Req.FileSystemControl.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FSCTL_SET_REPARSE_POINT:
|
||||
case FSCTL_DELETE_REPARSE_POINT:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [%s] %s%S%s%s "
|
||||
"ReparseData=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode ?
|
||||
"FSCTL_SET_REPARSE_POINT" : "FSCTL_DELETE_REPARSE_POINT",
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.FileSystemControl.UserContext, Request->Req.FileSystemControl.UserContext2,
|
||||
UserContextBuf),
|
||||
FspDebugLogReparseDataString(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset,
|
||||
InfoBuf));
|
||||
break;
|
||||
default:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [INVALID] %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.FileSystemControl.UserContext, Request->Req.FileSystemControl.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactDeviceControlKind:
|
||||
FspDebugLogRequestVoid(Request, "DEVICECONTROL");
|
||||
break;
|
||||
case FspFsctlTransactShutdownKind:
|
||||
FspDebugLogRequestVoid(Request, "SHUTDOWN");
|
||||
break;
|
||||
case FspFsctlTransactLockControlKind:
|
||||
FspDebugLogRequestVoid(Request, "LOCKCONTROL");
|
||||
break;
|
||||
case FspFsctlTransactQuerySecurityKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>QuerySecurity %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.QuerySecurity.UserContext, Request->Req.QuerySecurity.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactSetSecurityKind:
|
||||
if (0 != Request->Req.SetSecurity.SecurityDescriptor.Size)
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorA(
|
||||
Request->Buffer + Request->Req.SetSecurity.SecurityDescriptor.Offset,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0);
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetSecurity %s%S%s%s, "
|
||||
"SecurityInformation=%lx, Security=%s%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetSecurity.UserContext, Request->Req.SetSecurity.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.SetSecurity.SecurityInformation,
|
||||
Sddl ? "\"" : "",
|
||||
Sddl ? Sddl : "NULL",
|
||||
Sddl ? "\"" : "");
|
||||
LocalFree(Sddl);
|
||||
break;
|
||||
case FspFsctlTransactQueryStreamInformationKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryStreamInformation %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.QueryStreamInformation.UserContext, Request->Req.QueryStreamInformation.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
default:
|
||||
FspDebugLogRequestVoid(Request, "INVALID");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
if (STATUS_PENDING == Response->IoStatus.Status)
|
||||
return;
|
||||
|
||||
char UserContextBuf[40];
|
||||
char InfoBuf[256];
|
||||
char *Sddl = 0;
|
||||
|
||||
switch (Response->Kind)
|
||||
{
|
||||
case FspFsctlTransactReservedKind:
|
||||
FspDebugLogResponseStatus(Response, "RESERVED");
|
||||
break;
|
||||
case FspFsctlTransactCreateKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "Create");
|
||||
else if (STATUS_REPARSE == Response->IoStatus.Status)
|
||||
{
|
||||
if (0/*IO_REPARSE*/ == Response->IoStatus.Information)
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||
"Reparse.FileName=\"%s\"\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogWideCharBufferString(
|
||||
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
|
||||
Response->Rsp.Create.Reparse.Buffer.Size,
|
||||
InfoBuf));
|
||||
else if (1/*IO_REMOUNT*/ == Response->IoStatus.Information)
|
||||
FspDebugLogResponseStatus(Response, "Create");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||
"Reparse.Data=\"%s\"\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogReparseDataString(
|
||||
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
|
||||
InfoBuf));
|
||||
}
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||
"UserContext=%s, GrantedAccess=%lx, FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogUserContextString(
|
||||
Response->Rsp.Create.Opened.UserContext, Response->Rsp.Create.Opened.UserContext2,
|
||||
UserContextBuf),
|
||||
Response->Rsp.Create.Opened.GrantedAccess,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.Create.Opened.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactOverwriteKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "Overwrite");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Overwrite IoStatus=%lx[%ld] "
|
||||
"FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.Overwrite.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactCleanupKind:
|
||||
FspDebugLogResponseStatus(Response, "Cleanup");
|
||||
break;
|
||||
case FspFsctlTransactCloseKind:
|
||||
FspDebugLogResponseStatus(Response, "Close");
|
||||
break;
|
||||
case FspFsctlTransactReadKind:
|
||||
FspDebugLogResponseStatus(Response, "Read");
|
||||
break;
|
||||
case FspFsctlTransactWriteKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "Write");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Write IoStatus=%lx[%ld] "
|
||||
"FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.Write.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactQueryInformationKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "QueryInformation");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<QueryInformation IoStatus=%lx[%ld] "
|
||||
"FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.QueryInformation.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactSetInformationKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "SetInformation");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetInformation IoStatus=%lx[%ld] "
|
||||
"FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.SetInformation.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactQueryEaKind:
|
||||
FspDebugLogResponseStatus(Response, "QUERYEA");
|
||||
break;
|
||||
case FspFsctlTransactSetEaKind:
|
||||
FspDebugLogResponseStatus(Response, "SETEA");
|
||||
break;
|
||||
case FspFsctlTransactFlushBuffersKind:
|
||||
FspDebugLogResponseStatus(Response, "FlushBuffers");
|
||||
break;
|
||||
case FspFsctlTransactQueryVolumeInformationKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "QueryVolumeInformation");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<QueryVolumeInformation IoStatus=%lx[%ld] "
|
||||
"VolumeInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogVolumeInfoString(&Response->Rsp.QueryVolumeInformation.VolumeInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactSetVolumeInformationKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "SetVolumeInformation");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetVolumeInformation IoStatus=%lx[%ld] "
|
||||
"VolumeInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogVolumeInfoString(&Response->Rsp.SetVolumeInformation.VolumeInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactQueryDirectoryKind:
|
||||
FspDebugLogResponseStatus(Response, "QueryDirectory");
|
||||
break;
|
||||
case FspFsctlTransactFileSystemControlKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status) ||
|
||||
0 == Response->Rsp.FileSystemControl.Buffer.Size)
|
||||
FspDebugLogResponseStatus(Response, "FileSystemControl");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<FileSystemControl IoStatus=%lx[%ld] "
|
||||
"ReparseData=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogReparseDataString(Response->Buffer + Response->Rsp.FileSystemControl.Buffer.Offset,
|
||||
InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactDeviceControlKind:
|
||||
FspDebugLogResponseStatus(Response, "DEVICECONTROL");
|
||||
break;
|
||||
case FspFsctlTransactShutdownKind:
|
||||
FspDebugLogResponseStatus(Response, "SHUTDOWN");
|
||||
break;
|
||||
case FspFsctlTransactLockControlKind:
|
||||
FspDebugLogResponseStatus(Response, "LOCKCONTROL");
|
||||
break;
|
||||
case FspFsctlTransactQuerySecurityKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "QuerySecurity");
|
||||
else
|
||||
{
|
||||
if (0 != Response->Rsp.QuerySecurity.SecurityDescriptor.Size)
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorA(
|
||||
Response->Buffer + Response->Rsp.QuerySecurity.SecurityDescriptor.Offset,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0);
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<QuerySecurity IoStatus=%lx[%ld] "
|
||||
"Security=%s%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
Sddl ? "\"" : "",
|
||||
Sddl ? Sddl : "NULL",
|
||||
Sddl ? "\"" : "");
|
||||
LocalFree(Sddl);
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactSetSecurityKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "SetSecurity");
|
||||
else
|
||||
{
|
||||
if (0 != Response->Rsp.SetSecurity.SecurityDescriptor.Size)
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorA(
|
||||
Response->Buffer + Response->Rsp.SetSecurity.SecurityDescriptor.Offset,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0);
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetSecurity IoStatus=%lx[%ld] "
|
||||
"Security=%s%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
Sddl ? "\"" : "",
|
||||
Sddl ? Sddl : "NULL",
|
||||
Sddl ? "\"" : "");
|
||||
LocalFree(Sddl);
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactQueryStreamInformationKind:
|
||||
FspDebugLogResponseStatus(Response, "QueryStreamInformation");
|
||||
break;
|
||||
default:
|
||||
FspDebugLogResponseStatus(Response, "INVALID");
|
||||
break;
|
||||
}
|
||||
static SRWLOCK SlimLock = SRWLOCK_INIT;
|
||||
static ULONG Seed = 1;
|
||||
ULONG Result;
|
||||
|
||||
AcquireSRWLockExclusive(&SlimLock);
|
||||
|
||||
/* see ucrt sources */
|
||||
Seed = Seed * 214013 + 2531011;
|
||||
Result = (Seed >> 16) & 0x7fff;
|
||||
|
||||
ReleaseSRWLockExclusive(&SlimLock);
|
||||
|
||||
return Result;
|
||||
}
|
||||
#endif
|
||||
|
890
src/dll/debuglog.c
Normal file
890
src/dll/debuglog.c
Normal file
@ -0,0 +1,890 @@
|
||||
/**
|
||||
* @file dll/debuglog.c
|
||||
*
|
||||
* @copyright 2015-2022 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this software
|
||||
* in accordance with the commercial license agreement provided in
|
||||
* conjunction with the software. The terms and conditions of any such
|
||||
* commercial license agreement shall govern, supersede, and render
|
||||
* ineffective any application of the GPLv3 license to this software,
|
||||
* notwithstanding of any reference thereto in the software or
|
||||
* associated repository.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <sddl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
static HANDLE FspDebugLogHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
FSP_API VOID FspDebugLogSetHandle(HANDLE Handle)
|
||||
{
|
||||
FspDebugLogHandle = Handle;
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLog(const char *format, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
/* DbgPrint has a 512 byte limit, but wvsprintf is only safe with a 1024 byte buffer */
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
wvsprintfA(buf, format, ap);
|
||||
va_end(ap);
|
||||
buf[sizeof buf - 1] = '\0';
|
||||
if (INVALID_HANDLE_VALUE != FspDebugLogHandle)
|
||||
{
|
||||
DWORD bytes;
|
||||
WriteFile(FspDebugLogHandle, buf, lstrlenA(buf), &bytes, 0);
|
||||
}
|
||||
else
|
||||
OutputDebugStringA(buf);
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||
{
|
||||
char *Sddl;
|
||||
|
||||
if (0 == SecurityDescriptor)
|
||||
FspDebugLog(format, "null security descriptor");
|
||||
else if (ConvertSecurityDescriptorToStringSecurityDescriptorA(SecurityDescriptor,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0))
|
||||
{
|
||||
FspDebugLog(format, Sddl);
|
||||
LocalFree(Sddl);
|
||||
}
|
||||
else
|
||||
FspDebugLog(format, "invalid security descriptor");
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogSid(const char *format, PSID Sid)
|
||||
{
|
||||
char *S;
|
||||
|
||||
if (0 == Sid)
|
||||
FspDebugLog(format, "null SID");
|
||||
else if (ConvertSidToStringSidA(Sid, &S))
|
||||
{
|
||||
FspDebugLog(format, S);
|
||||
LocalFree(S);
|
||||
}
|
||||
else
|
||||
FspDebugLog(format, "invalid SID");
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime)
|
||||
{
|
||||
SYSTEMTIME SystemTime;
|
||||
char buf[32];
|
||||
|
||||
if (FileTimeToSystemTime(FileTime, &SystemTime))
|
||||
{
|
||||
wsprintfA(buf, "%04hu-%02hu-%02huT%02hu:%02hu:%02hu.%03huZ",
|
||||
SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay,
|
||||
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond,
|
||||
SystemTime.wMilliseconds);
|
||||
FspDebugLog(format, buf);
|
||||
}
|
||||
else
|
||||
FspDebugLog(format, "invalid file time");
|
||||
}
|
||||
|
||||
#define MAKE_UINT32_PAIR(v) \
|
||||
((PLARGE_INTEGER)&(v))->HighPart, ((PLARGE_INTEGER)&(v))->LowPart
|
||||
|
||||
static const char *FspDebugLogDispositionString(UINT32 CreateOptions)
|
||||
{
|
||||
switch ((CreateOptions >> 24) & 0xff)
|
||||
{
|
||||
case FILE_CREATE:
|
||||
return "FILE_CREATE";
|
||||
case FILE_OPEN:
|
||||
return "FILE_OPEN";
|
||||
case FILE_OPEN_IF:
|
||||
return "FILE_OPEN_IF";
|
||||
case FILE_OVERWRITE:
|
||||
return "FILE_OVERWRITE";
|
||||
case FILE_SUPERSEDE:
|
||||
return "FILE_SUPERSEDE";
|
||||
case FILE_OVERWRITE_IF:
|
||||
return "FILE_OVERWRITE_IF";
|
||||
default:
|
||||
return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *FspDebugLogUserContextString(UINT64 UserContext, UINT64 UserContext2, char *Buf)
|
||||
{
|
||||
wsprintfA(Buf, 0 == UserContext2 ? "%p" : "%p:%p", (PVOID)UserContext, (PVOID)UserContext2);
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogFileTimeString(UINT64 FileTime, char *Buf)
|
||||
{
|
||||
SYSTEMTIME SystemTime;
|
||||
|
||||
if (0 == FileTime)
|
||||
lstrcpyA(Buf, "0");
|
||||
else if (FileTimeToSystemTime((PFILETIME)&FileTime, &SystemTime))
|
||||
{
|
||||
wsprintfA(Buf, "%04hu-%02hu-%02huT%02hu:%02hu:%02hu.%03huZ",
|
||||
SystemTime.wYear, SystemTime.wMonth, SystemTime.wDay,
|
||||
SystemTime.wHour, SystemTime.wMinute, SystemTime.wSecond,
|
||||
SystemTime.wMilliseconds);
|
||||
}
|
||||
else
|
||||
lstrcpyA(Buf, "INVALID");
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogFileInfoString(FSP_FSCTL_FILE_INFO *FileInfo, char *Buf)
|
||||
{
|
||||
char CreationTimeBuf[32], LastAccessTimeBuf[32], LastWriteTimeBuf[32], ChangeTimeBuf[32];
|
||||
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"FileAttributes=%lx, "
|
||||
"ReparseTag=%lx, "
|
||||
"AllocationSize=%lx:%lx, "
|
||||
"FileSize=%lx:%lx, "
|
||||
"CreationTime=%s, "
|
||||
"LastAccessTime=%s, "
|
||||
"LastWriteTime=%s, "
|
||||
"ChangeTime=%s, "
|
||||
"IndexNumber=%lx:%lx"
|
||||
"}",
|
||||
FileInfo->FileAttributes,
|
||||
FileInfo->ReparseTag,
|
||||
MAKE_UINT32_PAIR(FileInfo->AllocationSize),
|
||||
MAKE_UINT32_PAIR(FileInfo->FileSize),
|
||||
FspDebugLogFileTimeString(FileInfo->CreationTime, CreationTimeBuf),
|
||||
FspDebugLogFileTimeString(FileInfo->LastAccessTime, LastAccessTimeBuf),
|
||||
FspDebugLogFileTimeString(FileInfo->LastWriteTime, LastWriteTimeBuf),
|
||||
FspDebugLogFileTimeString(FileInfo->ChangeTime, ChangeTimeBuf),
|
||||
MAKE_UINT32_PAIR(FileInfo->IndexNumber));
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogVolumeInfoString(FSP_FSCTL_VOLUME_INFO *VolumeInfo, char *Buf)
|
||||
{
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"TotalSize=%lx:%lx, "
|
||||
"FreeSize=%lx:%lx, "
|
||||
"VolumeLabel=\"%.32S\""
|
||||
"}",
|
||||
MAKE_UINT32_PAIR(VolumeInfo->TotalSize),
|
||||
MAKE_UINT32_PAIR(VolumeInfo->FreeSize),
|
||||
&VolumeInfo->VolumeLabel);
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogWideCharBufferString(PVOID WideCharBuf, ULONG Length, char *Buf)
|
||||
{
|
||||
WCHAR TempWideCharBuf[64 + 1];
|
||||
|
||||
if (Length > sizeof TempWideCharBuf - sizeof(WCHAR))
|
||||
Length = sizeof TempWideCharBuf - sizeof(WCHAR);
|
||||
|
||||
memcpy(TempWideCharBuf, WideCharBuf, Length);
|
||||
TempWideCharBuf[Length / sizeof(WCHAR)] = L'\0';
|
||||
|
||||
wsprintfA(Buf, "%.64S", TempWideCharBuf);
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static const char *FspDebugLogReparseDataString(PVOID ReparseData0, char *Buf)
|
||||
{
|
||||
union
|
||||
{
|
||||
PREPARSE_DATA_BUFFER D;
|
||||
PREPARSE_GUID_DATA_BUFFER G;
|
||||
} ReparseData;
|
||||
char SubstituteName[64 + 1], PrintName[64 + 1];
|
||||
|
||||
ReparseData.D = ReparseData0;
|
||||
if (0 == ReparseData.D->ReparseDataLength)
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=%#lx, "
|
||||
"ReparseDataLength=%hu"
|
||||
"}",
|
||||
ReparseData.D->ReparseTag, ReparseData.D->ReparseDataLength);
|
||||
else if (IO_REPARSE_TAG_MOUNT_POINT == ReparseData.D->ReparseTag)
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=IO_REPARSE_TAG_MOUNT_POINT, "
|
||||
"SubstituteName=\"%s\", "
|
||||
"PrintName=\"%s\""
|
||||
"}",
|
||||
FspDebugLogWideCharBufferString(
|
||||
ReparseData.D->MountPointReparseBuffer.PathBuffer +
|
||||
ReparseData.D->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
|
||||
ReparseData.D->MountPointReparseBuffer.SubstituteNameLength,
|
||||
SubstituteName),
|
||||
FspDebugLogWideCharBufferString(
|
||||
ReparseData.D->MountPointReparseBuffer.PathBuffer +
|
||||
ReparseData.D->MountPointReparseBuffer.PrintNameOffset / sizeof(WCHAR),
|
||||
ReparseData.D->MountPointReparseBuffer.PrintNameLength,
|
||||
PrintName));
|
||||
else if (IO_REPARSE_TAG_SYMLINK == ReparseData.D->ReparseTag)
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=IO_REPARSE_TAG_SYMLINK, "
|
||||
"SubstituteName=\"%s\", "
|
||||
"PrintName=\"%s\", "
|
||||
"Flags=%u"
|
||||
"}",
|
||||
FspDebugLogWideCharBufferString(
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.PathBuffer +
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR),
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.SubstituteNameLength,
|
||||
SubstituteName),
|
||||
FspDebugLogWideCharBufferString(
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.PathBuffer +
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR),
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.PrintNameLength,
|
||||
PrintName),
|
||||
ReparseData.D->SymbolicLinkReparseBuffer.Flags);
|
||||
else if (IsReparseTagMicrosoft(ReparseData.D->ReparseTag))
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=%#lx, "
|
||||
"ReparseDataLength=%hu"
|
||||
"}",
|
||||
ReparseData.D->ReparseTag, ReparseData.D->ReparseDataLength);
|
||||
else
|
||||
#define Guid ReparseData.G->ReparseGuid
|
||||
wsprintfA(Buf,
|
||||
"{"
|
||||
"ReparseTag=%#lx, "
|
||||
"ReparseDataLength=%hu, "
|
||||
"ReparseGuid={%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"
|
||||
"}",
|
||||
ReparseData.G->ReparseTag, ReparseData.G->ReparseDataLength,
|
||||
Guid.Data1, Guid.Data2, Guid.Data3,
|
||||
Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
|
||||
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
|
||||
#undef Guid
|
||||
|
||||
return Buf;
|
||||
}
|
||||
|
||||
static VOID FspDebugLogRequestVoid(FSP_FSCTL_TRANSACT_REQ *Request, const char *Name)
|
||||
{
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint, Name);
|
||||
}
|
||||
|
||||
static VOID FspDebugLogResponseStatus(FSP_FSCTL_TRANSACT_RSP *Response, const char *Name)
|
||||
{
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<%s IoStatus=%lx[%ld]\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint, Name,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information);
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
||||
{
|
||||
char UserContextBuf[40];
|
||||
char CreationTimeBuf[32], LastAccessTimeBuf[32], LastWriteTimeBuf[32];
|
||||
char InfoBuf[256];
|
||||
char *Sddl = 0;
|
||||
|
||||
switch (Request->Kind)
|
||||
{
|
||||
case FspFsctlTransactReservedKind:
|
||||
FspDebugLogRequestVoid(Request, "RESERVED");
|
||||
break;
|
||||
case FspFsctlTransactCreateKind:
|
||||
if (0 != Request->Req.Create.SecurityDescriptor.Offset)
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorA(
|
||||
Request->Buffer + Request->Req.Create.SecurityDescriptor.Offset,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0);
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Create [%c%c%c%c%c%c] \"%S\", "
|
||||
"%s, CreateOptions=%lx, FileAttributes=%lx, Security=%s%s%s, "
|
||||
"AllocationSize=%lx:%lx, "
|
||||
"AccessToken=%p[PID=%lx], DesiredAccess=%lx, GrantedAccess=%lx, "
|
||||
"ShareAccess=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->Req.Create.UserMode ? 'U' : 'K',
|
||||
Request->Req.Create.HasTraversePrivilege ? 'T' : '-',
|
||||
Request->Req.Create.HasBackupPrivilege ? 'B' : '-',
|
||||
Request->Req.Create.HasRestorePrivilege ? 'R' : '-',
|
||||
Request->Req.Create.OpenTargetDirectory ? 'D' : '-',
|
||||
Request->Req.Create.CaseSensitive ? 'C' : '-',
|
||||
(PWSTR)Request->Buffer,
|
||||
FspDebugLogDispositionString(Request->Req.Create.CreateOptions),
|
||||
Request->Req.Create.CreateOptions & 0xffffff,
|
||||
Request->Req.Create.FileAttributes,
|
||||
Sddl ? "\"" : "",
|
||||
Sddl ? Sddl : "NULL",
|
||||
Sddl ? "\"" : "",
|
||||
MAKE_UINT32_PAIR(Request->Req.Create.AllocationSize),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(Request->Req.Create.AccessToken),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(Request->Req.Create.AccessToken),
|
||||
Request->Req.Create.DesiredAccess,
|
||||
Request->Req.Create.GrantedAccess,
|
||||
Request->Req.Create.ShareAccess);
|
||||
LocalFree(Sddl);
|
||||
break;
|
||||
case FspFsctlTransactOverwriteKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Overwrite%s %s%S%s%s, "
|
||||
"FileAttributes=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->Req.Overwrite.Supersede ? " [Supersede]" : "",
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Overwrite.UserContext, Request->Req.Overwrite.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.Overwrite.FileAttributes);
|
||||
break;
|
||||
case FspFsctlTransactCleanupKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Cleanup%s %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->Req.Cleanup.Delete ? " [Delete]" : "",
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Cleanup.UserContext, Request->Req.Cleanup.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactCloseKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Close %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Close.UserContext, Request->Req.Close.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactReadKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Read %s%S%s%s, "
|
||||
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Read.UserContext, Request->Req.Read.UserContext2,
|
||||
UserContextBuf),
|
||||
(PVOID)Request->Req.Read.Address,
|
||||
MAKE_UINT32_PAIR(Request->Req.Read.Offset),
|
||||
Request->Req.Read.Length,
|
||||
Request->Req.Read.Key);
|
||||
break;
|
||||
case FspFsctlTransactWriteKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>Write%s %s%S%s%s, "
|
||||
"Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->Req.Write.ConstrainedIo ? " [C]" : "",
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.Write.UserContext, Request->Req.Write.UserContext2,
|
||||
UserContextBuf),
|
||||
(PVOID)Request->Req.Write.Address,
|
||||
MAKE_UINT32_PAIR(Request->Req.Write.Offset),
|
||||
Request->Req.Write.Length,
|
||||
Request->Req.Write.Key);
|
||||
break;
|
||||
case FspFsctlTransactQueryInformationKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryInformation %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.QueryInformation.UserContext, Request->Req.QueryInformation.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactSetInformationKind:
|
||||
switch (Request->Req.SetInformation.FileInformationClass)
|
||||
{
|
||||
case 4/*FileBasicInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Basic] %s%S%s%s, "
|
||||
"FileAttributes=%lx, CreationTime=%s, LastAccessTime=%s, LastWriteTime=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.SetInformation.Info.Basic.FileAttributes,
|
||||
FspDebugLogFileTimeString(Request->Req.SetInformation.Info.Basic.CreationTime,
|
||||
CreationTimeBuf),
|
||||
FspDebugLogFileTimeString(Request->Req.SetInformation.Info.Basic.LastAccessTime,
|
||||
LastAccessTimeBuf),
|
||||
FspDebugLogFileTimeString(Request->Req.SetInformation.Info.Basic.LastWriteTime,
|
||||
LastWriteTimeBuf));
|
||||
break;
|
||||
case 19/*FileAllocationInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Allocation] %s%S%s%s, "
|
||||
"AllocationSize=%lx:%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
MAKE_UINT32_PAIR(Request->Req.SetInformation.Info.Allocation.AllocationSize));
|
||||
break;
|
||||
case 20/*FileEndOfFileInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [EndOfFile] %s%S%s%s, "
|
||||
"FileSize = %lx:%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
MAKE_UINT32_PAIR(Request->Req.SetInformation.Info.EndOfFile.FileSize));
|
||||
break;
|
||||
case 13/*FileDispositionInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Disposition] %s%S%s%s, "
|
||||
"%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.SetInformation.Info.Disposition.Delete ? "Delete" : "Undelete");
|
||||
break;
|
||||
case 64/*FileDispositionInformationEx*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [DispositionEx] %s%S%s%s, "
|
||||
"Flags=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.SetInformation.Info.DispositionEx.Flags);
|
||||
break;
|
||||
case 10/*FileRenameInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [Rename] %s%S%s%s, "
|
||||
"NewFileName=\"%S\", AccessToken=%p[PID=%lx]\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
(PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(Request->Req.SetInformation.Info.Rename.AccessToken),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(Request->Req.SetInformation.Info.Rename.AccessToken));
|
||||
break;
|
||||
case 65/*FileRenameInformationEx*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [RenameEx] %s%S%s%s, "
|
||||
"NewFileName=\"%S\", AccessToken=%p[PID=%lx], Flags=%lx\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf),
|
||||
(PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_HANDLE(Request->Req.SetInformation.Info.Rename.AccessToken),
|
||||
FSP_FSCTL_TRANSACT_REQ_TOKEN_PID(Request->Req.SetInformation.Info.Rename.AccessToken),
|
||||
Request->Req.SetInformation.Info.RenameEx.Flags);
|
||||
break;
|
||||
default:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetInformation [INVALID] %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetInformation.UserContext, Request->Req.SetInformation.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactQueryEaKind:
|
||||
FspDebugLogRequestVoid(Request, "QUERYEA");
|
||||
break;
|
||||
case FspFsctlTransactSetEaKind:
|
||||
FspDebugLogRequestVoid(Request, "SETEA");
|
||||
break;
|
||||
case FspFsctlTransactFlushBuffersKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>FlushBuffers %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.FlushBuffers.UserContext, Request->Req.FlushBuffers.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactQueryVolumeInformationKind:
|
||||
FspDebugLogRequestVoid(Request, "QueryVolumeInformation");
|
||||
break;
|
||||
case FspFsctlTransactSetVolumeInformationKind:
|
||||
switch (Request->Req.SetVolumeInformation.FsInformationClass)
|
||||
{
|
||||
case 2/*FileFsLabelInformation*/:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [FsLabel] "
|
||||
"Label=\"%S\"\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
(PWSTR)Request->Buffer);
|
||||
break;
|
||||
default:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetVolumeInformation [INVALID]\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactQueryDirectoryKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryDirectory %s%S%s%s, "
|
||||
"Address=%p, Length=%ld, Pattern=%s%S%s, Marker=%s%S%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.QueryDirectory.UserContext, Request->Req.QueryDirectory.UserContext2,
|
||||
UserContextBuf),
|
||||
(PVOID)Request->Req.QueryDirectory.Address,
|
||||
Request->Req.QueryDirectory.Length,
|
||||
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
||||
Request->Req.QueryDirectory.Pattern.Size ?
|
||||
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Pattern.Offset) : L"NULL",
|
||||
Request->Req.QueryDirectory.Pattern.Size ? "\"" : "",
|
||||
Request->Req.QueryDirectory.Marker.Size ? "\"" : "",
|
||||
Request->Req.QueryDirectory.Marker.Size ?
|
||||
(PWSTR)(Request->Buffer + Request->Req.QueryDirectory.Marker.Offset) : L"NULL",
|
||||
Request->Req.QueryDirectory.Marker.Size ? "\"" : "");
|
||||
break;
|
||||
case FspFsctlTransactFileSystemControlKind:
|
||||
switch (Request->Req.FileSystemControl.FsControlCode)
|
||||
{
|
||||
case FSCTL_GET_REPARSE_POINT:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [FSCTL_GET_REPARSE_POINT] %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.FileSystemControl.UserContext, Request->Req.FileSystemControl.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FSCTL_SET_REPARSE_POINT:
|
||||
case FSCTL_DELETE_REPARSE_POINT:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [%s] %s%S%s%s "
|
||||
"ReparseData=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
FSCTL_SET_REPARSE_POINT == Request->Req.FileSystemControl.FsControlCode ?
|
||||
"FSCTL_SET_REPARSE_POINT" : "FSCTL_DELETE_REPARSE_POINT",
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.FileSystemControl.UserContext, Request->Req.FileSystemControl.UserContext2,
|
||||
UserContextBuf),
|
||||
FspDebugLogReparseDataString(Request->Buffer + Request->Req.FileSystemControl.Buffer.Offset,
|
||||
InfoBuf));
|
||||
break;
|
||||
default:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>FileSystemControl [INVALID] %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.FileSystemControl.UserContext, Request->Req.FileSystemControl.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactDeviceControlKind:
|
||||
FspDebugLogRequestVoid(Request, "DEVICECONTROL");
|
||||
break;
|
||||
case FspFsctlTransactShutdownKind:
|
||||
FspDebugLogRequestVoid(Request, "SHUTDOWN");
|
||||
break;
|
||||
case FspFsctlTransactLockControlKind:
|
||||
FspDebugLogRequestVoid(Request, "LOCKCONTROL");
|
||||
break;
|
||||
case FspFsctlTransactQuerySecurityKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>QuerySecurity %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.QuerySecurity.UserContext, Request->Req.QuerySecurity.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
case FspFsctlTransactSetSecurityKind:
|
||||
if (0 != Request->Req.SetSecurity.SecurityDescriptor.Size)
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorA(
|
||||
Request->Buffer + Request->Req.SetSecurity.SecurityDescriptor.Offset,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0);
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>SetSecurity %s%S%s%s, "
|
||||
"SecurityInformation=%lx, Security=%s%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.SetSecurity.UserContext, Request->Req.SetSecurity.UserContext2,
|
||||
UserContextBuf),
|
||||
Request->Req.SetSecurity.SecurityInformation,
|
||||
Sddl ? "\"" : "",
|
||||
Sddl ? Sddl : "NULL",
|
||||
Sddl ? "\"" : "");
|
||||
LocalFree(Sddl);
|
||||
break;
|
||||
case FspFsctlTransactQueryStreamInformationKind:
|
||||
FspDebugLog("%S[TID=%04lx]: %p: >>QueryStreamInformation %s%S%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Request->Hint,
|
||||
Request->FileName.Size ? "\"" : "",
|
||||
Request->FileName.Size ? (PWSTR)Request->Buffer : L"",
|
||||
Request->FileName.Size ? "\", " : "",
|
||||
FspDebugLogUserContextString(
|
||||
Request->Req.QueryStreamInformation.UserContext, Request->Req.QueryStreamInformation.UserContext2,
|
||||
UserContextBuf));
|
||||
break;
|
||||
default:
|
||||
FspDebugLogRequestVoid(Request, "INVALID");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response)
|
||||
{
|
||||
if (STATUS_PENDING == Response->IoStatus.Status)
|
||||
return;
|
||||
|
||||
char UserContextBuf[40];
|
||||
char InfoBuf[256];
|
||||
char *Sddl = 0;
|
||||
|
||||
switch (Response->Kind)
|
||||
{
|
||||
case FspFsctlTransactReservedKind:
|
||||
FspDebugLogResponseStatus(Response, "RESERVED");
|
||||
break;
|
||||
case FspFsctlTransactCreateKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "Create");
|
||||
else if (STATUS_REPARSE == Response->IoStatus.Status)
|
||||
{
|
||||
if (0/*IO_REPARSE*/ == Response->IoStatus.Information)
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||
"Reparse.FileName=\"%s\"\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogWideCharBufferString(
|
||||
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
|
||||
Response->Rsp.Create.Reparse.Buffer.Size,
|
||||
InfoBuf));
|
||||
else if (1/*IO_REMOUNT*/ == Response->IoStatus.Information)
|
||||
FspDebugLogResponseStatus(Response, "Create");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||
"Reparse.Data=\"%s\"\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogReparseDataString(
|
||||
Response->Buffer + Response->Rsp.Create.Reparse.Buffer.Offset,
|
||||
InfoBuf));
|
||||
}
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Create IoStatus=%lx[%ld] "
|
||||
"UserContext=%s, GrantedAccess=%lx, FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogUserContextString(
|
||||
Response->Rsp.Create.Opened.UserContext, Response->Rsp.Create.Opened.UserContext2,
|
||||
UserContextBuf),
|
||||
Response->Rsp.Create.Opened.GrantedAccess,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.Create.Opened.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactOverwriteKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "Overwrite");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Overwrite IoStatus=%lx[%ld] "
|
||||
"FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.Overwrite.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactCleanupKind:
|
||||
FspDebugLogResponseStatus(Response, "Cleanup");
|
||||
break;
|
||||
case FspFsctlTransactCloseKind:
|
||||
FspDebugLogResponseStatus(Response, "Close");
|
||||
break;
|
||||
case FspFsctlTransactReadKind:
|
||||
FspDebugLogResponseStatus(Response, "Read");
|
||||
break;
|
||||
case FspFsctlTransactWriteKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "Write");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<Write IoStatus=%lx[%ld] "
|
||||
"FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.Write.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactQueryInformationKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "QueryInformation");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<QueryInformation IoStatus=%lx[%ld] "
|
||||
"FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.QueryInformation.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactSetInformationKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "SetInformation");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetInformation IoStatus=%lx[%ld] "
|
||||
"FileInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogFileInfoString(&Response->Rsp.SetInformation.FileInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactQueryEaKind:
|
||||
FspDebugLogResponseStatus(Response, "QUERYEA");
|
||||
break;
|
||||
case FspFsctlTransactSetEaKind:
|
||||
FspDebugLogResponseStatus(Response, "SETEA");
|
||||
break;
|
||||
case FspFsctlTransactFlushBuffersKind:
|
||||
FspDebugLogResponseStatus(Response, "FlushBuffers");
|
||||
break;
|
||||
case FspFsctlTransactQueryVolumeInformationKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "QueryVolumeInformation");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<QueryVolumeInformation IoStatus=%lx[%ld] "
|
||||
"VolumeInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogVolumeInfoString(&Response->Rsp.QueryVolumeInformation.VolumeInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactSetVolumeInformationKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "SetVolumeInformation");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetVolumeInformation IoStatus=%lx[%ld] "
|
||||
"VolumeInfo=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogVolumeInfoString(&Response->Rsp.SetVolumeInformation.VolumeInfo, InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactQueryDirectoryKind:
|
||||
FspDebugLogResponseStatus(Response, "QueryDirectory");
|
||||
break;
|
||||
case FspFsctlTransactFileSystemControlKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status) ||
|
||||
0 == Response->Rsp.FileSystemControl.Buffer.Size)
|
||||
FspDebugLogResponseStatus(Response, "FileSystemControl");
|
||||
else
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<FileSystemControl IoStatus=%lx[%ld] "
|
||||
"ReparseData=%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
FspDebugLogReparseDataString(Response->Buffer + Response->Rsp.FileSystemControl.Buffer.Offset,
|
||||
InfoBuf));
|
||||
break;
|
||||
case FspFsctlTransactDeviceControlKind:
|
||||
FspDebugLogResponseStatus(Response, "DEVICECONTROL");
|
||||
break;
|
||||
case FspFsctlTransactShutdownKind:
|
||||
FspDebugLogResponseStatus(Response, "SHUTDOWN");
|
||||
break;
|
||||
case FspFsctlTransactLockControlKind:
|
||||
FspDebugLogResponseStatus(Response, "LOCKCONTROL");
|
||||
break;
|
||||
case FspFsctlTransactQuerySecurityKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "QuerySecurity");
|
||||
else
|
||||
{
|
||||
if (0 != Response->Rsp.QuerySecurity.SecurityDescriptor.Size)
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorA(
|
||||
Response->Buffer + Response->Rsp.QuerySecurity.SecurityDescriptor.Offset,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0);
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<QuerySecurity IoStatus=%lx[%ld] "
|
||||
"Security=%s%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
Sddl ? "\"" : "",
|
||||
Sddl ? Sddl : "NULL",
|
||||
Sddl ? "\"" : "");
|
||||
LocalFree(Sddl);
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactSetSecurityKind:
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
FspDebugLogResponseStatus(Response, "SetSecurity");
|
||||
else
|
||||
{
|
||||
if (0 != Response->Rsp.SetSecurity.SecurityDescriptor.Size)
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorA(
|
||||
Response->Buffer + Response->Rsp.SetSecurity.SecurityDescriptor.Offset,
|
||||
SDDL_REVISION_1,
|
||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
|
||||
&Sddl, 0);
|
||||
FspDebugLog("%S[TID=%04lx]: %p: <<SetSecurity IoStatus=%lx[%ld] "
|
||||
"Security=%s%s%s\n",
|
||||
FspDiagIdent(), GetCurrentThreadId(), (PVOID)Response->Hint,
|
||||
Response->IoStatus.Status, Response->IoStatus.Information,
|
||||
Sddl ? "\"" : "",
|
||||
Sddl ? Sddl : "NULL",
|
||||
Sddl ? "\"" : "");
|
||||
LocalFree(Sddl);
|
||||
}
|
||||
break;
|
||||
case FspFsctlTransactQueryStreamInformationKind:
|
||||
FspDebugLogResponseStatus(Response, "QueryStreamInformation");
|
||||
break;
|
||||
default:
|
||||
FspDebugLogResponseStatus(Response, "INVALID");
|
||||
break;
|
||||
}
|
||||
}
|
@ -26,6 +26,12 @@
|
||||
#define PREFIXW L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX
|
||||
#define PREFIXW_SIZE (sizeof PREFIXW - sizeof(WCHAR))
|
||||
|
||||
static INIT_ONCE FspFsctlServiceVersionInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static ULONG FspFsctlServiceVersionValue;
|
||||
static DWORD FspFsctlTransactCode = FSP_FSCTL_TRANSACT;
|
||||
static DWORD FspFsctlTransactBatchCode = FSP_FSCTL_TRANSACT_BATCH;
|
||||
|
||||
static VOID FspFsctlServiceVersion(PUINT32 PVersion);
|
||||
static NTSTATUS FspFsctlStartService(VOID);
|
||||
|
||||
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
@ -76,6 +82,9 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
/* initialize FspFsctlTransactCode */
|
||||
FspFsctlServiceVersion(0);
|
||||
|
||||
VolumeHandle = CreateFileW(DevicePathBuf,
|
||||
0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
||||
if (INVALID_HANDLE_VALUE == VolumeHandle)
|
||||
@ -127,6 +136,7 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||
BOOLEAN Batch)
|
||||
{
|
||||
NTSTATUS Result = STATUS_SUCCESS;
|
||||
DWORD ControlCode;
|
||||
DWORD Bytes = 0;
|
||||
|
||||
if (0 != PRequestBufSize)
|
||||
@ -135,8 +145,18 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||
*PRequestBufSize = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* During file system volume creation FspFsctlCreateVolume called FspFsctlServiceVersion
|
||||
* which examined the version of the driver in use and initialized the variables
|
||||
* FspFsctlTransactCode and FspFsctlTransactBatchCode with either the new
|
||||
* FSP_IOCTL_TRANSACT* codes or the old FSP_FSCTL_TRANSACT* codes.
|
||||
*/
|
||||
ControlCode = Batch ?
|
||||
(DEBUGTEST(50) ? FspFsctlTransactBatchCode : FSP_FSCTL_TRANSACT_BATCH) :
|
||||
(DEBUGTEST(50) ? FspFsctlTransactCode : FSP_FSCTL_TRANSACT);
|
||||
|
||||
if (!DeviceIoControl(VolumeHandle,
|
||||
Batch ? FSP_FSCTL_TRANSACT_BATCH : FSP_FSCTL_TRANSACT,
|
||||
ControlCode,
|
||||
ResponseBuf, (DWORD)ResponseBufSize, RequestBuf, Bytes,
|
||||
&Bytes, 0))
|
||||
{
|
||||
@ -262,6 +282,79 @@ FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static BOOL WINAPI FspFsctlServiceVersionInitialize(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||
PWSTR ModuleFileName;
|
||||
SC_HANDLE ScmHandle = 0;
|
||||
SC_HANDLE SvcHandle = 0;
|
||||
QUERY_SERVICE_CONFIGW *ServiceConfig = 0;
|
||||
DWORD Size;
|
||||
|
||||
ScmHandle = OpenSCManagerW(0, 0, 0);
|
||||
if (0 == ScmHandle)
|
||||
goto exit;
|
||||
|
||||
SvcHandle = OpenServiceW(ScmHandle, DriverName, SERVICE_QUERY_CONFIG);
|
||||
if (0 == SvcHandle)
|
||||
goto exit;
|
||||
|
||||
if (QueryServiceConfig(SvcHandle, 0, 0, &Size) ||
|
||||
ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||
goto exit;
|
||||
|
||||
ServiceConfig = MemAlloc(Size);
|
||||
if (0 == ServiceConfig)
|
||||
goto exit;
|
||||
|
||||
if (!QueryServiceConfig(SvcHandle, ServiceConfig, Size, &Size))
|
||||
goto exit;
|
||||
|
||||
ModuleFileName = ServiceConfig->lpBinaryPathName;
|
||||
if (L'\\' == ModuleFileName[0] &&
|
||||
L'?' == ModuleFileName[1] &&
|
||||
L'?' == ModuleFileName[2] &&
|
||||
L'\\' == ModuleFileName[3])
|
||||
{
|
||||
if (L'U' == ModuleFileName[4] &&
|
||||
L'N' == ModuleFileName[5] &&
|
||||
L'C' == ModuleFileName[6] &&
|
||||
L'\\' == ModuleFileName[7])
|
||||
{
|
||||
ModuleFileName[6] = L'\\';
|
||||
ModuleFileName = ModuleFileName + 6;
|
||||
}
|
||||
else
|
||||
ModuleFileName = ModuleFileName + 4;
|
||||
}
|
||||
|
||||
FspGetModuleVersion(ModuleFileName, &FspFsctlServiceVersionValue);
|
||||
|
||||
if (0x0001000b /*v1.11*/ <= FspFsctlServiceVersionValue)
|
||||
{
|
||||
FspFsctlTransactCode = FSP_IOCTL_TRANSACT;
|
||||
FspFsctlTransactBatchCode = FSP_IOCTL_TRANSACT_BATCH;
|
||||
}
|
||||
|
||||
exit:
|
||||
MemFree(ServiceConfig);
|
||||
if (0 != SvcHandle)
|
||||
CloseServiceHandle(SvcHandle);
|
||||
if (0 != ScmHandle)
|
||||
CloseServiceHandle(ScmHandle);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static VOID FspFsctlServiceVersion(PUINT32 PVersion)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspFsctlServiceVersionInitOnce, FspFsctlServiceVersionInitialize, 0, 0);
|
||||
|
||||
if (0 != PVersion)
|
||||
*PVersion = FspFsctlServiceVersionValue;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsctlStartService(VOID)
|
||||
{
|
||||
static SRWLOCK Lock = SRWLOCK_INIT;
|
||||
|
@ -82,6 +82,8 @@ static struct fuse_opt fsp_fuse_core_opts[] =
|
||||
FUSE_OPT_KEY("fstypename=", 'F'),
|
||||
FUSE_OPT_KEY("volname=", 'v'),
|
||||
|
||||
FUSE_OPT_KEY("uidmap=", 'm'),
|
||||
|
||||
FSP_FUSE_CORE_OPT("SectorSize=%hu", VolumeParams.SectorSize, 4096),
|
||||
FSP_FUSE_CORE_OPT("SectorsPerAllocationUnit=%hu", VolumeParams.SectorsPerAllocationUnit, 1),
|
||||
FSP_FUSE_CORE_OPT("MaxComponentLength=%hu", VolumeParams.MaxComponentLength, 0),
|
||||
@ -293,43 +295,241 @@ static int fsp_fuse_sddl_to_security(const char *Sddl, PUINT8 Security, PULONG P
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fsp_fuse_username_to_uid(const char *username, int *puid)
|
||||
static int fsp_fuse_tokenuser_to_sid(HANDLE Token, PSID Sid, PULONG PSidSize)
|
||||
{
|
||||
union
|
||||
{
|
||||
TOKEN_USER V;
|
||||
UINT8 B[128];
|
||||
} InfoBuf;
|
||||
PTOKEN_USER InfoPtr = &InfoBuf.V;
|
||||
DWORD Size;
|
||||
int res = -1;
|
||||
|
||||
if (!GetTokenInformation(Token, TokenUser, InfoPtr, sizeof InfoBuf, &Size))
|
||||
{
|
||||
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||
goto exit;
|
||||
|
||||
InfoPtr = MemAlloc(Size);
|
||||
if (0 == InfoPtr)
|
||||
goto exit;
|
||||
|
||||
if (!GetTokenInformation(Token, TokenUser, InfoPtr, Size, &Size))
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Size = GetLengthSid(InfoPtr->User.Sid);
|
||||
if (*PSidSize >= Size)
|
||||
{
|
||||
memcpy(Sid, InfoPtr->User.Sid, Size);
|
||||
*PSidSize = Size;
|
||||
|
||||
res = 0;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (InfoPtr != &InfoBuf.V)
|
||||
MemFree(InfoPtr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fsp_fuse_tokenuser_is_azuread(HANDLE Token)
|
||||
{
|
||||
union
|
||||
{
|
||||
SID V;
|
||||
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||
} SidBuf;
|
||||
ULONG Size;
|
||||
PSID Sid = &SidBuf.V;
|
||||
BYTE Count, Authority;
|
||||
UINT32 SubAuthority0;
|
||||
|
||||
Size = sizeof SidBuf;
|
||||
if (-1 == fsp_fuse_tokenuser_to_sid(Token, &SidBuf.V, &Size))
|
||||
return 0;
|
||||
|
||||
Count = *GetSidSubAuthorityCount(Sid);
|
||||
Authority = GetSidIdentifierAuthority(Sid)->Value[5];
|
||||
SubAuthority0 = 2 <= Count ? *GetSidSubAuthority(Sid, 0) : 0;
|
||||
|
||||
return 12 == Authority && 1 == SubAuthority0;
|
||||
}
|
||||
|
||||
static int fsp_fuse_username_to_sid(const char *UserName, PSID Sid, PULONG PSidSize)
|
||||
{
|
||||
union
|
||||
{
|
||||
SID V;
|
||||
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||
} SidBuf;
|
||||
PSID SidPtr = &SidBuf.V;
|
||||
char Name[256], Domn[256];
|
||||
DWORD SidSize, NameSize, DomnSize;
|
||||
DWORD Size, NameSize, DomnSize;
|
||||
SID_NAME_USE Use;
|
||||
int res = -1;
|
||||
|
||||
if ('S' == UserName[0] && '-' == UserName[1] && '1' == UserName[2] && '-' == UserName[3])
|
||||
{
|
||||
if (!ConvertStringSidToSidA(UserName, &SidPtr))
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
NameSize = lstrlenA(UserName) + 1;
|
||||
if (sizeof Name / sizeof Name[0] < NameSize)
|
||||
goto exit;
|
||||
memcpy(Name, UserName, NameSize);
|
||||
for (PSTR P = Name, EndP = P + NameSize; EndP > P; P++)
|
||||
if ('+' == *P)
|
||||
*P = '\\';
|
||||
|
||||
Size = sizeof SidBuf;
|
||||
DomnSize = sizeof Domn / sizeof Domn[0];
|
||||
if (!LookupAccountNameA(0, Name, SidPtr, &Size, Domn, &DomnSize, &Use))
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Size = GetLengthSid(SidPtr);
|
||||
if (*PSidSize >= Size)
|
||||
{
|
||||
memcpy(Sid, SidPtr, Size);
|
||||
*PSidSize = Size;
|
||||
|
||||
res = 0;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (SidPtr != &SidBuf.V)
|
||||
LocalFree(SidPtr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fsp_fuse_username_to_uid(const char *UserName, int *PUid)
|
||||
{
|
||||
union
|
||||
{
|
||||
SID V;
|
||||
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||
} SidBuf;
|
||||
ULONG SidSize;
|
||||
UINT32 Uid;
|
||||
NTSTATUS Result;
|
||||
|
||||
*puid = 0;
|
||||
|
||||
NameSize = lstrlenA(username) + 1;
|
||||
if (sizeof Name / sizeof Name[0] < NameSize)
|
||||
return -1;
|
||||
memcpy(Name, username, NameSize);
|
||||
for (PSTR P = Name, EndP = P + NameSize; EndP > P; P++)
|
||||
if ('+' == *P)
|
||||
*P = '\\';
|
||||
*PUid = 0;
|
||||
|
||||
SidSize = sizeof SidBuf;
|
||||
DomnSize = sizeof Domn / sizeof Domn[0];
|
||||
if (!LookupAccountNameA(0, Name, &SidBuf, &SidSize, Domn, &DomnSize, &Use))
|
||||
if (-1 == fsp_fuse_username_to_sid(UserName, &SidBuf.V, &SidSize))
|
||||
return -1;
|
||||
|
||||
Result = FspPosixMapSidToUid(&SidBuf, &Uid);
|
||||
Result = FspPosixMapSidToUid(&SidBuf.V, &Uid);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return -1;
|
||||
|
||||
*puid = Uid;
|
||||
*PUid = Uid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsp_fuse_set_uidmap(const char *Spec)
|
||||
{
|
||||
char Buf[1024], *P = Buf, *UidP, *UserP, C;
|
||||
int Len;
|
||||
UINT32 Uid[8];
|
||||
PSID Sid[8];
|
||||
union
|
||||
{
|
||||
SID V;
|
||||
UINT8 B[SECURITY_MAX_SID_SIZE];
|
||||
} SidBuf[8];
|
||||
ULONG SidSize;
|
||||
ULONG Count;
|
||||
NTSTATUS Result;
|
||||
int res = -1;
|
||||
|
||||
Len = lstrlenA(Spec);
|
||||
if (sizeof Buf <= Len)
|
||||
return -1;
|
||||
memcpy(Buf, Spec, Len + 1);
|
||||
|
||||
Count = 0;
|
||||
for (;;)
|
||||
{
|
||||
if (sizeof Uid / sizeof Uid[0] <= Count)
|
||||
{
|
||||
/* out of space */
|
||||
goto exit;
|
||||
}
|
||||
|
||||
UidP = P;
|
||||
for (; '\0' != (C = *P) && ';' != C && ':' != C; P++)
|
||||
;
|
||||
*P = '\0';
|
||||
|
||||
if (UidP == P)
|
||||
break;
|
||||
|
||||
Uid[Count] = strtouint(UidP, 0, 10, 0);
|
||||
if (0 == Uid[Count])
|
||||
{
|
||||
/* invalid uid */
|
||||
goto exit;
|
||||
}
|
||||
|
||||
UserP = 0;
|
||||
if (':' == C)
|
||||
{
|
||||
UserP = ++P;
|
||||
for (; '\0' != (C = *P) && ';' != C; P++)
|
||||
;
|
||||
*P = '\0';
|
||||
}
|
||||
|
||||
if (0 != UserP && '\0' != *UserP)
|
||||
{
|
||||
SidSize = sizeof SidBuf[Count];
|
||||
if (-1 == fsp_fuse_username_to_sid(UserP, &SidBuf[Count].V, &SidSize))
|
||||
{
|
||||
/* invalid SID */
|
||||
goto exit;
|
||||
}
|
||||
Sid[Count] = &SidBuf[Count].V;
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE Token;
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
|
||||
{
|
||||
SidSize = sizeof SidBuf[Count];
|
||||
if (-1 == fsp_fuse_tokenuser_to_sid(Token, &SidBuf[Count].V, &SidSize))
|
||||
{
|
||||
/* invalid SID */
|
||||
CloseHandle(Token);
|
||||
goto exit;
|
||||
}
|
||||
CloseHandle(Token);
|
||||
Sid[Count] = &SidBuf[Count].V;
|
||||
}
|
||||
}
|
||||
|
||||
Count++;
|
||||
|
||||
if ('\0' == C)
|
||||
break;
|
||||
|
||||
P++;
|
||||
}
|
||||
|
||||
Result = FspPosixSetUidMap(Uid, Sid, Count);
|
||||
res = NT_SUCCESS(Result) ? 0 : -1;
|
||||
|
||||
exit:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fsp_fuse_utf8towcs_trunc(
|
||||
const char *Str, int StrLen,
|
||||
PWSTR Wcs, int WcsLen)
|
||||
@ -424,6 +624,7 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
" -o KeepFileCache do not discard cache when files are closed\n"
|
||||
" -o LegacyUnlinkRename do not support new POSIX unlink/rename\n"
|
||||
" -o ThreadCount number of file system dispatcher threads\n"
|
||||
" -o uidmap=UID:SID[;...] explicit UID <-> SID map (max 8 entries)\n"
|
||||
);
|
||||
opt_data->help = 1;
|
||||
return 1;
|
||||
@ -531,6 +732,14 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
||||
if (0 == opt_data->VolumeLabelLength)
|
||||
return -1;
|
||||
return 0;
|
||||
case 'm':
|
||||
arg += sizeof "uidmap=" - 1;
|
||||
if (-1 == fsp_fuse_set_uidmap(arg))
|
||||
{
|
||||
opt_data->set_uidmap = -1;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,6 +788,11 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
ErrorMessage = L": invalid user or group name.";
|
||||
goto fail;
|
||||
}
|
||||
else if (-1 == opt_data.set_uidmap)
|
||||
{
|
||||
ErrorMessage = L": invalid uidmap.";
|
||||
goto fail;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (opt_data.help)
|
||||
@ -601,6 +815,10 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
||||
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token))
|
||||
{
|
||||
/* if an AzureAD user and no uidmap specified, set a default uidmap that matches Cygwin */
|
||||
if (!opt_data.set_uidmap && fsp_fuse_tokenuser_is_azuread(Token))
|
||||
fsp_fuse_set_uidmap("4096:");
|
||||
|
||||
fsp_fuse_get_token_uidgid(Token, TokenUser,
|
||||
opt_data.set_uid && -1 == opt_data.uid ? &opt_data.uid : 0,
|
||||
opt_data.set_gid && -1 == opt_data.gid ? &opt_data.gid : 0);
|
||||
|
@ -1028,7 +1028,7 @@ static NTSTATUS fsp_fuse_intf_Create(FSP_FILE_SYSTEM *FileSystem,
|
||||
{
|
||||
Result = FspFileSystemEnumerateEa(FileSystem,
|
||||
fsp_fuse_intf_SetEaEntry, contexthdr->PosixPath, ExtraBuffer, ExtraLength);
|
||||
if (!NT_SUCCESS(Result))
|
||||
if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result)
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
@ -1256,7 +1256,7 @@ static NTSTATUS fsp_fuse_intf_Overwrite(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
Result = FspFileSystemEnumerateEa(FileSystem,
|
||||
fsp_fuse_intf_SetEaEntry, filedesc->PosixPath, Ea, EaLength);
|
||||
if (!NT_SUCCESS(Result))
|
||||
if (!NT_SUCCESS(Result) && STATUS_INVALID_DEVICE_REQUEST != Result)
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,15 @@ static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
|
||||
f->VolumeParams.PostDispositionWhenNecessaryOnly = 1;
|
||||
if (0 != f->ops.listxattr && 0 != f->ops.getxattr &&
|
||||
0 != f->ops.setxattr && 0 != f->ops.removexattr)
|
||||
f->VolumeParams.ExtendedAttributes = 1;
|
||||
{
|
||||
char buf[1024];
|
||||
int err;
|
||||
|
||||
/* if this fails with ENOSYS, then no EA support */
|
||||
err = f->ops.getxattr("/",
|
||||
"non-existant-a11ec902d22f4ec49003af15282d3b00", buf, sizeof buf);
|
||||
f->VolumeParams.ExtendedAttributes = -ENOSYS_(f->env) != err;
|
||||
}
|
||||
|
||||
/* the FSD does not currently limit these VolumeParams fields; do so here! */
|
||||
if (f->VolumeParams.SectorSize < FSP_FUSE_SECTORSIZE_MIN ||
|
||||
@ -196,7 +204,7 @@ static NTSTATUS fsp_fuse_loop_start(struct fuse *f)
|
||||
f->VolumeParams.SectorSize = FSP_FUSE_SECTORSIZE_MAX;
|
||||
if (f->VolumeParams.SectorsPerAllocationUnit == 0)
|
||||
f->VolumeParams.SectorsPerAllocationUnit = 1;
|
||||
if (f->VolumeParams.MaxComponentLength > 255)
|
||||
if (f->VolumeParams.MaxComponentLength == 0 || f->VolumeParams.MaxComponentLength > 255)
|
||||
f->VolumeParams.MaxComponentLength = 255;
|
||||
|
||||
if (0 == f->VolumeParams.VolumeCreationTime)
|
||||
|
@ -147,6 +147,7 @@ struct fsp_fuse_core_opt_data
|
||||
set_create_dir_umask, create_dir_umask,
|
||||
set_uid, uid, username_to_uid_result,
|
||||
set_gid, gid,
|
||||
set_uidmap,
|
||||
set_attr_timeout, attr_timeout,
|
||||
rellinks,
|
||||
dothidden;
|
||||
|
@ -46,6 +46,15 @@
|
||||
#define DEBUGLOGSID(fmt, Sid) ((void)0)
|
||||
#endif
|
||||
|
||||
/* DEBUGTEST */
|
||||
#if !defined(NDEBUG)
|
||||
ULONG DebugRandom(VOID);
|
||||
#define DEBUGTEST(Percent) \
|
||||
(DebugRandom() <= (Percent) * 0x7fff / 100)
|
||||
#else
|
||||
#define DEBUGTEST(Percent) (TRUE)
|
||||
#endif
|
||||
|
||||
VOID FspWksidFinalize(BOOLEAN Dynamic);
|
||||
VOID FspPosixFinalize(BOOLEAN Dynamic);
|
||||
VOID FspEventLogFinalize(BOOLEAN Dynamic);
|
||||
@ -72,6 +81,7 @@ ULONG FspLdapGetDefaultNamingContext(PVOID Ldap, PWSTR *PValue);
|
||||
ULONG FspLdapGetTrustPosixOffset(PVOID Ldap, PWSTR Context, PWSTR Domain, PWSTR *PValue);
|
||||
|
||||
PWSTR FspDiagIdent(VOID);
|
||||
NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion);
|
||||
|
||||
#define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1)
|
||||
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <dbt.h>
|
||||
|
||||
static INIT_ONCE FspMountInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static NTSTATUS (NTAPI *FspNtOpenSymbolicLinkObject)(
|
||||
@ -28,21 +29,30 @@ static NTSTATUS (NTAPI *FspNtMakeTemporaryObject)(
|
||||
HANDLE Handle);
|
||||
static NTSTATUS (NTAPI *FspNtClose)(
|
||||
HANDLE Handle);
|
||||
static BOOLEAN FspMountDoNotUseLauncher;
|
||||
static BOOLEAN FspMountDoNotUseLauncherValue;
|
||||
static BOOLEAN FspMountBroadcastDriveChangeValue;
|
||||
|
||||
static VOID FspMountInitializeFromRegistry(VOID)
|
||||
{
|
||||
DWORD MountDoNotUseLauncher;
|
||||
DWORD Value;
|
||||
DWORD Size;
|
||||
LONG Result;
|
||||
|
||||
MountDoNotUseLauncher = 0;
|
||||
Size = sizeof MountDoNotUseLauncher;
|
||||
Value = 0;
|
||||
Size = sizeof Value;
|
||||
Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
|
||||
L"MountDoNotUseLauncher",
|
||||
RRF_RT_REG_DWORD, 0, &MountDoNotUseLauncher, &Size);
|
||||
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||
if (ERROR_SUCCESS == Result)
|
||||
FspMountDoNotUseLauncher = !!MountDoNotUseLauncher;
|
||||
FspMountDoNotUseLauncherValue = !!Value;
|
||||
|
||||
Value = 0;
|
||||
Size = sizeof Value;
|
||||
Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
|
||||
L"MountBroadcastDriveChange",
|
||||
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||
if (ERROR_SUCCESS == Result)
|
||||
FspMountBroadcastDriveChangeValue = !!Value;
|
||||
}
|
||||
|
||||
static BOOL WINAPI FspMountInitialize(
|
||||
@ -375,6 +385,48 @@ static NTSTATUS FspLauncherDefineDosDevice(
|
||||
return !NT_SUCCESS(Result) ? Result : FspNtStatusFromWin32(ErrorCode);
|
||||
}
|
||||
|
||||
static VOID FspMountBroadcastDriveChange(PWSTR MountPoint, WPARAM WParam)
|
||||
{
|
||||
/*
|
||||
* DefineDosDeviceW (either directly or via the CSRSS) broadcasts a WM_DEVICECHANGE message
|
||||
* when a drive is added/removed. Unfortunately on some systems this broadcast fails. The
|
||||
* result is that Explorer does not receive the WM_DEVICECHANGE notification and does not
|
||||
* become aware of the drive change. This results in only minor UI issues for local drives,
|
||||
* but more seriously it makes network drives inaccessible from some Explorer windows.
|
||||
*
|
||||
* The problem is that BroadcastSystemMessage can hang indefinitely when supplied the flags
|
||||
* NOHANG | FORCEIFHUNG | NOTIMEOUTIFNOTHUNG. The NOTIMEOUTIFNOTHUNG flag instructs the BSM
|
||||
* API to not timeout an app that is not considered hung; however an app that is not hung may
|
||||
* still fail to respond to a broadcasted message indefinitely. This can result in the BSM
|
||||
* API never returning ("hanging").
|
||||
*
|
||||
* To resolve this we simply call BroadcastSystemMessage with BSF_POSTMESSAGE. (It would work
|
||||
* with BSF_NOHANG | BSF_FORCEIFHUNG and without NOTIMEOUTIFNOTHUNG, but BSF_POSTMESSAGE is
|
||||
* faster).
|
||||
*/
|
||||
|
||||
BOOLEAN IsLocalSystem;
|
||||
DEV_BROADCAST_VOLUME DriveChange;
|
||||
DWORD Flags, Recipients;
|
||||
|
||||
FspServiceContextCheck(0, &IsLocalSystem);
|
||||
|
||||
memset(&DriveChange, 0, sizeof DriveChange);
|
||||
DriveChange.dbcv_size = sizeof DriveChange;
|
||||
DriveChange.dbcv_devicetype = DBT_DEVTYP_VOLUME;
|
||||
DriveChange.dbcv_flags = DBTF_NET;
|
||||
DriveChange.dbcv_unitmask = 1 << (MountPoint[0] - 'a');
|
||||
|
||||
Flags = BSF_POSTMESSAGE;
|
||||
Recipients = BSM_APPLICATIONS | (IsLocalSystem ? BSM_ALLDESKTOPS : 0);
|
||||
BroadcastSystemMessageW(
|
||||
Flags,
|
||||
&Recipients,
|
||||
WM_DEVICECHANGE,
|
||||
WParam,
|
||||
(LPARAM)&DriveChange);
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PMountHandle)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
@ -384,7 +436,7 @@ static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PM
|
||||
|
||||
Result = FspServiceContextCheck(0, &IsLocalSystem);
|
||||
IsServiceContext = NT_SUCCESS(Result) && !IsLocalSystem;
|
||||
if (IsServiceContext && !FspMountDoNotUseLauncher)
|
||||
if (IsServiceContext && !FspMountDoNotUseLauncherValue)
|
||||
{
|
||||
/*
|
||||
* If the current process is in the service context but not LocalSystem,
|
||||
@ -402,6 +454,13 @@ static NTSTATUS FspMountSet_Drive(PWSTR VolumeName, PWSTR MountPoint, PHANDLE PM
|
||||
{
|
||||
if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, MountPoint, VolumeName))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
/*
|
||||
* On some systems DefineDosDeviceW fails to properly broadcast the WM_DEVICECHANGE
|
||||
* notification. So use a workaround. See comments in FspMountBroadcastDriveChange.
|
||||
*/
|
||||
if (FspMountBroadcastDriveChangeValue)
|
||||
FspMountBroadcastDriveChange(MountPoint, DBT_DEVICEARRIVAL);
|
||||
}
|
||||
|
||||
if (0 != FspNtOpenSymbolicLinkObject)
|
||||
@ -457,9 +516,18 @@ static NTSTATUS FspMountRemove_Drive(PWSTR VolumeName, PWSTR MountPoint, HANDLE
|
||||
*/
|
||||
Result = FspLauncherDefineDosDevice(L'-', MountPoint, VolumeName);
|
||||
else
|
||||
{
|
||||
Result = DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_REMOVE_DEFINITION | DDD_EXACT_MATCH_ON_REMOVE,
|
||||
MountPoint, VolumeName) ? STATUS_SUCCESS : FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
/*
|
||||
* On some systems DefineDosDeviceW fails to properly broadcast the WM_DEVICECHANGE
|
||||
* notification. So use a workaround. See comments in FspMountBroadcastDriveChange.
|
||||
*/
|
||||
if (FspMountBroadcastDriveChangeValue)
|
||||
FspMountBroadcastDriveChange(MountPoint, DBT_DEVICEREMOVECOMPLETE);
|
||||
}
|
||||
|
||||
if (0 != MountHandle)
|
||||
FspNtClose(MountHandle);
|
||||
|
||||
|
@ -215,3 +215,36 @@ FSP_API NTSTATUS FspVersion(PUINT32 PVersion)
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion)
|
||||
{
|
||||
/* internal only: get version of any module */
|
||||
|
||||
PVOID VersionInfo;
|
||||
DWORD Size;
|
||||
VS_FIXEDFILEINFO *FixedFileInfo = 0;
|
||||
UINT32 Version;
|
||||
|
||||
*PVersion = 0;
|
||||
|
||||
Size = GetFileVersionInfoSizeW(ModuleFileName, &Size/*dummy*/);
|
||||
if (0 < Size)
|
||||
{
|
||||
VersionInfo = MemAlloc(Size);
|
||||
if (0 != VersionInfo &&
|
||||
GetFileVersionInfoW(ModuleFileName, 0, Size, VersionInfo) &&
|
||||
VerQueryValueW(VersionInfo, L"\\", &FixedFileInfo, &Size))
|
||||
{
|
||||
Version = FixedFileInfo->dwFileVersionMS;
|
||||
}
|
||||
|
||||
MemFree(VersionInfo);
|
||||
}
|
||||
|
||||
if (0 == FixedFileInfo)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
*PVersion = Version;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include <shared/ku/library.h>
|
||||
|
||||
FSP_API NTSTATUS FspPosixSetUidMap(UINT32 Uid[], PSID Sid[], ULONG Count);
|
||||
FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid);
|
||||
FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid);
|
||||
static PISID FspPosixCreateSid(BYTE Authority, ULONG Count, ...);
|
||||
@ -58,6 +59,7 @@ FSP_API VOID FspPosixDecodeWindowsPath(PWSTR WindowsPath, ULONG Size);
|
||||
|
||||
#if defined(_KERNEL_MODE)
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspPosixSetUidMap)
|
||||
#pragma alloc_text(PAGE, FspPosixMapUidToSid)
|
||||
#pragma alloc_text(PAGE, FspPosixMapSidToUid)
|
||||
#pragma alloc_text(PAGE, FspPosixCreateSid)
|
||||
@ -345,6 +347,8 @@ VOID FspPosixFinalize(BOOLEAN Dynamic)
|
||||
|
||||
if (Dynamic)
|
||||
{
|
||||
FspPosixSetUidMap(0, 0, 0);
|
||||
|
||||
MemFree(FspTrustedDomains);
|
||||
MemFree(FspAccountDomainSid);
|
||||
MemFree(FspPrimaryDomainSid);
|
||||
@ -425,6 +429,52 @@ static inline BOOLEAN FspPosixIsRelativeSid(PISID Sid1, PISID Sid2)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static UINT32 FspPosixUidMap_Uid[8];
|
||||
static PSID FspPosixUidMap_Sid[8];
|
||||
static ULONG FspPosixUidMap_Cnt = 0;
|
||||
|
||||
FSP_API NTSTATUS FspPosixSetUidMap(UINT32 Uid[], PSID Sid[], ULONG Count)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
if (sizeof FspPosixUidMap_Uid / sizeof FspPosixUidMap_Uid[0] < Count)
|
||||
Count = sizeof FspPosixUidMap_Uid / sizeof FspPosixUidMap_Uid[0];
|
||||
|
||||
for (ULONG I = 0; FspPosixUidMap_Cnt > I; I++)
|
||||
{
|
||||
MemFree(FspPosixUidMap_Sid[I]);
|
||||
FspPosixUidMap_Uid[I] = 0;
|
||||
FspPosixUidMap_Sid[I] = 0;
|
||||
}
|
||||
|
||||
FspPosixUidMap_Cnt = 0;
|
||||
for (ULONG I = 0; Count > I; I++)
|
||||
{
|
||||
ULONG L = GetLengthSid(Sid[I]);
|
||||
PSID S = MemAlloc(L);
|
||||
if (0 == S)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
FspPosixUidMap_Uid[I] = Uid[I];
|
||||
FspPosixUidMap_Sid[I] = S;
|
||||
memcpy(S, Sid[I], L);
|
||||
FspPosixUidMap_Cnt = I + 1;
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
FspPosixSetUidMap(0, 0, 0);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
@ -433,6 +483,20 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
||||
|
||||
*PSid = 0;
|
||||
|
||||
/*
|
||||
* UidMap overrides default UID <-> SID mapping.
|
||||
*/
|
||||
for (ULONG I = 0; FspPosixUidMap_Cnt > I; I++)
|
||||
if (FspPosixUidMap_Uid[I] == Uid)
|
||||
{
|
||||
ULONG L = GetLengthSid(FspPosixUidMap_Sid[I]);
|
||||
PSID S = MemAlloc(L);
|
||||
if (0 != S)
|
||||
memcpy(S, FspPosixUidMap_Sid[I], L);
|
||||
*PSid = S;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* UID namespace partitioning (from [IDMAP] rules):
|
||||
*
|
||||
@ -556,6 +620,7 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
||||
else if (FspUnmappedUid != Uid && 0x1000 <= Uid && Uid < 0x100000)
|
||||
*PSid = FspPosixCreateSid(5, 2, Uid >> 12, Uid & 0xfff);
|
||||
|
||||
exit:
|
||||
if (0 == *PSid)
|
||||
*PSid = FspUnmappedSid;
|
||||
|
||||
@ -577,6 +642,16 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
||||
if (!IsValidSid(Sid) || 0 == (Count = *GetSidSubAuthorityCount(Sid)))
|
||||
return STATUS_INVALID_SID;
|
||||
|
||||
/*
|
||||
* UidMap overrides default UID <-> SID mapping.
|
||||
*/
|
||||
for (ULONG I = 0; FspPosixUidMap_Cnt > I; I++)
|
||||
if (EqualSid(FspPosixUidMap_Sid[I], Sid))
|
||||
{
|
||||
*PUid = FspPosixUidMap_Uid[I];
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Authority = GetSidIdentifierAuthority(Sid)->Value[5];
|
||||
SubAuthority0 = 2 <= Count ? *GetSidSubAuthority(Sid, 0) : 0;
|
||||
Rid = *GetSidSubAuthority(Sid, Count - 1);
|
||||
@ -671,6 +746,7 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
||||
*PUid = 0x10000 + 0x100 * Authority + Rid;
|
||||
}
|
||||
|
||||
exit:
|
||||
if (-1 == *PUid)
|
||||
*PUid = FspUnmappedUid;
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
FAST_IO_DEVICE_CONTROL FspFastIoDeviceControl;
|
||||
static NTSTATUS FspFsctlDeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static NTSTATUS FspFsvrtDeviceControl(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
static BOOLEAN FspFsvrtDeviceControlStorageQuery(
|
||||
@ -33,6 +36,8 @@ static FSP_IOP_REQUEST_FINI FspFsvolDeviceControlRequestFini;
|
||||
FSP_DRIVER_DISPATCH FspDeviceControl;
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspFastIoDeviceControl)
|
||||
#pragma alloc_text(PAGE, FspFsctlDeviceControl)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceControl)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceControlStorageQuery)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceControl)
|
||||
@ -46,6 +51,81 @@ enum
|
||||
RequestFileNode = 0,
|
||||
};
|
||||
|
||||
BOOLEAN FspFastIoDeviceControl(
|
||||
PFILE_OBJECT FileObject,
|
||||
BOOLEAN CanWait,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
ULONG IoControlCode,
|
||||
PIO_STATUS_BLOCK IoStatus,
|
||||
PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
FSP_ENTER_BOOL(PAGED_CODE());
|
||||
/* cannot use FSP_ENTER_FIO() because it only supports fsvol devices */
|
||||
|
||||
Result = DEBUGTEST(50) &&
|
||||
CanWait &&
|
||||
FSP_IOCTL_TRANSACT == IoControlCode &&
|
||||
FspFsctlDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind;
|
||||
if (!Result)
|
||||
FSP_RETURN();
|
||||
|
||||
#if 0
|
||||
PDEVICE_OBJECT FsctlDeviceObject = DeviceObject;
|
||||
if (!FspDeviceReference(FsctlDeviceObject))
|
||||
{
|
||||
IoStatus->Status = STATUS_CANCELLED;
|
||||
IoStatus->Information = 0;
|
||||
FSP_RETURN();
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSERT(0 == IoGetTopLevelIrp());
|
||||
IoSetTopLevelIrp((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP);
|
||||
|
||||
IoStatus->Status = FspVolumeFastTransact(
|
||||
FileObject->FsContext2,
|
||||
IoControlCode,
|
||||
InputBuffer,
|
||||
InputBufferLength,
|
||||
OutputBuffer,
|
||||
OutputBufferLength,
|
||||
IoStatus,
|
||||
(PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP);
|
||||
|
||||
IoSetTopLevelIrp(0);
|
||||
|
||||
#if 0
|
||||
FspDeviceDereference(FsctlDeviceObject);
|
||||
#endif
|
||||
|
||||
FSP_LEAVE_BOOL(
|
||||
"%s, FileObject=%p",
|
||||
IoctlCodeSym(IoControlCode),
|
||||
FileObject);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsctlDeviceControl(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result = STATUS_INVALID_DEVICE_REQUEST;
|
||||
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case FSP_IOCTL_TRANSACT:
|
||||
case FSP_IOCTL_TRANSACT_BATCH:
|
||||
case FSP_IOCTL_TRANSACT_INTERNAL:
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeTransact(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvrtDeviceControl(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
|
||||
{
|
||||
@ -258,6 +338,8 @@ NTSTATUS FspDeviceControl(
|
||||
FSP_RETURN(Result = FspFsvolDeviceControl(DeviceObject, Irp, IrpSp));
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
FSP_RETURN(Result = FspFsvrtDeviceControl(DeviceObject, Irp, IrpSp));
|
||||
case FspFsctlDeviceExtensionKind:
|
||||
FSP_RETURN(Result = FspFsctlDeviceControl(DeviceObject, Irp, IrpSp));
|
||||
default:
|
||||
FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ NTSTATUS DriverEntry(
|
||||
//FspFastIoDispatch.FastIoUnlockSingle = 0;
|
||||
//FspFastIoDispatch.FastIoUnlockAll = 0;
|
||||
//FspFastIoDispatch.FastIoUnlockAllByKey = 0;
|
||||
//FspFastIoDispatch.FastIoDeviceControl = 0;
|
||||
FspFastIoDispatch.FastIoDeviceControl = FspFastIoDeviceControl;
|
||||
FspFastIoDispatch.AcquireFileForNtCreateSection = FspAcquireFileForNtCreateSection;
|
||||
FspFastIoDispatch.ReleaseFileForNtCreateSection = FspReleaseFileForNtCreateSection;
|
||||
//FspFastIoDispatch.FastIoDetachDevice = 0;
|
||||
|
@ -306,8 +306,9 @@ VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Sta
|
||||
return Result
|
||||
#define FSP_ENTER_FIO(...) \
|
||||
PDEVICE_OBJECT FsvolDeviceObject; \
|
||||
if (FspFsmupDeviceExtensionKind == FspDeviceExtension(DeviceObject)->Kind)\
|
||||
switch (FspDeviceExtension(DeviceObject)->Kind)\
|
||||
{ \
|
||||
case FspFsmupDeviceExtensionKind: \
|
||||
FsvolDeviceObject = FspMupGetFsvolDeviceObject(FileObject);\
|
||||
if (0 == FsvolDeviceObject) \
|
||||
{ \
|
||||
@ -315,9 +316,13 @@ VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Sta
|
||||
IoStatus->Information = 0; \
|
||||
return TRUE; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
break; \
|
||||
case FspFsvolDeviceExtensionKind: \
|
||||
FsvolDeviceObject = DeviceObject;\
|
||||
break; \
|
||||
default: \
|
||||
return FALSE; \
|
||||
} \
|
||||
BOOLEAN Result = TRUE; \
|
||||
BOOLEAN fsp_device_deref = FALSE; \
|
||||
FSP_ENTER_(ioentr, __VA_ARGS__); \
|
||||
@ -420,6 +425,7 @@ FSP_IOPREP_DISPATCH FspFsvolWritePrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolWriteComplete;
|
||||
|
||||
/* fast I/O and resource acquisition callbacks */
|
||||
FAST_IO_DEVICE_CONTROL FspFastIoDeviceControl;
|
||||
FAST_IO_READ FspFastIoRead;
|
||||
FAST_IO_WRITE FspFastIoWrite;
|
||||
FAST_IO_QUERY_BASIC_INFO FspFastIoQueryBasicInfo;
|
||||
@ -682,6 +688,8 @@ NTSTATUS FspOplockFsctrl(
|
||||
FspNotifyFullReportChange(NS, NL, (PSTRING)(FN), FO, 0, (PSTRING)(NP), F, A, 0)
|
||||
#define FSP_NEXT_EA(Ea, EaEnd) \
|
||||
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))
|
||||
#define FSP_FUNCTION_FROM_CTL_CODE(ControlCode)\
|
||||
(((ControlCode) >> 2) & 0xfff)
|
||||
|
||||
/* utility: synchronous work queue */
|
||||
typedef struct
|
||||
@ -921,7 +929,7 @@ retry:
|
||||
{
|
||||
if (PsIsThreadTerminating(PsGetCurrentThread()))
|
||||
return STATUS_THREAD_IS_TERMINATING;
|
||||
if (0 != Irp && Irp->Cancel)
|
||||
if (0 != Irp && ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG >= Irp || Irp->Cancel))
|
||||
return STATUS_CANCELLED;
|
||||
if (0 != ExpirationTime)
|
||||
{
|
||||
@ -1419,6 +1427,15 @@ NTSTATUS FspVolumeGetNameList(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeTransact(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeFastTransact(
|
||||
PDEVICE_OBJECT FsvolDeviceObject,
|
||||
ULONG ControlCode,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
PIO_STATUS_BLOCK IoStatus,
|
||||
PIRP Irp);
|
||||
NTSTATUS FspVolumeTransactFsext(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeStop(
|
||||
@ -1429,6 +1446,7 @@ NTSTATUS FspVolumeWork(
|
||||
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
|
||||
/* file objects */
|
||||
//#define FSP_FILE_NODE_NO_PGIO
|
||||
#define FspFileNodeKind(FileNode) \
|
||||
(((FSP_FILE_NODE *)FileNode)->Header.NodeTypeCode)
|
||||
#define FspFileNodeIsValid(FileNode) \
|
||||
|
@ -407,8 +407,10 @@ VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
||||
if (Flags & FspFileNodeAcquireMain)
|
||||
ExAcquireResourceSharedLite(FileNode->Header.Resource, TRUE);
|
||||
|
||||
#if !defined(FSP_FILE_NODE_NO_PGIO)
|
||||
if (Flags & FspFileNodeAcquirePgio)
|
||||
ExAcquireResourceSharedLite(FileNode->Header.PagingIoResource, TRUE);
|
||||
#endif
|
||||
|
||||
FSP_FILE_NODE_SET_FLAGS();
|
||||
}
|
||||
@ -432,6 +434,7 @@ BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLE
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if !defined(FSP_FILE_NODE_NO_PGIO)
|
||||
if (Flags & FspFileNodeAcquirePgio)
|
||||
{
|
||||
Result = ExAcquireResourceSharedLite(FileNode->Header.PagingIoResource, Wait);
|
||||
@ -442,6 +445,7 @@ BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags, BOOLE
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Result)
|
||||
FSP_FILE_NODE_SET_FLAGS();
|
||||
@ -462,8 +466,10 @@ VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
||||
if (Flags & FspFileNodeAcquireMain)
|
||||
ExAcquireResourceExclusiveLite(FileNode->Header.Resource, TRUE);
|
||||
|
||||
#if !defined(FSP_FILE_NODE_NO_PGIO)
|
||||
if (Flags & FspFileNodeAcquirePgio)
|
||||
ExAcquireResourceExclusiveLite(FileNode->Header.PagingIoResource, TRUE);
|
||||
#endif
|
||||
|
||||
FSP_FILE_NODE_SET_FLAGS();
|
||||
}
|
||||
@ -487,6 +493,7 @@ BOOLEAN FspFileNodeTryAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags, BO
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if !defined(FSP_FILE_NODE_NO_PGIO)
|
||||
if (Flags & FspFileNodeAcquirePgio)
|
||||
{
|
||||
Result = ExAcquireResourceExclusiveLite(FileNode->Header.PagingIoResource, Wait);
|
||||
@ -497,6 +504,7 @@ BOOLEAN FspFileNodeTryAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags, BO
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Result)
|
||||
FSP_FILE_NODE_SET_FLAGS();
|
||||
@ -513,8 +521,10 @@ VOID FspFileNodeConvertExclusiveToSharedF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
||||
|
||||
FSP_FILE_NODE_GET_FLAGS();
|
||||
|
||||
#if !defined(FSP_FILE_NODE_NO_PGIO)
|
||||
if (Flags & FspFileNodeAcquirePgio)
|
||||
ExConvertExclusiveToSharedLite(FileNode->Header.PagingIoResource);
|
||||
#endif
|
||||
|
||||
if (Flags & FspFileNodeAcquireMain)
|
||||
ExConvertExclusiveToSharedLite(FileNode->Header.Resource);
|
||||
@ -534,8 +544,10 @@ VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
|
||||
if (Flags & FspFileNodeAcquireMain)
|
||||
ExSetResourceOwnerPointer(FileNode->Header.Resource, Owner);
|
||||
|
||||
#if !defined(FSP_FILE_NODE_NO_PGIO)
|
||||
if (Flags & FspFileNodeAcquirePgio)
|
||||
ExSetResourceOwnerPointer(FileNode->Header.PagingIoResource, Owner);
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
||||
@ -548,8 +560,10 @@ VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags)
|
||||
FSP_FILE_NODE_GET_FLAGS();
|
||||
FSP_FILE_NODE_ASSERT_FLAGS_SET();
|
||||
|
||||
#if !defined(FSP_FILE_NODE_NO_PGIO)
|
||||
if (Flags & FspFileNodeAcquirePgio)
|
||||
ExReleaseResourceLite(FileNode->Header.PagingIoResource);
|
||||
#endif
|
||||
|
||||
if (Flags & FspFileNodeAcquireMain)
|
||||
ExReleaseResourceLite(FileNode->Header.Resource);
|
||||
@ -569,6 +583,7 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
|
||||
|
||||
Owner = (PVOID)((UINT_PTR)Owner | 3);
|
||||
|
||||
#if !defined(FSP_FILE_NODE_NO_PGIO)
|
||||
if (Flags & FspFileNodeAcquirePgio)
|
||||
{
|
||||
if (ExIsResourceAcquiredLite(FileNode->Header.PagingIoResource))
|
||||
@ -576,6 +591,7 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
|
||||
else
|
||||
ExReleaseResourceForThreadLite(FileNode->Header.PagingIoResource, (ERESOURCE_THREAD)Owner);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Flags & FspFileNodeAcquireMain)
|
||||
{
|
||||
|
@ -152,6 +152,7 @@
|
||||
#define FspIoqEventSet(E) KeSetEvent(E, 1, FALSE)
|
||||
#define FspIoqEventCancellableWait(E,T,I) FsRtlCancellableWaitForSingleObject(E,T,I)
|
||||
#define FspIoqEventClear(E) KeClearEvent(E)
|
||||
#error FsRtlCancellableWaitForSingleObject needs to support FSRTL_FAST_IO_TOP_LEVEL_IRP cancellation
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
116
src/sys/volume.c
116
src/sys/volume.c
@ -46,6 +46,15 @@ static NTSTATUS FspVolumeGetNameListNoLock(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeTransact(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeFastTransact(
|
||||
PDEVICE_OBJECT FsvolDeviceObject,
|
||||
ULONG ControlCode,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
PIO_STATUS_BLOCK IoStatus,
|
||||
PIRP Irp);
|
||||
NTSTATUS FspVolumeTransactFsext(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeStop(
|
||||
@ -71,6 +80,7 @@ NTSTATUS FspVolumeWork(
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
||||
#pragma alloc_text(PAGE, FspVolumeTransact)
|
||||
#pragma alloc_text(PAGE, FspVolumeFastTransact)
|
||||
#pragma alloc_text(PAGE, FspVolumeTransactFsext)
|
||||
#pragma alloc_text(PAGE, FspVolumeStop)
|
||||
#pragma alloc_text(PAGE, FspVolumeNotify)
|
||||
@ -764,22 +774,35 @@ NTSTATUS FspVolumeTransact(
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
|
||||
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
|
||||
ASSERT(
|
||||
FSP_FSCTL_TRANSACT == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||
FSP_FSCTL_TRANSACT_BATCH == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||
FSP_FSCTL_TRANSACT_INTERNAL == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||
(
|
||||
IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction &&
|
||||
IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction &&
|
||||
(
|
||||
FSP_FSCTL_TRANSACT == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||
FSP_FSCTL_TRANSACT_BATCH == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||
FSP_FSCTL_TRANSACT_INTERNAL == IrpSp->Parameters.FileSystemControl.FsControlCode
|
||||
)
|
||||
) ||
|
||||
(
|
||||
IRP_MJ_DEVICE_CONTROL == IrpSp->MajorFunction &&
|
||||
(
|
||||
FSP_IOCTL_TRANSACT == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||
FSP_IOCTL_TRANSACT_BATCH == IrpSp->Parameters.FileSystemControl.FsControlCode ||
|
||||
FSP_IOCTL_TRANSACT_INTERNAL == IrpSp->Parameters.FileSystemControl.FsControlCode
|
||||
)
|
||||
));
|
||||
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
||||
|
||||
/* check parameters */
|
||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||
ULONG ControlCode = IrpSp->Parameters.FileSystemControl.FsControlCode;
|
||||
ULONG ControlFunction = FSP_FUNCTION_FROM_CTL_CODE(ControlCode);
|
||||
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
|
||||
PVOID InputBuffer = 0;
|
||||
PVOID OutputBuffer = 0;
|
||||
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||
if (FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction)
|
||||
{
|
||||
InputBuffer = IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
|
||||
if (KernelMode != Irp->RequestorMode)
|
||||
@ -796,13 +819,36 @@ NTSTATUS FspVolumeTransact(
|
||||
FSP_FSCTL_DEFAULT_ALIGN_UP(sizeof(FSP_FSCTL_TRANSACT_RSP)) > InputBufferLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (0 != OutputBufferLength &&
|
||||
((FSP_FSCTL_TRANSACT == ControlCode &&
|
||||
((FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT) == ControlFunction &&
|
||||
FSP_FSCTL_TRANSACT_BUFFER_SIZEMIN > OutputBufferLength) ||
|
||||
(FSP_FSCTL_TRANSACT_BATCH == ControlCode &&
|
||||
(FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_BATCH) == ControlFunction &&
|
||||
FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN > OutputBufferLength)))
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
return FspVolumeFastTransact(
|
||||
FsvolDeviceObject,
|
||||
ControlCode,
|
||||
InputBuffer,
|
||||
InputBufferLength,
|
||||
OutputBuffer,
|
||||
OutputBufferLength,
|
||||
&Irp->IoStatus,
|
||||
Irp);
|
||||
}
|
||||
|
||||
NTSTATUS FspVolumeFastTransact(
|
||||
PDEVICE_OBJECT FsvolDeviceObject,
|
||||
ULONG ControlCode,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputBufferLength,
|
||||
PVOID OutputBuffer,
|
||||
ULONG OutputBufferLength,
|
||||
PIO_STATUS_BLOCK IoStatus,
|
||||
PIRP Irp)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (!FspDeviceReference(FsvolDeviceObject))
|
||||
return STATUS_CANCELLED;
|
||||
|
||||
@ -813,6 +859,7 @@ NTSTATUS FspVolumeTransact(
|
||||
|
||||
NTSTATUS Result;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
ULONG ControlFunction = FSP_FUNCTION_FROM_CTL_CODE(ControlCode);
|
||||
PUINT8 BufferEnd;
|
||||
FSP_FSCTL_TRANSACT_RSP *Response, *NextResponse;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request, *PendingIrpRequest;
|
||||
@ -882,27 +929,30 @@ NTSTATUS FspVolumeTransact(
|
||||
}
|
||||
}
|
||||
|
||||
/* were we sent an output buffer? */
|
||||
switch (ControlCode & 3)
|
||||
if ((PIRP)FSRTL_MAX_TOP_LEVEL_IRP_FLAG < Irp)
|
||||
{
|
||||
case METHOD_NEITHER:
|
||||
OutputBuffer = Irp->UserBuffer;
|
||||
break;
|
||||
case METHOD_OUT_DIRECT:
|
||||
if (0 != Irp->MdlAddress)
|
||||
OutputBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
||||
break;
|
||||
case METHOD_BUFFERED:
|
||||
if (0 != OutputBufferLength)
|
||||
OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
/* were we sent an output buffer? */
|
||||
switch (ControlCode & 3)
|
||||
{
|
||||
case METHOD_NEITHER:
|
||||
OutputBuffer = Irp->UserBuffer;
|
||||
break;
|
||||
case METHOD_OUT_DIRECT:
|
||||
if (0 != Irp->MdlAddress)
|
||||
OutputBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
|
||||
break;
|
||||
case METHOD_BUFFERED:
|
||||
if (0 != OutputBufferLength)
|
||||
OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 == OutputBuffer)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoStatus->Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
@ -923,7 +973,7 @@ NTSTATUS FspVolumeTransact(
|
||||
}
|
||||
if (FspIoqTimeout == PendingIrp || FspIoqCancelled == PendingIrp)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoStatus->Information = 0;
|
||||
Result = FspIoqTimeout == PendingIrp ? STATUS_SUCCESS : STATUS_CANCELLED;
|
||||
goto exit;
|
||||
}
|
||||
@ -932,7 +982,7 @@ NTSTATUS FspVolumeTransact(
|
||||
RepostedIrp = 0;
|
||||
Request = OutputBuffer;
|
||||
BufferEnd = (PUINT8)OutputBuffer + OutputBufferLength;
|
||||
ASSERT(FSP_FSCTL_TRANSACT_INTERNAL == ControlCode ?
|
||||
ASSERT(FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction ?
|
||||
TRUE :
|
||||
FspFsctlTransactCanProduceRequest(Request, BufferEnd));
|
||||
LoopCount = FspIoqPendingIrpCount(FsvolDeviceExtension->Ioq);
|
||||
@ -955,7 +1005,7 @@ NTSTATUS FspVolumeTransact(
|
||||
FspIopCompleteIrp(PendingIrp, Result);
|
||||
else
|
||||
{
|
||||
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||
if (FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction)
|
||||
{
|
||||
InternalBuffer = FspAllocatePoolMustSucceed(
|
||||
PagedPool, PendingIrpRequest->Size, FSP_ALLOC_EXTERNAL_TAG);
|
||||
@ -979,7 +1029,7 @@ NTSTATUS FspVolumeTransact(
|
||||
ASSERT(FspIoqStopped(FsvolDeviceExtension->Ioq));
|
||||
if (0 != InternalBuffer)
|
||||
{
|
||||
ASSERT(FSP_FSCTL_TRANSACT_INTERNAL == ControlCode);
|
||||
ASSERT(FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction);
|
||||
*(PVOID *)OutputBuffer = 0;
|
||||
FspFree(InternalBuffer);
|
||||
}
|
||||
@ -989,14 +1039,14 @@ NTSTATUS FspVolumeTransact(
|
||||
}
|
||||
|
||||
/* are we doing single request or batch mode? */
|
||||
if (FSP_FSCTL_TRANSACT_INTERNAL == ControlCode)
|
||||
if (FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT_INTERNAL) == ControlFunction)
|
||||
{
|
||||
Irp->IoStatus.Information = sizeof(PVOID);
|
||||
IoStatus->Information = sizeof(PVOID);
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
if (FSP_FSCTL_TRANSACT == ControlCode)
|
||||
if (FSP_FUNCTION_FROM_CTL_CODE(FSP_FSCTL_TRANSACT) == ControlFunction)
|
||||
break;
|
||||
|
||||
/* check that we have enough space before pulling the next pending IRP off the queue */
|
||||
@ -1013,7 +1063,7 @@ NTSTATUS FspVolumeTransact(
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = (PUINT8)Request - (PUINT8)OutputBuffer;
|
||||
IoStatus->Information = (PUINT8)Request - (PUINT8)OutputBuffer;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
|
@ -1,152 +0,0 @@
|
||||
@echo off
|
||||
|
||||
setlocal
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
call "%~dp0myinfo.bat"
|
||||
|
||||
set MsiName="%MyProductName% - %MyDescription%"
|
||||
set CrossCert="%~dp0%MyCrossCert%"
|
||||
set Issuer="%MyCertIssuer%"
|
||||
set Subject="%MyCompanyName%"
|
||||
|
||||
set Configuration=Release
|
||||
set SignedPackage=
|
||||
|
||||
if not X%1==X set Configuration=%1
|
||||
if not X%2==X set SignedPackage=%2
|
||||
|
||||
echo Configuration=%Configuration%
|
||||
echo:
|
||||
|
||||
if X%~nx0==Xbuild-choco.bat (
|
||||
cd %~dp0..\build\VStudio
|
||||
goto :choco
|
||||
)
|
||||
|
||||
set BuildArm64=yes
|
||||
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" (
|
||||
set BuildArm64=no
|
||||
)
|
||||
if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
|
||||
set BuildArm64=no
|
||||
)
|
||||
if X%BuildArm64%==Xno (
|
||||
echo WARNING: APPVEYOR BUILD ON UNSUPPORTED VERSION OF VISUAL STUDIO.
|
||||
echo WARNING: ARM64 BUILD PRODUCTS ARE COPIES OF X64 BUILD PRODUCTS.
|
||||
echo:
|
||||
)
|
||||
|
||||
call "%~dp0vcvarsall.bat" x64
|
||||
|
||||
if not X%SignedPackage%==X (
|
||||
if not exist "%~dp0..\build\VStudio\build\%Configuration%\%MyProductFileName%-*.msi" (echo previous build not found >&2 & exit /b 1)
|
||||
if not exist "%SignedPackage%" (echo signed package not found >&2 & exit /b 1)
|
||||
del "%~dp0..\build\VStudio\build\%Configuration%\%MyProductFileName%-*.msi"
|
||||
if exist "%~dp0..\build\VStudio\build\%Configuration%\winfsp.*.nupkg" del "%~dp0..\build\VStudio\build\%Configuration%\winfsp.*.nupkg"
|
||||
for /R "%SignedPackage%" %%f in (*.sys) do (
|
||||
copy "%%f" "%~dp0..\build\VStudio\build\%Configuration%" >nul
|
||||
)
|
||||
)
|
||||
|
||||
cd %~dp0..\build\VStudio
|
||||
set signfail=0
|
||||
|
||||
if X%SignedPackage%==X (
|
||||
if exist build\ for /R build\ %%d in (%Configuration%) do (
|
||||
if exist "%%d" rmdir /s/q "%%d"
|
||||
)
|
||||
|
||||
if X%BuildArm64%==Xyes (
|
||||
devenv winfsp.sln /build "%Configuration%|ARM64"
|
||||
if errorlevel 1 goto fail
|
||||
)
|
||||
devenv winfsp.sln /build "%Configuration%|x64"
|
||||
if errorlevel 1 goto fail
|
||||
devenv winfsp.sln /build "%Configuration%|x86"
|
||||
if errorlevel 1 goto fail
|
||||
if X%BuildArm64%==Xno (
|
||||
copy build\%Configuration%\*-x64.* build\%Configuration%\*-a64.* >nul
|
||||
if errorlevel 1 goto fail
|
||||
)
|
||||
|
||||
for %%f in (build\%Configuration%\%MyProductFileName%-a64.sys build\%Configuration%\%MyProductFileName%-x64.sys build\%Configuration%\%MyProductFileName%-x86.sys) do (
|
||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com %%f
|
||||
if errorlevel 1 set /a signfail=signfail+1
|
||||
signtool sign /as /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 %%f
|
||||
if errorlevel 1 set /a signfail=signfail+1
|
||||
)
|
||||
|
||||
pushd build\%Configuration%
|
||||
echo .OPTION EXPLICIT >driver.ddf
|
||||
echo .Set CabinetFileCountThreshold=0 >>driver.ddf
|
||||
echo .Set FolderFileCountThreshold=0 >>driver.ddf
|
||||
echo .Set FolderSizeThreshold=0 >>driver.ddf
|
||||
echo .Set MaxCabinetSize=0 >>driver.ddf
|
||||
echo .Set MaxDiskFileCount=0 >>driver.ddf
|
||||
echo .Set MaxDiskSize=0 >>driver.ddf
|
||||
echo .Set CompressionType=MSZIP >>driver.ddf
|
||||
echo .Set Cabinet=on >>driver.ddf
|
||||
echo .Set Compress=on >>driver.ddf
|
||||
echo .Set CabinetNameTemplate=driver.cab >>driver.ddf
|
||||
echo .Set DiskDirectory1=. >>driver.ddf
|
||||
echo .Set DestinationDir=a64 >>driver.ddf
|
||||
echo driver-a64.inf >>driver.ddf
|
||||
echo %MyProductFileName%-a64.sys >>driver.ddf
|
||||
echo .Set DestinationDir=x64 >>driver.ddf
|
||||
echo driver-x64.inf >>driver.ddf
|
||||
echo %MyProductFileName%-x64.sys >>driver.ddf
|
||||
echo .Set DestinationDir=x86 >>driver.ddf
|
||||
echo driver-x86.inf >>driver.ddf
|
||||
echo %MyProductFileName%-x86.sys >>driver.ddf
|
||||
makecab /F driver.ddf
|
||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 driver.cab
|
||||
if errorlevel 1 set /a signfail=signfail+1
|
||||
popd
|
||||
)
|
||||
|
||||
devenv winfsp.sln /build "Installer.%Configuration%|x86"
|
||||
if errorlevel 1 goto fail
|
||||
|
||||
for %%f in (build\%Configuration%\%MyProductFileName%-*.msi) do (
|
||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com /d %MsiName% %%f
|
||||
if errorlevel 1 set /a signfail=signfail+1
|
||||
REM signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 /d %MsiName% %%f
|
||||
REM if errorlevel 1 set /a signfail=signfail+1
|
||||
)
|
||||
|
||||
if not %signfail%==0 echo SIGNING FAILED! The product has been successfully built, but not signed.
|
||||
|
||||
set Version=
|
||||
for %%f in (build\%Configuration%\%MyProductFileName%-*.msi) do set Version=%%~nf
|
||||
set Version=!Version:%MyProductFileName%-=!
|
||||
if X%SignedPackage%==X (
|
||||
pushd build\%Configuration%
|
||||
powershell -command "Compress-Archive -Path winfsp-tests-*.exe,..\..\..\..\License.txt,..\..\..\..\tst\winfsp-tests\README.md -DestinationPath winfsp-tests-!Version!.zip"
|
||||
if errorlevel 1 goto fail
|
||||
popd
|
||||
)
|
||||
|
||||
:choco
|
||||
if not exist "build\%Configuration%\%MyProductFileName%-*.msi" (echo installer msi not found >&2 & exit /b 1)
|
||||
if not X!MyProductName!==XWinFsp (echo skipping choco build for !MyProductName! >&2 & exit /b 0)
|
||||
set Version=
|
||||
for %%f in (build\%Configuration%\%MyProductFileName%-*.msi) do set Version=%%~nf
|
||||
set Version=!Version:%MyProductFileName%-=!
|
||||
set PackageVersion=!Version!
|
||||
if not X!MyProductStage!==XGold (
|
||||
set PackageVersion=!Version!-pre
|
||||
)
|
||||
where /q choco.exe
|
||||
if %ERRORLEVEL% equ 0 (
|
||||
copy ..\choco\* build\%Configuration%
|
||||
copy ..\choco\LICENSE.TXT /B + ..\..\License.txt /B build\%Configuration%\LICENSE.txt /B
|
||||
certutil -hashfile build\%Configuration%\%MyProductFileName%-!Version!.msi SHA256 >>build\%Configuration%\VERIFICATION.txt
|
||||
choco pack build\%Configuration%\winfsp.nuspec --version=!PackageVersion! --outputdirectory=build\%Configuration% MsiVersion=!Version!
|
||||
if errorlevel 1 goto fail
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
|
||||
:fail
|
||||
exit /b 1
|
1
tools/build-choco.bat
Symbolic link
1
tools/build-choco.bat
Symbolic link
@ -0,0 +1 @@
|
||||
build.bat
|
@ -70,12 +70,19 @@ if X%SignedPackage%==X (
|
||||
if errorlevel 1 goto fail
|
||||
)
|
||||
|
||||
for %%f in (build\%Configuration%\%MyProductFileName%-a64.sys build\%Configuration%\%MyProductFileName%-x64.sys build\%Configuration%\%MyProductFileName%-x86.sys) do (
|
||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com %%f
|
||||
if errorlevel 1 set /a signfail=signfail+1
|
||||
signtool sign /as /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 %%f
|
||||
if errorlevel 1 set /a signfail=signfail+1
|
||||
)
|
||||
pushd build\%Configuration%
|
||||
set signfiles=^
|
||||
%MyProductFileName%-a64.sys %MyProductFileName%-x64.sys %MyProductFileName%-x86.sys^
|
||||
%MyProductFileName%-a64.dll %MyProductFileName%-x64.dll %MyProductFileName%-x86.dll %MyProductFileName%-msil.dll^
|
||||
launcher-a64.exe launcher-x64.exe launcher-x86.exe^
|
||||
launchctl-a64.exe launchctl-x64.exe launchctl-x86.exe^
|
||||
fsptool-a64.exe fsptool-x64.exe fsptool-x86.exe^
|
||||
memfs-a64.exe memfs-x64.exe memfs-x86.exe memfs-dotnet-msil.exe
|
||||
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com !signfiles!
|
||||
if errorlevel 1 set /a signfail=signfail+1
|
||||
signtool sign /as /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 !signfiles!
|
||||
if errorlevel 1 set /a signfail=signfail+1
|
||||
popd
|
||||
|
||||
pushd build\%Configuration%
|
||||
echo .OPTION EXPLICIT >driver.ddf
|
||||
|
@ -30,25 +30,25 @@ pushd fsbench
|
||||
set OptFiles=1000 2000 3000 4000 5000
|
||||
if X%2==Xbaseline set OptFiles=10000
|
||||
for %%a in (%OptFiles%) do (
|
||||
call :csv %%a "%fsbench% --files=%%a file_*"
|
||||
call :csv %%a "%fsbench% --empty-cache --files=%%a file_*"
|
||||
)
|
||||
|
||||
set OptRdwrCc=100 200 300 400 500
|
||||
if X%2==Xbaseline set OptRdwrCc=1000
|
||||
for %%a in (%OptRdwrCc%) do (
|
||||
call :csv %%a "%fsbench% --rdwr-cc=%%a rdwr_cc_*"
|
||||
call :csv %%a "%fsbench% --empty-cache --rdwr-cc=%%a rdwr_cc_*"
|
||||
)
|
||||
|
||||
set OptRdwrNc=100 200 300 400 500
|
||||
if X%2==Xbaseline set OptRdwrNc=100
|
||||
for %%a in (%OptRdwrNc%) do (
|
||||
call :csv %%a "%fsbench% --rdwr-nc=%%a rdwr_nc_*"
|
||||
call :csv %%a "%fsbench% --empty-cache --rdwr-nc=%%a rdwr_nc_*"
|
||||
)
|
||||
|
||||
set OptMmap=100 200 300 400 500
|
||||
if X%2==Xbaseline set OptMmap=1000
|
||||
for %%a in (%OptMmap%) do (
|
||||
call :csv %%a "%fsbench% --mmap=%%a mmap_*"
|
||||
call :csv %%a "%fsbench% --empty-cache --mmap=%%a mmap_*"
|
||||
)
|
||||
|
||||
popd
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <strsafe.h>
|
||||
#include <tlib/testsuite.h>
|
||||
|
||||
static BOOLEAN OptEmptyCache = FALSE;
|
||||
static ULONG OptFileCount = 1000;
|
||||
static ULONG OptListCount = 100;
|
||||
static ULONG OptRdwrFileSize = 4096 * 1024;
|
||||
@ -398,6 +399,64 @@ static void mmap_tests(void)
|
||||
TEST(mmap_read_test);
|
||||
}
|
||||
|
||||
static void EmptyCache(const char *name, void (*fn)(void), int v)
|
||||
{
|
||||
NTSYSCALLAPI NTSTATUS NTAPI
|
||||
NtSetSystemInformation(
|
||||
ULONG SystemInformationClass,
|
||||
PVOID SystemInformation,
|
||||
ULONG SystemInformationLength);
|
||||
|
||||
if (+1 == v) /* setup */
|
||||
{
|
||||
/* flush the file system cache (requires SE_INCREASE_QUOTA_NAME) */
|
||||
ASSERT(SetSystemFileCacheSize((SIZE_T)-1, (SIZE_T)-1, 0));
|
||||
|
||||
/* flush/purge the standby list (requires SE_PROF_SINGLE_PROCESS_NAME) */
|
||||
ULONG Command;
|
||||
Command = 3 /*MemoryFlushModifiedList*/;
|
||||
ASSERT(0 == NtSetSystemInformation(80 /*SystemMemoryListInformation*/, &Command, sizeof Command));
|
||||
Command = 4 /*MemoryPurgeStandbyList*/;
|
||||
ASSERT(0 == NtSetSystemInformation(80 /*SystemMemoryListInformation*/, &Command, sizeof Command));
|
||||
}
|
||||
else
|
||||
if (-1 == v) /* teardown */
|
||||
{
|
||||
}
|
||||
}
|
||||
static DWORD EnablePrivilegesForEmptyCache(VOID)
|
||||
{
|
||||
union
|
||||
{
|
||||
TOKEN_PRIVILEGES P;
|
||||
UINT8 B[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)];
|
||||
} Privileges;
|
||||
HANDLE Token;
|
||||
|
||||
Privileges.P.PrivilegeCount = 2;
|
||||
Privileges.P.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
Privileges.P.Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (!LookupPrivilegeValueW(0, SE_PROF_SINGLE_PROCESS_NAME, &Privileges.P.Privileges[0].Luid) ||
|
||||
!LookupPrivilegeValueW(0, SE_INCREASE_QUOTA_NAME, &Privileges.P.Privileges[1].Luid))
|
||||
return GetLastError();
|
||||
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &Token))
|
||||
return GetLastError();
|
||||
|
||||
if (!AdjustTokenPrivileges(Token, FALSE, &Privileges.P, 0, 0, 0) ||
|
||||
ERROR_NOT_ALL_ASSIGNED == GetLastError())
|
||||
{
|
||||
CloseHandle(Token);
|
||||
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
CloseHandle(Token);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
#define rmarg(argv, argc, argi) \
|
||||
argc--, \
|
||||
memmove(argv + argi, argv + argi + 1, (argc - argi) * sizeof(char *)),\
|
||||
@ -414,7 +473,12 @@ int main(int argc, char *argv[])
|
||||
const char *a = argv[argi];
|
||||
if ('-' == a[0])
|
||||
{
|
||||
if (0 == strncmp("--files=", a, sizeof "--files=" - 1))
|
||||
if (0 == strcmp("--empty-cache", a))
|
||||
{
|
||||
OptEmptyCache = TRUE;
|
||||
rmarg(argv, argc, argi);
|
||||
}
|
||||
else if (0 == strncmp("--files=", a, sizeof "--files=" - 1))
|
||||
{
|
||||
OptFileCount = strtoul(a + sizeof "--files=" - 1, 0, 10);
|
||||
rmarg(argv, argc, argi);
|
||||
@ -442,6 +506,16 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (OptEmptyCache)
|
||||
{
|
||||
if (0 != EnablePrivilegesForEmptyCache())
|
||||
{
|
||||
tlib_printf("ABORT: cannot enable privileges required for empty cache\n");
|
||||
abort();
|
||||
}
|
||||
TESTHOOK(EmptyCache);
|
||||
}
|
||||
|
||||
tlib_run_tests(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
@ -182,6 +182,51 @@ UINT64 MemfsGetSystemTime(VOID)
|
||||
return ((PLARGE_INTEGER)&FileTime)->QuadPart;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned MemfsUpperChar(unsigned c)
|
||||
{
|
||||
/*
|
||||
* Bit-twiddling upper case char:
|
||||
*
|
||||
* - Let signbit(x) = x & 0x100 (treat bit 0x100 as "signbit").
|
||||
* - 'A' <= c && c <= 'Z' <=> s = signbit(c - 'A') ^ signbit(c - ('Z' + 1)) == 1
|
||||
* - c >= 'A' <=> c - 'A' >= 0 <=> signbit(c - 'A') = 0
|
||||
* - c <= 'Z' <=> c - ('Z' + 1) < 0 <=> signbit(c - ('Z' + 1)) = 1
|
||||
* - Bit 0x20 = 0x100 >> 3 toggles uppercase to lowercase and vice-versa.
|
||||
*
|
||||
* This is actually faster than `(c - 'a' <= 'z' - 'a') ? (c & ~0x20) : c`, even
|
||||
* when compiled using cmov conditional moves at least on this system (i7-1065G7).
|
||||
*
|
||||
* See https://godbolt.org/z/ebv131Wrh
|
||||
*/
|
||||
unsigned s = ((c - 'a') ^ (c - ('z' + 1))) & 0x100;
|
||||
return c & ~(s >> 3);
|
||||
}
|
||||
|
||||
static inline
|
||||
int MemfsWcsnicmp(const wchar_t *s0, const wchar_t *t0, int n)
|
||||
{
|
||||
/* Use fast loop for ASCII and fall back to CompareStringW for general case. */
|
||||
const wchar_t *s = s0;
|
||||
const wchar_t *t = t0;
|
||||
int v = 0;
|
||||
for (const void *e = t + n; e > (const void *)t; ++s, ++t)
|
||||
{
|
||||
unsigned sc = *s, tc = *t;
|
||||
if (0xffffff80 & (sc | tc))
|
||||
{
|
||||
v = CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, s0, n, t0, n);
|
||||
if (0 != v)
|
||||
return v - 2;
|
||||
else
|
||||
return _wcsnicmp(s, t, n);
|
||||
}
|
||||
if (0 != (v = MemfsUpperChar(sc) - MemfsUpperChar(tc)) || !tc)
|
||||
break;
|
||||
}
|
||||
return v;/*(0 < v) - (0 > v);*/
|
||||
}
|
||||
|
||||
static inline
|
||||
int MemfsFileNameCompare(PWSTR a, int alen, PWSTR b, int blen, BOOLEAN CaseInsensitive)
|
||||
{
|
||||
@ -226,13 +271,7 @@ int MemfsFileNameCompare(PWSTR a, int alen, PWSTR b, int blen, BOOLEAN CaseInsen
|
||||
len = plen < qlen ? plen : qlen;
|
||||
|
||||
if (CaseInsensitive)
|
||||
{
|
||||
res = CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, partp, plen, partq, qlen);
|
||||
if (0 != res)
|
||||
res -= 2;
|
||||
else
|
||||
res = _wcsnicmp(partp, partq, len);
|
||||
}
|
||||
res = MemfsWcsnicmp(partp, partq, len);
|
||||
else
|
||||
res = wcsncmp(partp, partq, len);
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
static void posix_map_sid_test(void)
|
||||
{
|
||||
#define TEST_UIDMAP_UID 1000042
|
||||
#define TEST_UIDMAP_SID L"S-1-12-1-1111-2222-3333-4444"
|
||||
struct
|
||||
{
|
||||
PWSTR SidStr;
|
||||
@ -100,6 +102,7 @@ static void posix_map_sid_test(void)
|
||||
{ L"S-1-16-16384", 0x64000 },
|
||||
{ L"S-1-16-20480", 0x65000 },
|
||||
{ L"S-1-16-28672", 0x67000 },
|
||||
{ TEST_UIDMAP_SID, TEST_UIDMAP_UID },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
};
|
||||
@ -112,6 +115,14 @@ static void posix_map_sid_test(void)
|
||||
PSID Sid0, Sid1;
|
||||
UINT32 Uid;
|
||||
|
||||
UINT32 UidMap_Uid[1] = { TEST_UIDMAP_UID };
|
||||
PSID UidMap_Sid[1];
|
||||
Success = ConvertStringSidToSidW(TEST_UIDMAP_SID, &UidMap_Sid[0]);
|
||||
ASSERT(Success);
|
||||
Result = FspPosixSetUidMap(UidMap_Uid, UidMap_Sid, 1);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
LocalFree(UidMap_Sid[0]);
|
||||
|
||||
Success = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
|
||||
ASSERT(Success);
|
||||
|
||||
@ -169,6 +180,12 @@ static void posix_map_sid_test(void)
|
||||
|
||||
LocalFree(map[sizeof map / sizeof map[0] - 2].SidStr);
|
||||
LocalFree(map[sizeof map / sizeof map[0] - 1].SidStr);
|
||||
|
||||
Result = FspPosixSetUidMap(0, 0, 0);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
#undef TEST_UIDMAP_UID
|
||||
#undef TEST_UIDMAP_SID
|
||||
}
|
||||
|
||||
static void posix_map_sd_test(void)
|
||||
|
Reference in New Issue
Block a user