mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	tst: passthrough-cpp: initial implementation
This commit is contained in:
		
							
								
								
									
										5
									
								
								tst/passthrough-cpp/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								tst/passthrough-cpp/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| build | ||||
| *.ncb | ||||
| *.suo | ||||
| *.vcproj.* | ||||
| *.vcxproj.user | ||||
							
								
								
									
										903
									
								
								tst/passthrough-cpp/passthrough-cpp.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										903
									
								
								tst/passthrough-cpp/passthrough-cpp.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,903 @@ | ||||
| /** | ||||
|  * @file passthrough-cpp.cpp | ||||
|  * | ||||
|  * @copyright 2015-2017 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 file in | ||||
|  * accordance with the commercial license agreement provided with the | ||||
|  * software. | ||||
|  */ | ||||
|  | ||||
| #include <winfsp/winfsp.hpp> | ||||
| #include <strsafe.h> | ||||
|  | ||||
| #define PROGNAME                        "passthrough-cpp" | ||||
|  | ||||
| #define ALLOCATION_UNIT                 4096 | ||||
| #define FULLPATH_SIZE                   (MAX_PATH + FSP_FSCTL_TRANSACT_PATH_SIZEMAX / sizeof(WCHAR)) | ||||
|  | ||||
| #define info(format, ...)               FspServiceLog(EVENTLOG_INFORMATION_TYPE, format, __VA_ARGS__) | ||||
| #define warn(format, ...)               FspServiceLog(EVENTLOG_WARNING_TYPE, format, __VA_ARGS__) | ||||
| #define fail(format, ...)               FspServiceLog(EVENTLOG_ERROR_TYPE, format, __VA_ARGS__) | ||||
|  | ||||
| #define ConcatPath(FN, FP)              (0 == StringCbPrintfW(FP, sizeof FP, L"%s%s", _Path, FN)) | ||||
| #define HandleFromContext(FC)           ((PTFS_FILE_DESC *)FileContext->FileDesc)->Handle | ||||
|  | ||||
| class PTFS : public Fsp::FileSystem | ||||
| { | ||||
| public: | ||||
|     PTFS(); | ||||
|     ~PTFS(); | ||||
|     NTSTATUS SetPath(PWSTR Path); | ||||
|  | ||||
| protected: | ||||
|     static NTSTATUS GetFileInfoInternal(HANDLE Handle, FILE_INFO *FileInfo); | ||||
|     NTSTATUS GetVolumeInfo(VOLUME_INFO *VolumeInfo); | ||||
|     NTSTATUS GetSecurityByName( | ||||
|         PWSTR FileName, PUINT32 PFileAttributes/* or ReparsePointIndex */, | ||||
|         PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize); | ||||
|     NTSTATUS Create( | ||||
|         PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, | ||||
|         UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize, | ||||
|         FILE_CONTEXT *FileContext, OPEN_FILE_INFO *OpenFileInfo); | ||||
|     NTSTATUS Open( | ||||
|         PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, | ||||
|         FILE_CONTEXT *FileContext, OPEN_FILE_INFO *OpenFileInfo); | ||||
|     NTSTATUS Overwrite( | ||||
|         const FILE_CONTEXT *FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize, | ||||
|         FILE_INFO *FileInfo); | ||||
|     VOID Cleanup( | ||||
|         const FILE_CONTEXT *FileContext, PWSTR FileName, ULONG Flags); | ||||
|     VOID Close( | ||||
|         const FILE_CONTEXT *FileContext); | ||||
|     NTSTATUS Read( | ||||
|         const FILE_CONTEXT *FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, | ||||
|         PULONG PBytesTransferred); | ||||
|     NTSTATUS Write( | ||||
|         const FILE_CONTEXT *FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, | ||||
|         BOOLEAN WriteToEndOfFile, BOOLEAN ConstrainedIo, | ||||
|         PULONG PBytesTransferred, FILE_INFO *FileInfo); | ||||
|     NTSTATUS Flush( | ||||
|         const FILE_CONTEXT *FileContext, | ||||
|         FILE_INFO *FileInfo); | ||||
|     NTSTATUS GetFileInfo( | ||||
|         const FILE_CONTEXT *FileContext, | ||||
|         FILE_INFO *FileInfo); | ||||
|     NTSTATUS SetBasicInfo( | ||||
|         const FILE_CONTEXT *FileContext, UINT32 FileAttributes, | ||||
|         UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, UINT64 ChangeTime, | ||||
|         FILE_INFO *FileInfo); | ||||
|     NTSTATUS SetFileSize( | ||||
|         const FILE_CONTEXT *FileContext, UINT64 NewSize, BOOLEAN SetAllocationSize, | ||||
|         FILE_INFO *FileInfo); | ||||
|     NTSTATUS CanDelete( | ||||
|         const FILE_CONTEXT *FileContext, PWSTR FileName); | ||||
|     NTSTATUS Rename( | ||||
|         const FILE_CONTEXT *FileContext, | ||||
|         PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists); | ||||
|     NTSTATUS GetSecurity( | ||||
|         const FILE_CONTEXT *FileContext, | ||||
|         PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize); | ||||
|     NTSTATUS SetSecurity( | ||||
|         const FILE_CONTEXT *FileContext, | ||||
|         SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor); | ||||
|     NTSTATUS ReadDirectory( | ||||
|         const FILE_CONTEXT *FileContext, PWSTR Pattern, PWSTR Marker, | ||||
|         PVOID Buffer, ULONG Length, PULONG PBytesTransferred); | ||||
|  | ||||
| private: | ||||
|     PWSTR _Path; | ||||
| }; | ||||
|  | ||||
| struct PTFS_FILE_DESC | ||||
| { | ||||
|     PTFS_FILE_DESC() : Handle(INVALID_HANDLE_VALUE), DirBuffer() | ||||
|     { | ||||
|     } | ||||
|     ~PTFS_FILE_DESC() | ||||
|     { | ||||
|         CloseHandle(Handle); | ||||
|         FspFileSystemDeleteDirectoryBuffer(&DirBuffer); | ||||
|     } | ||||
|     HANDLE Handle; | ||||
|     PVOID DirBuffer; | ||||
| }; | ||||
|  | ||||
| PTFS::PTFS() : _Path() | ||||
| { | ||||
|     SetSectorSize(ALLOCATION_UNIT); | ||||
|     SetSectorsPerAllocationUnit(1); | ||||
|     SetFileInfoTimeout(1000); | ||||
|     SetCaseSensitiveSearch(FALSE); | ||||
|     SetCasePreservedNames(TRUE); | ||||
|     SetUnicodeOnDisk(TRUE); | ||||
|     SetPersistentAcls(TRUE); | ||||
|     SetPostCleanupWhenModifiedOnly(TRUE); | ||||
|     SetPassQueryDirectoryPattern(TRUE); | ||||
| } | ||||
|  | ||||
| PTFS::~PTFS() | ||||
| { | ||||
|     delete[] _Path; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::SetPath(PWSTR Path) | ||||
| { | ||||
|     WCHAR FullPath[MAX_PATH]; | ||||
|     ULONG Length; | ||||
|     HANDLE Handle; | ||||
|     FILETIME CreationTime; | ||||
|     DWORD LastError; | ||||
|  | ||||
|     Handle = CreateFileW( | ||||
|         Path, FILE_READ_ATTRIBUTES, 0, 0, | ||||
|         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|     if (INVALID_HANDLE_VALUE == Handle) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     Length = GetFinalPathNameByHandleW(Handle, FullPath, FULLPATH_SIZE - 1, 0); | ||||
|     if (0 == Length) | ||||
|     { | ||||
|         LastError = GetLastError(); | ||||
|         CloseHandle(Handle); | ||||
|         return FspNtStatusFromWin32(LastError); | ||||
|     } | ||||
|     if (L'\\' == FullPath[Length - 1]) | ||||
|         FullPath[--Length] = L'\0'; | ||||
|  | ||||
|     if (!GetFileTime(Handle, &CreationTime, 0, 0)) | ||||
|     { | ||||
|         LastError = GetLastError(); | ||||
|         CloseHandle(Handle); | ||||
|         return FspNtStatusFromWin32(LastError); | ||||
|     } | ||||
|  | ||||
|     CloseHandle(Handle); | ||||
|  | ||||
|     Length++; | ||||
|     _Path = new WCHAR[Length]; | ||||
|     memcpy(_Path, FullPath, Length * sizeof(WCHAR)); | ||||
|  | ||||
|     SetVolumeCreationTime(((PLARGE_INTEGER)&CreationTime)->QuadPart); | ||||
|     SetVolumeSerialNumber(0); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::GetFileInfoInternal(HANDLE Handle, FILE_INFO *FileInfo) | ||||
| { | ||||
|     BY_HANDLE_FILE_INFORMATION ByHandleFileInfo; | ||||
|  | ||||
|     if (!GetFileInformationByHandle(Handle, &ByHandleFileInfo)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     FileInfo->FileAttributes = ByHandleFileInfo.dwFileAttributes; | ||||
|     FileInfo->ReparseTag = 0; | ||||
|     FileInfo->FileSize = | ||||
|         ((UINT64)ByHandleFileInfo.nFileSizeHigh << 32) | (UINT64)ByHandleFileInfo.nFileSizeLow; | ||||
|     FileInfo->AllocationSize = (FileInfo->FileSize + ALLOCATION_UNIT - 1) | ||||
|         / ALLOCATION_UNIT * ALLOCATION_UNIT; | ||||
|     FileInfo->CreationTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftCreationTime)->QuadPart; | ||||
|     FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart; | ||||
|     FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart; | ||||
|     FileInfo->ChangeTime = FileInfo->LastWriteTime; | ||||
|     FileInfo->IndexNumber = 0; | ||||
|     FileInfo->HardLinks = 0; | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::GetVolumeInfo(VOLUME_INFO *VolumeInfo) | ||||
| { | ||||
|     WCHAR Root[MAX_PATH]; | ||||
|     ULARGE_INTEGER TotalSize, FreeSize; | ||||
|  | ||||
|     if (!GetVolumePathName(_Path, Root, MAX_PATH)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     if (!GetDiskFreeSpaceEx(Root, 0, &TotalSize, &FreeSize)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     VolumeInfo->TotalSize = TotalSize.QuadPart; | ||||
|     VolumeInfo->FreeSize = FreeSize.QuadPart; | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::GetSecurityByName( | ||||
|     PWSTR FileName, PUINT32 PFileAttributes/* or ReparsePointIndex */, | ||||
|     PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize) | ||||
| { | ||||
|     WCHAR FullPath[FULLPATH_SIZE]; | ||||
|     HANDLE Handle; | ||||
|     FILE_ATTRIBUTE_TAG_INFO AttributeTagInfo; | ||||
|     DWORD SecurityDescriptorSizeNeeded; | ||||
|     NTSTATUS Result; | ||||
|  | ||||
|     if (!ConcatPath(FileName, FullPath)) | ||||
|         return STATUS_OBJECT_NAME_INVALID; | ||||
|  | ||||
|     Handle = CreateFileW(FullPath, | ||||
|         FILE_READ_ATTRIBUTES | READ_CONTROL, 0, 0, | ||||
|         OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0); | ||||
|     if (INVALID_HANDLE_VALUE == Handle) | ||||
|     { | ||||
|         Result = FspNtStatusFromWin32(GetLastError()); | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     if (0 != PFileAttributes) | ||||
|     { | ||||
|         if (!GetFileInformationByHandleEx(Handle, | ||||
|             FileAttributeTagInfo, &AttributeTagInfo, sizeof AttributeTagInfo)) | ||||
|         { | ||||
|             Result = FspNtStatusFromWin32(GetLastError()); | ||||
|             goto exit; | ||||
|         } | ||||
|  | ||||
|         *PFileAttributes = AttributeTagInfo.FileAttributes; | ||||
|     } | ||||
|  | ||||
|     if (0 != PSecurityDescriptorSize) | ||||
|     { | ||||
|         if (!GetKernelObjectSecurity(Handle, | ||||
|             OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, | ||||
|             SecurityDescriptor, (DWORD)*PSecurityDescriptorSize, &SecurityDescriptorSizeNeeded)) | ||||
|         { | ||||
|             *PSecurityDescriptorSize = SecurityDescriptorSizeNeeded; | ||||
|             Result = FspNtStatusFromWin32(GetLastError()); | ||||
|             goto exit; | ||||
|         } | ||||
|  | ||||
|         *PSecurityDescriptorSize = SecurityDescriptorSizeNeeded; | ||||
|     } | ||||
|  | ||||
|     Result = STATUS_SUCCESS; | ||||
|  | ||||
| exit: | ||||
|     if (INVALID_HANDLE_VALUE != Handle) | ||||
|         CloseHandle(Handle); | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::Create( | ||||
|     PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, | ||||
|     UINT32 FileAttributes, PSECURITY_DESCRIPTOR SecurityDescriptor, UINT64 AllocationSize, | ||||
|     FILE_CONTEXT *FileContext, OPEN_FILE_INFO *OpenFileInfo) | ||||
| { | ||||
|     WCHAR FullPath[FULLPATH_SIZE]; | ||||
|     SECURITY_ATTRIBUTES SecurityAttributes; | ||||
|     ULONG CreateFlags; | ||||
|     PTFS_FILE_DESC *FileDesc; | ||||
|  | ||||
|     if (!ConcatPath(FileName, FullPath)) | ||||
|         return STATUS_OBJECT_NAME_INVALID; | ||||
|  | ||||
|     FileDesc = new PTFS_FILE_DESC; | ||||
|  | ||||
|     SecurityAttributes.nLength = sizeof SecurityAttributes; | ||||
|     SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor; | ||||
|     SecurityAttributes.bInheritHandle = FALSE; | ||||
|  | ||||
|     CreateFlags = FILE_FLAG_BACKUP_SEMANTICS; | ||||
|     if (CreateOptions & FILE_DELETE_ON_CLOSE) | ||||
|         CreateFlags |= FILE_FLAG_DELETE_ON_CLOSE; | ||||
|  | ||||
|     if (CreateOptions & FILE_DIRECTORY_FILE) | ||||
|     { | ||||
|         /* | ||||
|          * It is not widely known but CreateFileW can be used to create directories! | ||||
|          * It requires the specification of both FILE_FLAG_BACKUP_SEMANTICS and | ||||
|          * FILE_FLAG_POSIX_SEMANTICS. It also requires that FileAttributes has | ||||
|          * FILE_ATTRIBUTE_DIRECTORY set. | ||||
|          */ | ||||
|         CreateFlags |= FILE_FLAG_POSIX_SEMANTICS; | ||||
|         FileAttributes |= FILE_ATTRIBUTE_DIRECTORY; | ||||
|     } | ||||
|     else | ||||
|         FileAttributes &= ~FILE_ATTRIBUTE_DIRECTORY; | ||||
|  | ||||
|     if (0 == FileAttributes) | ||||
|         FileAttributes = FILE_ATTRIBUTE_NORMAL; | ||||
|  | ||||
|     FileDesc->Handle = CreateFileW(FullPath, | ||||
|         GrantedAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &SecurityAttributes, | ||||
|         CREATE_NEW, CreateFlags | FileAttributes, 0); | ||||
|     if (INVALID_HANDLE_VALUE == FileDesc->Handle) | ||||
|     { | ||||
|         delete FileDesc; | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|     } | ||||
|  | ||||
|     FileContext->FileDesc = FileDesc; | ||||
|  | ||||
|     return GetFileInfoInternal(FileDesc->Handle, &OpenFileInfo->FileInfo); | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::Open( | ||||
|     PWSTR FileName, UINT32 CreateOptions, UINT32 GrantedAccess, | ||||
|     FILE_CONTEXT *FileContext, OPEN_FILE_INFO *OpenFileInfo) | ||||
| { | ||||
|     WCHAR FullPath[FULLPATH_SIZE]; | ||||
|     ULONG CreateFlags; | ||||
|     PTFS_FILE_DESC *FileDesc; | ||||
|  | ||||
|     if (!ConcatPath(FileName, FullPath)) | ||||
|         return STATUS_OBJECT_NAME_INVALID; | ||||
|  | ||||
|     FileDesc = new PTFS_FILE_DESC; | ||||
|  | ||||
|     CreateFlags = FILE_FLAG_BACKUP_SEMANTICS; | ||||
|     if (CreateOptions & FILE_DELETE_ON_CLOSE) | ||||
|         CreateFlags |= FILE_FLAG_DELETE_ON_CLOSE; | ||||
|  | ||||
|     FileDesc->Handle = CreateFileW(FullPath, | ||||
|         GrantedAccess, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, | ||||
|         OPEN_EXISTING, CreateFlags, 0); | ||||
|     if (INVALID_HANDLE_VALUE == FileDesc->Handle) | ||||
|     { | ||||
|         delete FileDesc; | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|     } | ||||
|  | ||||
|     FileContext->FileDesc = FileDesc; | ||||
|  | ||||
|     return GetFileInfoInternal(FileDesc->Handle, &OpenFileInfo->FileInfo); | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::Overwrite( | ||||
|     const FILE_CONTEXT *FileContext, UINT32 FileAttributes, BOOLEAN ReplaceFileAttributes, UINT64 AllocationSize, | ||||
|     FILE_INFO *FileInfo) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|     FILE_BASIC_INFO BasicInfo = { 0 }; | ||||
|     FILE_ALLOCATION_INFO AllocationInfo = { 0 }; | ||||
|     FILE_ATTRIBUTE_TAG_INFO AttributeTagInfo; | ||||
|  | ||||
|     if (ReplaceFileAttributes) | ||||
|     { | ||||
|         if (0 == FileAttributes) | ||||
|             FileAttributes = FILE_ATTRIBUTE_NORMAL; | ||||
|  | ||||
|         BasicInfo.FileAttributes = FileAttributes; | ||||
|         if (!SetFileInformationByHandle(Handle, | ||||
|             FileBasicInfo, &BasicInfo, sizeof BasicInfo)) | ||||
|             return FspNtStatusFromWin32(GetLastError()); | ||||
|     } | ||||
|     else if (0 != FileAttributes) | ||||
|     { | ||||
|         if (!GetFileInformationByHandleEx(Handle, | ||||
|             FileAttributeTagInfo, &AttributeTagInfo, sizeof AttributeTagInfo)) | ||||
|             return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|         BasicInfo.FileAttributes = FileAttributes | AttributeTagInfo.FileAttributes; | ||||
|         if (BasicInfo.FileAttributes ^ FileAttributes) | ||||
|         { | ||||
|             if (!SetFileInformationByHandle(Handle, | ||||
|                 FileBasicInfo, &BasicInfo, sizeof BasicInfo)) | ||||
|                 return FspNtStatusFromWin32(GetLastError()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (!SetFileInformationByHandle(Handle, | ||||
|         FileAllocationInfo, &AllocationInfo, sizeof AllocationInfo)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     return GetFileInfoInternal(Handle, FileInfo); | ||||
| } | ||||
|  | ||||
| VOID PTFS::Cleanup( | ||||
|     const FILE_CONTEXT *FileContext, PWSTR FileName, ULONG Flags) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|  | ||||
|     if (Flags & CleanupDelete) | ||||
|     { | ||||
|         CloseHandle(Handle); | ||||
|  | ||||
|         /* this will make all future uses of Handle to fail with STATUS_INVALID_HANDLE */ | ||||
|         HandleFromContext(FileContext) = INVALID_HANDLE_VALUE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| VOID PTFS::Close( | ||||
|     const FILE_CONTEXT *FileContext) | ||||
| { | ||||
|     PTFS_FILE_DESC *FileDesc = (PTFS_FILE_DESC *)FileContext->FileDesc; | ||||
|  | ||||
|     delete FileDesc; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::Read( | ||||
|     const FILE_CONTEXT *FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, | ||||
|     PULONG PBytesTransferred) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|     OVERLAPPED Overlapped = { 0 }; | ||||
|  | ||||
|     Overlapped.Offset = (DWORD)Offset; | ||||
|     Overlapped.OffsetHigh = (DWORD)(Offset >> 32); | ||||
|  | ||||
|     if (!ReadFile(Handle, Buffer, Length, PBytesTransferred, &Overlapped)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::Write( | ||||
|     const FILE_CONTEXT *FileContext, PVOID Buffer, UINT64 Offset, ULONG Length, | ||||
|     BOOLEAN WriteToEndOfFile, BOOLEAN ConstrainedIo, | ||||
|     PULONG PBytesTransferred, FILE_INFO *FileInfo) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|     LARGE_INTEGER FileSize; | ||||
|     OVERLAPPED Overlapped = { 0 }; | ||||
|  | ||||
|     if (ConstrainedIo) | ||||
|     { | ||||
|         if (!GetFileSizeEx(Handle, &FileSize)) | ||||
|             return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|         if (Offset >= (UINT64)FileSize.QuadPart) | ||||
|             return STATUS_SUCCESS; | ||||
|         if (Offset + Length > (UINT64)FileSize.QuadPart) | ||||
|             Length = (ULONG)((UINT64)FileSize.QuadPart - Offset); | ||||
|     } | ||||
|  | ||||
|     Overlapped.Offset = (DWORD)Offset; | ||||
|     Overlapped.OffsetHigh = (DWORD)(Offset >> 32); | ||||
|  | ||||
|     if (!WriteFile(Handle, Buffer, Length, PBytesTransferred, &Overlapped)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     return GetFileInfoInternal(Handle, FileInfo); | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::Flush( | ||||
|     const FILE_CONTEXT *FileContext, | ||||
|     FILE_INFO *FileInfo) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|  | ||||
|     /* we do not flush the whole volume, so just return SUCCESS */ | ||||
|     if (0 == Handle) | ||||
|         return STATUS_SUCCESS; | ||||
|  | ||||
|     if (!FlushFileBuffers(Handle)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     return GetFileInfoInternal(Handle, FileInfo); | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::GetFileInfo( | ||||
|     const FILE_CONTEXT *FileContext, | ||||
|     FILE_INFO *FileInfo) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|  | ||||
|     return GetFileInfoInternal(Handle, FileInfo); | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::SetBasicInfo( | ||||
|     const FILE_CONTEXT *FileContext, UINT32 FileAttributes, | ||||
|     UINT64 CreationTime, UINT64 LastAccessTime, UINT64 LastWriteTime, UINT64 ChangeTime, | ||||
|     FILE_INFO *FileInfo) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|     FILE_BASIC_INFO BasicInfo = { 0 }; | ||||
|  | ||||
|     if (INVALID_FILE_ATTRIBUTES == FileAttributes) | ||||
|         FileAttributes = 0; | ||||
|     else if (0 == FileAttributes) | ||||
|         FileAttributes = FILE_ATTRIBUTE_NORMAL; | ||||
|  | ||||
|     BasicInfo.FileAttributes = FileAttributes; | ||||
|     BasicInfo.CreationTime.QuadPart = CreationTime; | ||||
|     BasicInfo.LastAccessTime.QuadPart = LastAccessTime; | ||||
|     BasicInfo.LastWriteTime.QuadPart = LastWriteTime; | ||||
|     //BasicInfo.ChangeTime = ChangeTime; | ||||
|  | ||||
|     if (!SetFileInformationByHandle(Handle, | ||||
|         FileBasicInfo, &BasicInfo, sizeof BasicInfo)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     return GetFileInfoInternal(Handle, FileInfo); | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::SetFileSize( | ||||
|     const FILE_CONTEXT *FileContext, UINT64 NewSize, BOOLEAN SetAllocationSize, | ||||
|     FILE_INFO *FileInfo) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|     FILE_ALLOCATION_INFO AllocationInfo; | ||||
|     FILE_END_OF_FILE_INFO EndOfFileInfo; | ||||
|  | ||||
|     if (SetAllocationSize) | ||||
|     { | ||||
|         /* | ||||
|          * This file system does not maintain AllocationSize, although NTFS clearly can. | ||||
|          * However it must always be FileSize <= AllocationSize and NTFS will make sure | ||||
|          * to truncate the FileSize if it sees an AllocationSize < FileSize. | ||||
|          * | ||||
|          * If OTOH a very large AllocationSize is passed, the call below will increase | ||||
|          * the AllocationSize of the underlying file, although our file system does not | ||||
|          * expose this fact. This AllocationSize is only temporary as NTFS will reset | ||||
|          * the AllocationSize of the underlying file when it is closed. | ||||
|          */ | ||||
|  | ||||
|         AllocationInfo.AllocationSize.QuadPart = NewSize; | ||||
|  | ||||
|         if (!SetFileInformationByHandle(Handle, | ||||
|             FileAllocationInfo, &AllocationInfo, sizeof AllocationInfo)) | ||||
|             return FspNtStatusFromWin32(GetLastError()); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         EndOfFileInfo.EndOfFile.QuadPart = NewSize; | ||||
|  | ||||
|         if (!SetFileInformationByHandle(Handle, | ||||
|             FileEndOfFileInfo, &EndOfFileInfo, sizeof EndOfFileInfo)) | ||||
|             return FspNtStatusFromWin32(GetLastError()); | ||||
|     } | ||||
|  | ||||
|     return GetFileInfoInternal(Handle, FileInfo); | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::CanDelete( | ||||
|     const FILE_CONTEXT *FileContext, PWSTR FileName) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|     FILE_DISPOSITION_INFO DispositionInfo; | ||||
|  | ||||
|     DispositionInfo.DeleteFile = TRUE; | ||||
|  | ||||
|     if (!SetFileInformationByHandle(Handle, | ||||
|         FileDispositionInfo, &DispositionInfo, sizeof DispositionInfo)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::Rename( | ||||
|     const FILE_CONTEXT *FileContext, | ||||
|     PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists) | ||||
| { | ||||
|     WCHAR FullPath[FULLPATH_SIZE], NewFullPath[FULLPATH_SIZE]; | ||||
|  | ||||
|     if (!ConcatPath(FileName, FullPath)) | ||||
|         return STATUS_OBJECT_NAME_INVALID; | ||||
|  | ||||
|     if (!ConcatPath(NewFileName, NewFullPath)) | ||||
|         return STATUS_OBJECT_NAME_INVALID; | ||||
|  | ||||
|     if (!MoveFileExW(FullPath, NewFullPath, ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::GetSecurity( | ||||
|     const FILE_CONTEXT *FileContext, | ||||
|     PSECURITY_DESCRIPTOR SecurityDescriptor, SIZE_T *PSecurityDescriptorSize) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|     DWORD SecurityDescriptorSizeNeeded; | ||||
|  | ||||
|     if (!GetKernelObjectSecurity(Handle, | ||||
|         OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, | ||||
|         SecurityDescriptor, (DWORD)*PSecurityDescriptorSize, &SecurityDescriptorSizeNeeded)) | ||||
|     { | ||||
|         *PSecurityDescriptorSize = SecurityDescriptorSizeNeeded; | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|     } | ||||
|  | ||||
|     *PSecurityDescriptorSize = SecurityDescriptorSizeNeeded; | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::SetSecurity( | ||||
|     const FILE_CONTEXT *FileContext, | ||||
|     SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR ModificationDescriptor) | ||||
| { | ||||
|     HANDLE Handle = HandleFromContext(FileContext); | ||||
|  | ||||
|     if (!SetKernelObjectSecurity(Handle, SecurityInformation, ModificationDescriptor)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| NTSTATUS PTFS::ReadDirectory( | ||||
|     const FILE_CONTEXT *FileContext, PWSTR Pattern, PWSTR Marker, | ||||
|     PVOID Buffer, ULONG BufferLength, PULONG PBytesTransferred) | ||||
| { | ||||
|     PTFS_FILE_DESC *FileDesc = (PTFS_FILE_DESC *)FileContext->FileDesc; | ||||
|     HANDLE Handle = FileDesc->Handle; | ||||
|     WCHAR FullPath[FULLPATH_SIZE]; | ||||
|     ULONG Length, PatternLength; | ||||
|     HANDLE FindHandle; | ||||
|     WIN32_FIND_DATAW FindData; | ||||
|     union | ||||
|     { | ||||
|         UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + MAX_PATH * sizeof(WCHAR)]; | ||||
|         FSP_FSCTL_DIR_INFO D; | ||||
|     } DirInfoBuf; | ||||
|     FSP_FSCTL_DIR_INFO *DirInfo = &DirInfoBuf.D; | ||||
|     NTSTATUS DirBufferResult; | ||||
|  | ||||
|     DirBufferResult = STATUS_SUCCESS; | ||||
|     if (FspFileSystemAcquireDirectoryBuffer(&FileDesc->DirBuffer, 0 == Marker, &DirBufferResult)) | ||||
|     { | ||||
|         if (0 == Pattern) | ||||
|             Pattern = L"*"; | ||||
|         PatternLength = (ULONG)wcslen(Pattern); | ||||
|  | ||||
|         Length = GetFinalPathNameByHandleW(Handle, FullPath, FULLPATH_SIZE - 1, 0); | ||||
|         if (0 == Length) | ||||
|             DirBufferResult = FspNtStatusFromWin32(GetLastError()); | ||||
|         else if (Length + 1 + PatternLength >= FULLPATH_SIZE) | ||||
|             DirBufferResult = STATUS_OBJECT_NAME_INVALID; | ||||
|         if (!NT_SUCCESS(DirBufferResult)) | ||||
|         { | ||||
|             FspFileSystemReleaseDirectoryBuffer(&FileDesc->DirBuffer); | ||||
|             return DirBufferResult; | ||||
|         } | ||||
|  | ||||
|         if (L'\\' != FullPath[Length - 1]) | ||||
|             FullPath[Length++] = L'\\'; | ||||
|         memcpy(FullPath + Length, Pattern, PatternLength * sizeof(WCHAR)); | ||||
|         FullPath[Length + PatternLength] = L'\0'; | ||||
|  | ||||
|         FindHandle = FindFirstFileW(FullPath, &FindData); | ||||
|         if (INVALID_HANDLE_VALUE != FindHandle) | ||||
|         { | ||||
|             do | ||||
|             { | ||||
|                 memset(DirInfo, 0, sizeof *DirInfo); | ||||
|                 Length = (ULONG)wcslen(FindData.cFileName); | ||||
|                 DirInfo->Size = (UINT16)(FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) + Length * sizeof(WCHAR)); | ||||
|                 DirInfo->FileInfo.FileAttributes = FindData.dwFileAttributes; | ||||
|                 DirInfo->FileInfo.ReparseTag = 0; | ||||
|                 DirInfo->FileInfo.FileSize = | ||||
|                     ((UINT64)FindData.nFileSizeHigh << 32) | (UINT64)FindData.nFileSizeLow; | ||||
|                 DirInfo->FileInfo.AllocationSize = (DirInfo->FileInfo.FileSize + ALLOCATION_UNIT - 1) | ||||
|                     / ALLOCATION_UNIT * ALLOCATION_UNIT; | ||||
|                 DirInfo->FileInfo.CreationTime = ((PLARGE_INTEGER)&FindData.ftCreationTime)->QuadPart; | ||||
|                 DirInfo->FileInfo.LastAccessTime = ((PLARGE_INTEGER)&FindData.ftLastAccessTime)->QuadPart; | ||||
|                 DirInfo->FileInfo.LastWriteTime = ((PLARGE_INTEGER)&FindData.ftLastWriteTime)->QuadPart; | ||||
|                 DirInfo->FileInfo.ChangeTime = DirInfo->FileInfo.LastWriteTime; | ||||
|                 DirInfo->FileInfo.IndexNumber = 0; | ||||
|                 DirInfo->FileInfo.HardLinks = 0; | ||||
|                 memcpy(DirInfo->FileNameBuf, FindData.cFileName, Length * sizeof(WCHAR)); | ||||
|  | ||||
|                 if (!FspFileSystemFillDirectoryBuffer(&FileDesc->DirBuffer, DirInfo, &DirBufferResult)) | ||||
|                     break; | ||||
|             } while (FindNextFileW(FindHandle, &FindData)); | ||||
|  | ||||
|             FindClose(FindHandle); | ||||
|         } | ||||
|  | ||||
|         FspFileSystemReleaseDirectoryBuffer(&FileDesc->DirBuffer); | ||||
|     } | ||||
|  | ||||
|     if (!NT_SUCCESS(DirBufferResult)) | ||||
|         return DirBufferResult; | ||||
|  | ||||
|     FspFileSystemReadDirectoryBuffer(&FileDesc->DirBuffer, | ||||
|         Marker, Buffer, BufferLength, PBytesTransferred); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static NTSTATUS EnableBackupRestorePrivileges(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_BACKUP_NAME, &Privileges.P.Privileges[0].Luid) || | ||||
|         !LookupPrivilegeValueW(0, SE_RESTORE_NAME, &Privileges.P.Privileges[1].Luid)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &Token)) | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|  | ||||
|     if (!AdjustTokenPrivileges(Token, FALSE, &Privileges.P, 0, 0, 0)) | ||||
|     { | ||||
|         CloseHandle(Token); | ||||
|  | ||||
|         return FspNtStatusFromWin32(GetLastError()); | ||||
|     } | ||||
|  | ||||
|     CloseHandle(Token); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static ULONG wcstol_deflt(wchar_t *w, ULONG deflt) | ||||
| { | ||||
|     wchar_t *endp; | ||||
|     ULONG ul = wcstol(w, &endp, 0); | ||||
|     return L'\0' != w[0] && L'\0' == *endp ? ul : deflt; | ||||
| } | ||||
|  | ||||
| static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv) | ||||
| { | ||||
| #define argtos(v)                       if (arge > ++argp) v = *argp; else goto usage | ||||
| #define argtol(v)                       if (arge > ++argp) v = wcstol_deflt(*argp, v); else goto usage | ||||
|  | ||||
|     wchar_t **argp, **arge; | ||||
|     PWSTR DebugLogFile = 0; | ||||
|     ULONG DebugFlags = 0; | ||||
|     PWSTR VolumePrefix = 0; | ||||
|     PWSTR PassThrough = 0; | ||||
|     PWSTR MountPoint = 0; | ||||
|     HANDLE DebugLogHandle = INVALID_HANDLE_VALUE; | ||||
|     WCHAR PassThroughBuf[MAX_PATH]; | ||||
|     PTFS *Ptfs = 0; | ||||
|     NTSTATUS Result; | ||||
|  | ||||
|     for (argp = argv + 1, arge = argv + argc; arge > argp; argp++) | ||||
|     { | ||||
|         if (L'-' != argp[0][0]) | ||||
|             break; | ||||
|         switch (argp[0][1]) | ||||
|         { | ||||
|         case L'?': | ||||
|             goto usage; | ||||
|         case L'd': | ||||
|             argtol(DebugFlags); | ||||
|             break; | ||||
|         case L'D': | ||||
|             argtos(DebugLogFile); | ||||
|             break; | ||||
|         case L'm': | ||||
|             argtos(MountPoint); | ||||
|             break; | ||||
|         case L'p': | ||||
|             argtos(PassThrough); | ||||
|             break; | ||||
|         case L'u': | ||||
|             argtos(VolumePrefix); | ||||
|             break; | ||||
|         default: | ||||
|             goto usage; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (arge > argp) | ||||
|         goto usage; | ||||
|  | ||||
|     if (0 == PassThrough && 0 != VolumePrefix) | ||||
|     { | ||||
|         PWSTR P; | ||||
|  | ||||
|         P = wcschr(VolumePrefix, L'\\'); | ||||
|         if (0 != P && L'\\' != P[1]) | ||||
|         { | ||||
|             P = wcschr(P + 1, L'\\'); | ||||
|             if (0 != P && | ||||
|                 ( | ||||
|                 (L'A' <= P[1] && P[1] <= L'Z') || | ||||
|                 (L'a' <= P[1] && P[1] <= L'z') | ||||
|                 ) && | ||||
|                 L'$' == P[2]) | ||||
|             { | ||||
|                 StringCbPrintf(PassThroughBuf, sizeof PassThroughBuf, L"%c:%s", P[1], P + 3); | ||||
|                 PassThrough = PassThroughBuf; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (0 == PassThrough || 0 == MountPoint) | ||||
|         goto usage; | ||||
|  | ||||
|     EnableBackupRestorePrivileges(); | ||||
|  | ||||
|     if (0 != DebugLogFile) | ||||
|     { | ||||
|         if (0 == wcscmp(L"-", DebugLogFile)) | ||||
|             DebugLogHandle = GetStdHandle(STD_ERROR_HANDLE); | ||||
|         else | ||||
|             DebugLogHandle = CreateFileW( | ||||
|                 DebugLogFile, | ||||
|                 FILE_APPEND_DATA, | ||||
|                 FILE_SHARE_READ | FILE_SHARE_WRITE, | ||||
|                 0, | ||||
|                 OPEN_ALWAYS, | ||||
|                 FILE_ATTRIBUTE_NORMAL, | ||||
|                 0); | ||||
|         if (INVALID_HANDLE_VALUE == DebugLogHandle) | ||||
|         { | ||||
|             fail(L"cannot open debug log file"); | ||||
|             goto usage; | ||||
|         } | ||||
|  | ||||
|         FspDebugLogSetHandle(DebugLogHandle); | ||||
|     } | ||||
|  | ||||
|     Ptfs = new PTFS; | ||||
|  | ||||
|     Ptfs->SetPrefix(VolumePrefix); | ||||
|  | ||||
|     Result = Ptfs->SetPath(PassThrough); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         fail(L"cannot create file system"); | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     Result = Ptfs->Mount(MountPoint, 0, FALSE, DebugFlags); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         fail(L"cannot mount file system"); | ||||
|         goto exit; | ||||
|     } | ||||
|  | ||||
|     MountPoint = Ptfs->MountPoint(); | ||||
|  | ||||
|     info(L"%s%s%s -p %s -m %s", | ||||
|         L"" PROGNAME, | ||||
|         0 != VolumePrefix && L'\0' != VolumePrefix[0] ? L" -u " : L"", | ||||
|             0 != VolumePrefix && L'\0' != VolumePrefix[0] ? VolumePrefix : L"", | ||||
|         PassThrough, | ||||
|         MountPoint); | ||||
|  | ||||
|     Service->UserContext = Ptfs; | ||||
|     Result = STATUS_SUCCESS; | ||||
|  | ||||
| exit: | ||||
|     if (!NT_SUCCESS(Result) && 0 != Ptfs) | ||||
|         delete Ptfs; | ||||
|  | ||||
|     return Result; | ||||
|  | ||||
| usage: | ||||
|     static wchar_t usage[] = L"" | ||||
|         "usage: %s OPTIONS\n" | ||||
|         "\n" | ||||
|         "options:\n" | ||||
|         "    -d DebugFlags       [-1: enable all debug logs]\n" | ||||
|         "    -D DebugLogFile     [file path; use - for stderr]\n" | ||||
|         "    -u \\Server\\Share    [UNC prefix (single backslash)]\n" | ||||
|         "    -p Directory        [directory to expose as pass through file system]\n" | ||||
|         "    -m MountPoint       [X:|*|directory]\n"; | ||||
|  | ||||
|     fail(usage, L"" PROGNAME); | ||||
|  | ||||
|     return STATUS_UNSUCCESSFUL; | ||||
|  | ||||
| #undef argtos | ||||
| #undef argtol | ||||
| } | ||||
|  | ||||
| static NTSTATUS SvcStop(FSP_SERVICE *Service) | ||||
| { | ||||
|     PTFS *Ptfs = (PTFS *)Service->UserContext; | ||||
|  | ||||
|     Ptfs->Unmount(); | ||||
|     delete Ptfs; | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| int wmain(int argc, wchar_t **argv) | ||||
| { | ||||
|     return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0); | ||||
| } | ||||
							
								
								
									
										28
									
								
								tst/passthrough-cpp/passthrough-cpp.sln
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								tst/passthrough-cpp/passthrough-cpp.sln
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
|  | ||||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
| # Visual Studio 14 | ||||
| VisualStudioVersion = 14.0.25420.1 | ||||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "passthrough-cpp", "passthrough-cpp.vcxproj", "{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|x64 = Debug|x64 | ||||
| 		Debug|x86 = Debug|x86 | ||||
| 		Release|x64 = Release|x64 | ||||
| 		Release|x86 = Release|x86 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||||
| 		{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x64.ActiveCfg = Debug|x64 | ||||
| 		{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x64.Build.0 = Debug|x64 | ||||
| 		{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x86.ActiveCfg = Debug|Win32 | ||||
| 		{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Debug|x86.Build.0 = Debug|Win32 | ||||
| 		{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x64.ActiveCfg = Release|x64 | ||||
| 		{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x64.Build.0 = Release|x64 | ||||
| 		{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x86.ActiveCfg = Release|Win32 | ||||
| 		{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}.Release|x86.Build.0 = Release|Win32 | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| 	EndGlobalSection | ||||
| EndGlobal | ||||
							
								
								
									
										178
									
								
								tst/passthrough-cpp/passthrough-cpp.vcxproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								tst/passthrough-cpp/passthrough-cpp.vcxproj
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemGroup Label="ProjectConfigurations"> | ||||
|     <ProjectConfiguration Include="Debug|Win32"> | ||||
|       <Configuration>Debug</Configuration> | ||||
|       <Platform>Win32</Platform> | ||||
|     </ProjectConfiguration> | ||||
|     <ProjectConfiguration Include="Release|Win32"> | ||||
|       <Configuration>Release</Configuration> | ||||
|       <Platform>Win32</Platform> | ||||
|     </ProjectConfiguration> | ||||
|     <ProjectConfiguration Include="Debug|x64"> | ||||
|       <Configuration>Debug</Configuration> | ||||
|       <Platform>x64</Platform> | ||||
|     </ProjectConfiguration> | ||||
|     <ProjectConfiguration Include="Release|x64"> | ||||
|       <Configuration>Release</Configuration> | ||||
|       <Platform>x64</Platform> | ||||
|     </ProjectConfiguration> | ||||
|   </ItemGroup> | ||||
|   <PropertyGroup Label="Globals"> | ||||
|     <ProjectGuid>{E8A4060D-E6A4-42CC-9BCA-DC82E6EDB2C5}</ProjectGuid> | ||||
|     <Keyword>Win32Proj</Keyword> | ||||
|     <RootNamespace>passthroughcpp</RootNamespace> | ||||
|     <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> | ||||
|   </PropertyGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>true</UseDebugLibraries> | ||||
|     <PlatformToolset>v140</PlatformToolset> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>false</UseDebugLibraries> | ||||
|     <PlatformToolset>v140</PlatformToolset> | ||||
|     <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>true</UseDebugLibraries> | ||||
|     <PlatformToolset>v140</PlatformToolset> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> | ||||
|     <ConfigurationType>Application</ConfigurationType> | ||||
|     <UseDebugLibraries>false</UseDebugLibraries> | ||||
|     <PlatformToolset>v140</PlatformToolset> | ||||
|     <WholeProgramOptimization>true</WholeProgramOptimization> | ||||
|     <CharacterSet>Unicode</CharacterSet> | ||||
|   </PropertyGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||||
|   <ImportGroup Label="ExtensionSettings"> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="Shared"> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|   </ImportGroup> | ||||
|   <PropertyGroup Label="UserMacros" /> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <LinkIncremental>true</LinkIncremental> | ||||
|     <OutDir>$(SolutionDir)build\$(Configuration)\</OutDir> | ||||
|     <IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir> | ||||
|     <TargetName>$(ProjectName)-$(PlatformTarget)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||
|     <LinkIncremental>true</LinkIncremental> | ||||
|     <OutDir>$(SolutionDir)build\$(Configuration)\</OutDir> | ||||
|     <IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir> | ||||
|     <TargetName>$(ProjectName)-$(PlatformTarget)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <LinkIncremental>false</LinkIncremental> | ||||
|     <OutDir>$(SolutionDir)build\$(Configuration)\</OutDir> | ||||
|     <IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir> | ||||
|     <TargetName>$(ProjectName)-$(PlatformTarget)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||||
|     <LinkIncremental>false</LinkIncremental> | ||||
|     <OutDir>$(SolutionDir)build\$(Configuration)\</OutDir> | ||||
|     <IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir> | ||||
|     <TargetName>$(ProjectName)-$(PlatformTarget)</TargetName> | ||||
|   </PropertyGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
|     <ClCompile> | ||||
|       <PrecompiledHeader> | ||||
|       </PrecompiledHeader> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <Optimization>Disabled</Optimization> | ||||
|       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <SDLCheck>true</SDLCheck> | ||||
|       <AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc;..\..\inc</AdditionalIncludeDirectories> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|       <DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||
|     <ClCompile> | ||||
|       <PrecompiledHeader> | ||||
|       </PrecompiledHeader> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <Optimization>Disabled</Optimization> | ||||
|       <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <SDLCheck>true</SDLCheck> | ||||
|       <AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc;..\..\inc</AdditionalIncludeDirectories> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|       <DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | ||||
|     <ClCompile> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <PrecompiledHeader> | ||||
|       </PrecompiledHeader> | ||||
|       <Optimization>MaxSpeed</Optimization> | ||||
|       <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
|       <IntrinsicFunctions>true</IntrinsicFunctions> | ||||
|       <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <SDLCheck>true</SDLCheck> | ||||
|       <AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc;..\..\inc</AdditionalIncludeDirectories> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <EnableCOMDATFolding>true</EnableCOMDATFolding> | ||||
|       <OptimizeReferences>true</OptimizeReferences> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|       <DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||||
|     <ClCompile> | ||||
|       <WarningLevel>Level3</WarningLevel> | ||||
|       <PrecompiledHeader> | ||||
|       </PrecompiledHeader> | ||||
|       <Optimization>MaxSpeed</Optimization> | ||||
|       <FunctionLevelLinking>true</FunctionLevelLinking> | ||||
|       <IntrinsicFunctions>true</IntrinsicFunctions> | ||||
|       <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|       <SDLCheck>true</SDLCheck> | ||||
|       <AdditionalIncludeDirectories>$(MSBuildProgramFiles32)\WinFsp\inc;..\..\inc</AdditionalIncludeDirectories> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Console</SubSystem> | ||||
|       <EnableCOMDATFolding>true</EnableCOMDATFolding> | ||||
|       <OptimizeReferences>true</OptimizeReferences> | ||||
|       <GenerateDebugInformation>true</GenerateDebugInformation> | ||||
|       <AdditionalDependencies>$(MSBuildProgramFiles32)\WinFsp\lib\winfsp-$(PlatformTarget).lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|       <DelayLoadDLLs>winfsp-$(PlatformTarget).dll</DelayLoadDLLs> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="passthrough-cpp.cpp" /> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||
|   <ImportGroup Label="ExtensionTargets"> | ||||
|   </ImportGroup> | ||||
| </Project> | ||||
							
								
								
									
										14
									
								
								tst/passthrough-cpp/passthrough-cpp.vcxproj.filters
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								tst/passthrough-cpp/passthrough-cpp.vcxproj.filters
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemGroup> | ||||
|     <Filter Include="Source"> | ||||
|       <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> | ||||
|       <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> | ||||
|     </Filter> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="passthrough-cpp.cpp"> | ||||
|       <Filter>Source</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
		Reference in New Issue
	
	Block a user