diff --git a/build/VStudio/version.properties b/build/VStudio/version.properties index 99d5647b..340a3cfc 100644 --- a/build/VStudio/version.properties +++ b/build/VStudio/version.properties @@ -7,7 +7,7 @@ 2015-2016 Bill Zissimopoulos $([System.DateTime]::Now.ToString(`yy`))$([System.DateTime]::Now.DayOfYear.ToString(`000`)) - 0.11.$(MyBuildNumber) + 0.12.$(MyBuildNumber) $(MyVersion.Replace('.',',')),0 \ No newline at end of file diff --git a/build/VStudio/winfsp_dll.vcxproj b/build/VStudio/winfsp_dll.vcxproj index 7fd0ff17..ca35988c 100644 --- a/build/VStudio/winfsp_dll.vcxproj +++ b/build/VStudio/winfsp_dll.vcxproj @@ -37,6 +37,7 @@ + diff --git a/build/VStudio/winfsp_dll.vcxproj.filters b/build/VStudio/winfsp_dll.vcxproj.filters index b5b3be22..acb82f28 100644 --- a/build/VStudio/winfsp_dll.vcxproj.filters +++ b/build/VStudio/winfsp_dll.vcxproj.filters @@ -64,6 +64,9 @@ Source + + Source + diff --git a/inc/winfsp/winfsp.h b/inc/winfsp/winfsp.h index 802589ee..21d90a2d 100644 --- a/inc/winfsp/winfsp.h +++ b/inc/winfsp/winfsp.h @@ -591,6 +591,7 @@ typedef struct _FSP_FILE_SYSTEM NTSTATUS DispatcherResult; PWSTR MountPoint; LIST_ENTRY MountEntry; + UINT32 DebugLog; } FSP_FILE_SYSTEM; /** * Create a file system object. @@ -737,6 +738,12 @@ VOID FspFileSystemSetDispatcherResult(FSP_FILE_SYSTEM *FileSystem, return; InterlockedCompareExchange(&FileSystem->DispatcherResult, DispatcherResult, 0); } +static inline +VOID FspFileSystemSetDebugLog(FSP_FILE_SYSTEM *FileSystem, + UINT32 DebugLog) +{ + FileSystem->DebugLog = DebugLog; +} /* * Operations @@ -1034,6 +1041,8 @@ FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap); FSP_API VOID FspDebugLog(const char *format, ...); FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDescriptor); FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime); +FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request); +FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response); FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName, PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize, PULONG PBytesTransferred, ULONG Timeout, diff --git a/src/dll/debug.c b/src/dll/debug.c index 7c237784..bb001e6e 100644 --- a/src/dll/debug.c +++ b/src/dll/debug.c @@ -37,7 +37,8 @@ FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDesc if (0 == SecurityDescriptor) FspDebugLog(format, "null security descriptor"); - else if (ConvertSecurityDescriptorToStringSecurityDescriptorA(SecurityDescriptor, SDDL_REVISION_1, + else if (ConvertSecurityDescriptorToStringSecurityDescriptorA(SecurityDescriptor, + SDDL_REVISION_1, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, &Sddl, 0)) @@ -65,3 +66,560 @@ FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime) else FspDebugLog(format, "invalid file time"); } + +#define MAKE_UINT32_PAIR(v) (((v) >> 32) & 0xffffffff), ((v) & 0xffffffff) + +static inline 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 *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 inline VOID FspDebugLogRequestVoid(FSP_FSCTL_TRANSACT_REQ *Request, const char *Name) +{ + FspDebugLog("%S[TID=%ld]: %p: >>%s\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, Name); +} + +static inline VOID FspDebugLogResponseStatus(FSP_FSCTL_TRANSACT_RSP *Response, const char *Name) +{ + FspDebugLog("%S[TID=%ld]: %p: <<%s IoStatus=%lx[%ld]\n", + FspDiagIdent(), GetCurrentThreadId(), Response->Hint, Name, + Response->IoStatus.Status, Response->IoStatus.Information); +} + +FSP_API VOID FspDebugLogRequest(FSP_FSCTL_TRANSACT_REQ *Request) +{ + char CreationTimeBuf[32], LastAccessTimeBuf[32], LastWriteTimeBuf[32]; + 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=%ld]: %p: >>Create[%c%c%c%c] \"%S\", " + "%s, CreateOptions=%lx, FileAttributes=%lx, Security=%s%s%s, " + "AllocationSize=%lx:%lx, AccessToken=%lx, DesiredAccess=%lx, ShareAccess=%lx\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->Req.Create.UserMode ? 'U' : 'K', + Request->Req.Create.HasTraversePrivilege ? 'T' : '-', + 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), + Request->Req.Create.AccessToken, + Request->Req.Create.DesiredAccess, + Request->Req.Create.ShareAccess); + LocalFree(Sddl); + break; + case FspFsctlTransactOverwriteKind: + FspDebugLog("%S[TID=%ld]: %p: >>Overwrite%s %s%S%s%p, %p, " + "FileAttributes=%lx\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->Req.Overwrite.Supersede ? " [Supersede]" : "", + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.Overwrite.UserContext, + (PVOID)Request->Req.Overwrite.UserContext2, + Request->Req.Overwrite.FileAttributes); + break; + case FspFsctlTransactCleanupKind: + FspDebugLog("%S[TID=%ld]: %p: >>Cleanup%s %s%S%s%p, %p\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->Req.Cleanup.Delete ? " [Delete]" : "", + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.Cleanup.UserContext, + (PVOID)Request->Req.Cleanup.UserContext2); + break; + case FspFsctlTransactCloseKind: + FspDebugLog("%S[TID=%ld]: %p: >>Close %s%S%s%p, %p\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.Close.UserContext, + (PVOID)Request->Req.Close.UserContext2); + break; + case FspFsctlTransactReadKind: + FspDebugLog("%S[TID=%ld]: %p: >>Read %s%S%s%p, %p, " + "Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.Read.UserContext, + (PVOID)Request->Req.Read.UserContext2, + 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=%ld]: %p: >>Write%s %s%S%s%p, %p, " + "Address=%p, Offset=%lx:%lx, Length=%ld, Key=%lx\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->Req.Write.ConstrainedIo ? " [C]" : "", + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.Write.UserContext, + (PVOID)Request->Req.Write.UserContext2, + 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=%ld]: %p: >>QueryInformation %s%S%s%p, %p\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.QueryInformation.UserContext, + (PVOID)Request->Req.QueryInformation.UserContext2); + break; + case FspFsctlTransactSetInformationKind: + switch (Request->Req.SetInformation.FileInformationClass) + { + case 4/*FileBasicInformation*/: + FspDebugLog("%S[TID=%ld]: %p: >>SetInformation [Basic] %s%S%s%p, %p, " + "FileAttributes=%lx, CreationTime=%s, LastAccessTime=%s, LastWriteTime=%s\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.SetInformation.UserContext, + (PVOID)Request->Req.SetInformation.UserContext2, + 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=%ld]: %p: >>SetInformation [Allocation] %s%S%s%p, %p, " + "AllocationSize=%lx:%lx\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.SetInformation.UserContext, + (PVOID)Request->Req.SetInformation.UserContext2, + MAKE_UINT32_PAIR(Request->Req.SetInformation.Info.Allocation.AllocationSize)); + break; + case 20/*FileEndOfFileInformation*/: + FspDebugLog("%S[TID=%ld]: %p: >>SetInformation [EndOfFile] %s%S%s%p, %p, " + "FileSize = %lx:%lx\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.SetInformation.UserContext, + (PVOID)Request->Req.SetInformation.UserContext2, + MAKE_UINT32_PAIR(Request->Req.SetInformation.Info.EndOfFile.FileSize)); + break; + case 13/*FileDispositionInformation*/: + FspDebugLog("%S[TID=%ld]: %p: >>SetInformation [Disposition] %s%S%s%p, %p, " + "%s\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.SetInformation.UserContext, + (PVOID)Request->Req.SetInformation.UserContext2, + Request->Req.SetInformation.Info.Disposition.Delete ? "Delete" : "Undelete"); + break; + case 10/*FileRenameInformation*/: + FspDebugLog("%S[TID=%ld]: %p: >>SetInformation [Rename] %s%S%s%p, %p, " + "NewFileName=\"%S\"%s\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.SetInformation.UserContext, + (PVOID)Request->Req.SetInformation.UserContext2, + (PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Offset), + Request->Req.SetInformation.Info.Rename.ReplaceIfExists ? " ReplaceIfExists" : ""); + break; + default: + FspDebugLog("%S[TID=%ld]: %p: >>SetInformation [INVALID] %s%S%s%p, %p\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.SetInformation.UserContext, + (PVOID)Request->Req.SetInformation.UserContext2); + } + break; + case FspFsctlTransactQueryEaKind: + FspDebugLogRequestVoid(Request, "QUERYEA"); + break; + case FspFsctlTransactSetEaKind: + FspDebugLogRequestVoid(Request, "SETEA"); + break; + case FspFsctlTransactFlushBuffersKind: + FspDebugLog("%S[TID=%ld]: %p: >>FlushBuffers %s%S%s%p, %p\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.FlushBuffers.UserContext, + (PVOID)Request->Req.FlushBuffers.UserContext2); + break; + case FspFsctlTransactQueryVolumeInformationKind: + FspDebugLogRequestVoid(Request, "QueryVolumeInformation"); + break; + case FspFsctlTransactSetVolumeInformationKind: + switch (Request->Req.SetVolumeInformation.FsInformationClass) + { + case 2/*FileFsLabelInformation*/: + FspDebugLog("%S[TID=%ld]: %p: >>SetVolumeInformation [FsLabel] " + "Label=\"%S\"\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + (PWSTR)Request->Buffer); + break; + default: + FspDebugLog("%S[TID=%ld]: %p: >>SetVolumeInformation [INVALID]\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint); + break; + } + break; + case FspFsctlTransactQueryDirectoryKind: + FspDebugLog("%S[TID=%ld]: %p: >>QueryDirectory %s%S%s%p, %p, " + "Address=%p, Offset=%lx:%lx, Length=%ld, Pattern=%s%S%s\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.QueryDirectory.UserContext, + (PVOID)Request->Req.QueryDirectory.UserContext2, + Request->Req.QueryDirectory.Address, + MAKE_UINT32_PAIR(Request->Req.QueryDirectory.Offset), + 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 ? "\"" : ""); + break; + case FspFsctlTransactFileSystemControlKind: + FspDebugLogRequestVoid(Request, "FILESYSTEMCONTROL"); + break; + case FspFsctlTransactDeviceControlKind: + FspDebugLogRequestVoid(Request, "DEVICECONTROL"); + break; + case FspFsctlTransactShutdownKind: + FspDebugLogRequestVoid(Request, "SHUTDOWN"); + break; + case FspFsctlTransactLockControlKind: + FspDebugLogRequestVoid(Request, "LOCKCONTROL"); + break; + case FspFsctlTransactQuerySecurityKind: + FspDebugLog("%S[TID=%ld]: %p: >>QuerySecurity %s%S%s%p, %p\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.QuerySecurity.UserContext, + (PVOID)Request->Req.QuerySecurity.UserContext2); + 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=%ld]: %p: >>SetSecurity %s%S%s%p, %p, " + "SecurityInformation=%lx, AccessToken=%lx, Security=%s%s%s\n", + FspDiagIdent(), GetCurrentThreadId(), Request->Hint, + Request->FileName.Size ? "\"" : "", + Request->FileName.Size ? (PWSTR)Request->Buffer : L"", + Request->FileName.Size ? "\", " : "", + (PVOID)Request->Req.SetSecurity.UserContext, + (PVOID)Request->Req.SetSecurity.UserContext2, + Request->Req.SetSecurity.SecurityInformation, + Request->Req.SetSecurity.AccessToken, + Sddl ? "\"" : "", + Sddl ? Sddl : "NULL", + Sddl ? "\"" : ""); + LocalFree(Sddl); + break; + default: + FspDebugLogRequestVoid(Request, "INVALID"); + break; + } +} + +FSP_API VOID FspDebugLogResponse(FSP_FSCTL_TRANSACT_RSP *Response) +{ + if (STATUS_PENDING == Response->IoStatus.Status) + return; + + 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) + FspDebugLog("%S[TID=%ld]: %p: <Hint, + Response->IoStatus.Status, Response->IoStatus.Information, + (PWSTR)(Response->Buffer + Response->Rsp.Create.Reparse.FileName.Offset)); + else + FspDebugLog("%S[TID=%ld]: %p: <Hint, + Response->IoStatus.Status, Response->IoStatus.Information, + (PVOID)Response->Rsp.Create.Opened.UserContext, + (PVOID)Response->Rsp.Create.Opened.UserContext2, + 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=%ld]: %p: <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=%ld]: %p: <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=%ld]: %p: <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=%ld]: %p: <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=%ld]: %p: <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=%ld]: %p: <Hint, + Response->IoStatus.Status, Response->IoStatus.Information, + FspDebugLogVolumeInfoString(&Response->Rsp.SetVolumeInformation.VolumeInfo, InfoBuf)); + break; + case FspFsctlTransactQueryDirectoryKind: + FspDebugLogResponseStatus(Response, "QueryDirectory"); + break; + case FspFsctlTransactFileSystemControlKind: + FspDebugLogResponseStatus(Response, "FILESYSTEMCONTROL"); + 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=%ld]: %p: <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=%ld]: %p: <Hint, + Response->IoStatus.Status, Response->IoStatus.Information, + Sddl ? "\"" : "", + Sddl ? Sddl : "NULL", + Sddl ? "\"" : ""); + LocalFree(Sddl); + } + break; + default: + FspDebugLogResponseStatus(Response, "INVALID"); + break; + } +} diff --git a/src/dll/fs.c b/src/dll/fs.c index a5b5b5bd..fcca24b3 100644 --- a/src/dll/fs.c +++ b/src/dll/fs.c @@ -267,10 +267,12 @@ static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0) if (0 == RequestSize) continue; -#if 0 - FspDebugLog("FspFileSystemDispatcherThread: TID=%ld, Request={Kind=%d, Hint=%p}\n", - GetCurrentThreadId(), Request->Kind, (PVOID)Request->Hint); -#endif + if (FileSystem->DebugLog) + { + if (FspFsctlTransactKindCount <= Request->Kind || + (FileSystem->DebugLog & (1 << Request->Kind))) + FspDebugLogRequest(Request); + } Response->Size = sizeof *Response; Response->Kind = Request->Kind; @@ -285,6 +287,13 @@ static DWORD WINAPI FspFileSystemDispatcherThread(PVOID FileSystem0) else Response->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + if (FileSystem->DebugLog) + { + if (FspFsctlTransactKindCount <= Response->Kind || + (FileSystem->DebugLog & (1 << Response->Kind))) + FspDebugLogResponse(Response); + } + ResponseSize = FSP_FSCTL_DEFAULT_ALIGN_UP(Response->Size); if (FSP_FSCTL_TRANSACT_RSP_SIZEMAX < ResponseSize/* should NOT happen */) { @@ -364,6 +373,13 @@ FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem, { NTSTATUS Result; + if (FileSystem->DebugLog) + { + if (FspFsctlTransactKindCount <= Response->Kind || + (FileSystem->DebugLog & (1 << Response->Kind))) + FspDebugLogResponse(Response); + } + Result = FspFsctlTransact(FileSystem->VolumeHandle, Response, Response->Size, 0, 0, FALSE); if (!NT_SUCCESS(Result)) diff --git a/src/dll/fsop.c b/src/dll/fsop.c index 2ebdfb0a..7b7f82e4 100644 --- a/src/dll/fsop.c +++ b/src/dll/fsop.c @@ -617,6 +617,7 @@ FSP_API NTSTATUS FspFileSystemOpSetVolumeInformation(FSP_FILE_SYSTEM *FileSystem Result = FileSystem->Interface->SetVolumeLabel(FileSystem, Request, (PWSTR)Request->Buffer, &VolumeInfo); + break; } if (!NT_SUCCESS(Result)) diff --git a/src/dll/library.h b/src/dll/library.h index 50b24fd3..148cc911 100644 --- a/src/dll/library.h +++ b/src/dll/library.h @@ -52,4 +52,6 @@ NTSTATUS FspNpUnregister(VOID); NTSTATUS FspEventLogRegister(VOID); NTSTATUS FspEventLogUnregister(VOID); +PWSTR FspDiagIdent(VOID); + #endif diff --git a/src/dll/np.c b/src/dll/np.c index 464e2eef..65c26ef5 100644 --- a/src/dll/np.c +++ b/src/dll/np.c @@ -17,117 +17,11 @@ #include #include -#include #include #define FSP_NP_NAME LIBRARY_NAME ".Np" #define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */ -FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName, - PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize, - PULONG PBytesTransferred, ULONG Timeout, - PSID Sid) -{ - NTSTATUS Result; - HANDLE Pipe = INVALID_HANDLE_VALUE; - DWORD PipeMode; - - Pipe = CreateFileW(PipeName, - GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, - SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, 0); - if (INVALID_HANDLE_VALUE == Pipe) - { - if (ERROR_PIPE_BUSY != GetLastError()) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - WaitNamedPipeW(PipeName, Timeout); - - Pipe = CreateFileW(PipeName, - GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, - SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, 0); - if (INVALID_HANDLE_VALUE == Pipe) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - } - - if (0 != Sid) - { - PSECURITY_DESCRIPTOR SecurityDescriptor = 0; - PSID OwnerSid, WellKnownSid = 0; - DWORD SidSize, LastError; - - /* if it is a small number treat it like a well known SID */ - if (1024 > (INT_PTR)Sid) - { - SidSize = SECURITY_MAX_SID_SIZE; - WellKnownSid = MemAlloc(SidSize); - if (0 == WellKnownSid) - { - Result = STATUS_INSUFFICIENT_RESOURCES; - goto sid_exit; - } - - if (!CreateWellKnownSid((INT_PTR)Sid, 0, WellKnownSid, &SidSize)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto sid_exit; - } - } - - LastError = GetSecurityInfo(Pipe, SE_FILE_OBJECT, - OWNER_SECURITY_INFORMATION, &OwnerSid, 0, 0, 0, &SecurityDescriptor); - if (0 != LastError) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto sid_exit; - } - - if (!EqualSid(OwnerSid, WellKnownSid ? WellKnownSid : Sid)) - { - Result = STATUS_ACCESS_DENIED; - goto sid_exit; - } - - Result = STATUS_SUCCESS; - - sid_exit: - MemFree(WellKnownSid); - LocalFree(SecurityDescriptor); - - if (!NT_SUCCESS(Result)) - goto exit; - } - - PipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; - if (!SetNamedPipeHandleState(Pipe, &PipeMode, 0, 0)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - if (!TransactNamedPipe(Pipe, InBuffer, InBufferSize, OutBuffer, OutBufferSize, - PBytesTransferred, 0)) - { - Result = FspNtStatusFromWin32(GetLastError()); - goto exit; - } - - Result = STATUS_SUCCESS; - -exit: - if (INVALID_HANDLE_VALUE != Pipe) - CloseHandle(Pipe); - - return Result; -} - DWORD APIENTRY NPGetCaps(DWORD Index) { switch (Index) diff --git a/src/dll/util.c b/src/dll/util.c new file mode 100644 index 00000000..173c5296 --- /dev/null +++ b/src/dll/util.c @@ -0,0 +1,165 @@ +/** + * @file dll/util.c + * + * @copyright 2015-2016 Bill Zissimopoulos + */ +/* + * This file is part of WinFsp. + * + * You can redistribute it and/or modify it under the terms of the + * GNU Affero General Public License version 3 as published by the + * Free Software Foundation. + * + * Licensees holding a valid commercial license may use this file in + * accordance with the commercial license agreement provided with the + * software. + */ + +#include +#include + +static INIT_ONCE FspDiagIdentInitOnce = INIT_ONCE_STATIC_INIT; +static WCHAR FspDiagIdentBuf[16] = L"UNKNOWN"; + +static BOOL WINAPI FspDiagIdentInit( + PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) +{ + WCHAR ModuleFileName[MAX_PATH]; + WCHAR Root[2] = L"\\"; + PWSTR Parent, ModuleBaseName; + + if (0 != GetModuleFileNameW(0, ModuleFileName, sizeof ModuleFileName / sizeof(WCHAR))) + FspPathSuffix(ModuleFileName, &Parent, &ModuleBaseName, Root); + else + lstrcpyW(ModuleBaseName = ModuleFileName, L"UNKNOWN"); + + for (PWSTR P = ModuleBaseName, Dot = 0;; P++) + { + if (L'\0' == *P) + { + if (0 != Dot) + *Dot = L'\0'; + break; + } + if (L'.' == *P) + Dot = P; + } + + memcpy(FspDiagIdentBuf, ModuleBaseName, sizeof FspDiagIdentBuf); + FspDiagIdentBuf[(sizeof FspDiagIdentBuf / sizeof(WCHAR)) - 1] = L'\0'; + + return TRUE; +} + +PWSTR FspDiagIdent(VOID) +{ + /* internal only: get a diagnostic identifier (eventlog, debug) */ + + InitOnceExecuteOnce(&FspDiagIdentInitOnce, FspDiagIdentInit, 0, 0); + return FspDiagIdentBuf; +} + +FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName, + PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize, + PULONG PBytesTransferred, ULONG Timeout, + PSID Sid) +{ + NTSTATUS Result; + HANDLE Pipe = INVALID_HANDLE_VALUE; + DWORD PipeMode; + + Pipe = CreateFileW(PipeName, + GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, + SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, 0); + if (INVALID_HANDLE_VALUE == Pipe) + { + if (ERROR_PIPE_BUSY != GetLastError()) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + WaitNamedPipeW(PipeName, Timeout); + + Pipe = CreateFileW(PipeName, + GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, + SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, 0); + if (INVALID_HANDLE_VALUE == Pipe) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + } + + if (0 != Sid) + { + PSECURITY_DESCRIPTOR SecurityDescriptor = 0; + PSID OwnerSid, WellKnownSid = 0; + DWORD SidSize, LastError; + + /* if it is a small number treat it like a well known SID */ + if (1024 > (INT_PTR)Sid) + { + SidSize = SECURITY_MAX_SID_SIZE; + WellKnownSid = MemAlloc(SidSize); + if (0 == WellKnownSid) + { + Result = STATUS_INSUFFICIENT_RESOURCES; + goto sid_exit; + } + + if (!CreateWellKnownSid((INT_PTR)Sid, 0, WellKnownSid, &SidSize)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto sid_exit; + } + } + + LastError = GetSecurityInfo(Pipe, SE_FILE_OBJECT, + OWNER_SECURITY_INFORMATION, &OwnerSid, 0, 0, 0, &SecurityDescriptor); + if (0 != LastError) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto sid_exit; + } + + if (!EqualSid(OwnerSid, WellKnownSid ? WellKnownSid : Sid)) + { + Result = STATUS_ACCESS_DENIED; + goto sid_exit; + } + + Result = STATUS_SUCCESS; + + sid_exit: + MemFree(WellKnownSid); + LocalFree(SecurityDescriptor); + + if (!NT_SUCCESS(Result)) + goto exit; + } + + PipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT; + if (!SetNamedPipeHandleState(Pipe, &PipeMode, 0, 0)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + if (!TransactNamedPipe(Pipe, InBuffer, InBufferSize, OutBuffer, OutBufferSize, + PBytesTransferred, 0)) + { + Result = FspNtStatusFromWin32(GetLastError()); + goto exit; + } + + Result = STATUS_SUCCESS; + +exit: + if (INVALID_HANDLE_VALUE != Pipe) + CloseHandle(Pipe); + + return Result; +}