├── .gitignore ├── Common ├── Common.vcxproj ├── HelperMacros.h ├── Log │ ├── NdLog.cpp │ ├── NdLog.h │ ├── NtLogString.cpp │ └── NtLogString.h ├── String │ ├── StringHelper.cpp │ ├── StringHelper.h │ ├── StringHelperEx.cpp │ ├── StringHelperEx.h │ ├── UnicodeHelper.cpp │ └── UnicodeHelper.h ├── WinNT │ ├── AutoReleaseLock.h │ ├── Console.cpp │ ├── Console.h │ ├── Explorer.cpp │ ├── Explorer.h │ ├── FileSystem.cpp │ ├── FileSystem.h │ ├── GuiUtil.cpp │ ├── GuiUtil.h │ ├── Guid.cpp │ ├── Guid.h │ ├── NtServiceCtrl.cpp │ ├── NtServiceCtrl.h │ ├── NtServiceInfo.cpp │ ├── NtServiceInfo.h │ ├── NtVolume.cpp │ ├── NtVolume.h │ ├── OsVersion.cpp │ ├── OsVersion.h │ ├── PipeClient.cpp │ ├── PipeClient.h │ ├── QueryVirtualMemory.cpp │ ├── QueryVirtualMemory.h │ ├── Registry.cpp │ ├── Registry.h │ ├── Uac.cpp │ └── Uac.h ├── misc.cpp ├── misc.h └── stlhelper.h ├── DokanStatus.h ├── ProcMonDebugOutput ├── ProcMonDebugOutput.cpp ├── ProcMonDebugOutput.h ├── ProcMonDebugOutput.rc ├── ProcMonDebugOutput.vcxproj ├── ProcMonDebugOutput.vcxproj.filters ├── ProcMonDebugOutputWIN32.def ├── resource.h ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── README.md ├── Sysinternals.Debug ├── CodeAnalysisDictionary.xml ├── GlobalSuppressions.cs ├── NativeMethods.cs ├── ProcessMonitorTraceListerner.cs ├── Properties │ └── AssemblyInfo.cs └── Sysinternals.Debug.csproj ├── dokan.h ├── dokanc.h ├── dokani.h ├── dokanx.sln ├── dokanx ├── access.cpp ├── cleanup.cpp ├── close.cpp ├── create.cpp ├── directory.cpp ├── dokan.cpp ├── dokanx.vcxproj ├── dokanx.vcxproj.user ├── fileinfo.cpp ├── fileinfo.h ├── flush.cpp ├── list.h ├── lock.cpp ├── mount.cpp ├── read.cpp ├── security.cpp ├── setfile.cpp ├── stdafx.cpp ├── stdafx.h ├── timeout.cpp ├── version.cpp ├── volume.cpp └── write.cpp ├── dokanx_control ├── dokanctl.cpp ├── dokanx_control.sln ├── dokanx_control.vcxproj ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── dokanx_mount ├── Release │ └── dokanx_mount.res ├── Resource.h ├── dokanx_mount.cpp ├── dokanx_mount.ico ├── dokanx_mount.rc ├── dokanx_mount.sln ├── dokanx_mount.vcxproj ├── mount.cpp ├── mount.h ├── mounter.cpp ├── small.ico ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── license.gpl.txt ├── license.lgpl.txt ├── license.mit.txt ├── mirrorfs ├── mirrorfs.cpp ├── mirrorfs.vcxproj ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── public.h └── sys ├── COPYING ├── COPYING.LESSER ├── access.c ├── cleanup.c ├── close.c ├── create.c ├── ddkbuild.bat ├── device.c ├── directory.c ├── dokan.c ├── dokan.h ├── dokan.rc ├── event.c ├── fileinfo.c ├── flush.c ├── fscontrol.c ├── howtobuild.txt ├── init.c ├── lock.c ├── makefile ├── notification.c ├── precomp.h ├── read.c ├── security.c ├── sources ├── sys.vcxproj ├── sys.vcxproj.filters ├── timeout.c ├── volume.c └── write.c /.gitignore: -------------------------------------------------------------------------------- 1 | # git ignore file 2 | *.map 3 | *.pdb 4 | *.sys 5 | *.exe 6 | *.filters 7 | *.user 8 | *.tlog 9 | *.log 10 | *.obj 11 | *.lastbuildstate 12 | *.idb 13 | *.dll 14 | *.lib 15 | *.exp 16 | *.ilk 17 | *.manifest 18 | *.opensdf 19 | *.suo 20 | *.sdf 21 | *.pch 22 | dokanx_control/Debug 23 | dokanx_control/ipch 24 | dokanx_mount/ipch 25 | dokanx_mount/Debug 26 | ProcMonDebugOutput/Release*/ 27 | ProcMonDebugOutput/Debug*/ 28 | Common/Debug 29 | mirrorfs/Debug 30 | sys/obj* 31 | sys/prefast* 32 | dokan_sshfs 33 | dokan_net 34 | dokan_install 35 | dokan_np 36 | *.unsuccessfulbuild 37 | *.cache 38 | ipch\ 39 | *.ipch 40 | -------------------------------------------------------------------------------- /Common/HelperMacros.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | // 5 | // You can use this macro instead of using a comment. 6 | // It prints its contents to output window when you build the project. 7 | // 8 | #define chSTR2(x) #x 9 | #define chSTR(x) chSTR2(x) 10 | 11 | #define chMSG(desc) message(__FILE__ "(" chSTR(__LINE__) "): --------" #desc "--------") 12 | #define chFixLater message(__FILE__ "(" chSTR(__LINE__) "): --------Fix this later--------") 13 | 14 | #define FixLater \ 15 | do { \ 16 | __pragma(chFixLater) \ 17 | __pragma (warning(push)) \ 18 | __pragma (warning(disable:4127)) \ 19 | } while(0) \ 20 | __pragma (warning(pop)) 21 | 22 | #define MSG(desc) \ 23 | do { \ 24 | __pragma(chMSG(desc)) \ 25 | __pragma (warning(push)) \ 26 | __pragma (warning(disable:4127)) \ 27 | } while(0) \ 28 | __pragma (warning(pop)) 29 | 30 | 31 | 32 | // A macro to disallow the copy constructor and operator= functions 33 | // This should be used in the private: declarations for a class 34 | #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 35 | TypeName(const TypeName&); \ 36 | void operator=(const TypeName&) 37 | 38 | 39 | #define UNREFERENCED_PARAMETERS(...) __VA_ARGS__ 40 | 41 | // 42 | // Extracting function name as widechar. 43 | // 44 | #define __STR2WSTR(str) L##str 45 | #define _STR2WSTR(str) __STR2WSTR(str) 46 | #define __FUNCTIONW__ _STR2WSTR(__FUNCTION__) 47 | 48 | 49 | 50 | #define _DOKAN_DEPRECATE(_AlternativeFunc) __declspec(deprecated("This function or variable has been deprecated."\ 51 | " Consider using " #_AlternativeFunc " instead.")) 52 | 53 | 54 | #define CASE_RETURN_CODE_TO_STRING(str) case str: return L#str 55 | -------------------------------------------------------------------------------- /Common/Log/NdLog.cpp: -------------------------------------------------------------------------------- 1 | #include "NdLog.h" 2 | 3 | #include "../misc.h" 4 | #include "../HelperMacros.h" 5 | #include "../String/UnicodeHelper.h" 6 | #include "../WinNT/Registry.h" 7 | #include "../../ProcMonDebugOutput/ProcMonDebugOutput.h" 8 | 9 | #ifdef _DEBUG 10 | enum LOG_OUTPUT_FLAG g_OutputLogFlag = LOF_PROCESS_MONITOR; 11 | #else 12 | enum LOG_OUTPUT_FLAG g_OutputLogFlag = LOF_NULL; 13 | #endif 14 | 15 | /* 16 | static variables 17 | */ 18 | static HANDLE s_hLogMutex = INVALID_HANDLE_VALUE; 19 | 20 | VOID NdLogVar(LOG_OUTPUT_FLAG outputLogFlag, __in __format_string LPCWSTR fmt, ...) 21 | { 22 | va_list argList; 23 | va_start(argList, fmt); 24 | WCHAR szMsg[4096]; 25 | StringCchVPrintfW(szMsg, _countof(szMsg), fmt, argList); 26 | va_end(argList); 27 | 28 | if (outputLogFlag & LOF_DEBUG_VIEW) 29 | { 30 | OutputDebugStringW(szMsg); 31 | } 32 | 33 | if (outputLogFlag & LOF_PROCESS_MONITOR) 34 | { 35 | ProcMonDebugOutput(szMsg); 36 | } 37 | 38 | if (outputLogFlag & LOF_FILE) 39 | { 40 | //NdFileLog(szMsg); 41 | } 42 | } 43 | 44 | #define _ENABLE_PERF_LOG 45 | #include 46 | 47 | std::wstring GetWin32FormatMessage(DWORD dwWin32Error) 48 | { 49 | HLOCAL hlocal = NULL; 50 | BOOL fOk = FormatMessage( 51 | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, 52 | NULL, 53 | dwWin32Error, 54 | MAKELANGID(LANG_KOREAN, SUBLANG_ENGLISH_US), 55 | (LPTSTR)&hlocal, 56 | 0, 57 | NULL 58 | ); 59 | 60 | std::wstring sFormatMessage; 61 | if (fOk) 62 | { 63 | sFormatMessage = (PCTSTR)LocalLock(hlocal); 64 | } 65 | return sFormatMessage; 66 | } 67 | 68 | VOID PrintFormatMessage(DWORD dwWin32Error) 69 | { 70 | OutputDebugString(GetWin32FormatMessage(dwWin32Error).c_str()); 71 | } 72 | 73 | VOID PrintFormatMessage_Dbg(DWORD dwWin32Error) 74 | { 75 | #ifdef _DEBUG 76 | PrintFormatMessage(dwWin32Error); 77 | #else 78 | UNREFERENCED_PARAMETER(dwWin32Error); 79 | #endif //_DEBUG 80 | } 81 | 82 | VOID NdPerfLog(__in LPCWSTR logfile, __in __format_string LPCWSTR fmt, ...) 83 | { 84 | va_list argList; 85 | va_start(argList, fmt); 86 | WCHAR szMsg[4096]; 87 | StringCchVPrintfW(szMsg, _countof(szMsg), fmt, argList); 88 | va_end(argList); 89 | 90 | MSG(Add synchronization); 91 | HANDLE hFile = CreateFile( 92 | logfile, 93 | GENERIC_WRITE, 94 | FILE_SHARE_READ | FILE_SHARE_WRITE, 95 | NULL, 96 | OPEN_ALWAYS, 97 | FILE_ATTRIBUTE_NORMAL, 98 | NULL 99 | ); 100 | if (hFile == INVALID_HANDLE_VALUE) 101 | { 102 | _stprintf_s(szMsg, L"Cannot create a log file. [errcode: %d][%s]\n", GetLastError(), logfile); 103 | OutputDebugString(szMsg); 104 | } 105 | else 106 | { 107 | (VOID)SetFilePointer(hFile, 0, 0, FILE_END); 108 | std::string s; 109 | s.append(ToAnsiStr(GetCurrentTimeStr().c_str())); 110 | s.append(" "); 111 | s.append(ToAnsiStr(szMsg)); 112 | s.append(""); 113 | DWORD dwWritten; 114 | (VOID)WriteFile(hFile, s.c_str(), (DWORD)s.size(), &dwWritten, 0); 115 | CloseHandle(hFile); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /Common/Log/NdLog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #pragma warning(push) 8 | #pragma warning(disable:4995) 9 | #include 10 | #pragma warning(pop) 11 | 12 | #include "../HelperMacros.h" 13 | 14 | enum LOG_OUTPUT_FLAG 15 | { 16 | LOF_NULL = 0x00, 17 | LOF_DEBUG_VIEW = 0x01, 18 | LOF_FILE = 0x02, 19 | LOF_PROCESS_MONITOR = 0x04, 20 | }; 21 | 22 | extern enum LOG_OUTPUT_FLAG g_OutputLogFlag; 23 | 24 | 25 | VOID NdLogVar(LOG_OUTPUT_FLAG outputLogFlag, __in __format_string LPCWSTR fmt, ...); 26 | VOID NdFileLog(__in LPCWSTR lpszLogMessage); 27 | VOID NdPerfLog(__in LPCWSTR logfile, __in __format_string LPCWSTR fmt, ...); 28 | 29 | inline VOID SetOutputLogFlag(LOG_OUTPUT_FLAG flag) 30 | { 31 | g_OutputLogFlag = flag; 32 | } 33 | 34 | #if !defined(_MODULE_NAME) 35 | #define _MODULE_NAME L"Unnamed" 36 | #endif 37 | 38 | #define logbasic(outputMode, fmt, ...) \ 39 | do { \ 40 | NdLogVar(outputMode, L"[%04d]" _MODULE_NAME L"!" __FUNCTIONW__ L": " fmt L"\n", GetCurrentThreadId(), __VA_ARGS__);\ 41 | __pragma (warning(push)) \ 42 | __pragma (warning(disable:4127)) \ 43 | } while (0) \ 44 | __pragma (warning(pop)) 45 | 46 | #if defined(_DISABLE_LOGGING) 47 | #define logw(fmt, ...) \ 48 | __noop(fmt, __VA_ARGS__); \ 49 | UNREFERENCED_PARAMETERS(__VA_ARGS__) 50 | #else 51 | #define logw(fmt, ...) logbasic(g_OutputLogFlag, fmt, __VA_ARGS__); 52 | #endif 53 | 54 | #define logf(fmt, ...) logbasic(static_cast(LOF_DEBUG_VIEW | LOF_FILE), fmt, __VA_ARGS__); 55 | 56 | #define logd(fmt, ...) logbasic(static_cast(LOF_DEBUG_VIEW), fmt, __VA_ARGS__); 57 | 58 | std::wstring GetWin32FormatMessage(DWORD dwWin32Error); 59 | VOID PrintFormatMessage(DWORD dwWin32Error); 60 | VOID PrintFormatMessage_Dbg(DWORD dwWin32Error); 61 | -------------------------------------------------------------------------------- /Common/Log/NtLogString.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "NtLogString.h" 4 | #include "../../dokanx/fileinfo.h" 5 | 6 | #define GET_NT_STATUS_STRING_SWITCH()\ 7 | switch (status)\ 8 | {\ 9 | CASE_RETURN(STATUS_SUCCESS);\ 10 | CASE_RETURN(STATUS_ABANDONED);\ 11 | CASE_RETURN(STATUS_MORE_PROCESSING_REQUIRED);\ 12 | CASE_RETURN(STATUS_DATA_NOT_ACCEPTED);\ 13 | CASE_RETURN(STATUS_INVALID_DEVICE_REQUEST);\ 14 | CASE_RETURN(STATUS_BAD_NETWORK_NAME);\ 15 | CASE_RETURN(STATUS_BAD_NETWORK_PATH);\ 16 | CASE_RETURN(STATUS_INSUFFICIENT_RESOURCES);\ 17 | CASE_RETURN(STATUS_PENDING);\ 18 | CASE_RETURN(STATUS_INVALID_PARAMETER);\ 19 | CASE_RETURN(STATUS_NO_MORE_FILES);\ 20 | CASE_RETURN(STATUS_NO_SUCH_FILE);\ 21 | CASE_RETURN(STATUS_NOT_IMPLEMENTED);\ 22 | CASE_RETURN(STATUS_OBJECT_NAME_NOT_FOUND);\ 23 | CASE_RETURN(STATUS_OBJECT_PATH_NOT_FOUND);\ 24 | CASE_RETURN(STATUS_NETWORK_ACCESS_DENIED);\ 25 | CASE_RETURN(STATUS_BUFFER_TOO_SMALL);\ 26 | CASE_RETURN(STATUS_WMI_GUID_NOT_FOUND);\ 27 | CASE_RETURN(STATUS_QUOTA_EXCEEDED);\ 28 | CASE_RETURN(STATUS_DISK_FULL);\ 29 | CASE_RETURN(STATUS_NOT_SUPPORTED);\ 30 | CASE_RETURN(STATUS_FILE_IS_A_DIRECTORY);\ 31 | CASE_RETURN(STATUS_FILES_OPEN);\ 32 | CASE_RETURN(STATUS_CANCELLED);\ 33 | CASE_RETURN(STATUS_CONNECTION_IN_USE);\ 34 | CASE_RETURN(STATUS_LOCK_NOT_GRANTED);\ 35 | CASE_RETURN(STATUS_NOT_FOUND);\ 36 | CASE_RETURN(STATUS_ACCESS_DENIED);\ 37 | CASE_RETURN(STATUS_OBJECT_NAME_COLLISION);\ 38 | CASE_RETURN(STATUS_OBJECT_NAME_INVALID);\ 39 | CASE_RETURN(STATUS_OBJECT_TYPE_MISMATCH);\ 40 | CASE_RETURN(STATUS_END_OF_FILE);\ 41 | CASE_RETURN(STATUS_DELETE_PENDING);\ 42 | CASE_RETURN(STATUS_REDIRECTOR_HAS_OPEN_HANDLES);\ 43 | CASE_RETURN(STATUS_REDIRECTOR_PAUSED);\ 44 | CASE_RETURN(STATUS_REDIRECTOR_NOT_STARTED);\ 45 | CASE_RETURN(STATUS_REDIRECTOR_STARTED);\ 46 | CASE_RETURN(STATUS_NOT_A_DIRECTORY);\ 47 | CASE_RETURN(STATUS_RETRY);\ 48 | CASE_RETURN(STATUS_BUFFER_OVERFLOW);\ 49 | CASE_RETURN(STATUS_SHARING_VIOLATION);\ 50 | } 51 | 52 | LPCWSTR GetNtStatusString(NTSTATUS status) 53 | { 54 | #define CASE_RETURN(code) case code: return L#code 55 | 56 | GET_NT_STATUS_STRING_SWITCH(); 57 | 58 | #undef CASE_RETURN 59 | 60 | return L"Unknown"; 61 | } 62 | 63 | 64 | #define FILE_INFORMATION_CLASS_STRING_SWITCH()\ 65 | switch (clazz)\ 66 | {\ 67 | CASE_RETURN(FileDirectoryInformation);\ 68 | CASE_RETURN(FileFullDirectoryInformation);\ 69 | CASE_RETURN(FileBothDirectoryInformation);\ 70 | CASE_RETURN(FileBasicInformation);\ 71 | CASE_RETURN(FileStandardInformation);\ 72 | CASE_RETURN(FileInternalInformation);\ 73 | CASE_RETURN(FileEaInformation);\ 74 | CASE_RETURN(FileAccessInformation);\ 75 | CASE_RETURN(FileNameInformation);\ 76 | CASE_RETURN(FileRenameInformation);\ 77 | CASE_RETURN(FileLinkInformation);\ 78 | CASE_RETURN(FileNamesInformation);\ 79 | CASE_RETURN(FileDispositionInformation);\ 80 | CASE_RETURN(FilePositionInformation);\ 81 | CASE_RETURN(FileFullEaInformation);\ 82 | CASE_RETURN(FileModeInformation);\ 83 | CASE_RETURN(FileAlignmentInformation);\ 84 | CASE_RETURN(FileAllInformation);\ 85 | CASE_RETURN(FileAllocationInformation);\ 86 | CASE_RETURN(FileEndOfFileInformation);\ 87 | CASE_RETURN(FileAlternateNameInformation);\ 88 | CASE_RETURN(FileStreamInformation);\ 89 | CASE_RETURN(FilePipeInformation);\ 90 | CASE_RETURN(FilePipeLocalInformation);\ 91 | CASE_RETURN(FilePipeRemoteInformation);\ 92 | CASE_RETURN(FileMailslotQueryInformation);\ 93 | CASE_RETURN(FileMailslotSetInformation);\ 94 | CASE_RETURN(FileCompressionInformation);\ 95 | CASE_RETURN(FileObjectIdInformation);\ 96 | CASE_RETURN(FileCompletionInformation);\ 97 | CASE_RETURN(FileMoveClusterInformation);\ 98 | CASE_RETURN(FileQuotaInformation);\ 99 | CASE_RETURN(FileReparsePointInformation);\ 100 | CASE_RETURN(FileNetworkOpenInformation);\ 101 | CASE_RETURN(FileAttributeTagInformation);\ 102 | CASE_RETURN(FileTrackingInformation);\ 103 | CASE_RETURN(FileIdBothDirectoryInformation);\ 104 | CASE_RETURN(FileIdFullDirectoryInformation);\ 105 | CASE_RETURN(FileValidDataLengthInformation);\ 106 | CASE_RETURN(FileShortNameInformation);\ 107 | CASE_RETURN(FileIoCompletionNotificationInformation);\ 108 | CASE_RETURN(FileIoStatusBlockRangeInformation);\ 109 | CASE_RETURN(FileIoPriorityHintInformation);\ 110 | CASE_RETURN(FileSfioReserveInformation);\ 111 | CASE_RETURN(FileSfioVolumeInformation);\ 112 | CASE_RETURN(FileHardLinkInformation);\ 113 | CASE_RETURN(FileProcessIdsUsingFileInformation);\ 114 | CASE_RETURN(FileNormalizedNameInformation);\ 115 | CASE_RETURN(FileNetworkPhysicalNameInformation);\ 116 | CASE_RETURN(FileMaximumInformation);\ 117 | } 118 | 119 | LPCWSTR FileInformationClassString(INT clazz) 120 | { 121 | #define CASE_RETURN(clazz) case clazz: return L#clazz 122 | 123 | FILE_INFORMATION_CLASS_STRING_SWITCH(); 124 | 125 | #undef CASE_RETURN 126 | 127 | return L"Unknown"; 128 | } 129 | 130 | LPCWSTR GetMajorFunctionString(UCHAR majorFunction) 131 | { 132 | switch (majorFunction) 133 | { 134 | case 0x00: 135 | return L"IRP_MJ_CREATE"; 136 | /*case 0x01: 137 | return L"IRP_MJ_CREATE_NAMED_PIPE";*/ 138 | case 0x02: 139 | return L"IRP_MJ_CLOSE"; 140 | case 0x03: 141 | return L"IRP_MJ_READ"; 142 | case 0x04: 143 | return L"IRP_MJ_WRITE"; 144 | case 0x05: 145 | return L"IRP_MJ_QUERY_INFORMATION"; 146 | case 0x06: 147 | return L"IRP_MJ_SET_INFORMATION"; 148 | /*case 0x07: 149 | return L"IRP_MJ_QUERY_EA"; 150 | case 0x08: 151 | return L"IRP_MJ_SET_EA";*/ 152 | case 0x09: 153 | return L"IRP_MJ_FLUSH_BUFFERS"; 154 | case 0x0a: 155 | return L"IRP_MJ_QUERY_VOLUME_INFORMATION"; 156 | case 0x0b: 157 | return L"IRP_MJ_SET_VOLUME_INFORMATION"; 158 | case 0x0c: 159 | return L"IRP_MJ_DIRECTORY_CONTROL"; 160 | case 0x0d: 161 | return L"IRP_MJ_FILE_SYSTEM_CONTROL"; 162 | case 0x0e: 163 | return L"IRP_MJ_DEVICE_CONTROL"; 164 | /*case 0x0f: 165 | return L"IRP_MJ_INTERNAL_DEVICE_CONTROL";*/ 166 | case 0x10: 167 | return L"IRP_MJ_SHUTDOWN"; 168 | case 0x11: 169 | return L"IRP_MJ_LOCK_CONTROL"; 170 | case 0x12: 171 | return L"IRP_MJ_CLEANUP"; 172 | /*case 0x13: 173 | return L"IRP_MJ_CREATE_MAILSLOT";*/ 174 | case 0x14: 175 | return L"IRP_MJ_QUERY_SECURITY"; 176 | case 0x15: 177 | return L"IRP_MJ_SET_SECURITY"; 178 | /*case 0x16: 179 | return L"IRP_MJ_POWER";*/ 180 | /*case 0x17: 181 | return L"IRP_MJ_SYSTEM_CONTROL";*/ 182 | /*case 0x18: 183 | return L"IRP_MJ_DEVICE_CHANGE";*/ 184 | case 0x19: 185 | return L"IRP_MJ_QUERY_QUOTA"; 186 | case 0x1a: 187 | return L"IRP_MJ_SET_QUOTA"; 188 | /*case 0x1b: 189 | return L"IRP_MJ_PNP";*/ 190 | default: 191 | return L"Unknown Major Function"; 192 | } 193 | } 194 | 195 | LPCWSTR Win32CreateDispositionStr(DWORD dwDisposition) 196 | { 197 | switch (dwDisposition) 198 | { 199 | case CREATE_NEW: 200 | return L"CREATE_NEW"; 201 | case CREATE_ALWAYS: 202 | return L"CREATE_ALWAYS"; 203 | case OPEN_EXISTING: 204 | return L"OPEN_EXISTING"; 205 | case OPEN_ALWAYS: 206 | return L"OPEN_ALWAYS"; 207 | case TRUNCATE_EXISTING: 208 | return L"TRUNCATE_EXISTING"; 209 | default: 210 | return L"Unknown disposition"; 211 | } 212 | } 213 | 214 | LPCWSTR GetNtCreateDispositionStr(DWORD dwDisposition) 215 | { 216 | switch (dwDisposition) 217 | { 218 | case 0x00000000: 219 | return L"FILE_SUPERSEDE"; 220 | case 0x00000001: 221 | return L"FILE_OPEN"; 222 | case 0x00000002: 223 | return L"FILE_CREATE"; 224 | case 0x00000003: 225 | return L"FILE_OPEN_IF"; 226 | case 0x00000004: 227 | return L"FILE_OVERWRITE"; 228 | case 0x00000005: 229 | return L"FILE_OVERWRITE_IF"; 230 | default: 231 | return L"Unknown disposition"; 232 | } 233 | } -------------------------------------------------------------------------------- /Common/Log/NtLogString.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../DokanStatus.h" 4 | 5 | LPCWSTR GetNtStatusString(NTSTATUS status); 6 | LPCWSTR FileInformationClassString(INT clazz); 7 | LPCWSTR GetMajorFunctionString(UCHAR majorFunction); 8 | LPCWSTR Win32CreateDispositionStr(DWORD dwDisposition); 9 | LPCWSTR GetNtCreateDispositionStr(DWORD dwDisposition); -------------------------------------------------------------------------------- /Common/String/StringHelper.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/Common/String/StringHelper.cpp -------------------------------------------------------------------------------- /Common/String/StringHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #pragma warning(push) 5 | #pragma warning(disable:4995) 6 | #include 7 | #include 8 | #include 9 | #pragma warning(pop) 10 | 11 | std::wstring AddComma(const std::wstring& source); 12 | std::wstring AddComma(INT64 jNumber); 13 | size_t SplitStringW( 14 | __in LPCWSTR str, 15 | __in LPCWSTR delim, 16 | __out std::vector& results 17 | ); 18 | std::string& ReplaceinA(std::string &s, const std::string &sub, const std::string &other); 19 | std::wstring& ReplaceinW(std::wstring &s, const std::wstring &sub, const std::wstring &other); 20 | #if defined(UNICODE) || defined(_UNICODE) 21 | #define Replacein ReplaceinW 22 | #else 23 | #define Replacein ReplaceinA 24 | #endif 25 | 26 | void SelfGrow( std::string& s, size_t appendlength ); 27 | std::wstring BasePath(const std::wstring& sBinaryPath); 28 | std::wstring FileName(const std::wstring& sBinaryPath); 29 | bool StartWith(const std::wstring& fullStr, const std::wstring& startStr, BOOL fIgnoreCase); 30 | std::string TrimLeft(const std::string& str); 31 | std::string TrimRight(const std::string& str); 32 | std::string Trim(const std::string& str); 33 | std::wstring TrimLeftW(const std::wstring& str); 34 | std::wstring TrimRightW(const std::wstring& str); 35 | std::wstring TrimW(const std::wstring& str); 36 | bool Compare(const std::string& origin, const std::string& dest); 37 | //Function to convert a Hex string of length 2 to an unsigned char 38 | bool Hex2Char(CHAR const* szHex, UCHAR& rch); 39 | std::wstring TrimLastRightPathSeperator( 40 | __in const std::wstring& str, 41 | __in_opt WCHAR pathSeperator = L'/' 42 | ); 43 | std::string & TrimBothSide(std::string &str); 44 | 45 | void SHTokenizeA( const std::string& target, std::vector& tokens, const std::string &delim ); 46 | void SHTokenizeW( const std::wstring& target, std::vector& tokens, const std::wstring &delim ); 47 | #if defined(UNICODE) || defined(_UNICODE) 48 | #define SHTokenize SHTokenizeW 49 | #else 50 | #define SHTokenize SHTokenizeA 51 | #endif 52 | 53 | int StringAToInt( const std::string &str ); 54 | int StringWToInt( const std::wstring &str ); 55 | #if defined(UNICODE) || defined(_UNICODE) 56 | #define StringToInt StringWToInt 57 | #else 58 | #define StringToInt StringAToInt 59 | #endif 60 | 61 | std::wstring IntegerToStr(LONGLONG num); 62 | std::wstring AbbreviateFileName(__in const std::wstring& ntFileName, __in size_t cchMaxFileName); 63 | std::wstring AbbreviateString(__in const std::wstring& sString, __in size_t cchMaxLen); 64 | std::wstring AppendPathSeperatorIfNotExist( 65 | __in const std::wstring& path, 66 | __in WCHAR pathSeperator = L'/' 67 | ); 68 | std::wstring AddTrailBackSlashIfNotExist(__in const std::wstring& path); 69 | std::wstring AddFrontSlashIfNotExist(__in const std::wstring& path); 70 | std::wstring AddFrontAndRearSlashIfNotExist(__in const std::wstring& path); 71 | std::string Hexify(__in const std::vector& v); 72 | std::wstring ToLower(__in const std::wstring &ori); 73 | std::wstring ToLower(__in LPCWSTR ori); 74 | bool CiStringCompare(const std::wstring& s1, const std::wstring& s2); 75 | bool StringEqualNoCase(const std::wstring& s1, const std::wstring& s2); 76 | std::wstring ConvertNtPathToUnixPath(const std::wstring& sNtPath); 77 | std::wstring ConvertUnixPathToNtPath(const std::wstring& sNdPath, WCHAR chVolume); 78 | std::wstring __cdecl FormatV(PCWSTR pszFormat, ...); -------------------------------------------------------------------------------- /Common/String/StringHelperEx.cpp: -------------------------------------------------------------------------------- 1 | #include "StringHelper.h" 2 | #include "StringHelperEx.h" 3 | #include 4 | #include 5 | 6 | CString ReplaceBackslashToSlash(__in CONST CString& strPath) 7 | { 8 | CString s(strPath); 9 | s.Replace(L"\\", L"/"); 10 | return TrimLastRightPathSeperator((LPCWSTR)s, L'/').c_str(); 11 | } 12 | 13 | CString ReplaceSlashToBackslash(__in CONST CString& strPath) 14 | { 15 | CString s(strPath); 16 | s.Replace(L"/", L"\\"); 17 | return TrimLastRightPathSeperator((LPCWSTR)s, L'\\').c_str(); 18 | } 19 | 20 | CString GetResString(UINT uStringID, HINSTANCE hResource) 21 | { 22 | CString resString; 23 | //resString.LoadString(g_hResInst, uStringID); 24 | _TCHAR* ch = resString.GetBuffer(512); 25 | if (hResource) 26 | { 27 | ::LoadString(hResource, uStringID, ch, 512); 28 | } 29 | else 30 | { 31 | ::LoadString(GetModuleHandle(NULL), uStringID, ch, 512); 32 | } 33 | 34 | resString.ReleaseBuffer(); 35 | resString.Replace(_T("\\n"), _T("\n")); 36 | return resString; 37 | } 38 | 39 | CString ConvertToHumanReadableSize(INT64 jSize, UINT nDefault) 40 | { 41 | double size = static_cast(jSize); 42 | double temp = 0; 43 | 44 | for ( ; ; ) 45 | { 46 | temp = size / 1024; 47 | if (temp < 1) 48 | { 49 | break; 50 | } 51 | 52 | ++nDefault; 53 | 54 | size = temp; 55 | 56 | if (nDefault == FILESIZE_MBYTE) 57 | { 58 | size = floor(10. * (temp)) / 10.; 59 | } 60 | else if ( nDefault == FILESIZE_GBYTE ) 61 | { 62 | size = floor(100. * (temp)) / 100.; 63 | } 64 | else if ( nDefault == FILESIZE_TBYTE ) 65 | { 66 | size = floor(1000. * (temp)) / 1000.; 67 | } 68 | else 69 | { 70 | size = temp; 71 | } 72 | } 73 | 74 | TCHAR *Byte; 75 | switch (nDefault) 76 | { 77 | case FILESIZE_BYTE: 78 | Byte = L"Bytes"; 79 | break; 80 | case FILESIZE_KBYTE: 81 | Byte = L"KB"; 82 | break; 83 | case FILESIZE_MBYTE: 84 | Byte = L"MB"; 85 | break; 86 | case FILESIZE_GBYTE: 87 | Byte = L"GB"; 88 | break; 89 | case FILESIZE_TBYTE: 90 | Byte = L"TB"; 91 | break; 92 | default: 93 | Byte = L"MB"; 94 | break; 95 | } 96 | 97 | CString rString; 98 | rString.Format(L"%f", size); 99 | 100 | if (rString.GetLength() > 3) 101 | { 102 | rString = rString.Left(4); 103 | if (rString[3] == L'.') 104 | { 105 | rString = rString.Left(3); 106 | } 107 | } 108 | rString += Byte; 109 | 110 | return rString; 111 | } 112 | 113 | CString ConvertToHumanReadableSize(CONST CString& strSize, UINT nDefault) 114 | { 115 | INT64 jSize = _wtoi64(strSize); 116 | return ConvertToHumanReadableSize(jSize, nDefault); 117 | } -------------------------------------------------------------------------------- /Common/String/StringHelperEx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #pragma warning(push) 6 | #pragma warning(disable:4995) 7 | #include 8 | #include 9 | #include 10 | #pragma warning(pop) 11 | 12 | enum FileSizeFlags 13 | { 14 | FILESIZE_BYTE = 0x0001, 15 | FILESIZE_KBYTE = 0x0002, 16 | FILESIZE_MBYTE = 0x0003, 17 | FILESIZE_GBYTE = 0x0004, 18 | FILESIZE_TBYTE = 0x0005, 19 | }; 20 | 21 | CString ReplaceBackslashToSlash(__in CONST CString& strPath); 22 | CString ReplaceSlashToBackslash(__in CONST CString& strPath); 23 | CString GetResString(UINT uStringID, HINSTANCE hResource); 24 | CString ConvertToHumanReadableSize(INT64 jSize, UINT nDefault = FILESIZE_BYTE); 25 | CString ConvertToHumanReadableSize(CONST CString& strSize, UINT nDefault = FILESIZE_BYTE); -------------------------------------------------------------------------------- /Common/String/UnicodeHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning(push) 4 | #pragma warning(disable:4995) 5 | #include 6 | #include 7 | #pragma warning(pop) 8 | 9 | std::string ToAnsiStr(__in LPCWSTR uniStr); 10 | std::wstring ToUniStr(__in LPCSTR ansiStr); 11 | std::wstring ToWideCharString(__in LPCSTR pszAnsiStr); 12 | std::wstring UTF8ToUTF16(__in LPCSTR pszTextUTF8); 13 | std::string UTF16ToUTF8(__in LPCWSTR pszTextUTF16); 14 | std::string AnsiToUTF8(__in const std::string& strAnsi); 15 | std::string UTF8ToAnsi(__in const std::string& sUtf8); 16 | int Utf8CharCount(const char* pStr); -------------------------------------------------------------------------------- /Common/WinNT/AutoReleaseLock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /** 6 | */ 7 | class AutoReleaseLock 8 | { 9 | public: 10 | AutoReleaseLock(CRITICAL_SECTION* pLock) 11 | { 12 | _ASSERT(pLock); 13 | m_pLock = pLock; 14 | EnterCriticalSection(m_pLock); 15 | } 16 | ~AutoReleaseLock() 17 | { 18 | if (m_pLock) 19 | { 20 | LeaveCriticalSection(m_pLock); 21 | } 22 | } 23 | VOID Release() 24 | { 25 | if (m_pLock) 26 | { 27 | LeaveCriticalSection(m_pLock); 28 | m_pLock = NULL; 29 | } 30 | } 31 | private: 32 | CRITICAL_SECTION* m_pLock; 33 | }; -------------------------------------------------------------------------------- /Common/WinNT/Console.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "Console.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | CConsole::CConsole(bool bWideChar) 11 | { 12 | int nCharMode = (bWideChar) ? _O_WTEXT : _O_TEXT; 13 | 14 | AllocConsole(); 15 | int hCrtOut = _open_osfhandle((LONG)GetStdHandle(STD_OUTPUT_HANDLE), nCharMode); 16 | FILE *hOut = _fdopen(hCrtOut, "w"); 17 | *stdout = *hOut; 18 | int hCrtIn = _open_osfhandle((LONG)GetStdHandle(STD_INPUT_HANDLE), nCharMode); 19 | FILE *hIn = _fdopen(hCrtIn, "r"); 20 | *stdin = *hIn; 21 | setvbuf(stdin, NULL, _IONBF, 0); 22 | 23 | SetConsoleTitle(L"NDrive's console"); 24 | } 25 | 26 | CConsole::~CConsole() 27 | { 28 | _fcloseall(); 29 | FreeConsole(); 30 | } 31 | 32 | void CConsole::EnableConsole(bool bWideChar) 33 | { 34 | static CConsole console(bWideChar); 35 | } -------------------------------------------------------------------------------- /Common/WinNT/Console.h: -------------------------------------------------------------------------------- 1 | 2 | #pragma once 3 | 4 | /** 5 | */ 6 | class CConsole 7 | { 8 | public: 9 | 10 | static void EnableConsole(bool bWideChar); 11 | 12 | private: 13 | CConsole(); 14 | explicit CConsole(bool bWideChar); 15 | ~CConsole(); 16 | }; -------------------------------------------------------------------------------- /Common/WinNT/Explorer.cpp: -------------------------------------------------------------------------------- 1 | #include "explorer.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #pragma warning(push) 7 | #pragma warning(disable:4995) 8 | #include 9 | #pragma warning(push) 10 | 11 | #include 12 | #pragma comment(lib, "Psapi.lib") 13 | 14 | #include "../Log/NdLog.h" 15 | #include "Registry.h" 16 | #include "OsVersion.h" 17 | 18 | #undef Shell_GetCachedImageIndex 19 | 20 | bool OpenWindowsExplorer( 21 | __in const std::wstring& filePath, 22 | __in bool withSelectingFileItem 23 | ) 24 | { 25 | if (filePath.empty()) 26 | { 27 | return false; 28 | } 29 | 30 | std::wstring sCmdParameters; 31 | if (withSelectingFileItem) 32 | { 33 | sCmdParameters = L"/select,"; 34 | } 35 | else 36 | { 37 | sCmdParameters = L"/e,"; 38 | } 39 | 40 | if (filePath[0] != L'"') 41 | { 42 | sCmdParameters += std::wstring(L"\"") + filePath + L"\""; 43 | } 44 | else 45 | { 46 | sCmdParameters += filePath; 47 | } 48 | 49 | SHELLEXECUTEINFO sei = { 0 }; 50 | sei.cbSize = sizeof(sei); 51 | sei.fMask = SEE_MASK_NOCLOSEPROCESS; 52 | sei.nShow = SW_SHOWNORMAL; 53 | sei.lpVerb = L"open"; 54 | sei.lpParameters = sCmdParameters.c_str(); 55 | sei.lpFile = L"explorer"; 56 | 57 | return !!ShellExecuteExW(&sei); 58 | } 59 | 60 | std::wstring GetSpecialFolderPath( 61 | __in int csidl 62 | ) 63 | { 64 | WCHAR szPath[MAX_PATH]; 65 | BOOL fOk = SHGetSpecialFolderPath(0, szPath, csidl, FALSE); 66 | if (!fOk) 67 | { 68 | return L""; 69 | } 70 | 71 | return std::wstring(szPath); 72 | } 73 | 74 | bool ProcessNameMatched( 75 | __in const std::wstring& imageFileName, 76 | __in DWORD pid 77 | ) 78 | { 79 | std::wstring sProcessImageName = ProcessImageName(pid); 80 | logw(L"ProcessImageName(%d)<%s>", pid, sProcessImageName.c_str()); 81 | if (sProcessImageName.size() < imageFileName.size()) 82 | { 83 | return false; 84 | } 85 | 86 | sProcessImageName = sProcessImageName.substr(sProcessImageName.size() - imageFileName.size()); 87 | return (_wcsicmp(sProcessImageName.c_str(), imageFileName.c_str()) == 0); 88 | } 89 | 90 | std::wstring ProcessImageName( 91 | __in DWORD pid 92 | ) 93 | { 94 | TCHAR szFilePath[MAX_PATH] = { 0 }; 95 | std::wstring sImageName = L""; 96 | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); 97 | if (hProcess) 98 | { 99 | if (GetProcessImageFileName(hProcess, szFilePath, _countof(szFilePath))) 100 | { 101 | sImageName = szFilePath; 102 | } 103 | 104 | CloseHandle(hProcess); 105 | } 106 | 107 | return sImageName; 108 | } 109 | 110 | bool IsExplorerProcess( 111 | __in DWORD pid 112 | ) 113 | { 114 | return ProcessNameMatched(L"explorer.exe", pid); 115 | } 116 | 117 | bool SetVolumeIcon( 118 | __in wchar_t volumeDesignator, 119 | __in const std::wstring& canonicalIconPath 120 | ) 121 | { 122 | logw(L"Start<%s>(%c:)", canonicalIconPath.c_str(), volumeDesignator); 123 | WCHAR defaultIconBase[MAX_PATH]; 124 | StringCchPrintf( 125 | defaultIconBase, 126 | _countof(defaultIconBase), 127 | L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%c\\DefaultIcon", 128 | volumeDesignator 129 | ); 130 | 131 | if (canonicalIconPath.empty()) 132 | { 133 | logw(L"Delete the key<%s>", defaultIconBase); 134 | return (Registry::RegDeleteKeyNT(HKEY_LOCAL_MACHINE, defaultIconBase) == ERROR_SUCCESS); 135 | } 136 | else 137 | { 138 | return Registry::RegSetSimpleStringW( 139 | HKEY_LOCAL_MACHINE, 140 | defaultIconBase, 141 | L"", 142 | canonicalIconPath.c_str(), 143 | false 144 | ) ? true : false; 145 | } 146 | } 147 | 148 | HRESULT GetFolderDescriptionId( 149 | __in LPCWSTR pszPath, 150 | __out SHDESCRIPTIONID *pdid 151 | ) 152 | { 153 | HRESULT hr; 154 | LPITEMIDLIST pidl; 155 | if (SUCCEEDED(hr = SHParseDisplayName(pszPath, NULL, &pidl, 0, NULL))) 156 | { 157 | IShellFolder *psf; 158 | LPCITEMIDLIST pidlChild; 159 | if (SUCCEEDED(hr = SHBindToParent(pidl, IID_IShellFolder, (void**)&psf, &pidlChild))) 160 | { 161 | hr = SHGetDataFromIDList(psf, pidlChild, SHGDFIL_DESCRIPTIONID, pdid, sizeof(*pdid)); 162 | psf->Release(); 163 | } 164 | CoTaskMemFree(pidl); 165 | } 166 | return hr; 167 | } 168 | 169 | bool IsRecycleBin(const std::wstring& path) 170 | { 171 | SHDESCRIPTIONID did; 172 | return (SUCCEEDED(GetFolderDescriptionId(path.c_str(), &did)) && did.clsid == CLSID_RecycleBin); 173 | } 174 | 175 | void MarkShortcutRunAs(const std::wstring& sShortcut) 176 | { 177 | CoInitialize(NULL); 178 | 179 | do 180 | { 181 | CComPtr sppf; 182 | if (FAILED(sppf.CoCreateInstance(CLSID_ShellLink))) 183 | { 184 | break; 185 | } 186 | if (FAILED(sppf->Load(sShortcut.c_str(), STGM_READWRITE))) 187 | { 188 | break; 189 | } 190 | CComQIPtr spdl(sppf); 191 | if (!spdl) 192 | { 193 | break; 194 | } 195 | DWORD dwFlags; 196 | if (FAILED(spdl->GetFlags(&dwFlags))) 197 | { 198 | break; 199 | } 200 | dwFlags |= SLDF_RUNAS_USER; 201 | if (FAILED(spdl->SetFlags(dwFlags))) 202 | { 203 | break; 204 | } 205 | if (FAILED(sppf->Save(NULL, TRUE))) 206 | { 207 | break; 208 | } 209 | #pragma warning(push) 210 | #pragma warning(disable:4127) 211 | } while (0); 212 | #pragma warning(pop) 213 | 214 | CoUninitialize(); 215 | } 216 | 217 | void BroadcastDeviceChange(WPARAM message, int nDosDriveNo, DWORD driveMap) 218 | { 219 | DEV_BROADCAST_VOLUME dbv; 220 | DWORD_PTR dwResult; 221 | LONG eventId = 0; 222 | 223 | if (message == DBT_DEVICEARRIVAL) 224 | { 225 | eventId = SHCNE_DRIVEADD; 226 | } 227 | else if (message == DBT_DEVICEREMOVECOMPLETE) 228 | { 229 | eventId = SHCNE_DRIVEREMOVED; 230 | } 231 | else if (IsWindows7() && message == DBT_DEVICEREMOVEPENDING) 232 | { 233 | // Explorer on Windows 7 holds open handles of all drives when 'Computer' is expanded in navigation pane. 234 | // SHCNE_DRIVEREMOVED must be used as DBT_DEVICEREMOVEPENDING is ignored. 235 | eventId = SHCNE_DRIVEREMOVED; 236 | } 237 | 238 | if (driveMap == 0) 239 | { 240 | driveMap = (1 << nDosDriveNo); 241 | } 242 | 243 | if (eventId != 0) 244 | { 245 | int i; 246 | for (i = 0; i < 26; i++) 247 | { 248 | if (driveMap & (1 << i)) 249 | { 250 | char root[] = { (char) i + 'A', ':', '\\', 0 }; 251 | SHChangeNotify(eventId, SHCNF_PATH, root, NULL); 252 | 253 | // We don't need to support Windows 2000 254 | 255 | //if (nCurrentOS == WIN_2000 && RemoteSession) 256 | //{ 257 | // char target[32]; 258 | // //wsprintf (target, "%ls%c", TC_MOUNT_PREFIX, i + 'A'); 259 | // root[2] = 0; 260 | 261 | // if (message == DBT_DEVICEARRIVAL) 262 | // DefineDosDevice (DDD_RAW_TARGET_PATH, root, target); 263 | // else if (message == DBT_DEVICEREMOVECOMPLETE) 264 | // DefineDosDevice (DDD_RAW_TARGET_PATH| DDD_REMOVE_DEFINITION 265 | // | DDD_EXACT_MATCH_ON_REMOVE, root, target); 266 | //} 267 | } 268 | } 269 | } 270 | 271 | dbv.dbcv_size = sizeof (dbv); 272 | dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME; 273 | dbv.dbcv_reserved = 0; 274 | dbv.dbcv_unitmask = driveMap; 275 | dbv.dbcv_flags = 0; 276 | 277 | UINT timeOut = 1000; 278 | 279 | // SHChangeNotify() works on Vista, so the Explorer does not require WM_DEVICECHANGE 280 | if (IsVistaOrLater()) 281 | { 282 | timeOut = 100; 283 | } 284 | 285 | SendMessageTimeout(HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, timeOut, &dwResult); 286 | 287 | // Explorer prior Vista sometimes fails to register a new drive 288 | if (!IsVistaOrLater() && message == DBT_DEVICEARRIVAL) 289 | { 290 | SendMessageTimeout(HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, 200, &dwResult); 291 | } 292 | } 293 | -------------------------------------------------------------------------------- /Common/WinNT/Explorer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/Common/WinNT/Explorer.h -------------------------------------------------------------------------------- /Common/WinNT/FileSystem.cpp: -------------------------------------------------------------------------------- 1 | #include "FileSystem.h" 2 | 3 | #include 4 | 5 | //BOOL FileHasReadOnlyAttribute( 6 | // __in const WCHAR* path 7 | // ) 8 | //{ 9 | // DWORD attributes = GetFileAttributesW(path); 10 | // return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_READONLY) != 0; 11 | //} 12 | // 13 | //BOOL IsFileOnReadOnlyFilesystem( 14 | // __in const WCHAR *path 15 | // ) 16 | //{ 17 | // WCHAR root[MAX_PATH]; 18 | // if (!GetVolumePathNameW(path, root, _countof(root))) 19 | // { 20 | // return FALSE; 21 | // } 22 | // 23 | // DWORD flags, d; 24 | // if (!GetVolumeInformationW(root, NULL, 0, NULL, &d, &flags, NULL, 0)) 25 | // { 26 | // return FALSE; 27 | // } 28 | // 29 | // return (flags & FILE_READ_ONLY_VOLUME) ? TRUE : FALSE; 30 | //} 31 | 32 | //DWORD MoveFileOverwriteIf( 33 | // __in const std::wstring& sSrcFile, 34 | // __in const std::wstring& sDestFile 35 | // ) 36 | //{ 37 | // DWORD dwError; 38 | // DWORD srcAttributes = GetFileAttributes(sSrcFile.c_str()); 39 | // if (srcAttributes & FILE_ATTRIBUTE_DIRECTORY) 40 | // { 41 | // DWORD destAttributes = GetFileAttributes(sDestFile.c_str()); 42 | // if (destAttributes == INVALID_FILE_ATTRIBUTES) 43 | // { 44 | // if (!CreateDirectory(sDestFile.c_str(), NULL)) 45 | // { 46 | // dwError = GetLastError(); 47 | // return dwError; 48 | // } 49 | // } 50 | // 51 | // BOOL fOk = RemoveDirectory(sSrcFile.c_str()); 52 | // if (fOk) 53 | // { 54 | // if (!CreateDirectory(sDestFile.c_str(), NULL)) 55 | // { 56 | // dwError = GetLastError(); 57 | // if (dwError != ERROR_ALREADY_EXISTS && dwError != ERROR_SUCCESS) 58 | // { 59 | // return dwError; 60 | // } 61 | // } 62 | // } 63 | // else 64 | // { 65 | // dwError = GetLastError(); 66 | // if (dwError == ERROR_DIR_NOT_EMPTY) 67 | // { 68 | // WIN32_FIND_DATA findData; 69 | // HANDLE hFindFile = FindFirstFile((sSrcFile + L"\\*").c_str(), &findData); 70 | // std::vector vFiles; 71 | // if (hFindFile != INVALID_HANDLE_VALUE) 72 | // { 73 | // if (_wcsicmp(findData.cFileName, L".") != 0 && 74 | // _wcsicmp(findData.cFileName, L"..") != 0) 75 | // { 76 | // vFiles.push_back(findData); 77 | // } 78 | // 79 | // while (FindNextFile(hFindFile, &findData)) 80 | // { 81 | // if (_wcsicmp(findData.cFileName, L".") != 0 && 82 | // _wcsicmp(findData.cFileName, L"..") != 0) 83 | // { 84 | // vFiles.push_back(findData); 85 | // } 86 | // } 87 | // 88 | // FindClose(hFindFile); 89 | // } 90 | // else 91 | // { 92 | // dwError = GetLastError(); 93 | // return dwError; 94 | // } 95 | // 96 | // for (size_t i = 0; i < vFiles.size(); ++i) 97 | // { 98 | // dwError = MoveFileOverwriteIf( 99 | // sSrcFile + L"\\" + vFiles[i].cFileName, 100 | // sDestFile + L"\\" + vFiles[i].cFileName 101 | // ); 102 | // if (dwError != ERROR_SUCCESS) 103 | // { 104 | // return dwError; 105 | // } 106 | // } 107 | // } 108 | // 109 | // fOk = RemoveDirectory(sSrcFile.c_str()); 110 | // if (fOk) 111 | // { 112 | // return ERROR_SUCCESS; 113 | // } 114 | // else 115 | // { 116 | // return GetLastError(); 117 | // } 118 | // } 119 | // } 120 | // else 121 | // { 122 | // if (srcAttributes == INVALID_FILE_ATTRIBUTES) 123 | // { 124 | // dwError = GetLastError(); 125 | // return dwError; 126 | // } 127 | // 128 | // if (!MoveFileEx(sSrcFile.c_str(), sDestFile.c_str(), MOVEFILE_REPLACE_EXISTING)) 129 | // { 130 | // dwError = GetLastError(); 131 | // return dwError; 132 | // } 133 | // } 134 | // 135 | // return ERROR_SUCCESS; 136 | //} 137 | 138 | BOOL IsFileAlreadyOpenedByAnotherProcess( 139 | __in const std::wstring& sPath 140 | ) 141 | { 142 | HANDLE hFile = CreateFile(sPath.c_str(), GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); 143 | if(hFile != INVALID_HANDLE_VALUE) 144 | { 145 | CloseHandle(hFile); 146 | return FALSE; 147 | } 148 | else 149 | { 150 | DWORD dwErr = GetLastError(); 151 | if(dwErr == ERROR_FILE_NOT_FOUND || dwErr == ERROR_PATH_NOT_FOUND) 152 | { 153 | return FALSE; 154 | } 155 | } 156 | 157 | return TRUE; 158 | } 159 | 160 | DWORD GetFileList( 161 | __in const std::wstring& canonicalPath, 162 | __out std::vector* pFileList 163 | ) 164 | { 165 | WIN32_FIND_DATA findData; 166 | HANDLE hFindFile = FindFirstFile((canonicalPath + L"\\*").c_str(), &findData); 167 | if (hFindFile != INVALID_HANDLE_VALUE) 168 | { 169 | if (_wcsicmp(findData.cFileName, L".") != 0 && 170 | _wcsicmp(findData.cFileName, L"..") != 0) 171 | { 172 | pFileList->push_back(findData); 173 | } 174 | 175 | while (FindNextFile(hFindFile, &findData)) 176 | { 177 | if (_wcsicmp(findData.cFileName, L".") != 0 && 178 | _wcsicmp(findData.cFileName, L"..") != 0) 179 | { 180 | pFileList->push_back(findData); 181 | } 182 | } 183 | 184 | FindClose(hFindFile); 185 | } 186 | else 187 | { 188 | return GetLastError(); 189 | } 190 | 191 | return ERROR_SUCCESS; 192 | } -------------------------------------------------------------------------------- /Common/WinNT/FileSystem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #pragma warning(push) 5 | #pragma warning(disable:4995) 6 | #include 7 | #include 8 | #pragma warning(pop) 9 | 10 | BOOL FileHasReadOnlyAttribute( 11 | __in const WCHAR* path 12 | ); 13 | BOOL IsFileOnReadOnlyFilesystem( 14 | __in const WCHAR *path 15 | ); 16 | BOOL IsFileAlreadyOpenedByAnotherProcess( 17 | __in const std::wstring& sPath 18 | ); 19 | DWORD MoveFileOverwriteIf( 20 | __in const std::wstring& sSrcFile, 21 | __in const std::wstring& sDestFile 22 | ); 23 | DWORD GetFileList( 24 | __in const std::wstring& canonicalPath, 25 | __out std::vector* pFileList 26 | ); -------------------------------------------------------------------------------- /Common/WinNT/GuiUtil.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/Common/WinNT/GuiUtil.cpp -------------------------------------------------------------------------------- /Common/WinNT/GuiUtil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | void PullWindowToTopWithActive(HWND hWnd); 6 | void PullWindowToTopWithInactive(HWND hWnd); -------------------------------------------------------------------------------- /Common/WinNT/Guid.cpp: -------------------------------------------------------------------------------- 1 | #include "Guid.h" 2 | 3 | #include 4 | #include 5 | 6 | std::wstring GenerateGUID() 7 | { 8 | GUID guid; 9 | ::CoCreateGuid(&guid); 10 | WCHAR strGuid[40] = {0}; 11 | StringFromGUID2(guid, strGuid, _countof(strGuid)); 12 | 13 | return std::wstring(strGuid); 14 | } -------------------------------------------------------------------------------- /Common/WinNT/Guid.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | std::wstring GenerateGUID(); -------------------------------------------------------------------------------- /Common/WinNT/NtServiceCtrl.cpp: -------------------------------------------------------------------------------- 1 | #include "NtServiceCtrl.h" 2 | 3 | DWORD InstallService( 4 | __in LPCWSTR lpServiceName, 5 | __in_opt LPCWSTR lpDisplayName, 6 | __in DWORD dwDesiredAccess, 7 | __in DWORD dwServiceType, 8 | __in DWORD dwStartType, 9 | __in DWORD dwErrorControl, 10 | __in_opt LPCWSTR lpBinaryPathName, 11 | __in_opt LPCWSTR lpLoadOrderGroup, 12 | __out_opt LPDWORD lpdwTagId, 13 | __in_opt LPCWSTR lpDependencies, 14 | __in_opt LPCWSTR lpServiceStartName, 15 | __in_opt LPCWSTR lpPassword 16 | ) // NS 17 | { 18 | SC_HANDLE sch; 19 | SC_HANDLE service; 20 | DWORD dwError = ERROR_SUCCESS; 21 | 22 | sch = OpenSCManager(NULL, NULL, GENERIC_WRITE); 23 | if(sch) 24 | { 25 | service = CreateServiceW( 26 | sch, 27 | lpServiceName, 28 | lpDisplayName, 29 | dwDesiredAccess, 30 | dwServiceType, 31 | dwStartType, 32 | dwErrorControl, 33 | lpBinaryPathName, 34 | lpLoadOrderGroup, 35 | lpdwTagId, 36 | lpDependencies, 37 | lpServiceStartName, 38 | lpPassword); 39 | 40 | if(service) 41 | { 42 | CloseServiceHandle(service); 43 | } 44 | else 45 | { 46 | dwError = GetLastError(); 47 | } 48 | 49 | CloseServiceHandle(sch); 50 | } 51 | else 52 | { 53 | dwError = GetLastError(); 54 | } 55 | 56 | return dwError; 57 | } 58 | 59 | BOOL LoadDriver( 60 | __in LPCWSTR lpServiceName 61 | ) 62 | { 63 | DWORD dwError = LoadDriverEx(lpServiceName, 0, 0); 64 | 65 | if(dwError != ERROR_SUCCESS) 66 | { 67 | SetLastError(dwError); 68 | } 69 | 70 | return (dwError == ERROR_SUCCESS || dwError == ERROR_SERVICE_ALREADY_RUNNING); 71 | } 72 | 73 | DWORD LoadDriverEx( 74 | __in LPCWSTR lpServiceName, 75 | __in DWORD dwNumServiceArgs, 76 | __in_ecount_opt(dwNumServiceArgs) LPCWSTR *lpServiceArgVectors 77 | ) 78 | { 79 | DWORD dwError = ERROR_SUCCESS; 80 | SC_HANDLE sch = OpenSCManager(NULL, NULL, GENERIC_EXECUTE); 81 | 82 | if(sch) 83 | { 84 | SC_HANDLE service = OpenServiceW(sch, lpServiceName, GENERIC_EXECUTE); 85 | if(service) 86 | { 87 | BOOL result = StartServiceW(service, dwNumServiceArgs, lpServiceArgVectors); 88 | 89 | if(!result) 90 | { 91 | dwError = GetLastError(); 92 | } 93 | 94 | CloseServiceHandle(service); 95 | } 96 | else 97 | { 98 | dwError = GetLastError(); 99 | } 100 | CloseServiceHandle(sch); 101 | } 102 | else 103 | { 104 | dwError = GetLastError(); 105 | } 106 | 107 | return dwError; 108 | } 109 | 110 | BOOL StopService( 111 | __in LPCWSTR lpServiceName 112 | ) 113 | { 114 | SC_HANDLE sch; 115 | SC_HANDLE service; 116 | BOOL fStopped = FALSE; 117 | DWORD dwError = ERROR_SUCCESS; 118 | 119 | sch = OpenSCManager(NULL, NULL, GENERIC_EXECUTE); 120 | if(sch) 121 | { 122 | service = OpenService(sch, lpServiceName, GENERIC_EXECUTE); 123 | if(service) 124 | { 125 | SERVICE_STATUS ss; 126 | 127 | BOOL result = ControlService(service, SERVICE_CONTROL_STOP, &ss); 128 | dwError = GetLastError(); 129 | 130 | if(result) 131 | { 132 | fStopped = TRUE; 133 | } 134 | else if(dwError == ERROR_SERVICE_NOT_ACTIVE) 135 | { 136 | fStopped = TRUE; 137 | } 138 | CloseServiceHandle(service); 139 | } 140 | else 141 | { 142 | dwError = GetLastError(); 143 | } 144 | CloseServiceHandle(sch); 145 | } 146 | else 147 | { 148 | dwError = GetLastError(); 149 | } 150 | 151 | SetLastError(dwError); 152 | return fStopped; 153 | } 154 | 155 | BOOL UninstallService( 156 | __in LPCWSTR lpServiceName 157 | ) 158 | { 159 | SC_HANDLE sch; 160 | SC_HANDLE service; 161 | BOOL success = TRUE; 162 | DWORD dwError = ERROR_SUCCESS; 163 | 164 | sch = OpenSCManager(NULL, NULL, GENERIC_WRITE); 165 | if(sch) 166 | { 167 | service = OpenService(sch, lpServiceName, DELETE); 168 | if(service) 169 | { 170 | if(IsServiceRunning(lpServiceName)) 171 | { 172 | (VOID)StopService(lpServiceName); 173 | } 174 | 175 | BOOL result = DeleteService(service); 176 | 177 | if(result) 178 | { 179 | success = TRUE; 180 | } 181 | else 182 | { 183 | dwError = GetLastError(); 184 | if(dwError == ERROR_SERVICE_MARKED_FOR_DELETE) 185 | { 186 | success = TRUE; 187 | } 188 | else 189 | { 190 | success = FALSE; 191 | } 192 | } 193 | 194 | CloseServiceHandle(service); 195 | } 196 | else 197 | { 198 | dwError = GetLastError(); 199 | } 200 | CloseServiceHandle(sch); 201 | } 202 | else 203 | { 204 | dwError = GetLastError(); 205 | success = FALSE; 206 | } 207 | 208 | SetLastError(dwError); 209 | return success; 210 | } 211 | 212 | BOOL IsServiceRunning( 213 | __in LPCWSTR lpServiceName 214 | ) 215 | { 216 | SC_HANDLE hService; 217 | SERVICE_STATUS ss; 218 | BOOL fOk; 219 | SC_HANDLE sch = OpenSCManager(NULL, NULL, GENERIC_READ); 220 | if(sch == 0) 221 | { 222 | return FALSE; 223 | } 224 | 225 | hService = OpenService(sch, lpServiceName, GENERIC_READ); 226 | 227 | if(!hService) 228 | { 229 | CloseServiceHandle(sch); 230 | return FALSE; 231 | } 232 | 233 | fOk = QueryServiceStatus(hService, &ss); 234 | 235 | CloseServiceHandle(hService); 236 | CloseServiceHandle(sch); 237 | 238 | if(!fOk) 239 | { 240 | return FALSE; 241 | } 242 | 243 | return (ss.dwCurrentState == SERVICE_RUNNING); 244 | } 245 | 246 | BOOL IsServiceInstalled( 247 | __in LPCWSTR lpServiceName 248 | ) 249 | { 250 | BOOL fOk = FALSE; 251 | SC_HANDLE hService; 252 | SC_HANDLE sch = OpenSCManager(NULL, NULL, GENERIC_READ); 253 | if(sch == 0) 254 | { 255 | return FALSE; 256 | } 257 | 258 | hService = OpenService(sch, lpServiceName, GENERIC_READ); 259 | 260 | if(hService) 261 | { 262 | fOk = TRUE; 263 | CloseServiceHandle(hService); 264 | } 265 | 266 | CloseServiceHandle(sch); 267 | 268 | return fOk; 269 | } -------------------------------------------------------------------------------- /Common/WinNT/NtServiceCtrl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | DWORD InstallService( 6 | __in LPCWSTR lpServiceName, 7 | __in_opt LPCWSTR lpDisplayName, 8 | __in DWORD dwDesiredAccess, 9 | __in DWORD dwServiceType, 10 | __in DWORD dwStartType, 11 | __in DWORD dwErrorControl, 12 | __in_opt LPCWSTR lpBinaryPathName, 13 | __in_opt LPCWSTR lpLoadOrderGroup, 14 | __out_opt LPDWORD lpdwTagId, 15 | __in_opt LPCWSTR lpDependencies, 16 | __in_opt LPCWSTR lpServiceStartName, 17 | __in_opt LPCWSTR lpPassword 18 | ); // NS 19 | 20 | BOOL LoadDriver( 21 | __in LPCWSTR lpServiceName 22 | ); 23 | 24 | DWORD LoadDriverEx( 25 | __in LPCWSTR lpServiceName, 26 | __in DWORD dwNumServiceArgs, 27 | __in_ecount_opt(dwNumServiceArgs) LPCWSTR *lpServiceArgVectors 28 | ); 29 | 30 | BOOL StopService( 31 | __in LPCWSTR lpServiceName 32 | ); 33 | 34 | BOOL UninstallService( 35 | __in LPCWSTR lpServiceName 36 | ); 37 | 38 | BOOL IsServiceRunning( 39 | __in LPCWSTR lpServiceName 40 | ); 41 | 42 | BOOL IsServiceInstalled( 43 | __in LPCWSTR lpServiceName 44 | ); -------------------------------------------------------------------------------- /Common/WinNT/NtServiceInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "NTServiceInfo.h" 2 | 3 | #include 4 | #include 5 | 6 | #pragma warning(push) 7 | #pragma warning(disable:4995) 8 | #include 9 | #pragma warning(pop) 10 | 11 | #include "../Log/NdLog.h" 12 | 13 | BOOL NTServiceInfo::IsServiceRunning(LPCWSTR lpServiceName) 14 | { 15 | SC_HANDLE sch = OpenSCManager(NULL, NULL, GENERIC_READ); 16 | if(sch == 0) 17 | { 18 | return FALSE; 19 | } 20 | 21 | SC_HANDLE hService = OpenService(sch, lpServiceName, GENERIC_READ); 22 | 23 | if(!hService) 24 | { 25 | CloseServiceHandle(sch); 26 | return FALSE; 27 | } 28 | 29 | SERVICE_STATUS ss; 30 | BOOL fOk = QueryServiceStatus(hService, &ss); 31 | if(!fOk) 32 | { 33 | CloseServiceHandle(hService); 34 | CloseServiceHandle(sch); 35 | return FALSE; 36 | } 37 | 38 | CloseServiceHandle(hService); 39 | CloseServiceHandle(sch); 40 | 41 | if (ss.dwCurrentState == SERVICE_RUNNING) 42 | { 43 | logw(L"%s", (std::wstring(lpServiceName) + L", The service is running\n").c_str()); 44 | return TRUE; 45 | } 46 | else 47 | { 48 | logw(L"%s", (std::wstring(lpServiceName) + L", The service is not running\n").c_str()); 49 | return FALSE; 50 | } 51 | } 52 | 53 | BOOL NTServiceInfo::IsServiceInstalled(LPCWSTR lpServiceName) 54 | { 55 | SC_HANDLE sch = OpenSCManager(NULL, NULL, GENERIC_READ); 56 | if(sch == 0) 57 | { 58 | return FALSE; 59 | } 60 | 61 | SC_HANDLE hService = OpenService(sch, lpServiceName, GENERIC_READ); 62 | 63 | BOOL fOk = hService ? TRUE : FALSE; 64 | 65 | if(hService) 66 | { 67 | CloseServiceHandle(hService); 68 | } 69 | 70 | if(sch) 71 | { 72 | CloseServiceHandle(sch); 73 | } 74 | 75 | return fOk; 76 | } 77 | -------------------------------------------------------------------------------- /Common/WinNT/NtServiceInfo.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /** 6 | * 7 | */ 8 | class NTServiceInfo 9 | { 10 | public: 11 | static BOOL IsServiceRunning(LPCWSTR lpServiceName); 12 | static BOOL IsServiceInstalled(LPCWSTR lpServiceName); 13 | }; -------------------------------------------------------------------------------- /Common/WinNT/NtVolume.cpp: -------------------------------------------------------------------------------- 1 | #include "NtVolume.h" 2 | 3 | #include 4 | 5 | int GetFirstAvailableDrive() 6 | { 7 | DWORD dwUsedDrives = GetLogicalDrives(); 8 | int i; 9 | 10 | for (i = 3; i < 26; i++) 11 | { 12 | if (!(dwUsedDrives & 1 << i)) 13 | { 14 | return i; 15 | } 16 | } 17 | 18 | return -1; 19 | } 20 | 21 | int GetLastAvailableDrive() 22 | { 23 | DWORD dwUsedDrives = GetLogicalDrives(); 24 | int i; 25 | 26 | for (i = 25; i > 2; i--) 27 | { 28 | if (!(dwUsedDrives & 1 << i)) 29 | { 30 | return i; 31 | } 32 | } 33 | 34 | return -1; 35 | } 36 | 37 | std::vector GetAvailableVolumes() 38 | { 39 | std::vector av; 40 | DWORD dwUsedDrives = GetLogicalDrives(); 41 | for (WCHAR i = 3; i < 26; i++) 42 | { 43 | if (!(dwUsedDrives & (1 << i))) 44 | { 45 | av.push_back(i + L'A'); 46 | } 47 | } 48 | 49 | return av; 50 | } 51 | 52 | bool IsDriveAvailable(int driveNo) 53 | { 54 | return (GetLogicalDrives() & (1 << driveNo)) == 0; 55 | } 56 | 57 | bool IsVolumeDesignatorAvailable(WCHAR chVolume) 58 | { 59 | return IsDriveAvailable(towupper(chVolume) - L'A'); 60 | } 61 | 62 | bool IsDeviceMounted(WCHAR* deviceName) 63 | { 64 | BOOL bResult = FALSE; 65 | DWORD dwResult; 66 | HANDLE dev = INVALID_HANDLE_VALUE; 67 | 68 | if ((dev = CreateFileW(deviceName, 69 | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 70 | NULL, 71 | OPEN_EXISTING, 72 | 0, 73 | NULL)) != INVALID_HANDLE_VALUE) 74 | { 75 | bResult = DeviceIoControl(dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL); 76 | CloseHandle (dev); 77 | } 78 | 79 | return bResult ? true : false; 80 | } 81 | 82 | bool GetDriveLabel(int driveNo, wchar_t *label, int labelSize) 83 | { 84 | DWORD fileSystemFlags; 85 | wchar_t root[] = { L'A' + (wchar_t) driveNo, L':', L'\\', 0 }; 86 | 87 | return GetVolumeInformationW(root, label, labelSize / 2, NULL, NULL, &fileSystemFlags, NULL, 0) ? true : false; 88 | } 89 | 90 | 91 | /* Callback command types */ 92 | typedef enum 93 | { 94 | PROGRESS = 0, 95 | DONEWITHSTRUCTURE, 96 | UNKNOWN2, 97 | UNKNOWN3, 98 | UNKNOWN4, 99 | UNKNOWN5, 100 | INSUFFICIENTRIGHTS, 101 | FSNOTSUPPORTED, 102 | VOLUMEINUSE, 103 | UNKNOWN9, 104 | UNKNOWNA, 105 | DONE, 106 | FMIFS_HARDDISK, 107 | UNKNOWND, 108 | OUTPUT, 109 | STRUCTUREPROGRESS, 110 | CLUSTERSIZETOOSMALL, 111 | } CALLBACKCOMMAND; 112 | 113 | // FMIFS 114 | typedef BOOLEAN (__stdcall *PFMIFSCALLBACK)( int command, DWORD subCommand, PVOID parameter ); 115 | typedef VOID (__stdcall *PFORMATEX)(PWCHAR DriveRoot, DWORD MediaFlag, PWCHAR Format, PWCHAR Label, 116 | BOOL QuickFormat, DWORD ClusterSize, PFMIFSCALLBACK Callback ); 117 | volatile BOOLEAN FormatExResult; 118 | PUSHORT g_pFormatProgressCount = 0; 119 | 120 | BOOLEAN __stdcall FormatExCallback(int command, DWORD /*subCommand*/, PVOID parameter) 121 | { 122 | switch(command) 123 | { 124 | case STRUCTUREPROGRESS: 125 | if(g_pFormatProgressCount) 126 | { 127 | ++(*g_pFormatProgressCount); 128 | } 129 | break; 130 | 131 | case DONE: 132 | FormatExResult = *(BOOLEAN *) parameter; 133 | return TRUE; 134 | } 135 | 136 | return TRUE; 137 | } 138 | 139 | // 140 | // Requires a symbolic link in GLOBAL namespace. 141 | // 142 | BOOL FormatNtfs(LPCWSTR pszVolume, int clusterSize, __out_opt PUSHORT pProgressCount) 143 | { 144 | PFORMATEX FormatEx; 145 | HMODULE hDllInstance = LoadLibraryA("fmifs.dll"); 146 | int i; 147 | WCHAR szVolume[MAX_PATH] = { 0 }; 148 | _tcscpy_s(szVolume, pszVolume); 149 | 150 | if (hDllInstance == NULL) 151 | { 152 | return FALSE; 153 | } 154 | 155 | HMODULE hModule = GetModuleHandle(L"fmifs.dll"); 156 | if (hModule == NULL) 157 | { 158 | FreeLibrary(hDllInstance); 159 | return FALSE; 160 | } 161 | 162 | if ((FormatEx = (PFORMATEX)GetProcAddress(hModule, "FormatEx")) == 0) 163 | { 164 | FreeLibrary(hDllInstance); 165 | return FALSE; 166 | } 167 | 168 | FormatExResult = FALSE; 169 | 170 | // Windows sometimes fails to format a volume (hosted on a removable medium) as NTFS. 171 | // It often helps to retry several times. 172 | for (i = 0; i < 50 && FormatExResult != TRUE; i++) 173 | { 174 | if(pProgressCount) 175 | { 176 | *pProgressCount = 0; 177 | g_pFormatProgressCount = pProgressCount; 178 | } 179 | FormatEx(szVolume, FMIFS_HARDDISK, L"NTFS", L"", TRUE, clusterSize * 512, FormatExCallback); 180 | } 181 | 182 | // The device may be referenced for some time after FormatEx() returns 183 | Sleep (2000); 184 | 185 | FreeLibrary (hModule); 186 | return FormatExResult; 187 | } -------------------------------------------------------------------------------- /Common/WinNT/NtVolume.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #pragma warning(push) 4 | #pragma warning(disable:4995) 5 | #include 6 | #pragma warning(pop) 7 | #include 8 | 9 | int GetFirstAvailableDrive(); 10 | int GetLastAvailableDrive(); 11 | std::vector GetAvailableVolumes(); 12 | bool IsDriveAvailable(int driveNo); 13 | bool IsVolumeDesignatorAvailable(WCHAR chVolumeDesignator); 14 | bool IsDeviceMounted(WCHAR* deviceName); 15 | bool GetDriveLabel(int driveNo, wchar_t *label, int labelSize); 16 | BOOL FormatNtfs(LPCWSTR pszVolume, int clusterSize, __out_opt PUSHORT pProgressCount); -------------------------------------------------------------------------------- /Common/WinNT/OsVersion.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/Common/WinNT/OsVersion.cpp -------------------------------------------------------------------------------- /Common/WinNT/OsVersion.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | BOOL Is64BitWindows(); 5 | BOOL IsWindows7(); 6 | BOOL IsWindows7OrLater(); 7 | BOOL IsVistaOrLater(); 8 | BOOL IsVistaOrWinServer2008Basic(); 9 | BOOL IsServerOS(); 10 | bool IsVistaProcessElevation(); 11 | bool IsUacSupported(); -------------------------------------------------------------------------------- /Common/WinNT/PipeClient.cpp: -------------------------------------------------------------------------------- 1 | #include "PipeClient.h" 2 | 3 | #include 4 | #pragma warning(push) 5 | #pragma warning(disable:4995) 6 | #include 7 | #pragma warning(pop) 8 | 9 | #include "../Log/NdLog.h" 10 | 11 | Pipe::Pipe(LPCWSTR lpPipeName): m_PipeName(lpPipeName), m_hPipe(INVALID_HANDLE_VALUE) 12 | { 13 | } 14 | 15 | Pipe::~Pipe() 16 | { 17 | Close(); 18 | } 19 | 20 | BOOL Pipe::Close() 21 | { 22 | if (m_hPipe != INVALID_HANDLE_VALUE) 23 | { 24 | BOOL fOk = CloseHandle(m_hPipe); 25 | m_hPipe = INVALID_HANDLE_VALUE; 26 | return fOk; 27 | } 28 | 29 | return TRUE; 30 | } 31 | 32 | BOOL Pipe::Connect() 33 | { 34 | if (m_PipeName.empty()) 35 | { 36 | return FALSE; 37 | } 38 | 39 | return Connect(m_PipeName.c_str(), false); 40 | } 41 | 42 | BOOL Pipe::Connect(BOOL fAsync) 43 | { 44 | if (m_PipeName.empty()) 45 | { 46 | return FALSE; 47 | } 48 | 49 | return Connect(m_PipeName.c_str(), fAsync); 50 | } 51 | 52 | BOOL Pipe::Connect(LPCWSTR lpszPipename, BOOL fCreateAsyncPipe) 53 | { 54 | BOOL fSuccess; 55 | DWORD dwMode; 56 | 57 | // Try to open a named pipe; wait for it, if necessary. 58 | 59 | for ( ; ; ) 60 | { 61 | m_hPipe = CreateFile( 62 | lpszPipename, // pipe name 63 | GENERIC_READ | // read and write access 64 | GENERIC_WRITE, 65 | 0, // no sharing 66 | NULL, // default security attributes 67 | OPEN_EXISTING, // opens existing pipe 68 | fCreateAsyncPipe ? FILE_FLAG_OVERLAPPED : 0, // default attributes 69 | NULL); // no template file 70 | 71 | // Break if the pipe handle is valid. 72 | if (m_hPipe != INVALID_HANDLE_VALUE) 73 | { 74 | logw(L"The pipe created."); 75 | break; 76 | } 77 | 78 | // Exit if an error other than ERROR_PIPE_BUSY occurs. 79 | 80 | if (GetLastError() != ERROR_PIPE_BUSY) 81 | { 82 | logw(L"Could not open pipe(%d)", GetLastError()); 83 | return FALSE; 84 | } 85 | 86 | // All pipe instances are busy, so wait for 20 seconds. 87 | 88 | if (!WaitNamedPipe(lpszPipename, 20000)) 89 | { 90 | logw(L"Could not open pipe(%d)", GetLastError()); 91 | return FALSE; 92 | } 93 | } 94 | 95 | // The pipe connected; change to message-read mode. 96 | 97 | dwMode = PIPE_READMODE_MESSAGE; 98 | fSuccess = SetNamedPipeHandleState( 99 | m_hPipe, // pipe handle 100 | &dwMode, // new pipe mode 101 | NULL, // don't set maximum bytes 102 | NULL); // don't set maximum time 103 | if (!fSuccess) 104 | { 105 | logw(L"SetNamedPipeHandleState failed(%d)", GetLastError()); 106 | return FALSE; 107 | } 108 | 109 | return TRUE; 110 | } 111 | 112 | BOOL Pipe::Connect(const std::wstring& sPipename) 113 | { 114 | return Connect(sPipename.c_str(), false); 115 | } 116 | 117 | BOOL Pipe::Send(PBYTE buf, DWORD cbBuffer) 118 | { 119 | DWORD sentTotalBytes = 0; 120 | while (sentTotalBytes < cbBuffer) 121 | { 122 | int remainSize = cbBuffer - sentTotalBytes; 123 | DWORD cbWritten; 124 | BOOL fOk = WriteFile(m_hPipe, buf + sentTotalBytes, remainSize, &cbWritten, nullptr); 125 | if (!fOk || cbWritten == 0) 126 | { 127 | break; 128 | } 129 | sentTotalBytes += cbWritten; 130 | } 131 | 132 | return (cbBuffer == sentTotalBytes); 133 | } 134 | 135 | BOOL Pipe::Send(PBYTE buf, DWORD maxlen, DWORD& cbWritten, LPOVERLAPPED lpOverlapped) 136 | { 137 | return WriteFile( 138 | m_hPipe, // pipe handle 139 | buf, // message 140 | maxlen, // message length 141 | &cbWritten, // bytes written 142 | lpOverlapped); // not overlapped 143 | } 144 | 145 | BOOL Pipe::Recv(PBYTE buf, DWORD maxlen, DWORD& cbRead) 146 | { 147 | return ReadFile( 148 | m_hPipe, // pipe handle 149 | buf, 150 | maxlen, // size of buffer 151 | &cbRead, // number of bytes read 152 | NULL); // not overlapped 153 | } 154 | 155 | BOOL Pipe::Recv(PBYTE buf, DWORD maxlen, DWORD& cbRead, LPOVERLAPPED lpOverlapped) 156 | { 157 | return ReadFile( 158 | m_hPipe, // pipe handle 159 | buf, 160 | maxlen, // size of buffer 161 | &cbRead, // number of bytes read 162 | lpOverlapped); // not overlapped 163 | } -------------------------------------------------------------------------------- /Common/WinNT/PipeClient.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #pragma warning(push) 6 | #pragma warning(disable:4995) 7 | #include 8 | #pragma warning(pop) 9 | 10 | /** 11 | */ 12 | class Pipe 13 | { 14 | public: 15 | Pipe(LPCWSTR lpPipeName); 16 | ~Pipe(); 17 | BOOL Close(); 18 | BOOL Connect(); 19 | BOOL Connect(BOOL fAsync); 20 | BOOL Connect(LPCWSTR lpszPipename, BOOL fCreateAsyncPipe); 21 | BOOL Connect(const std::wstring& sPipename); 22 | BOOL Send(PBYTE buf, DWORD cbBuffer); 23 | BOOL Send(PBYTE buf, DWORD maxlen, DWORD& cbWritten, LPOVERLAPPED pOverlapped); 24 | BOOL Recv(PBYTE buf, DWORD maxlen, DWORD& cbRead); 25 | BOOL Recv(PBYTE buf, DWORD maxlen, DWORD& cbRead, LPOVERLAPPED pOverlapped); 26 | 27 | private: 28 | HANDLE m_hPipe; 29 | std::wstring m_PipeName; 30 | }; -------------------------------------------------------------------------------- /Common/WinNT/QueryVirtualMemory.cpp: -------------------------------------------------------------------------------- 1 | #include "QueryVirtualMemory.h" 2 | 3 | BOOL AvailablePhysicsMemory(__out UINT64& availablePhysicsMemory) 4 | { 5 | MEMORYSTATUSEX m; 6 | m.dwLength = sizeof(m); 7 | BOOL fOk = GlobalMemoryStatusEx(&m); 8 | 9 | if (!fOk) 10 | { 11 | availablePhysicsMemory = 0; 12 | return FALSE; 13 | } 14 | 15 | availablePhysicsMemory = m.ullAvailPhys; 16 | return TRUE; 17 | } 18 | 19 | INT64 GetAvailableMemory() 20 | { 21 | UINT64 i; 22 | BOOL fOk = AvailablePhysicsMemory(i); 23 | return fOk ? (INT64)i : -1; 24 | } 25 | 26 | VOID PrintAvailableMemory() 27 | { 28 | WCHAR sz[MAX_PATH] = { 0 }; 29 | _i64tow_s(GetAvailableMemory(), sz, _countof(sz), 10); 30 | std::wstring s = AddComma(sz); 31 | logw(L"AvailableMemory: %s", s.c_str()); 32 | } -------------------------------------------------------------------------------- /Common/WinNT/QueryVirtualMemory.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/Common/WinNT/QueryVirtualMemory.h -------------------------------------------------------------------------------- /Common/WinNT/Registry.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/Common/WinNT/Registry.cpp -------------------------------------------------------------------------------- /Common/WinNT/Registry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #pragma warning(push) 6 | #pragma warning(disable:4995) 7 | #include 8 | #include 9 | #pragma warning(pop) 10 | 11 | /** 12 | * 13 | */ 14 | class Registry 15 | { 16 | public: 17 | static HKEY GetKeyName( 18 | __in const std::wstring& strData 19 | ); 20 | static std::wstring GetKeyNameString( 21 | __in HKEY hKey 22 | ); 23 | static std::wstring RegGetSimpleString( 24 | __in HKEY hKey, 25 | __in const std::wstring& strOpenKey, 26 | __in const std::wstring& strValue, 27 | __in const std::wstring& strDefaultData, 28 | __in REGSAM samDesired = KEY_READ 29 | ); 30 | static DWORD RegGetSimpleDword( 31 | __in HKEY hKey, 32 | __in const std::wstring& strOpenKey, 33 | __in const std::wstring& strValueName, 34 | __in DWORD dwDefaultData, 35 | __in REGSAM samDesired = KEY_READ 36 | ); 37 | static BOOL RegSetSimpleStringA( 38 | __in HKEY hKey, 39 | __in const std::string& strOpenKey, 40 | __in const std::string& strValueName, 41 | __in const std::string& strData, 42 | __in BOOL fPermanently, 43 | __in REGSAM samDesired = KEY_ALL_ACCESS 44 | ); // NS 45 | // 46 | // Delete if strData is "" 47 | // 48 | static BOOL RegSetSimpleStringW( 49 | __in HKEY hKey, 50 | __in const std::wstring& strOpenKey, 51 | __in const std::wstring& strValueName, 52 | __in const std::wstring& strData, 53 | __in BOOL fPermanently, 54 | __in REGSAM samDesired = KEY_ALL_ACCESS 55 | ); 56 | static BOOL RegSetSimpleStringVolatileW( 57 | __in HKEY hKey, 58 | __in const std::wstring& strOpenKey, 59 | __in const std::wstring& strValueName, 60 | __in const std::wstring& strData 61 | ); 62 | static BOOL RegSetSimpleDword( 63 | __in HKEY hKey, 64 | __in const std::wstring& strOpenKey, 65 | __in const std::wstring& strValueName, 66 | __in DWORD dwData, 67 | __in BOOL fPermanently, 68 | __in BOOL bDelete, 69 | __in REGSAM samDesired = KEY_ALL_ACCESS 70 | ); 71 | static BOOL RegSetSimpleBinary( 72 | __in HKEY hKey, 73 | __in const std::wstring& strOpenKey, 74 | __in const std::wstring& strValueName, 75 | __in const void* pData, 76 | __in int nDataSize, 77 | __in REGSAM samDesired = KEY_ALL_ACCESS 78 | ); 79 | static BOOL RegSetExpandString( 80 | __in HKEY hKey, 81 | __in const std::wstring& sOpenKey, 82 | __in const std::wstring& sValueName, 83 | __in const std::wstring& sData, 84 | __in REGSAM samDesired = KEY_ALL_ACCESS 85 | ); 86 | static std::wstring RegGetExpandString( 87 | __in HKEY hKey, 88 | __in const std::wstring& strOpenKey, 89 | __in const std::wstring& strValue, 90 | __in const std::wstring& strDefaultData, 91 | __in REGSAM samDesired 92 | ); 93 | static BOOL HasRegisterdValue( 94 | __in HKEY hKey, 95 | __in const std::wstring& strOpenKey, 96 | __in const std::wstring& strValueName, 97 | __in REGSAM samDesired = KEY_READ 98 | ); 99 | static BOOL HasRegisterdKey( 100 | __in HKEY hKey, 101 | __in const std::wstring& strOpenKey, 102 | __in REGSAM samDesired = KEY_READ 103 | ); 104 | static DWORD RegDeleteKeyNT( 105 | __in HKEY hStartKey, 106 | __in LPCWSTR pKeyName, 107 | __in REGSAM samDesired = KEY_ENUMERATE_SUB_KEYS | DELETE 108 | ); 109 | static void GetValueNames( 110 | __in HKEY hRootKey, 111 | __in LPTSTR lpKey, 112 | __out std::vector& vFoundValueNames, 113 | __in REGSAM samDesired = KEY_READ 114 | ); 115 | }; 116 | -------------------------------------------------------------------------------- /Common/WinNT/Uac.cpp: -------------------------------------------------------------------------------- 1 | #include "UAC.h" 2 | 3 | #include "OSVersion.h" 4 | 5 | BOOL IsUacSupported() 6 | { 7 | HKEY hkey; 8 | DWORD value = 1, size = sizeof (DWORD); 9 | 10 | if (!IsVistaOrLater()) 11 | { 12 | return FALSE; 13 | } 14 | 15 | if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, 16 | L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_READ, &hkey) == ERROR_SUCCESS) 17 | { 18 | if (RegQueryValueExW(hkey, L"EnableLUA", 0, 0, (LPBYTE) &value, &size) != ERROR_SUCCESS) 19 | { 20 | value = 1; 21 | } 22 | 23 | RegCloseKey (hkey); 24 | } 25 | 26 | return value != 0; 27 | } 28 | -------------------------------------------------------------------------------- /Common/WinNT/Uac.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | BOOL IsUacSupported(); 6 | -------------------------------------------------------------------------------- /Common/misc.cpp: -------------------------------------------------------------------------------- 1 | #include "misc.h" 2 | #include 3 | #include 4 | #include 5 | #pragma warning(push) 6 | #pragma warning(disable:4995) 7 | #include 8 | #pragma warning(pop) 9 | 10 | VOID TrimMilliSeconds(LONGLONG* pTime) 11 | { 12 | *pTime = *pTime / 10000000 * 10000000; 13 | } 14 | 15 | VOID TrimFileTime(__inout FILETIME* ft) 16 | { 17 | LARGE_INTEGER li; 18 | li.HighPart = ft->dwHighDateTime; 19 | li.LowPart = ft->dwLowDateTime; 20 | TrimMilliSeconds(&li.QuadPart); 21 | ft->dwHighDateTime = li.HighPart; 22 | ft->dwLowDateTime = li.LowPart; 23 | } 24 | 25 | FILETIME TrimFileTime(__in const FILETIME& ft) 26 | { 27 | LARGE_INTEGER li; 28 | li.HighPart = ft.dwHighDateTime; 29 | li.LowPart = ft.dwLowDateTime; 30 | TrimMilliSeconds(&li.QuadPart); 31 | FILETIME trimmedTime; 32 | trimmedTime.dwHighDateTime = li.HighPart; 33 | trimmedTime.dwLowDateTime = li.LowPart; 34 | return trimmedTime; 35 | } 36 | 37 | std::wstring GetCurrentTimeStr() 38 | { 39 | SYSTEMTIME cTime; 40 | ::GetLocalTime(&cTime); 41 | 42 | std::wstringstream stm; 43 | stm << std::setfill(L'0') << 44 | cTime.wYear << L"/" << 45 | std::setw(2) << cTime.wMonth << L"/" << 46 | std::setw(2) << cTime.wDay << L" " << 47 | std::setw(2) << cTime.wHour << L":" << 48 | std::setw(2) << cTime.wMinute << L":" << 49 | std::setw(2) << cTime.wSecond << L"." << 50 | std::setw(3) << cTime.wMilliseconds; 51 | return stm.str(); 52 | } 53 | 54 | FILETIME CurrentTime() 55 | { 56 | FILETIME ft; 57 | SYSTEMTIME st; 58 | 59 | GetSystemTime(&st); // Gets the current system time 60 | SystemTimeToFileTime(&st, &ft); // Converts the current system time to file time format 61 | 62 | FILETIME localFileTime; 63 | FileTimeToLocalFileTime(&ft, &localFileTime); 64 | 65 | return localFileTime; 66 | } 67 | 68 | time_t CurrentTime_t() 69 | { 70 | time_t current; 71 | time(¤t); 72 | return current; 73 | } 74 | 75 | std::wstring FileTimeToHumanReadableTime( 76 | __in FILETIME fileTime 77 | ) 78 | { 79 | SYSTEMTIME localTime; 80 | if (FileTimeToSystemTime(&fileTime, &localTime)) 81 | { 82 | WCHAR sz[48]; 83 | HRESULT hr = StringCchPrintf( 84 | sz, 85 | _countof(sz), 86 | L"%04d-%02d-%02dT%02d:%02d:%02d", 87 | localTime.wYear, localTime.wMonth, localTime.wDay, localTime.wHour, localTime.wMinute, localTime.wSecond 88 | ); 89 | 90 | if (SUCCEEDED(hr)) 91 | { 92 | return sz; 93 | } 94 | } 95 | 96 | return L""; 97 | } 98 | 99 | VOID BuildSecurityAttributes(PSECURITY_ATTRIBUTES SecurityAttributes) 100 | { 101 | LPTSTR sd = L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGW;;;WD)(A;;GR;;;RC)"; 102 | 103 | ZeroMemory(SecurityAttributes, sizeof(SECURITY_ATTRIBUTES)); 104 | 105 | ConvertStringSecurityDescriptorToSecurityDescriptor( 106 | sd, 107 | SDDL_REVISION_1, 108 | &SecurityAttributes->lpSecurityDescriptor, 109 | NULL); 110 | 111 | SecurityAttributes->nLength = sizeof(SECURITY_ATTRIBUTES); 112 | SecurityAttributes->bInheritHandle = TRUE; 113 | } 114 | 115 | HANDLE OpenNamedPipeHandle( 116 | __in const std::wstring& pipeName, 117 | __in DWORD dwTimeout 118 | ) 119 | { 120 | HANDLE hPipe = INVALID_HANDLE_VALUE; 121 | 122 | for ( ; ; ) 123 | { 124 | hPipe = CreateFile(pipeName.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 125 | if (hPipe != INVALID_HANDLE_VALUE) 126 | { 127 | break; 128 | } 129 | 130 | if (!WaitNamedPipe(pipeName.c_str(), dwTimeout)) 131 | { 132 | break; 133 | } 134 | } 135 | 136 | return hPipe; 137 | } 138 | 139 | bool MsOfficeTmpFileForJournalling(const std::wstring& sFileName) 140 | { 141 | std::wregex r(L"^[a-zA-Z0-9]+\\.tmp", std::tr1::regex_constants::icase); 142 | return std::regex_match(sFileName.begin(), sFileName.end(), r); 143 | } 144 | 145 | bool MsOfficeTmpFileForSharing(const std::wstring& sFileName) 146 | { 147 | std::wregex r(L"^~\\$.+\\.(doc|xls|ppt)x?", std::tr1::regex_constants::icase); 148 | return std::regex_match(sFileName.begin(), sFileName.end(), r); 149 | } 150 | 151 | bool IsTemporaryFileNameMsOfficeMakes(const std::wstring& sFileName) 152 | { 153 | return (MsOfficeTmpFileForJournalling(sFileName) || MsOfficeTmpFileForSharing(sFileName)); 154 | } -------------------------------------------------------------------------------- /Common/misc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #pragma warning(push) 5 | #pragma warning(disable:4995) 6 | #include 7 | #pragma warning(pop) 8 | #include 9 | #include 10 | 11 | #if !defined(tstring) 12 | #define tstring std::basic_string 13 | #endif 14 | 15 | // 16 | // Miscellaneous functions. 17 | // 18 | 19 | VOID TrimFileTime(__inout FILETIME* ft); 20 | FILETIME TrimFileTime(__in const FILETIME& ft); 21 | std::wstring GetCurrentTimeStr(); 22 | FILETIME CurrentTime(); 23 | time_t CurrentTime_t(); 24 | std::wstring FileTimeToHumanReadableTime( 25 | __in FILETIME fileTime 26 | ); 27 | VOID BuildSecurityAttributes(PSECURITY_ATTRIBUTES SecurityAttributes); 28 | HANDLE OpenNamedPipeHandle( 29 | __in const std::wstring& pipeName, 30 | __in DWORD dwTimeout 31 | ); 32 | bool MsOfficeTmpFileForJournalling(const std::wstring& sFileName); 33 | bool MsOfficeTmpFileForSharing(const std::wstring& sFileName); 34 | bool IsTemporaryFileNameMsOfficeMakes(const std::wstring& sFileName); 35 | -------------------------------------------------------------------------------- /Common/stlhelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | template 8 | inline void map_erase_if(Map& m, Fn1 pred) 9 | { 10 | typename Map::iterator it = m.begin(); 11 | while ((it = std::find_if(it, m.end(), pred)) != m.end()) 12 | { 13 | m.erase(it++); 14 | } 15 | } 16 | 17 | /** 18 | * A unary functor for accumulation. 19 | * NOTE: 20 | * Don't use this macro with std::remove_if 21 | */ 22 | struct Accumulator 23 | : std::unary_function, void> 24 | { 25 | Accumulator() 26 | : m_totalCount(0) 27 | { 28 | } 29 | 30 | void operator()(const std::pair& p) 31 | { 32 | m_totalCount += p.second; 33 | } 34 | 35 | int Result() const 36 | { 37 | return m_totalCount; 38 | } 39 | 40 | int m_totalCount; 41 | }; -------------------------------------------------------------------------------- /ProcMonDebugOutput/ProcMonDebugOutput.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "stdafx.h" 3 | #include "ProcMonDebugOutput.h" 4 | 5 | #define FILE_DEVICE_PROCMON_LOG 0x00009535 6 | #define IOCTL_EXTERNAL_LOG_DEBUGOUT (ULONG) CTL_CODE(FILE_DEVICE_PROCMON_LOG ,\ 7 | 0x81 ,\ 8 | METHOD_BUFFERED ,\ 9 | FILE_WRITE_ACCESS ) 10 | 11 | // The global file handle to the Process Monitor device. 12 | static HANDLE g_hDevice = INVALID_HANDLE_VALUE; 13 | 14 | // Anonymous namespace for private helpers 15 | namespace { 16 | 17 | HANDLE OpenProcessMonitorLogger() 18 | { 19 | if (INVALID_HANDLE_VALUE == g_hDevice) 20 | { 21 | // I'm attempting the open every time because the user could start 22 | // Process Monitor after their process. 23 | g_hDevice = ::CreateFile(L"\\\\.\\Global\\ProcmonDebugLogger", 24 | GENERIC_WRITE, 25 | FILE_SHARE_WRITE, 26 | nullptr, 27 | OPEN_EXISTING, 28 | FILE_ATTRIBUTE_NORMAL, 29 | nullptr); 30 | } 31 | return g_hDevice; 32 | } 33 | 34 | void CloseProcessMonitorLogger() 35 | { 36 | if (INVALID_HANDLE_VALUE != g_hDevice) 37 | { 38 | ::CloseHandle(g_hDevice); 39 | g_hDevice = INVALID_HANDLE_VALUE; 40 | } 41 | } 42 | 43 | // Used to pass strings to legacy C APIs expecting a raw void* pointer. 44 | inline void* StringToPVoid(PCWSTR psz) 45 | { 46 | return reinterpret_cast(const_cast(psz)); 47 | } 48 | 49 | } // anonymous namespace 50 | 51 | 52 | PROCMONDEBUGOUTPUT_DLLINTERFACE _Success_(return == TRUE) 53 | BOOL __stdcall ProcMonDebugOutput(_In_z_ LPCWSTR pszOutputString) 54 | { 55 | BOOL bRet = FALSE; 56 | 57 | if (nullptr == pszOutputString) 58 | { 59 | ::SetLastError(ERROR_INVALID_PARAMETER); 60 | bRet = FALSE; 61 | } 62 | else 63 | { 64 | HANDLE hProcMon = OpenProcessMonitorLogger(); 65 | if (INVALID_HANDLE_VALUE != hProcMon) 66 | { 67 | DWORD iLen = static_cast(wcslen(pszOutputString) * sizeof (WCHAR)); 68 | DWORD iOutLen = 0; 69 | bRet = ::DeviceIoControl(hProcMon, 70 | IOCTL_EXTERNAL_LOG_DEBUGOUT, 71 | StringToPVoid(pszOutputString), 72 | iLen, 73 | nullptr, 74 | 0, 75 | &iOutLen, 76 | nullptr); 77 | if (FALSE == bRet) 78 | { 79 | DWORD dwLastError = ::GetLastError(); 80 | if (ERROR_INVALID_PARAMETER == dwLastError) 81 | { 82 | // The driver is loaded but the user mode Process Monitor 83 | // program is not running so turn the last error into a 84 | // write failure. 85 | ::SetLastError(ERROR_WRITE_FAULT); 86 | } 87 | } 88 | } 89 | else 90 | { 91 | // Process Monitor isn't loaded. 92 | ::SetLastError(ERROR_BAD_DRIVER); 93 | bRet = FALSE; 94 | } 95 | } 96 | return bRet; 97 | } 98 | 99 | BOOL APIENTRY DllMain(HMODULE /*hModule*/, 100 | DWORD ul_reason_for_call, 101 | LPVOID /*lpReserved*/) 102 | { 103 | switch (ul_reason_for_call) 104 | { 105 | case DLL_PROCESS_ATTACH: 106 | case DLL_THREAD_ATTACH: 107 | case DLL_THREAD_DETACH: 108 | break; 109 | case DLL_PROCESS_DETACH: 110 | // Close the handle to the driver. 111 | CloseProcessMonitorLogger(); 112 | break; 113 | } 114 | return TRUE; 115 | } 116 | 117 | -------------------------------------------------------------------------------- /ProcMonDebugOutput/ProcMonDebugOutput.h: -------------------------------------------------------------------------------- 1 | /*////////////////////////////////////////////////////////////////////////////// 2 | // Process Monitor Debug Output Header File 3 | // 4 | // History: 5 | // - April 1, 2010 - Version 1.0 - John Robbins/Wintellect 6 | // - Initial release 7 | // - March 1, 2014 - Version 1.1 - John Robbins/Wintellect 8 | // - Fixed an issue in DLL main where the handle could get close too 9 | // soon. 10 | // - Moved the project to VS 2013. 11 | // 12 | //////////////////////////////////////////////////////////////////////////////*/ 13 | 14 | #pragma once 15 | 16 | #ifdef __cplusplus 17 | extern "C" { 18 | #endif 19 | 20 | /*////////////////////////////////////////////////////////////////////////////// 21 | // The defines that set up how the functions or classes are exported or 22 | // imported. 23 | //////////////////////////////////////////////////////////////////////////////*/ 24 | #ifndef PROCMONDEBUGOUTPUT_DLLINTERFACE 25 | #ifdef PROCMONDEBUGOUTPUT_EXPORTS 26 | #define PROCMONDEBUGOUTPUT_DLLINTERFACE __declspec ( dllexport ) 27 | #else 28 | #define PROCMONDEBUGOUTPUT_DLLINTERFACE __declspec ( dllimport ) 29 | #endif 30 | #endif 31 | 32 | 33 | /*////////////////////////////////////////////////////////////////////////////// 34 | // ProcMonDebugOutput 35 | // Sends a string to Process Monitor for display. 36 | // 37 | // Parameters: 38 | // pszOutputString 39 | // The null-terminated wide character string to be displayed. 40 | // 41 | // Return Values: 42 | // TRUE - The string was sent to Process Monitor. 43 | // FALSE - There was a problem sending the string to Process Monitor. To get 44 | // extended error information, call GetLastError to determine the 45 | // exact failure. 46 | // 47 | // Last Error Codes: 48 | // ERROR_INVALID_PARAMETER - The pszOutputString parameter is NULL. 49 | // ERROR_WRITE_FAULT - The Process Monitor driver is loaded but the 50 | // Process Monitor user mode portion is not running. 51 | // ERROR_BAD_DRIVER - The Process Monitor driver is not loaded. 52 | //////////////////////////////////////////////////////////////////////////////*/ 53 | PROCMONDEBUGOUTPUT_DLLINTERFACE 54 | _Success_(return == TRUE) 55 | BOOL __stdcall ProcMonDebugOutput(_In_z_ LPCWSTR pszOutputString); 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | -------------------------------------------------------------------------------- /ProcMonDebugOutput/ProcMonDebugOutput.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/ProcMonDebugOutput/ProcMonDebugOutput.rc -------------------------------------------------------------------------------- /ProcMonDebugOutput/ProcMonDebugOutput.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | 40 | 41 | Resource Files 42 | 43 | 44 | 45 | 46 | Source Files 47 | 48 | 49 | -------------------------------------------------------------------------------- /ProcMonDebugOutput/ProcMonDebugOutputWIN32.def: -------------------------------------------------------------------------------- 1 | LIBRARY "ProcMonDebugOutputWin32" 2 | 3 | EXPORTS 4 | 5 | ProcMonDebugOutput 6 | -------------------------------------------------------------------------------- /ProcMonDebugOutput/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by ProcMonDebugOutput.rc 4 | 5 | // Next default values for new objects 6 | // 7 | #ifdef APSTUDIO_INVOKED 8 | #ifndef APSTUDIO_READONLY_SYMBOLS 9 | #define _APS_NEXT_RESOURCE_VALUE 101 10 | #define _APS_NEXT_COMMAND_VALUE 40001 11 | #define _APS_NEXT_CONTROL_VALUE 1001 12 | #define _APS_NEXT_SYMED_VALUE 101 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /ProcMonDebugOutput/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // ProcMonDebugOutput.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /ProcMonDebugOutput/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 11 | // Windows Header Files: 12 | #include 13 | #include 14 | 15 | 16 | 17 | // TODO: reference additional headers your program requires here 18 | -------------------------------------------------------------------------------- /ProcMonDebugOutput/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DokanX 2 | [![PayPayl donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=MGCVHFBUUMSN6&lc=US&item_name=Support%20dokanx¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted "Donate once-off to this project using Paypal") 3 | 4 | ## Dokanx is a Fork of Dokan 0.6.0 5 | Because the original Dokan is no longer maintained, I have decided to fork it. 6 | You can read about the original Dokan at [dokan-dev.net/en/docs/](http://dokan-dev.net/en/docs/) . 7 | 8 | ## What is Improved 9 | * A Visual Studio 2013 solution file is provided along with makefile and ddkbuild, so you can build more easily. 10 | * All Dokan library dll code has been recompiled in C++ 11 | * Uses a precompiled header for the driver, making building much faster. 12 | * Usermode filesystem implementations return their result code as an NTSTATUS (not a win32 status), giving applications more control. 13 | * Uses a better logger. 14 | * The PREfast analyzer (static analyzing driver source code) has been applied. 15 | 16 | ## To Build 17 | * Download and install the [WDK 7.1.0](http://www.microsoft.com/en-us/download/details.aspx?id=11800) 18 | * Set the Windows environment variables DOKANX_PATH and WIN7BASE before compiling the driver. 19 | 20 | ```bash 21 | # Note. Do not enclose the WIN7BASE environment value in double quotes. 22 | # It seems ddkbuild can't handle this. 23 | DOKANX_PATH=YOURWORKSPACE\dokanx 24 | WIN7BASE=C:\WinDDK\7600.16385.1 25 | ``` 26 | * Choose build configuration `debug_win7` or `release_win7` regardless your actual target. The driver binary(.sys) will work on any target. 27 | 28 | ### When your Build Succeeds, you will have... 29 | * dokanx.dll 30 | * dokanx.lib 31 | * mirrorfs.exe 32 | * dokanx_win7.sys 33 | * dokanx_mount.exe 34 | * dokanx_control.exe 35 | 36 | WDK 8.x is not supported yet, but this doesn't mean Dokanx can't run on Windows 8 or later. 37 | 38 | ## How to Mount Mirrorfs 39 | ### Registering and Starting the DokanX Filesystem Driver 40 | Before mounting a volume with the filesystem, you need to *register* and *start* the filesystem driver. 41 | This can be done with [CreateService](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682450(v=vs.85).aspx) and [StartService](http://msdn.microsoft.com/en-us/library/windows/desktop/ms686321(v=vs.85).aspx) functions. You could write your own code for registering/starting the driver if you want, maybe when your product is ready to deploy for end-users. At that time, [this simple wrapper](https://github.com/BenjaminKim/dokanx/blob/master/Common/WinNT/NtServiceCtrl.cpp) could be helpful to you. 42 | 43 | But you don't need to deal with that just for testing; there is a simple tool for you. 44 | You can easily *register* and *start* the Dokanx driver with the [osrloader](http://www.osronline.com/article.cfm?article=157) app. 45 | * Move `dokanx_win7.sys` to `%SystemRoot%\System32\drivers\dokanx.sys`. 46 | * Set this path in osrloader's `Driver Path` and write `dokanx` to `Display Name` 47 | * Click `Register Service` and `Start Service`. 48 | 49 | Alternatively, you can use `sc` command: 50 | 51 | `# install driver service and name it 'dokanx'` 52 | `sc create dokanx type= kernel binPath= system32\drivers\dokanx_win7.sys` 53 | `# start dokanx service` 54 | `sc start dokanx` 55 | 56 | If there was no problem, you are ready to mount a volume. 57 | Note that if you once do `Stop Service` then you can't restart service until you reboot. This may be `dokanx.sys`'s problem. (It is very hard to write device driver stopping code in Windows. I haven't found what is the problem in dokanx.sys code yet.) 58 | 59 | ### Mounting a Volume 60 | ``` 61 | > dokanx_control.exe /i s 62 | > mirrorfs.exe /l m /r c:\your_actual_folder 63 | ``` 64 | 65 | You should see that the M:\ drive has been mounted in Windows Explorer. 66 | 67 | ## How to Test Your Own Filesystem 68 | 1. Use [FileTest](https://github.com/ladislav-zezula/FileTest). This is the best tool to check a single filesystem operation. 69 | 2. Use [FileSystemTest](https://github.com/BenjaminKim/FileSystemTest). I made hundreds of test cases for filesystem operations. If you run this program on *your file system volume* **and** an *NTFS volume*, you can get input-output results for both file systems and you can find what is wrong with your file system by diffing these files. 70 | 3. Use [ProcessMonitor](http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx). If you are facing a new problem, ProcessMonitor is a great first tool to use. 71 | 72 | ## Contribution 73 | ### How do I report an issue? 74 | You can ask about the problem you met. But don't ask it to me personally. Please make it as a github issue. 75 | If you are not sure about the problem which you report, please run `Process Monitor` and `DebugView` and capture the logs. And gist or attatch the logs when you make new issue. 76 | -------------------------------------------------------------------------------- /Sysinternals.Debug/CodeAnalysisDictionary.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Wintellect 8 | Sysinternals 9 | 10 | 11 | 12 | 13 | 14 | 15 | ListView 16 | RegEx 17 | 18 | 19 | 20 | 21 | WiX 22 | log 23 | net 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sysinternals.Debug/GlobalSuppressions.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/Sysinternals.Debug/GlobalSuppressions.cs -------------------------------------------------------------------------------- /Sysinternals.Debug/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | /*////////////////////////////////////////////////////////////////////////////// 2 | // ProcessMonitorTraceListener 3 | // 4 | // History: 5 | // - April 1, 2010 - Version 1.0 - John Robbins/Wintellect 6 | // - Initial release. 7 | // - March 1, 2014 - Version 1.1 - John Robbins/Wintellect 8 | // - Moved to VS 2013 and .NET 4.5.1 9 | //////////////////////////////////////////////////////////////////////////////*/ 10 | 11 | namespace Sysinternals.Debug 12 | { 13 | using Microsoft.Win32.SafeHandles; 14 | using System; 15 | using System.Diagnostics; 16 | using System.Diagnostics.CodeAnalysis; 17 | using System.Globalization; 18 | using System.Runtime.InteropServices; 19 | using System.Security; 20 | using System.Text; 21 | 22 | /// 23 | /// A class to wrap all the native code needed by this assembly. 24 | /// 25 | [SuppressMessage("Microsoft.Portability", 26 | "CA1903:UseOnlyApiFromTargetedFramework", 27 | MessageId = "System.Security.SecuritySafeCriticalAttribute", 28 | Justification = "Everyone is running .NET 2.0 SP2 so they have SecuritySafeCritical")] 29 | [SecuritySafeCritical] 30 | internal static class NativeMethods 31 | { 32 | // Constants to represent C preprocessor macros for PInvokes 33 | private const uint GENERIC_WRITE = 0x40000000; 34 | private const uint OPEN_EXISTING = 3; 35 | private const uint FILE_WRITE_ACCESS = 0x0002; 36 | private const uint FILE_SHARE_WRITE = 0x00000002; 37 | private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; 38 | private const uint METHOD_BUFFERED = 0; 39 | 40 | // Process Monitor Constants 41 | private const uint FILE_DEVICE_PROCMON_LOG = 0x00009535; 42 | private const string PROCMON_DEBUGGER_HANDLER = "\\\\.\\Global\\ProcmonDebugLogger"; 43 | 44 | /// 45 | /// The handle to the Process Monitor log device. 46 | /// 47 | private static SafeFileHandle hProcMon; 48 | 49 | /// 50 | /// Gets the IO Control code for the ProcMon log. 51 | /// 52 | private static uint IOCTL_EXTERNAL_LOG_DEBUGOUT { get { return CTL_CODE(); } } 53 | 54 | /// 55 | /// Builds the control code for the Process Monitor driver access. 56 | /// 57 | /// 58 | private static uint CTL_CODE(uint DeviceType = FILE_DEVICE_PROCMON_LOG, 59 | uint Function = 0x81, 60 | uint Method = METHOD_BUFFERED, 61 | uint Access = FILE_WRITE_ACCESS) 62 | { 63 | return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method); 64 | } 65 | 66 | /// 67 | /// Handles calling CreateFile. 68 | /// 69 | /// 70 | /// This is only used for opening the Process Monitor log handle, hence the default parameters. 71 | /// 72 | /// 73 | [SuppressMessage("Microsoft.Security", 74 | "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", 75 | Justification = "This is a bug in Code Analysis on pre-4.0 assemblies: http://connect.microsoft.com/VisualStudio/feedback/details/729254/bogus-ca5122-warning-about-p-invoke-declarations-should-not-be-safe-critical")] 76 | [DllImport("kernel32.dll", 77 | SetLastError = true, 78 | CharSet = CharSet.Unicode)] 79 | private static extern SafeFileHandle CreateFile(string lpFileName = PROCMON_DEBUGGER_HANDLER, 80 | uint dwDesiredAccess = GENERIC_WRITE, 81 | uint dwShareMode = FILE_SHARE_WRITE, 82 | IntPtr lpSecurityAttributes = default(IntPtr), 83 | uint dwCreationDisposition = OPEN_EXISTING, 84 | uint dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL, 85 | IntPtr hTemplateFile = default(IntPtr)); 86 | 87 | [SuppressMessage("Microsoft.Security", 88 | "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", 89 | Justification = "This is a bug in Code Analysis on pre-4.0 assemblies: http://connect.microsoft.com/VisualStudio/feedback/details/729254/bogus-ca5122-warning-about-p-invoke-declarations-should-not-be-safe-critical")] 90 | [DllImport("kernel32.dll", 91 | ExactSpelling = true, 92 | SetLastError = true, 93 | CharSet = CharSet.Unicode)] 94 | [return: MarshalAs(UnmanagedType.Bool)] 95 | private static extern bool DeviceIoControl(SafeFileHandle hDevice, 96 | uint dwIoControlCode, 97 | StringBuilder lpInBuffer, 98 | uint nInBufferSize, 99 | IntPtr lpOutBuffer, 100 | uint nOutBufferSize, 101 | out uint lpBytesReturned, 102 | IntPtr lpOverlapped); 103 | 104 | [SuppressMessage("Microsoft.Performance", 105 | "CA1810:InitializeReferenceTypeStaticFieldsInline", 106 | Justification = "How else are you going to set up a static event? (http://social.msdn.microsoft.com/Forums/en-US/d11fe313-278c-4cae-bfcc-b119204866c7/ca1810-incorrect?forum=vstscode)")] 107 | static NativeMethods() 108 | { 109 | AppDomain.CurrentDomain.ProcessExit += (sender, args) => 110 | { 111 | if (!hProcMon.IsInvalid) 112 | { 113 | hProcMon.Close(); 114 | } 115 | }; 116 | } 117 | 118 | /// 119 | /// Does the actual tracing to Process Monitor. 120 | /// 121 | /// 122 | /// The message to display. 123 | /// 124 | /// 125 | /// The formatting arguments for the message 126 | /// 127 | /// 128 | /// True if the trace succeeded, false otherwise. 129 | /// 130 | public static bool ProcMonDebugOutput(string message, params object[] args) 131 | { 132 | bool returnValue = false; 133 | StringBuilder renderedMessage = new StringBuilder(); 134 | renderedMessage.AppendFormat(CultureInfo.CurrentCulture, message, args); 135 | uint outLen; 136 | 137 | if (hProcMon == null || hProcMon.IsInvalid) 138 | { 139 | hProcMon = CreateFile(); 140 | } 141 | 142 | returnValue = DeviceIoControl(hProcMon, 143 | IOCTL_EXTERNAL_LOG_DEBUGOUT, 144 | renderedMessage, 145 | (uint)(message.Length * sizeof(System.Char)), 146 | IntPtr.Zero, 147 | 0, 148 | out outLen, 149 | IntPtr.Zero); 150 | return returnValue; 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Sysinternals.Debug/ProcessMonitorTraceListerner.cs: -------------------------------------------------------------------------------- 1 | /*////////////////////////////////////////////////////////////////////////////// 2 | // ProcessMonitorTraceListener 3 | // 4 | // History: 5 | // - April 1, 2010 - Version 1.0 - John Robbins/Wintellect 6 | // - Initial release. 7 | // - March 1, 2014 - Version 1.1 - John Robbins/Wintellect 8 | // - Moved to VS 2013 and .NET 4.5.1 9 | //////////////////////////////////////////////////////////////////////////////*/ 10 | 11 | namespace Sysinternals.Debug 12 | { 13 | using System; 14 | using System.Diagnostics; 15 | 16 | /// 17 | /// Implements a that redirects output to 18 | /// Sysinternal's Process Monitor program. 19 | /// 20 | public class ProcessMonitorTraceListener : TraceListener 21 | { 22 | /// 23 | /// Writes a trace message to Process Monitor. 24 | /// 25 | /// 26 | /// A message to write. 27 | /// 28 | public override void Write(string message) 29 | { 30 | NativeMethods.ProcMonDebugOutput(message); 31 | } 32 | 33 | /// 34 | /// Writes a trace message to Process Monitor. 35 | /// 36 | /// 37 | /// A message to write. 38 | /// 39 | public override void WriteLine(string message) 40 | { 41 | NativeMethods.ProcMonDebugOutput(message); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Sysinternals.Debug/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Security; 6 | 7 | [assembly: CLSCompliant(true)] 8 | // General Information about an assembly is controlled through the following 9 | // set of attributes. Change these attribute values to modify the information 10 | // associated with an assembly. 11 | [assembly: AssemblyTitle("Sysinternals.Debug")] 12 | [assembly: AssemblyDescription("Send Trace output to Process Monitor")] 13 | [assembly: AssemblyConfiguration("")] 14 | [assembly: AssemblyCompany("Wintellect")] 15 | [assembly: AssemblyProduct("Sysinternals.Debug")] 16 | [assembly: AssemblyCopyright("Copyright 2014 John Robbins/Wintellect")] 17 | [assembly: AssemblyTrademark("")] 18 | [assembly: AssemblyCulture("")] 19 | 20 | [assembly: SecurityCritical] 21 | 22 | 23 | 24 | // Setting ComVisible to false makes the types in this assembly not visible 25 | // to COM components. If you need to access a type in this assembly from 26 | // COM, set the ComVisible attribute to true on that type. 27 | [assembly: ComVisible(false)] 28 | 29 | // The following GUID is for the ID of the typelib if this project is exposed to COM 30 | [assembly: Guid("c8467a9a-9e22-41cf-aaf1-114c9ee949b6")] 31 | 32 | // Version information for an assembly consists of the following four values: 33 | // 34 | // Major Version 35 | // Minor Version 36 | // Build Number 37 | // Revision 38 | // 39 | // You can specify all the values or you can default the Build and Revision Numbers 40 | // by using the '*' as shown below: 41 | // [assembly: AssemblyVersion("1.0.*")] 42 | [assembly: AssemblyVersion("1.1.0.0")] 43 | [assembly: AssemblyFileVersion("1.1.0.0")] 44 | -------------------------------------------------------------------------------- /Sysinternals.Debug/Sysinternals.Debug.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FB1D522E-1ACB-49DD-93D4-123E6EA13AED} 8 | Library 9 | Properties 10 | Sysinternals.Debug 11 | Sysinternals.Debug 12 | v2.0 13 | 512 14 | 15 | 16 | 17 | 18 | true 19 | full 20 | false 21 | ..\Debugx64\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | true 26 | AllCodeAnalysisRulesAsErrors.ruleset 27 | true 28 | ..\Debugx64\Sysinternals.Debug.XML 29 | true 30 | 31 | 32 | pdbonly 33 | true 34 | ..\Releasex64\ 35 | TRACE 36 | prompt 37 | 4 38 | true 39 | AllCodeAnalysisRulesAsErrors.ruleset 40 | true 41 | ..\Releasex64\Sysinternals.Debug.XML 42 | true 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | copy $(OutDir)\$(TargetFileName) ..\$(ConfigurationName)Win32\ 61 | copy $(OutDir)\$(ProjectName).xml ..\$(ConfigurationName)Win32\ 62 | 63 | 70 | -------------------------------------------------------------------------------- /dokanc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | 22 | #ifndef _DOKANC_H_ 23 | #define _DOKANC_H_ 24 | 25 | #include "dokan.h" 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #define DOKAN_MOUNT_POINT_SUPPORTED_VERSION 600 32 | #define DOKAN_SECURITY_SUPPORTED_VERSION 600 33 | 34 | #define DOKAN_GLOBAL_DEVICE_NAME L"\\\\.\\Dokan" 35 | #define DOKAN_CONTROL_PIPE L"\\\\.\\pipe\\DokanMounter" 36 | 37 | #define DOKAN_MOUNTER_SERVICE L"DokanMounter" 38 | #define DOKAN_DRIVER_SERVICE L"Dokan" 39 | 40 | #define DOKAN_CONTROL_MOUNT 1 41 | #define DOKAN_CONTROL_UNMOUNT 2 42 | #define DOKAN_CONTROL_CHECK 3 43 | #define DOKAN_CONTROL_FIND 4 44 | #define DOKAN_CONTROL_LIST 5 45 | 46 | #define DOKAN_CONTROL_OPTION_FORCE_UNMOUNT 1 47 | 48 | #define DOKAN_CONTROL_SUCCESS 1 49 | #define DOKAN_CONTROL_FAIL 0 50 | 51 | #define DOKAN_SERVICE_START 1 52 | #define DOKAN_SERVICE_STOP 2 53 | #define DOKAN_SERVICE_DELETE 3 54 | 55 | #define DOKAN_KEEPALIVE_TIME 3000 // in miliseconds 56 | 57 | #define DOKAN_MAX_THREAD 15 58 | 59 | // DokanOptions->DebugMode is ON? 60 | extern BOOL g_DebugMode; 61 | 62 | // DokanOptions->UseStdErr is ON? 63 | extern BOOL g_UseStdErr; 64 | 65 | typedef struct _DOKAN_CONTROL { 66 | ULONG Type; 67 | WCHAR MountPoint[MAX_PATH]; 68 | WCHAR DeviceName[64]; 69 | ULONG Option; 70 | ULONG Status; 71 | 72 | } DOKAN_CONTROL, *PDOKAN_CONTROL; 73 | 74 | BOOL DOKANAPI 75 | DokanServiceInstall( 76 | LPCWSTR ServiceName, 77 | DWORD ServiceType, 78 | LPCWSTR ServiceFullPath); 79 | 80 | BOOL DOKANAPI 81 | DokanServiceDelete( 82 | LPCWSTR ServiceName); 83 | 84 | BOOL DOKANAPI 85 | DokanNetworkProviderInstall(); 86 | 87 | BOOL DOKANAPI 88 | DokanNetworkProviderUninstall(); 89 | 90 | BOOL DOKANAPI 91 | DokanSetDebugMode(ULONG Mode); 92 | 93 | BOOL DOKANAPI 94 | DokanMountControl(PDOKAN_CONTROL Control); 95 | 96 | 97 | #ifdef __cplusplus 98 | } 99 | #endif 100 | 101 | 102 | #endif -------------------------------------------------------------------------------- /dokani.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/dokani.h -------------------------------------------------------------------------------- /dokanx/access.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2010 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "../dokani.h" 23 | #include "fileinfo.h" 24 | 25 | HANDLE DOKANAPI 26 | DokanOpenRequestorToken(PDOKAN_FILE_INFO FileInfo) 27 | { 28 | BOOL status; 29 | ULONG returnedLength; 30 | PDOKAN_INSTANCE instance; 31 | PDOKAN_OPEN_INFO openInfo; 32 | PEVENT_CONTEXT eventContext; 33 | PEVENT_INFORMATION eventInfo; 34 | HANDLE handle = INVALID_HANDLE_VALUE; 35 | ULONG eventInfoSize; 36 | 37 | openInfo = (PDOKAN_OPEN_INFO)(INT_PTR)FileInfo->DokanContext; 38 | if (openInfo == NULL) 39 | { 40 | logw(L"OpenInfo is null"); 41 | return INVALID_HANDLE_VALUE; 42 | } 43 | 44 | eventContext = openInfo->EventContext; 45 | if (eventContext == NULL) 46 | { 47 | logw(L"EventContext is null"); 48 | return INVALID_HANDLE_VALUE; 49 | } 50 | 51 | instance = openInfo->DokanInstance; 52 | if (instance == NULL) 53 | { 54 | logw(L"Dokan Instance is null"); 55 | return INVALID_HANDLE_VALUE; 56 | } 57 | 58 | if (eventContext->MajorFunction != IRP_MJ_CREATE) 59 | { 60 | logw(L"MajorFunction isn't IRP_MJ_CREATE") 61 | return INVALID_HANDLE_VALUE; 62 | } 63 | 64 | eventInfoSize = sizeof(EVENT_INFORMATION); 65 | eventInfo = (PEVENT_INFORMATION)malloc(eventInfoSize); 66 | RtlZeroMemory(eventInfo, eventInfoSize); 67 | 68 | eventInfo->SerialNumber = eventContext->SerialNumber; 69 | 70 | WCHAR rawDeviceName[MAX_PATH]; 71 | if (!GetRawDeviceName(instance->DeviceName, rawDeviceName, _countof(rawDeviceName))) 72 | { 73 | logw(L"Failed to get raw device name from <%s>", instance->DeviceName); 74 | return INVALID_HANDLE_VALUE; 75 | } 76 | 77 | status = SendToDevice( 78 | rawDeviceName, 79 | IOCTL_GET_ACCESS_TOKEN, 80 | eventInfo, 81 | eventInfoSize, 82 | eventInfo, 83 | eventInfoSize, 84 | &returnedLength); 85 | if (status) 86 | { 87 | handle = eventInfo->AccessToken.Handle; 88 | } 89 | else 90 | { 91 | logw(L"IOCTL_GET_ACCESS_TOKEN failed"); 92 | } 93 | free(eventInfo); 94 | return handle; 95 | } -------------------------------------------------------------------------------- /dokanx/cleanup.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "../dokani.h" 23 | #include "fileinfo.h" 24 | 25 | 26 | VOID 27 | DispatchCleanup( 28 | HANDLE Handle, 29 | PEVENT_CONTEXT EventContext, 30 | PDOKAN_INSTANCE DokanInstance) 31 | { 32 | PEVENT_INFORMATION eventInfo; 33 | DOKAN_FILE_INFO fileInfo; 34 | PDOKAN_OPEN_INFO openInfo; 35 | ULONG sizeOfEventInfo = sizeof(EVENT_INFORMATION); 36 | 37 | CheckFileName(EventContext->Cleanup.FileName); 38 | 39 | eventInfo = DispatchCommon( 40 | EventContext, sizeOfEventInfo, DokanInstance, &fileInfo, &openInfo); 41 | 42 | eventInfo->Status = STATUS_SUCCESS; // return success at any case 43 | 44 | logw(L"###Cleanup %04d", openInfo != NULL ? openInfo->EventId : -1); 45 | 46 | if (DokanInstance->DokanOperations->Cleanup) { 47 | // ignore return value 48 | DokanInstance->DokanOperations->Cleanup( 49 | EventContext->Cleanup.FileName, 50 | &fileInfo); 51 | } 52 | 53 | openInfo->UserContext = fileInfo.Context; 54 | 55 | SendEventInformation(Handle, eventInfo, sizeOfEventInfo, DokanInstance); 56 | 57 | free(eventInfo); 58 | return; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /dokanx/close.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "../dokani.h" 23 | #include "fileinfo.h" 24 | 25 | 26 | VOID 27 | DispatchClose( 28 | HANDLE Handle, 29 | PEVENT_CONTEXT EventContext, 30 | PDOKAN_INSTANCE DokanInstance) 31 | { 32 | PEVENT_INFORMATION eventInfo; 33 | DOKAN_FILE_INFO fileInfo; 34 | PDOKAN_OPEN_INFO openInfo; 35 | ULONG sizeOfEventInfo = sizeof(EVENT_INFORMATION); 36 | 37 | UNREFERENCED_PARAMETER(Handle); 38 | 39 | CheckFileName(EventContext->Close.FileName); 40 | 41 | eventInfo = DispatchCommon( 42 | EventContext, sizeOfEventInfo, DokanInstance, &fileInfo, &openInfo); 43 | 44 | eventInfo->Status = STATUS_SUCCESS; // return success at any case 45 | 46 | logw(L"###Close %04d", openInfo != NULL ? openInfo->EventId : -1); 47 | 48 | if (DokanInstance->DokanOperations->CloseFile) { 49 | // ignore return value 50 | DokanInstance->DokanOperations->CloseFile( 51 | EventContext->Close.FileName, &fileInfo); 52 | } 53 | 54 | // do not send it to the driver 55 | //SendEventInformation(Handle, eventInfo, length); 56 | 57 | if (openInfo != NULL) { 58 | EnterCriticalSection(&DokanInstance->CriticalSection); 59 | openInfo->OpenCount--; 60 | LeaveCriticalSection(&DokanInstance->CriticalSection); 61 | } 62 | ReleaseDokanOpenInfo(eventInfo, DokanInstance); 63 | free(eventInfo); 64 | 65 | return; 66 | } 67 | 68 | -------------------------------------------------------------------------------- /dokanx/dokanx.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {F25BA22F-2AB8-4859-9B89-8FE1E774B472} 23 | dokan 24 | 25 | 26 | 27 | DynamicLibrary 28 | Unicode 29 | true 30 | v120 31 | 32 | 33 | DynamicLibrary 34 | Unicode 35 | v120 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | <_ProjectFileVersion>10.0.40219.1 49 | AllRules.ruleset 50 | 51 | 52 | AllRules.ruleset 53 | 54 | 55 | 56 | 57 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 58 | 59 | 60 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 61 | 62 | 63 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 64 | 65 | 66 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 67 | 68 | 69 | 70 | Disabled 71 | ../sys;%(AdditionalIncludeDirectories) 72 | true 73 | EnableFastChecks 74 | MultiThreadedDebug 75 | Level4 76 | ProgramDatabase 77 | Use 78 | _WINDLL;%(PreprocessorDefinitions); 79 | 80 | 81 | $(OutDir)\$(TargetName).lib 82 | 83 | 84 | $(OutDir)\$(TargetName).lib 85 | 86 | 87 | 88 | 89 | MaxSpeed 90 | true 91 | ../sys;%(AdditionalIncludeDirectories) 92 | MultiThreadedDLL 93 | true 94 | Level4 95 | ProgramDatabase 96 | 97 | 98 | $(OutDir)\$(TargetName).lib 99 | 100 | 101 | $(OutDir)\$(TargetName).lib 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | Create 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | {6053d32f-0c6b-4a75-a5fd-d8143785abb0} 138 | true 139 | true 140 | false 141 | true 142 | false 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /dokanx/dokanx.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /dokanx/flush.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "../dokani.h" 23 | #include "fileinfo.h" 24 | 25 | 26 | VOID 27 | DispatchFlush( 28 | HANDLE Handle, 29 | PEVENT_CONTEXT EventContext, 30 | PDOKAN_INSTANCE DokanInstance) 31 | { 32 | DOKAN_FILE_INFO fileInfo; 33 | PEVENT_INFORMATION eventInfo; 34 | ULONG sizeOfEventInfo = sizeof(EVENT_INFORMATION); 35 | PDOKAN_OPEN_INFO openInfo; 36 | int status; 37 | 38 | CheckFileName(EventContext->Flush.FileName); 39 | 40 | eventInfo = DispatchCommon( 41 | EventContext, sizeOfEventInfo, DokanInstance, &fileInfo, &openInfo); 42 | 43 | logw(L"###Flush %04d", openInfo != NULL ? openInfo->EventId : -1); 44 | 45 | eventInfo->Status = STATUS_SUCCESS; 46 | 47 | if (DokanInstance->DokanOperations->FlushFileBuffers) { 48 | 49 | status = DokanInstance->DokanOperations->FlushFileBuffers( 50 | EventContext->Flush.FileName, 51 | &fileInfo); 52 | 53 | eventInfo->Status = status < 0 ? 54 | STATUS_NOT_SUPPORTED : STATUS_SUCCESS; 55 | } 56 | 57 | openInfo->UserContext = fileInfo.Context; 58 | 59 | SendEventInformation(Handle, eventInfo, sizeOfEventInfo, DokanInstance); 60 | 61 | free(eventInfo); 62 | return; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /dokanx/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | 22 | #ifndef _LIST_H_ 23 | #define _LIST_H_ 24 | 25 | #include 26 | 27 | #if _MSC_VER < 1300 28 | #define FORCEINLINE __inline 29 | #endif 30 | 31 | FORCEINLINE 32 | VOID 33 | InitializeListHead( 34 | PLIST_ENTRY ListHead) 35 | { 36 | ListHead->Flink = ListHead->Blink = ListHead; 37 | } 38 | 39 | FORCEINLINE 40 | BOOLEAN 41 | IsListEmpty( 42 | const LIST_ENTRY * ListHead) 43 | { 44 | return (BOOLEAN)(ListHead == NULL || ListHead->Flink == ListHead); 45 | } 46 | 47 | FORCEINLINE 48 | BOOLEAN 49 | RemoveEntryList( 50 | PLIST_ENTRY Entry) 51 | { 52 | PLIST_ENTRY Blink; 53 | PLIST_ENTRY Flink; 54 | 55 | if (Entry != NULL) { 56 | Flink = Entry->Flink; 57 | Blink = Entry->Blink; 58 | Blink->Flink = Flink; 59 | Flink->Blink = Blink; 60 | return (BOOLEAN)(Flink == Blink); 61 | } 62 | /* Assumes the list is empty */ 63 | return TRUE; 64 | } 65 | 66 | FORCEINLINE 67 | PLIST_ENTRY 68 | RemoveHeadList( 69 | PLIST_ENTRY ListHead) 70 | { 71 | PLIST_ENTRY Flink; 72 | PLIST_ENTRY Entry; 73 | 74 | Entry = ListHead->Flink; 75 | Flink = Entry->Flink; 76 | ListHead->Flink = Flink; 77 | Flink->Blink = ListHead; 78 | return Entry; 79 | } 80 | 81 | 82 | 83 | FORCEINLINE 84 | PLIST_ENTRY 85 | RemoveTailList( 86 | PLIST_ENTRY ListHead) 87 | { 88 | PLIST_ENTRY Blink; 89 | PLIST_ENTRY Entry; 90 | 91 | Entry = ListHead->Blink; 92 | Blink = Entry->Blink; 93 | ListHead->Blink = Blink; 94 | Blink->Flink = ListHead; 95 | return Entry; 96 | } 97 | 98 | 99 | FORCEINLINE 100 | VOID 101 | InsertTailList( 102 | PLIST_ENTRY ListHead, 103 | PLIST_ENTRY Entry) 104 | { 105 | PLIST_ENTRY Blink; 106 | 107 | Blink = ListHead->Blink; 108 | Entry->Flink = ListHead; 109 | Entry->Blink = Blink; 110 | Blink->Flink = Entry; 111 | ListHead->Blink = Entry; 112 | } 113 | 114 | 115 | FORCEINLINE 116 | VOID 117 | InsertHeadList( 118 | PLIST_ENTRY ListHead, 119 | PLIST_ENTRY Entry) 120 | { 121 | PLIST_ENTRY Flink; 122 | 123 | Flink = ListHead->Flink; 124 | Entry->Flink = Flink; 125 | Entry->Blink = ListHead; 126 | Flink->Blink = Entry; 127 | ListHead->Flink = Entry; 128 | } 129 | 130 | FORCEINLINE 131 | VOID 132 | AppendTailList( 133 | PLIST_ENTRY ListHead, 134 | PLIST_ENTRY ListToAppend) 135 | { 136 | PLIST_ENTRY ListEnd = ListHead->Blink; 137 | 138 | ListHead->Blink->Flink = ListToAppend; 139 | ListHead->Blink = ListToAppend->Blink; 140 | ListToAppend->Blink->Flink = ListHead; 141 | ListToAppend->Blink = ListEnd; 142 | } 143 | 144 | FORCEINLINE 145 | PSINGLE_LIST_ENTRY 146 | PopEntryList( 147 | PSINGLE_LIST_ENTRY ListHead) 148 | { 149 | PSINGLE_LIST_ENTRY FirstEntry; 150 | FirstEntry = ListHead->Next; 151 | if (FirstEntry != NULL) { 152 | ListHead->Next = FirstEntry->Next; 153 | } 154 | 155 | return FirstEntry; 156 | } 157 | 158 | 159 | FORCEINLINE 160 | VOID 161 | PushEntryList( 162 | PSINGLE_LIST_ENTRY ListHead, 163 | PSINGLE_LIST_ENTRY Entry) 164 | { 165 | Entry->Next = ListHead->Next; 166 | ListHead->Next = Entry; 167 | } 168 | 169 | #endif 170 | -------------------------------------------------------------------------------- /dokanx/lock.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "../dokani.h" 23 | #include "fileinfo.h" 24 | 25 | 26 | VOID 27 | DispatchLock( 28 | HANDLE Handle, 29 | PEVENT_CONTEXT EventContext, 30 | PDOKAN_INSTANCE DokanInstance) 31 | { 32 | DOKAN_FILE_INFO fileInfo; 33 | PEVENT_INFORMATION eventInfo; 34 | ULONG sizeOfEventInfo = sizeof(EVENT_INFORMATION); 35 | PDOKAN_OPEN_INFO openInfo; 36 | int status; 37 | 38 | CheckFileName(EventContext->Lock.FileName); 39 | 40 | eventInfo = DispatchCommon( 41 | EventContext, sizeOfEventInfo, DokanInstance, &fileInfo, &openInfo); 42 | 43 | logw(L"###Lock %04d", openInfo != NULL ? openInfo->EventId : -1); 44 | 45 | eventInfo->Status = STATUS_NOT_IMPLEMENTED; 46 | 47 | switch (EventContext->MinorFunction) { 48 | case IRP_MN_LOCK: 49 | if (DokanInstance->DokanOperations->LockFile) { 50 | 51 | status = DokanInstance->DokanOperations->LockFile( 52 | EventContext->Lock.FileName, 53 | EventContext->Lock.ByteOffset.QuadPart, 54 | EventContext->Lock.Length.QuadPart, 55 | //EventContext->Lock.Key, 56 | &fileInfo); 57 | 58 | eventInfo->Status = status < 0 ? 59 | STATUS_LOCK_NOT_GRANTED : STATUS_SUCCESS; 60 | } 61 | break; 62 | case IRP_MN_UNLOCK_ALL: 63 | break; 64 | case IRP_MN_UNLOCK_ALL_BY_KEY: 65 | break; 66 | case IRP_MN_UNLOCK_SINGLE: 67 | if (DokanInstance->DokanOperations->UnlockFile) { 68 | 69 | status = DokanInstance->DokanOperations->UnlockFile( 70 | EventContext->Lock.FileName, 71 | EventContext->Lock.ByteOffset.QuadPart, 72 | EventContext->Lock.Length.QuadPart, 73 | //EventContext->Lock.Key, 74 | &fileInfo); 75 | 76 | eventInfo->Status = STATUS_SUCCESS; // at any time return success ? 77 | } 78 | break; 79 | default: 80 | logw(L"unkown lock function %d\n", EventContext->MinorFunction); 81 | } 82 | 83 | openInfo->UserContext = fileInfo.Context; 84 | 85 | SendEventInformation(Handle, eventInfo, sizeOfEventInfo, DokanInstance); 86 | 87 | free(eventInfo); 88 | return; 89 | } 90 | -------------------------------------------------------------------------------- /dokanx/read.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "../dokani.h" 23 | #include "fileinfo.h" 24 | 25 | 26 | VOID 27 | DispatchRead( 28 | HANDLE Handle, 29 | PEVENT_CONTEXT EventContext, 30 | PDOKAN_INSTANCE DokanInstance) 31 | { 32 | PEVENT_INFORMATION eventInfo; 33 | PDOKAN_OPEN_INFO openInfo; 34 | ULONG readLength = 0; 35 | int status = -1; 36 | DOKAN_FILE_INFO fileInfo; 37 | ULONG sizeOfEventInfo; 38 | 39 | sizeOfEventInfo = sizeof(EVENT_INFORMATION) - 8 + EventContext->Read.BufferLength; 40 | 41 | CheckFileName(EventContext->Read.FileName); 42 | 43 | eventInfo = DispatchCommon( 44 | EventContext, sizeOfEventInfo, DokanInstance, &fileInfo, &openInfo); 45 | 46 | logw(L"###Read %04d", openInfo != NULL ? openInfo->EventId : -1); 47 | 48 | if (DokanInstance->DokanOperations->ReadFile) { 49 | status = DokanInstance->DokanOperations->ReadFile( 50 | EventContext->Read.FileName, 51 | eventInfo->Buffer, 52 | EventContext->Read.BufferLength, 53 | &readLength, 54 | EventContext->Read.ByteOffset.QuadPart, 55 | &fileInfo); 56 | } else { 57 | status = -1; 58 | } 59 | 60 | openInfo->UserContext = fileInfo.Context; 61 | eventInfo->BufferLength = 0; 62 | 63 | eventInfo->Status = status; 64 | 65 | if (status == STATUS_SUCCESS) 66 | { 67 | eventInfo->BufferLength = readLength; 68 | eventInfo->Read.CurrentByteOffset.QuadPart = 69 | EventContext->Read.ByteOffset.QuadPart + readLength; 70 | } 71 | 72 | /*if (status < 0) { 73 | eventInfo->Status = STATUS_INVALID_PARAMETER; 74 | } else if(readLength == 0) { 75 | eventInfo->Status = STATUS_END_OF_FILE; 76 | } else { 77 | eventInfo->Status = STATUS_SUCCESS; 78 | eventInfo->BufferLength = readLength; 79 | eventInfo->Read.CurrentByteOffset.QuadPart = 80 | EventContext->Read.ByteOffset.QuadPart + readLength; 81 | }*/ 82 | 83 | SendEventInformation(Handle, eventInfo, sizeOfEventInfo, DokanInstance); 84 | free(eventInfo); 85 | return; 86 | } 87 | -------------------------------------------------------------------------------- /dokanx/security.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2010 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include "../dokani.h" 23 | #include "fileinfo.h" 24 | 25 | VOID 26 | DispatchQuerySecurity( 27 | HANDLE Handle, 28 | PEVENT_CONTEXT EventContext, 29 | PDOKAN_INSTANCE DokanInstance) 30 | { 31 | PEVENT_INFORMATION eventInfo; 32 | DOKAN_FILE_INFO fileInfo; 33 | PDOKAN_OPEN_INFO openInfo; 34 | ULONG eventInfoLength; 35 | NTSTATUS status = STATUS_NOT_IMPLEMENTED; 36 | ULONG lengthNeeded = 0; 37 | 38 | eventInfoLength = sizeof(EVENT_INFORMATION) - 8 + EventContext->Security.BufferLength; 39 | CheckFileName(EventContext->Security.FileName); 40 | 41 | eventInfo = DispatchCommon(EventContext, eventInfoLength, DokanInstance, &fileInfo, &openInfo); 42 | 43 | if (DOKAN_SECURITY_SUPPORTED_VERSION <= DokanInstance->DokanOptions->Version && 44 | DokanInstance->DokanOperations->GetFileSecurity) { 45 | status = DokanInstance->DokanOperations->GetFileSecurity( 46 | EventContext->Security.FileName, 47 | &EventContext->Security.SecurityInformation, 48 | &eventInfo->Buffer, 49 | EventContext->Security.BufferLength, 50 | &lengthNeeded, 51 | &fileInfo); 52 | } 53 | 54 | eventInfo->Status = status; 55 | eventInfo->BufferLength = lengthNeeded; 56 | 57 | if (status != STATUS_SUCCESS && status != STATUS_BUFFER_OVERFLOW) { 58 | eventInfo->BufferLength = 0; 59 | } 60 | 61 | SendEventInformation(Handle, eventInfo, eventInfoLength, DokanInstance); 62 | free(eventInfo); 63 | } 64 | 65 | 66 | VOID 67 | DispatchSetSecurity( 68 | HANDLE Handle, 69 | PEVENT_CONTEXT EventContext, 70 | PDOKAN_INSTANCE DokanInstance) 71 | { 72 | PEVENT_INFORMATION eventInfo; 73 | DOKAN_FILE_INFO fileInfo; 74 | PDOKAN_OPEN_INFO openInfo; 75 | ULONG eventInfoLength; 76 | int status = -1; 77 | PSECURITY_DESCRIPTOR securityDescriptor; 78 | 79 | eventInfoLength = sizeof(EVENT_INFORMATION); 80 | CheckFileName(EventContext->SetSecurity.FileName); 81 | 82 | eventInfo = DispatchCommon(EventContext, eventInfoLength, DokanInstance, &fileInfo, &openInfo); 83 | 84 | securityDescriptor = (PCHAR)EventContext + EventContext->SetSecurity.BufferOffset; 85 | 86 | if (DOKAN_SECURITY_SUPPORTED_VERSION <= DokanInstance->DokanOptions->Version && 87 | DokanInstance->DokanOperations->SetFileSecurity) { 88 | status = DokanInstance->DokanOperations->SetFileSecurity( 89 | EventContext->SetSecurity.FileName, 90 | &EventContext->SetSecurity.SecurityInformation, 91 | securityDescriptor, 92 | EventContext->SetSecurity.BufferLength, 93 | &fileInfo); 94 | } 95 | 96 | if (status < 0) { 97 | eventInfo->Status = STATUS_INVALID_PARAMETER; 98 | eventInfo->BufferLength = 0; 99 | } else { 100 | eventInfo->Status = STATUS_SUCCESS; 101 | eventInfo->BufferLength = 0; 102 | } 103 | 104 | SendEventInformation(Handle, eventInfo, eventInfoLength, DokanInstance); 105 | free(eventInfo); 106 | } 107 | 108 | 109 | -------------------------------------------------------------------------------- /dokanx/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // dokanx_mount.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /dokanx/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | 9 | #undef _VARIADIC_MAX 10 | #define _VARIADIC_MAX 10 11 | 12 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 13 | // Windows Header Files: 14 | #include 15 | #include 16 | // C RunTime Header Files 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | // TODO: reference additional headers your program requires here 24 | #define _MODULE_NAME L"dokan_user_lib" 25 | #include "../Common/Log/NdLog.h" 26 | 27 | -------------------------------------------------------------------------------- /dokanx/timeout.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2010 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include 23 | #include "../dokani.h" 24 | 25 | BOOL DOKANAPI 26 | DokanResetTimeout(ULONG Timeout, PDOKAN_FILE_INFO FileInfo) 27 | { 28 | BOOL status; 29 | ULONG returnedLength; 30 | PDOKAN_INSTANCE instance; 31 | PDOKAN_OPEN_INFO openInfo; 32 | PEVENT_CONTEXT eventContext; 33 | PEVENT_INFORMATION eventInfo; 34 | ULONG eventInfoSize = sizeof(EVENT_INFORMATION); 35 | 36 | openInfo = (PDOKAN_OPEN_INFO)(INT_PTR)FileInfo->DokanContext; 37 | if (openInfo == NULL) { 38 | return FALSE; 39 | } 40 | 41 | eventContext = openInfo->EventContext; 42 | if (eventContext == NULL) { 43 | return FALSE; 44 | } 45 | 46 | instance = openInfo->DokanInstance; 47 | if (instance == NULL) { 48 | return FALSE; 49 | } 50 | 51 | eventInfo = (PEVENT_INFORMATION)malloc(eventInfoSize); 52 | RtlZeroMemory(eventInfo, eventInfoSize); 53 | 54 | eventInfo->SerialNumber = eventContext->SerialNumber; 55 | eventInfo->ResetTimeout.Timeout = Timeout; 56 | 57 | WCHAR rawDeviceName[MAX_PATH]; 58 | if (!GetRawDeviceName(instance->DeviceName, rawDeviceName, _countof(rawDeviceName))) 59 | { 60 | logw(L"Failed to get raw device name from <%s>", instance->DeviceName); 61 | return FALSE; 62 | } 63 | 64 | status = SendToDevice( 65 | rawDeviceName, 66 | IOCTL_RESET_TIMEOUT, 67 | eventInfo, 68 | eventInfoSize, 69 | NULL, 70 | 0, 71 | &returnedLength); 72 | free(eventInfo); 73 | return status; 74 | } 75 | 76 | 77 | UINT WINAPI 78 | DokanKeepAlive( 79 | PVOID pDokanInstance) 80 | { 81 | PDOKAN_INSTANCE DokanInstance = (PDOKAN_INSTANCE)pDokanInstance; 82 | HANDLE device; 83 | ULONG ReturnedLength; 84 | // ULONG returnedLength; 85 | BOOL status; 86 | 87 | WCHAR rawDeviceName[MAX_PATH]; 88 | if (!GetRawDeviceName(DokanInstance->DeviceName, rawDeviceName, _countof(rawDeviceName))) 89 | { 90 | logw(L"Failed to get raw device name from <%s>", DokanInstance->DeviceName); 91 | return ERROR_INVALID_PARAMETER; 92 | } 93 | 94 | device = CreateFile( 95 | rawDeviceName, 96 | GENERIC_READ | GENERIC_WRITE, // dwDesiredAccess 97 | FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode 98 | NULL, // lpSecurityAttributes 99 | OPEN_EXISTING, // dwCreationDistribution 100 | 0, // dwFlagsAndAttributes 101 | NULL // hTemplateFile 102 | ); 103 | 104 | while(device != INVALID_HANDLE_VALUE) { 105 | 106 | status = DeviceIoControl( 107 | device, // Handle to device 108 | IOCTL_KEEPALIVE, // IO Control code 109 | NULL, // Input Buffer to driver. 110 | 0, // Length of input buffer in bytes. 111 | NULL, // Output Buffer from driver. 112 | 0, // Length of output buffer in bytes. 113 | &ReturnedLength, // Bytes placed in buffer. 114 | NULL // synchronous call 115 | ); 116 | if (!status) { 117 | break; 118 | } 119 | Sleep(DOKAN_KEEPALIVE_TIME); 120 | } 121 | 122 | CloseHandle(device); 123 | 124 | _endthreadex(0); 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /dokanx/version.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | #include "stdafx.h" 22 | #include 23 | #include 24 | #include "../dokani.h" 25 | 26 | 27 | ULONG DOKANAPI 28 | DokanVersion() 29 | { 30 | return DOKAN_VERSION; 31 | } 32 | 33 | 34 | ULONG DOKANAPI 35 | DokanDriverVersion() 36 | { 37 | ULONG version = 0; 38 | ULONG ret = 0; 39 | 40 | if (SendToDevice( 41 | DOKAN_GLOBAL_DEVICE_NAME, 42 | IOCTL_TEST, 43 | NULL, // InputBuffer 44 | 0, // InputLength 45 | &version, // OutputBuffer 46 | sizeof(ULONG), // OutputLength 47 | &ret)) { 48 | 49 | return version; 50 | } 51 | 52 | return 0; 53 | } -------------------------------------------------------------------------------- /dokanx/write.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | 21 | 22 | #include "stdafx.h" 23 | #include "../dokani.h" 24 | #include "fileinfo.h" 25 | #include 26 | 27 | VOID SendWriteRequest( 28 | HANDLE Handle, 29 | PEVENT_INFORMATION EventInfo, 30 | ULONG EventLength, 31 | PVOID Buffer, 32 | ULONG BufferLength) 33 | { 34 | BOOL status; 35 | ULONG returnedLength; 36 | 37 | logw(L"SendWriteRequest"); 38 | 39 | status = DeviceIoControl( 40 | Handle, // Handle to device 41 | IOCTL_EVENT_WRITE, // IO Control code 42 | EventInfo, // Input Buffer to driver. 43 | EventLength, // Length of input buffer in bytes. 44 | Buffer, // Output Buffer from driver. 45 | BufferLength, // Length of output buffer in bytes. 46 | &returnedLength, // Bytes placed in buffer. 47 | NULL // synchronous call 48 | ); 49 | 50 | if ( !status ) { 51 | DWORD errorCode = GetLastError(); 52 | logw(L"Ioctl failed with code %d\n", errorCode ); 53 | } 54 | 55 | logw(L"SendWriteRequest got %d bytes\n", returnedLength); 56 | } 57 | 58 | 59 | VOID 60 | DispatchWrite( 61 | HANDLE Handle, 62 | PEVENT_CONTEXT EventContext, 63 | PDOKAN_INSTANCE DokanInstance) 64 | { 65 | PEVENT_INFORMATION eventInfo; 66 | PDOKAN_OPEN_INFO openInfo; 67 | ULONG writtenLength = 0; 68 | int status; 69 | DOKAN_FILE_INFO fileInfo; 70 | BOOL bufferAllocated = FALSE; 71 | ULONG sizeOfEventInfo = sizeof(EVENT_INFORMATION); 72 | 73 | eventInfo = DispatchCommon( 74 | EventContext, sizeOfEventInfo, DokanInstance, &fileInfo, &openInfo); 75 | 76 | // Since driver requested bigger memory, 77 | // allocate enough memory and send it to driver 78 | if (EventContext->Write.RequestLength > 0) { 79 | ULONG contextLength = EventContext->Write.RequestLength; 80 | PEVENT_CONTEXT contextBuf = (PEVENT_CONTEXT)malloc(contextLength); 81 | SendWriteRequest(Handle, eventInfo, sizeOfEventInfo, contextBuf, contextLength); 82 | EventContext = contextBuf; 83 | bufferAllocated = TRUE; 84 | } 85 | 86 | CheckFileName(EventContext->Write.FileName); 87 | 88 | logw(L"###WriteFile %04d", openInfo != NULL ? openInfo->EventId : -1); 89 | 90 | if (DokanInstance->DokanOperations->WriteFile) { 91 | status = DokanInstance->DokanOperations->WriteFile( 92 | EventContext->Write.FileName, 93 | (PCHAR)EventContext + EventContext->Write.BufferOffset, 94 | EventContext->Write.BufferLength, 95 | &writtenLength, 96 | EventContext->Write.ByteOffset.QuadPart, 97 | &fileInfo); 98 | } else { 99 | status = -1; 100 | } 101 | 102 | openInfo->UserContext = fileInfo.Context; 103 | eventInfo->BufferLength = 0; 104 | 105 | if (status < 0) { 106 | eventInfo->Status = STATUS_INVALID_PARAMETER; 107 | 108 | } else { 109 | eventInfo->Status = STATUS_SUCCESS; 110 | eventInfo->BufferLength = writtenLength; 111 | eventInfo->Write.CurrentByteOffset.QuadPart = 112 | EventContext->Write.ByteOffset.QuadPart + writtenLength; 113 | } 114 | 115 | SendEventInformation(Handle, eventInfo, sizeOfEventInfo, DokanInstance); 116 | free(eventInfo); 117 | 118 | if (bufferAllocated) 119 | free(EventContext); 120 | 121 | return; 122 | } 123 | -------------------------------------------------------------------------------- /dokanx_control/dokanx_control.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dokanx_control", "dokanx_control.vcxproj", "{A1881DF2-0A37-4AF4-86DC-EE0251CC6EA6}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {A1881DF2-0A37-4AF4-86DC-EE0251CC6EA6}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {A1881DF2-0A37-4AF4-86DC-EE0251CC6EA6}.Debug|Win32.Build.0 = Debug|Win32 14 | {A1881DF2-0A37-4AF4-86DC-EE0251CC6EA6}.Release|Win32.ActiveCfg = Release|Win32 15 | {A1881DF2-0A37-4AF4-86DC-EE0251CC6EA6}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /dokanx_control/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // dokanx_control.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /dokanx_control/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | #undef _VARIADIC_MAX 8 | #define _VARIADIC_MAX 10 9 | #include "targetver.h" 10 | 11 | #include 12 | #include 13 | 14 | 15 | 16 | // TODO: reference additional headers your program requires here 17 | #define _MODULE_NAME L"Control" 18 | #include "../Common/Log/NdLog.h" -------------------------------------------------------------------------------- /dokanx_control/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /dokanx_mount/Release/dokanx_mount.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/dokanx_mount/Release/dokanx_mount.res -------------------------------------------------------------------------------- /dokanx_mount/Resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by dokanx_mount.rc 4 | // 5 | 6 | #define IDS_APP_TITLE 103 7 | 8 | #define IDR_MAINFRAME 128 9 | #define IDD_DOKANX_MOUNT_DIALOG 102 10 | #define IDD_ABOUTBOX 103 11 | #define IDM_ABOUT 104 12 | #define IDM_EXIT 105 13 | #define IDI_DOKANX_MOUNT 107 14 | #define IDI_SMALL 108 15 | #define IDC_DOKANX_MOUNT 109 16 | #define IDC_MYICON 2 17 | #ifndef IDC_STATIC 18 | #define IDC_STATIC -1 19 | #endif 20 | // Next default values for new objects 21 | // 22 | #ifdef APSTUDIO_INVOKED 23 | #ifndef APSTUDIO_READONLY_SYMBOLS 24 | 25 | #define _APS_NO_MFC 130 26 | #define _APS_NEXT_RESOURCE_VALUE 129 27 | #define _APS_NEXT_COMMAND_VALUE 32771 28 | #define _APS_NEXT_CONTROL_VALUE 1000 29 | #define _APS_NEXT_SYMED_VALUE 110 30 | #endif 31 | #endif 32 | -------------------------------------------------------------------------------- /dokanx_mount/dokanx_mount.cpp: -------------------------------------------------------------------------------- 1 | // dokanx_mount.cpp : Defines the entry point for the application. 2 | // 3 | 4 | #include "stdafx.h" 5 | #include "dokanx_mount.h" 6 | 7 | #define MAX_LOADSTRING 100 8 | 9 | // Global Variables: 10 | HINSTANCE hInst; // current instance 11 | TCHAR szTitle[MAX_LOADSTRING]; // The title bar text 12 | TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name 13 | 14 | // Forward declarations of functions included in this code module: 15 | ATOM MyRegisterClass(HINSTANCE hInstance); 16 | BOOL InitInstance(HINSTANCE, int); 17 | LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 18 | INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); 19 | 20 | int APIENTRY _tWinMain(HINSTANCE hInstance, 21 | HINSTANCE hPrevInstance, 22 | LPTSTR lpCmdLine, 23 | int nCmdShow) 24 | { 25 | UNREFERENCED_PARAMETER(hPrevInstance); 26 | UNREFERENCED_PARAMETER(lpCmdLine); 27 | 28 | // TODO: Place code here. 29 | MSG msg; 30 | HACCEL hAccelTable; 31 | 32 | // Initialize global strings 33 | LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 34 | LoadString(hInstance, IDC_DOKANX_MOUNT, szWindowClass, MAX_LOADSTRING); 35 | MyRegisterClass(hInstance); 36 | 37 | // Perform application initialization: 38 | if (!InitInstance (hInstance, nCmdShow)) 39 | { 40 | return FALSE; 41 | } 42 | 43 | hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DOKANX_MOUNT)); 44 | 45 | // Main message loop: 46 | while (GetMessage(&msg, NULL, 0, 0)) 47 | { 48 | if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 49 | { 50 | TranslateMessage(&msg); 51 | DispatchMessage(&msg); 52 | } 53 | } 54 | 55 | return (int) msg.wParam; 56 | } 57 | 58 | 59 | 60 | // 61 | // FUNCTION: MyRegisterClass() 62 | // 63 | // PURPOSE: Registers the window class. 64 | // 65 | // COMMENTS: 66 | // 67 | // This function and its usage are only necessary if you want this code 68 | // to be compatible with Win32 systems prior to the 'RegisterClassEx' 69 | // function that was added to Windows 95. It is important to call this function 70 | // so that the application will get 'well formed' small icons associated 71 | // with it. 72 | // 73 | ATOM MyRegisterClass(HINSTANCE hInstance) 74 | { 75 | WNDCLASSEX wcex; 76 | 77 | wcex.cbSize = sizeof(WNDCLASSEX); 78 | 79 | wcex.style = CS_HREDRAW | CS_VREDRAW; 80 | wcex.lpfnWndProc = WndProc; 81 | wcex.cbClsExtra = 0; 82 | wcex.cbWndExtra = 0; 83 | wcex.hInstance = hInstance; 84 | wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DOKANX_MOUNT)); 85 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 86 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); 87 | wcex.lpszMenuName = MAKEINTRESOURCE(IDC_DOKANX_MOUNT); 88 | wcex.lpszClassName = szWindowClass; 89 | wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); 90 | 91 | return RegisterClassEx(&wcex); 92 | } 93 | 94 | // 95 | // FUNCTION: InitInstance(HINSTANCE, int) 96 | // 97 | // PURPOSE: Saves instance handle and creates main window 98 | // 99 | // COMMENTS: 100 | // 101 | // In this function, we save the instance handle in a global variable and 102 | // create and display the main program window. 103 | // 104 | BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 105 | { 106 | HWND hWnd; 107 | 108 | hInst = hInstance; // Store instance handle in our global variable 109 | 110 | hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 111 | CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); 112 | 113 | if (!hWnd) 114 | { 115 | return FALSE; 116 | } 117 | 118 | ShowWindow(hWnd, nCmdShow); 119 | UpdateWindow(hWnd); 120 | 121 | return TRUE; 122 | } 123 | 124 | // 125 | // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) 126 | // 127 | // PURPOSE: Processes messages for the main window. 128 | // 129 | // WM_COMMAND - process the application menu 130 | // WM_PAINT - Paint the main window 131 | // WM_DESTROY - post a quit message and return 132 | // 133 | // 134 | LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 135 | { 136 | int wmId, wmEvent; 137 | PAINTSTRUCT ps; 138 | HDC hdc; 139 | 140 | switch (message) 141 | { 142 | case WM_COMMAND: 143 | wmId = LOWORD(wParam); 144 | wmEvent = HIWORD(wParam); 145 | // Parse the menu selections: 146 | switch (wmId) 147 | { 148 | case IDM_ABOUT: 149 | DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); 150 | break; 151 | case IDM_EXIT: 152 | DestroyWindow(hWnd); 153 | break; 154 | default: 155 | return DefWindowProc(hWnd, message, wParam, lParam); 156 | } 157 | break; 158 | case WM_PAINT: 159 | hdc = BeginPaint(hWnd, &ps); 160 | // TODO: Add any drawing code here... 161 | EndPaint(hWnd, &ps); 162 | break; 163 | case WM_DESTROY: 164 | PostQuitMessage(0); 165 | break; 166 | default: 167 | return DefWindowProc(hWnd, message, wParam, lParam); 168 | } 169 | return 0; 170 | } 171 | 172 | // Message handler for about box. 173 | INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 174 | { 175 | UNREFERENCED_PARAMETER(lParam); 176 | switch (message) 177 | { 178 | case WM_INITDIALOG: 179 | return (INT_PTR)TRUE; 180 | 181 | case WM_COMMAND: 182 | if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 183 | { 184 | EndDialog(hDlg, LOWORD(wParam)); 185 | return (INT_PTR)TRUE; 186 | } 187 | break; 188 | } 189 | return (INT_PTR)FALSE; 190 | } 191 | -------------------------------------------------------------------------------- /dokanx_mount/dokanx_mount.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/dokanx_mount/dokanx_mount.ico -------------------------------------------------------------------------------- /dokanx_mount/dokanx_mount.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/dokanx_mount/dokanx_mount.rc -------------------------------------------------------------------------------- /dokanx_mount/dokanx_mount.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dokanx_mount", "dokanx_mount.vcxproj", "{688763EB-771C-44AA-A514-DF306DE83D83}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {688763EB-771C-44AA-A514-DF306DE83D83}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {688763EB-771C-44AA-A514-DF306DE83D83}.Debug|Win32.Build.0 = Debug|Win32 14 | {688763EB-771C-44AA-A514-DF306DE83D83}.Release|Win32.ActiveCfg = Release|Win32 15 | {688763EB-771C-44AA-A514-DF306DE83D83}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /dokanx_mount/dokanx_mount.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {688763EB-771C-44AA-A514-DF306DE83D83} 23 | Win32Proj 24 | dokanx_mount 25 | 26 | 27 | 28 | Application 29 | true 30 | Unicode 31 | v120 32 | 33 | 34 | Application 35 | false 36 | true 37 | Unicode 38 | v120 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | true 52 | 53 | 54 | false 55 | 56 | 57 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 58 | 59 | 60 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 61 | 62 | 63 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 64 | 65 | 66 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 67 | 68 | 69 | 70 | Use 71 | Level4 72 | Disabled 73 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions); 74 | ProgramDatabase 75 | MultiThreadedDebug 76 | 77 | 78 | Windows 79 | true 80 | 81 | 82 | 83 | 84 | Level3 85 | Use 86 | MaxSpeed 87 | true 88 | true 89 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 90 | 91 | 92 | Windows 93 | true 94 | true 95 | true 96 | 97 | 98 | 99 | 100 | Use 101 | Level4 102 | Disabled 103 | WIN32;WIN64;_DEBUG;_WINDOWS;%(PreprocessorDefinitions); 104 | ProgramDatabase 105 | MultiThreadedDebug 106 | 107 | 108 | Windows 109 | true 110 | 111 | 112 | 113 | 114 | Level3 115 | Use 116 | MaxSpeed 117 | true 118 | true 119 | WIN32;WIN64;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 120 | 121 | 122 | Windows 123 | true 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | Create 143 | Create 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | {6053d32f-0c6b-4a75-a5fd-d8143785abb0} 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /dokanx_mount/mount.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Copyright (c) 2007, 2008 Hiroki Asakawa asakaw@gmail.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | */ 23 | 24 | 25 | #ifndef _MOUNT_H_ 26 | #define _MOUNT_H_ 27 | 28 | #include "../dokanc.h" 29 | #include "../dokanx/list.h" 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | typedef struct _MOUNT_ENTRY { 36 | LIST_ENTRY ListEntry; 37 | DOKAN_CONTROL MountControl; 38 | } MOUNT_ENTRY, *PMOUNT_ENTRY; 39 | 40 | BOOL 41 | DokanControlMount( 42 | LPCWSTR MountPoint, 43 | LPCWSTR DeivceName); 44 | 45 | BOOL 46 | DokanControlUnmount( 47 | LPCWSTR MountPoint); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /dokanx_mount/small.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/dokanx_mount/small.ico -------------------------------------------------------------------------------- /dokanx_mount/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // dokanx_mount.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /dokanx_mount/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #undef _VARIADIC_MAX 11 | #define _VARIADIC_MAX 10 12 | 13 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 14 | // Windows Header Files: 15 | #include 16 | 17 | // C RunTime Header Files 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | // TODO: reference additional headers your program requires here 25 | #define _MODULE_NAME L"mount" 26 | #include "../Common/Log/NdLog.h" -------------------------------------------------------------------------------- /dokanx_mount/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /license.mit.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2007 Hiroki Asakawa 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /mirrorfs/mirrorfs.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {DADCBCAD-4429-422E-9FA9-D8E538D0EF94} 23 | Win32Proj 24 | mirrorfs 25 | 26 | 27 | 28 | Application 29 | true 30 | Unicode 31 | v120 32 | 33 | 34 | Application 35 | false 36 | true 37 | Unicode 38 | v120 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | true 52 | 53 | 54 | false 55 | 56 | 57 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 58 | 59 | 60 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 61 | 62 | 63 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 64 | 65 | 66 | $(SolutionDir)bin\$(PlatformTarget)\$(Configuration)\ 67 | 68 | 69 | 70 | Use 71 | Level4 72 | Disabled 73 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 74 | ProgramDatabase 75 | MultiThreadedDebug 76 | 77 | 78 | Console 79 | true 80 | ../debug 81 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 82 | 83 | 84 | 85 | 86 | Level3 87 | Use 88 | MaxSpeed 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | 93 | 94 | Console 95 | true 96 | true 97 | true 98 | 99 | 100 | 101 | 102 | Use 103 | Level4 104 | Disabled 105 | WIN32;WIN64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | ProgramDatabase 107 | MultiThreadedDebug 108 | 109 | 110 | Console 111 | true 112 | ../debug 113 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) 114 | 115 | 116 | 117 | 118 | Level3 119 | Use 120 | MaxSpeed 121 | true 122 | true 123 | WIN32;WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | 125 | 126 | Console 127 | true 128 | true 129 | true 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | Create 140 | Create 141 | 142 | 143 | 144 | 145 | {6053d32f-0c6b-4a75-a5fd-d8143785abb0} 146 | 147 | 148 | {f25ba22f-2ab8-4859-9b89-8fe1e774b472} 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /mirrorfs/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // mirrorfs.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /mirrorfs/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | #undef _VARIADIC_MAX 8 | #define _VARIADIC_MAX 10 9 | #include "targetver.h" 10 | 11 | #include 12 | #include 13 | 14 | 15 | 16 | // TODO: reference additional headers your program requires here 17 | #define _MODULE_NAME L"MirrorFs" 18 | #include "../Common/Log/NdLog.h" -------------------------------------------------------------------------------- /mirrorfs/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /sys/access.c: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2010 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | #include "precomp.h" 21 | #pragma hdrstop 22 | 23 | NTSTATUS 24 | DokanGetAccessToken( 25 | __in PDEVICE_OBJECT DeviceObject, 26 | __in PIRP Irp 27 | ) 28 | { 29 | KIRQL oldIrql; 30 | PLIST_ENTRY thisEntry, nextEntry, listHead; 31 | PIRP_ENTRY irpEntry; 32 | PDokanVCB vcb; 33 | PEVENT_INFORMATION eventInfo; 34 | PACCESS_TOKEN accessToken; 35 | NTSTATUS status = STATUS_INVALID_PARAMETER; 36 | HANDLE handle; 37 | PIO_STACK_LOCATION irpSp = NULL; 38 | BOOLEAN hasLock = FALSE; 39 | ULONG outBufferLen; 40 | ULONG inBufferLen; 41 | PACCESS_STATE accessState = NULL; 42 | 43 | DDbgPrint("==> DokanGetAccessToken"); 44 | 45 | __try { 46 | eventInfo = (PEVENT_INFORMATION)Irp->AssociatedIrp.SystemBuffer; 47 | ASSERT(eventInfo != NULL); 48 | 49 | if (Irp->RequestorMode != UserMode) { 50 | DDbgPrint(" needs to be called from user-mode"); 51 | status = STATUS_INVALID_PARAMETER; 52 | __leave; 53 | } 54 | 55 | vcb = DeviceObject->DeviceExtension; 56 | if (GetIdentifierType(vcb) != VCB) { 57 | DDbgPrint(" GetIdentifierType != VCB"); 58 | status = STATUS_INVALID_PARAMETER; 59 | __leave; 60 | } 61 | 62 | irpSp = IoGetCurrentIrpStackLocation(Irp); 63 | outBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength; 64 | inBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength; 65 | if (outBufferLen != sizeof(EVENT_INFORMATION) || 66 | inBufferLen != sizeof(EVENT_INFORMATION)) { 67 | DDbgPrint(" wrong input or output buffer length"); 68 | status = STATUS_INVALID_PARAMETER; 69 | __leave; 70 | } 71 | 72 | ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 73 | KeAcquireSpinLock(&vcb->Dcb->PendingIrp.ListLock, &oldIrql); 74 | hasLock = TRUE; 75 | 76 | // search corresponding IRP through pending IRP list 77 | listHead = &vcb->Dcb->PendingIrp.ListHead; 78 | 79 | for (thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = nextEntry) { 80 | 81 | nextEntry = thisEntry->Flink; 82 | 83 | irpEntry = CONTAINING_RECORD(thisEntry, IRP_ENTRY, ListEntry); 84 | 85 | if (irpEntry->SerialNumber != eventInfo->SerialNumber) { 86 | continue; 87 | } 88 | 89 | // this irp must be IRP_MJ_CREATE 90 | if (irpEntry->IrpSp->Parameters.Create.SecurityContext) { 91 | accessState = irpEntry->IrpSp->Parameters.Create.SecurityContext->AccessState; 92 | } 93 | break; 94 | } 95 | KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); 96 | hasLock = FALSE; 97 | 98 | if (accessState == NULL) { 99 | DDbgPrint(" can't find pending Irp: %d\n", eventInfo->SerialNumber); 100 | __leave; 101 | } 102 | 103 | accessToken = SeQuerySubjectContextToken(&accessState->SubjectSecurityContext); 104 | if (accessToken == NULL) { 105 | DDbgPrint(" accessToken == NULL"); 106 | __leave; 107 | } 108 | // NOTE: Accessing *SeTokenObjectType while acquring sping lock causes 109 | // BSOD on Windows XP. 110 | status = ObOpenObjectByPointer(accessToken, 0, NULL, GENERIC_ALL, 111 | *SeTokenObjectType, KernelMode, &handle); 112 | if (!NT_SUCCESS(status)) { 113 | DDbgPrint(" ObOpenObjectByPointer failed: 0x%x\n", status); 114 | __leave; 115 | } 116 | 117 | eventInfo->AccessToken.Handle = handle; 118 | Irp->IoStatus.Information = sizeof(EVENT_INFORMATION); 119 | status = STATUS_SUCCESS; 120 | 121 | } __finally { 122 | if (hasLock) { 123 | KeReleaseSpinLock(&vcb->Dcb->PendingIrp.ListLock, oldIrql); 124 | } 125 | } 126 | DDbgPrint("<== DokanGetAccessToken"); 127 | return status; 128 | } -------------------------------------------------------------------------------- /sys/cleanup.c: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | #include "precomp.h" 21 | #pragma hdrstop 22 | 23 | 24 | NTSTATUS 25 | DokanDispatchCleanup( 26 | __in PDEVICE_OBJECT DeviceObject, 27 | __in PIRP Irp 28 | ) 29 | 30 | /*++ 31 | 32 | Routine Description: 33 | 34 | This device control dispatcher handles Cleanup IRP. 35 | 36 | Arguments: 37 | 38 | DeviceObject - Context for the activity. 39 | Irp - The device control argument block. 40 | 41 | Return Value: 42 | 43 | NTSTATUS 44 | 45 | --*/ 46 | { 47 | PDokanVCB vcb; 48 | PIO_STACK_LOCATION irpSp; 49 | NTSTATUS status = STATUS_INVALID_PARAMETER; 50 | PFILE_OBJECT fileObject; 51 | PDokanCCB ccb = NULL; 52 | PDokanFCB fcb = NULL; 53 | PEVENT_CONTEXT eventContext; 54 | ULONG eventLength; 55 | 56 | //PAGED_CODE(); 57 | 58 | __try { 59 | 60 | FsRtlEnterFileSystem(); 61 | 62 | DDbgPrint("==> DokanCleanup"); 63 | 64 | irpSp = IoGetCurrentIrpStackLocation(Irp); 65 | fileObject = irpSp->FileObject; 66 | 67 | DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); 68 | DokanPrintFileName(fileObject); 69 | 70 | // Cleanup must be success in any case 71 | if (fileObject == NULL) { 72 | DDbgPrint(" fileObject == NULL"); 73 | status = STATUS_SUCCESS; 74 | __leave; 75 | } 76 | 77 | vcb = DeviceObject->DeviceExtension; 78 | if (GetIdentifierType(vcb) != VCB || 79 | !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { 80 | status = STATUS_SUCCESS; 81 | __leave; 82 | } 83 | 84 | ccb = fileObject->FsContext2; 85 | ASSERT(ccb != NULL); 86 | 87 | fcb = ccb->Fcb; 88 | ASSERT(fcb != NULL); 89 | 90 | eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; 91 | eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); 92 | 93 | if (eventContext == NULL) { 94 | status = STATUS_INSUFFICIENT_RESOURCES; 95 | __leave; 96 | } 97 | 98 | if (fileObject->SectionObjectPointer != NULL && 99 | fileObject->SectionObjectPointer->DataSectionObject != NULL) { 100 | CcFlushCache(&fcb->SectionObjectPointers, NULL, 0, NULL); 101 | CcPurgeCacheSection(&fcb->SectionObjectPointers, NULL, 0, FALSE); 102 | CcUninitializeCacheMap(fileObject, NULL, NULL); 103 | } 104 | fileObject->Flags |= FO_CLEANUP_COMPLETE; 105 | 106 | eventContext->Context = ccb->UserContext; 107 | //DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); 108 | 109 | // copy the filename to EventContext from ccb 110 | eventContext->Cleanup.FileNameLength = fcb->FileName.Length; 111 | RtlCopyMemory(eventContext->Cleanup.FileName, fcb->FileName.Buffer, fcb->FileName.Length); 112 | 113 | // register this IRP to pending IRP list 114 | status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); 115 | 116 | } __finally { 117 | 118 | if (status != STATUS_PENDING) { 119 | Irp->IoStatus.Status = status; 120 | Irp->IoStatus.Information = 0; 121 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 122 | DokanPrintNTStatus(status); 123 | } 124 | 125 | DDbgPrint("<== DokanCleanup"); 126 | 127 | FsRtlExitFileSystem(); 128 | } 129 | 130 | return status; 131 | } 132 | 133 | 134 | 135 | VOID 136 | DokanCompleteCleanup( 137 | __in PIRP_ENTRY IrpEntry, 138 | __in PEVENT_INFORMATION EventInfo 139 | ) 140 | { 141 | PIRP irp; 142 | PIO_STACK_LOCATION irpSp; 143 | NTSTATUS status = STATUS_SUCCESS; 144 | ULONG info = 0; 145 | PDokanCCB ccb; 146 | PDokanFCB fcb; 147 | PDokanVCB vcb; 148 | PFILE_OBJECT fileObject; 149 | 150 | DDbgPrint("==> DokanCompleteCleanup"); 151 | 152 | irp = IrpEntry->Irp; 153 | irpSp = IrpEntry->IrpSp; 154 | 155 | fileObject = IrpEntry->FileObject; 156 | ASSERT(fileObject != NULL); 157 | 158 | ccb = fileObject->FsContext2; 159 | ASSERT(ccb != NULL); 160 | 161 | ccb->UserContext = EventInfo->Context; 162 | //DDbgPrint(" set Context %X\n", (ULONG)ccb->UserContext); 163 | 164 | fcb = ccb->Fcb; 165 | ASSERT(fcb != NULL); 166 | 167 | vcb = fcb->Vcb; 168 | 169 | status = EventInfo->Status; 170 | 171 | if (fcb->Flags & DOKAN_FILE_DIRECTORY) { 172 | FsRtlNotifyCleanup(vcb->NotifySync, &vcb->DirNotifyList, ccb); 173 | } 174 | 175 | irp->IoStatus.Status = status; 176 | irp->IoStatus.Information = 0; 177 | IoCompleteRequest(irp, IO_NO_INCREMENT); 178 | 179 | DDbgPrint("<== DokanCompleteCleanup"); 180 | } 181 | 182 | 183 | -------------------------------------------------------------------------------- /sys/close.c: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | #include "precomp.h" 21 | #pragma hdrstop 22 | 23 | 24 | NTSTATUS 25 | DokanDispatchClose( 26 | __in PDEVICE_OBJECT DeviceObject, 27 | __in PIRP Irp 28 | ) 29 | 30 | /*++ 31 | 32 | Routine Description: 33 | 34 | This device control dispatcher handles create & close IRPs. 35 | 36 | Arguments: 37 | 38 | DeviceObject - Context for the activity. 39 | Irp - The device control argument block. 40 | 41 | Return Value: 42 | 43 | NTSTATUS 44 | 45 | --*/ 46 | { 47 | PDokanVCB vcb; 48 | PIO_STACK_LOCATION irpSp; 49 | NTSTATUS status = STATUS_INVALID_PARAMETER; 50 | PFILE_OBJECT fileObject; 51 | PDokanCCB ccb; 52 | PEVENT_CONTEXT eventContext; 53 | ULONG eventLength; 54 | PDokanFCB fcb; 55 | 56 | //PAGED_CODE(); 57 | 58 | __try { 59 | 60 | FsRtlEnterFileSystem(); 61 | 62 | DDbgPrint("==> DokanClose"); 63 | 64 | irpSp = IoGetCurrentIrpStackLocation(Irp); 65 | fileObject = irpSp->FileObject; 66 | 67 | if (fileObject == NULL) { 68 | DDbgPrint(" fileObject is NULL"); 69 | status = STATUS_SUCCESS; 70 | __leave; 71 | } 72 | 73 | DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); 74 | DokanPrintFileName(fileObject); 75 | 76 | vcb = DeviceObject->DeviceExtension; 77 | 78 | if (GetIdentifierType(vcb) != VCB || 79 | !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { 80 | 81 | if (fileObject->FsContext2) { 82 | ccb = fileObject->FsContext2; 83 | ASSERT(ccb != NULL); 84 | 85 | fcb = ccb->Fcb; 86 | ASSERT(fcb != NULL); 87 | 88 | DDbgPrint(" Free CCB:%X\n", ccb); 89 | DokanFreeCCB(ccb); 90 | 91 | DokanFreeFCB(fcb); 92 | } 93 | 94 | status = STATUS_SUCCESS; 95 | __leave; 96 | } 97 | 98 | ccb = fileObject->FsContext2; 99 | ASSERT(ccb != NULL); 100 | 101 | fcb = ccb->Fcb; 102 | ASSERT(fcb != NULL); 103 | 104 | eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; 105 | eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); 106 | 107 | if (eventContext == NULL) { 108 | //status = STATUS_INSUFFICIENT_RESOURCES; 109 | DDbgPrint(" eventContext == NULL"); 110 | DDbgPrint(" Free CCB:%X\n", ccb); 111 | DokanFreeCCB(ccb); 112 | DokanFreeFCB(fcb); 113 | status = STATUS_SUCCESS; 114 | __leave; 115 | } 116 | 117 | eventContext->Context = ccb->UserContext; 118 | DDbgPrint(" UserContext:%X\n", (ULONG)ccb->UserContext); 119 | 120 | // copy the file name to be closed 121 | eventContext->Close.FileNameLength = fcb->FileName.Length; 122 | RtlCopyMemory(eventContext->Close.FileName, fcb->FileName.Buffer, fcb->FileName.Length); 123 | 124 | DDbgPrint(" Free CCB:%X\n", ccb); 125 | DokanFreeCCB(ccb); 126 | 127 | DokanFreeFCB(fcb); 128 | 129 | // Close can not be pending status 130 | // don't register this IRP 131 | //status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext->SerialNumber, 0); 132 | 133 | // inform it to user-mode 134 | DokanEventNotification(&vcb->Dcb->NotifyEvent, eventContext); 135 | 136 | status = STATUS_SUCCESS; 137 | 138 | } __finally { 139 | 140 | if (status != STATUS_PENDING) { 141 | Irp->IoStatus.Status = status; 142 | Irp->IoStatus.Information = 0; 143 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 144 | } 145 | 146 | DDbgPrint("<== DokanClose"); 147 | 148 | FsRtlExitFileSystem(); 149 | } 150 | 151 | return status; 152 | } 153 | 154 | -------------------------------------------------------------------------------- /sys/dokan.rc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define VER_FILETYPE VFT_DRV 5 | #define VER_FILESUBTYPE VFT2_DRV_SYSTEM 6 | #define VER_FILEDESCRIPTION_STR "DokanX Filesystem Driver" 7 | #define VER_INTERNALNAME_STR "dokanx.sys" 8 | #define VER_ORIGINALFILENAME_STR "dokanx.sys" 9 | 10 | #define VER_FILEVERSION_STR "1.0.0.0" 11 | 12 | //#define VER_COMPANYNAME_STR "DokanX" 13 | //#define VER_FILEDESCRIPTION_STR "DokanX" 14 | //#define VER_LEGALCOPYRIGHT_STR "" 15 | //#define VER_PRODUCTNAME_STR "dokanx" 16 | //#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR 17 | 18 | #ifdef VER_PRODUCTVERSION 19 | #undef VER_PRODUCTVERSION 20 | #endif 21 | #define VER_PRODUCTVERSION 1, 0, 0,0 22 | #include "common.ver" -------------------------------------------------------------------------------- /sys/flush.c: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | #include "precomp.h" 21 | #pragma hdrstop 22 | 23 | 24 | NTSTATUS 25 | DokanDispatchFlush( 26 | __in PDEVICE_OBJECT DeviceObject, 27 | __in PIRP Irp 28 | ) 29 | { 30 | PIO_STACK_LOCATION irpSp; 31 | PFILE_OBJECT fileObject; 32 | PVOID buffer; 33 | NTSTATUS status = STATUS_INVALID_PARAMETER; 34 | PDokanFCB fcb; 35 | PDokanCCB ccb; 36 | PDokanVCB vcb; 37 | PEVENT_CONTEXT eventContext; 38 | ULONG eventLength; 39 | 40 | //PAGED_CODE(); 41 | 42 | __try { 43 | FsRtlEnterFileSystem(); 44 | 45 | DDbgPrint("==> DokanFlush"); 46 | 47 | irpSp = IoGetCurrentIrpStackLocation(Irp); 48 | fileObject = irpSp->FileObject; 49 | 50 | if (fileObject == NULL) { 51 | DDbgPrint(" fileObject == NULL"); 52 | status = STATUS_SUCCESS; 53 | __leave; 54 | } 55 | 56 | vcb = DeviceObject->DeviceExtension; 57 | if (GetIdentifierType(vcb) != VCB || 58 | !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { 59 | status = STATUS_SUCCESS; 60 | __leave; 61 | } 62 | 63 | 64 | DokanPrintFileName(fileObject); 65 | 66 | ccb = fileObject->FsContext2; 67 | ASSERT(ccb != NULL); 68 | 69 | fcb = ccb->Fcb; 70 | ASSERT(fcb != NULL); 71 | 72 | eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; 73 | eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); 74 | 75 | if (eventContext == NULL) { 76 | status = STATUS_INSUFFICIENT_RESOURCES; 77 | __leave; 78 | } 79 | 80 | eventContext->Context = ccb->UserContext; 81 | DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); 82 | 83 | // copy file name to be flushed 84 | eventContext->Flush.FileNameLength = fcb->FileName.Length; 85 | RtlCopyMemory(eventContext->Flush.FileName, fcb->FileName.Buffer, fcb->FileName.Length); 86 | 87 | CcUninitializeCacheMap(fileObject, NULL, NULL); 88 | //fileObject->Flags &= FO_CLEANUP_COMPLETE; 89 | 90 | // register this IRP to waiting IRP list and make it pending status 91 | status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); 92 | 93 | } __finally { 94 | 95 | // if status is not pending, must complete current IRPs 96 | if (status != STATUS_PENDING) { 97 | Irp->IoStatus.Status = status; 98 | Irp->IoStatus.Information = 0; 99 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 100 | DokanPrintNTStatus(status); 101 | } else { 102 | DDbgPrint(" STATUS_PENDING"); 103 | } 104 | 105 | DDbgPrint("<== DokanFlush"); 106 | 107 | FsRtlExitFileSystem(); 108 | } 109 | 110 | return status; 111 | } 112 | 113 | 114 | VOID 115 | DokanCompleteFlush( 116 | __in PIRP_ENTRY IrpEntry, 117 | __in PEVENT_INFORMATION EventInfo 118 | ) 119 | { 120 | PIRP irp; 121 | PIO_STACK_LOCATION irpSp; 122 | NTSTATUS status = STATUS_SUCCESS; 123 | ULONG info = 0; 124 | PDokanCCB ccb; 125 | PDokanFCB fcb; 126 | PFILE_OBJECT fileObject; 127 | 128 | irp = IrpEntry->Irp; 129 | irpSp = IrpEntry->IrpSp; 130 | 131 | //FsRtlEnterFileSystem(); 132 | 133 | DDbgPrint("==> DokanCompleteFlush"); 134 | 135 | fileObject = irpSp->FileObject; 136 | ccb = fileObject->FsContext2; 137 | ASSERT(ccb != NULL); 138 | 139 | ccb->UserContext = EventInfo->Context; 140 | DDbgPrint(" set Context %X\n", (ULONG)ccb->UserContext); 141 | 142 | status = EventInfo->Status; 143 | 144 | irp->IoStatus.Status = status; 145 | irp->IoStatus.Information = 0; 146 | 147 | IoCompleteRequest(irp, IO_NO_INCREMENT); 148 | 149 | DokanPrintNTStatus(status); 150 | 151 | DDbgPrint("<== DokanCompleteFlush"); 152 | 153 | //FsRtlExitFileSystem(); 154 | 155 | } 156 | 157 | -------------------------------------------------------------------------------- /sys/howtobuild.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenjaminKim/dokanx/88b8e764981508f6a9e75cfc93a9b679474f3c7f/sys/howtobuild.txt -------------------------------------------------------------------------------- /sys/lock.c: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | #include "precomp.h" 21 | #pragma hdrstop 22 | 23 | #include "dokan.h" 24 | 25 | 26 | NTSTATUS 27 | DokanDispatchLock( 28 | __in PDEVICE_OBJECT DeviceObject, 29 | __in PIRP Irp 30 | ) 31 | { 32 | PIO_STACK_LOCATION irpSp; 33 | NTSTATUS status = STATUS_INVALID_PARAMETER; 34 | PFILE_OBJECT fileObject; 35 | PDokanCCB ccb; 36 | PDokanFCB fcb; 37 | PDokanVCB vcb; 38 | PEVENT_CONTEXT eventContext; 39 | ULONG eventLength; 40 | 41 | //PAGED_CODE(); 42 | 43 | __try { 44 | FsRtlEnterFileSystem(); 45 | 46 | DDbgPrint("==> DokanLock"); 47 | 48 | irpSp = IoGetCurrentIrpStackLocation(Irp); 49 | fileObject = irpSp->FileObject; 50 | 51 | if (fileObject == NULL) { 52 | DDbgPrint(" fileObject == NULL"); 53 | status = STATUS_INVALID_PARAMETER; 54 | __leave; 55 | } 56 | 57 | vcb = DeviceObject->DeviceExtension; 58 | if (GetIdentifierType(vcb) != VCB || 59 | !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { 60 | status = STATUS_INVALID_PARAMETER; 61 | __leave; 62 | } 63 | 64 | DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); 65 | DokanPrintFileName(fileObject); 66 | 67 | switch(irpSp->MinorFunction) { 68 | case IRP_MN_LOCK: 69 | DDbgPrint(" IRP_MN_LOCK"); 70 | break; 71 | case IRP_MN_UNLOCK_ALL: 72 | DDbgPrint(" IRP_MN_UNLOCK_ALL"); 73 | break; 74 | case IRP_MN_UNLOCK_ALL_BY_KEY: 75 | DDbgPrint(" IRP_MN_UNLOCK_ALL_BY_KEY"); 76 | break; 77 | case IRP_MN_UNLOCK_SINGLE: 78 | DDbgPrint(" IRP_MN_UNLOCK_SINGLE"); 79 | break; 80 | default: 81 | DDbgPrint(" unknown function : %d\n", irpSp->MinorFunction); 82 | break; 83 | } 84 | 85 | ccb = fileObject->FsContext2; 86 | ASSERT(ccb != NULL); 87 | 88 | fcb = ccb->Fcb; 89 | ASSERT(fcb != NULL); 90 | 91 | eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length; 92 | eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb); 93 | 94 | if (eventContext == NULL) { 95 | status = STATUS_INSUFFICIENT_RESOURCES; 96 | __leave; 97 | } 98 | 99 | eventContext->Context = ccb->UserContext; 100 | DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); 101 | 102 | // copy file name to be locked 103 | eventContext->Lock.FileNameLength = fcb->FileName.Length; 104 | RtlCopyMemory(eventContext->Lock.FileName, fcb->FileName.Buffer, fcb->FileName.Length); 105 | 106 | // parameters of Lock 107 | eventContext->Lock.ByteOffset = irpSp->Parameters.LockControl.ByteOffset; 108 | if (irpSp->Parameters.LockControl.Length != NULL) { 109 | eventContext->Lock.Length.QuadPart = irpSp->Parameters.LockControl.Length->QuadPart; 110 | } else { 111 | DDbgPrint(" LockControl.Length = NULL"); 112 | } 113 | eventContext->Lock.Key = irpSp->Parameters.LockControl.Key; 114 | 115 | // register this IRP to waiting IRP list and make it pending status 116 | status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); 117 | 118 | } __finally { 119 | 120 | if (status != STATUS_PENDING) { 121 | // 122 | // complete the Irp 123 | // 124 | Irp->IoStatus.Status = status; 125 | Irp->IoStatus.Information = 0; 126 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 127 | DokanPrintNTStatus(status); 128 | } 129 | 130 | DDbgPrint("<== DokanLock"); 131 | FsRtlExitFileSystem(); 132 | } 133 | 134 | return status; 135 | } 136 | 137 | 138 | VOID 139 | DokanCompleteLock( 140 | __in PIRP_ENTRY IrpEntry, 141 | __in PEVENT_INFORMATION EventInfo 142 | ) 143 | { 144 | PIRP irp; 145 | PIO_STACK_LOCATION irpSp; 146 | PDokanCCB ccb; 147 | PFILE_OBJECT fileObject; 148 | NTSTATUS status; 149 | 150 | irp = IrpEntry->Irp; 151 | irpSp = IrpEntry->IrpSp; 152 | 153 | //FsRtlEnterFileSystem(); 154 | 155 | DDbgPrint("==> DokanCompleteLock"); 156 | 157 | fileObject = irpSp->FileObject; 158 | ccb = fileObject->FsContext2; 159 | ASSERT(ccb != NULL); 160 | 161 | ccb->UserContext = EventInfo->Context; 162 | // DDbgPrint(" set Context %X\n", (ULONG)ccb->UserContext); 163 | 164 | status = EventInfo->Status; 165 | irp->IoStatus.Status = status; 166 | irp->IoStatus.Information = 0; 167 | IoCompleteRequest(irp, IO_NO_INCREMENT); 168 | 169 | DokanPrintNTStatus(status); 170 | 171 | DDbgPrint("<== DokanCompleteLock"); 172 | 173 | //FsRtlExitFileSystem(); 174 | } 175 | -------------------------------------------------------------------------------- /sys/makefile: -------------------------------------------------------------------------------- 1 | # 2 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 3 | # file to this component. This file merely indirects to the real make file 4 | # that is shared by all the driver components of the Windows NT DDK 5 | # 6 | 7 | !INCLUDE $(NTMAKEENV)\makefile.def 8 | 9 | -------------------------------------------------------------------------------- /sys/precomp.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define _DOKAN_SYS 4 | #include "dokan.h" 5 | 6 | /* 7 | When the compiler sees a line like this: 8 | chMSG(Fix this later); 9 | 10 | it outputs a line like this: 11 | 12 | c:\CD\CmnHdr.h(82):Fix this later 13 | 14 | You can easily jump directly to this line and examine the surrounding code. 15 | */ 16 | 17 | #define chSTR2(x) #x 18 | #define chSTR(x) chSTR2(x) 19 | 20 | #define chMSG(desc) message(__FILE__ "("chSTR(__LINE__)"): --------" #desc "--------") 21 | #define chFixLater message(__FILE__ "("chSTR(__LINE__)"): Fix this later") 22 | 23 | #define FixLater \ 24 | do { \ 25 | __pragma(chFixLater) \ 26 | __pragma (warning(push)) \ 27 | __pragma (warning(disable:4127)) \ 28 | } while(0) \ 29 | __pragma (warning(pop)) 30 | 31 | #define MSG(desc) \ 32 | do { \ 33 | __pragma(chMSG(desc)) \ 34 | __pragma (warning(push)) \ 35 | __pragma (warning(disable:4127)) \ 36 | } while(0) \ 37 | __pragma (warning(pop)) 38 | 39 | //#define _LOG_ENABLED -------------------------------------------------------------------------------- /sys/sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=dokanx 2 | TARGETTYPE=DRIVER 3 | 4 | TARGETLIBS= \ 5 | $(DDK_LIB_PATH)\wdmsec.lib 6 | 7 | LINKER_FLAGS=$(LINKER_FLAGS) -MAP 8 | 9 | SOURCES=dokan.c \ 10 | init.c \ 11 | create.c \ 12 | close.c \ 13 | event.c \ 14 | directory.c \ 15 | fileinfo.c \ 16 | read.c \ 17 | write.c \ 18 | volume.c \ 19 | cleanup.c \ 20 | lock.c \ 21 | timeout.c \ 22 | flush.c \ 23 | device.c \ 24 | fscontrol.c \ 25 | notification.c \ 26 | security.c \ 27 | access.c \ 28 | dokan.rc 29 | 30 | PRECOMPILED_INCLUDE=precomp.h 31 | PRECOMPILED_OBJ=precomp.obj -------------------------------------------------------------------------------- /sys/sys.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 6 | h;hpp;hxx;hm;inl;inc;xsd 7 | 8 | 9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 10 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files 71 | 72 | 73 | Source Files 74 | 75 | 76 | 77 | 78 | Source Files 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | Header Files 89 | 90 | 91 | 92 | 93 | Resources 94 | 95 | 96 | -------------------------------------------------------------------------------- /sys/volume.c: -------------------------------------------------------------------------------- 1 | /* 2 | Dokan : user-mode file system library for Windows 3 | 4 | Copyright (C) 2008 Hiroki Asakawa info@dokan-dev.net 5 | 6 | http://dokan-dev.net/en 7 | 8 | This program is free software; you can redistribute it and/or modify it under 9 | the terms of the GNU Lesser General Public License as published by the Free 10 | Software Foundation; either version 3 of the License, or (at your option) any 11 | later version. 12 | 13 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public License along 18 | with this program. If not, see . 19 | */ 20 | #include "precomp.h" 21 | #pragma hdrstop 22 | 23 | #include "dokan.h" 24 | 25 | 26 | NTSTATUS 27 | DokanDispatchQueryVolumeInformation( 28 | __in PDEVICE_OBJECT DeviceObject, 29 | __in PIRP Irp 30 | ) 31 | { 32 | NTSTATUS status = STATUS_INVALID_PARAMETER; 33 | PIO_STACK_LOCATION irpSp; 34 | PVOID buffer; 35 | PFILE_OBJECT fileObject; 36 | PDokanVCB vcb; 37 | PDokanDCB dcb; 38 | PDokanCCB ccb; 39 | ULONG info = 0; 40 | 41 | //PAGED_CODE(); 42 | 43 | __try { 44 | 45 | FsRtlEnterFileSystem(); 46 | 47 | DDbgPrint("==> DokanQueryVolumeInformation"); 48 | DDbgPrint(" ProcessId %lu\n", IoGetRequestorProcessId(Irp)); 49 | 50 | vcb = DeviceObject->DeviceExtension; 51 | if (GetIdentifierType(vcb) != VCB) { 52 | return STATUS_INVALID_PARAMETER; 53 | } 54 | dcb = vcb->Dcb; 55 | 56 | irpSp = IoGetCurrentIrpStackLocation(Irp); 57 | buffer = Irp->AssociatedIrp.SystemBuffer; 58 | 59 | fileObject = irpSp->FileObject; 60 | 61 | if (fileObject == NULL) { 62 | DDbgPrint(" fileObject == NULL"); 63 | status = STATUS_INVALID_PARAMETER; 64 | __leave; 65 | } 66 | 67 | 68 | DDbgPrint(" FileName: %wZ\n", &fileObject->FileName); 69 | 70 | ccb = fileObject->FsContext2; 71 | 72 | // ASSERT(ccb != NULL); 73 | 74 | switch(irpSp->Parameters.QueryVolume.FsInformationClass) { 75 | case FileFsVolumeInformation: 76 | DDbgPrint(" FileFsVolumeInformation"); 77 | break; 78 | 79 | case FileFsLabelInformation: 80 | DDbgPrint(" FileFsLabelInformation"); 81 | break; 82 | 83 | case FileFsSizeInformation: 84 | DDbgPrint(" FileFsSizeInformation"); 85 | break; 86 | 87 | case FileFsDeviceInformation: 88 | { 89 | PFILE_FS_DEVICE_INFORMATION device; 90 | DDbgPrint(" FileFsDeviceInformation"); 91 | device = (PFILE_FS_DEVICE_INFORMATION)Irp->AssociatedIrp.SystemBuffer; 92 | if (irpSp->Parameters.QueryVolume.Length < sizeof(FILE_FS_DEVICE_INFORMATION)) { 93 | status = STATUS_BUFFER_TOO_SMALL; 94 | info = sizeof(FILE_FS_DEVICE_INFORMATION); 95 | __leave; 96 | } 97 | device->DeviceType = FILE_DEVICE_DISK;//dcb->DeviceType; 98 | device->Characteristics = dcb->DeviceCharacteristics; 99 | status = STATUS_SUCCESS; 100 | info = sizeof(FILE_FS_DEVICE_INFORMATION); 101 | __leave; 102 | } 103 | break; 104 | 105 | case FileFsAttributeInformation: 106 | DDbgPrint(" FileFsAttributeInformation"); 107 | break; 108 | 109 | case FileFsControlInformation: 110 | DDbgPrint(" FileFsControlInformation"); 111 | break; 112 | 113 | case FileFsFullSizeInformation: 114 | DDbgPrint(" FileFsFullSizeInformation"); 115 | break; 116 | case FileFsObjectIdInformation: 117 | DDbgPrint(" FileFsObjectIdInformation"); 118 | break; 119 | 120 | case FileFsMaximumInformation: 121 | DDbgPrint(" FileFsMaximumInformation"); 122 | break; 123 | 124 | default: 125 | break; 126 | } 127 | 128 | 129 | if (irpSp->Parameters.QueryVolume.FsInformationClass == FileFsVolumeInformation 130 | || irpSp->Parameters.QueryVolume.FsInformationClass == FileFsSizeInformation 131 | || irpSp->Parameters.QueryVolume.FsInformationClass == FileFsAttributeInformation 132 | || irpSp->Parameters.QueryVolume.FsInformationClass == FileFsFullSizeInformation) { 133 | 134 | 135 | ULONG eventLength = sizeof(EVENT_CONTEXT); 136 | PEVENT_CONTEXT eventContext; 137 | 138 | if (ccb && !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) { 139 | status = STATUS_INVALID_PARAMETER; 140 | __leave; 141 | } 142 | 143 | // this memory must be freed in this {} 144 | eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, NULL); 145 | 146 | if (eventContext == NULL) { 147 | status = STATUS_INSUFFICIENT_RESOURCES; 148 | __leave; 149 | } 150 | 151 | if (ccb) { 152 | eventContext->Context = ccb->UserContext; 153 | eventContext->FileFlags = ccb->Flags; 154 | //DDbgPrint(" get Context %X\n", (ULONG)ccb->UserContext); 155 | } 156 | 157 | eventContext->Volume.FsInformationClass = 158 | irpSp->Parameters.QueryVolume.FsInformationClass; 159 | 160 | // the length which can be returned to user-mode 161 | eventContext->Volume.BufferLength = irpSp->Parameters.QueryVolume.Length; 162 | 163 | 164 | status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0); 165 | } 166 | 167 | } __finally { 168 | 169 | if (status != STATUS_PENDING) { 170 | Irp->IoStatus.Status = status; 171 | Irp->IoStatus.Information = info; 172 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 173 | DokanPrintNTStatus(status); 174 | } 175 | 176 | DDbgPrint("<== DokanQueryVolumeInformation"); 177 | 178 | FsRtlExitFileSystem(); 179 | } 180 | 181 | return status; 182 | } 183 | 184 | 185 | VOID 186 | DokanCompleteQueryVolumeInformation( 187 | __in PIRP_ENTRY IrpEntry, 188 | __in PEVENT_INFORMATION EventInfo 189 | ) 190 | { 191 | PIRP irp; 192 | PIO_STACK_LOCATION irpSp; 193 | NTSTATUS status = STATUS_SUCCESS; 194 | ULONG info = 0; 195 | ULONG bufferLen= 0; 196 | PVOID buffer = NULL; 197 | PDokanCCB ccb; 198 | 199 | //FsRtlEnterFileSystem(); 200 | 201 | DDbgPrint("==> DokanCompleteQueryVolumeInformation"); 202 | 203 | irp = IrpEntry->Irp; 204 | irpSp = IrpEntry->IrpSp; 205 | 206 | ccb = IrpEntry->FileObject->FsContext2; 207 | 208 | //ASSERT(ccb != NULL); 209 | 210 | // does not save Context!! 211 | // ccb->UserContext = EventInfo->Context; 212 | 213 | // buffer which is used to copy VolumeInfo 214 | buffer = irp->AssociatedIrp.SystemBuffer; 215 | 216 | // available buffer size to inform 217 | bufferLen = irpSp->Parameters.QueryVolume.Length; 218 | 219 | // if buffer is invalid or short of length 220 | if (bufferLen == 0 || buffer == NULL || bufferLen < EventInfo->BufferLength) { 221 | 222 | info = 0; 223 | status = STATUS_INSUFFICIENT_RESOURCES; 224 | 225 | } else { 226 | 227 | // copy the information from user-mode to specified buffer 228 | ASSERT(buffer != NULL); 229 | 230 | RtlZeroMemory(buffer, bufferLen); 231 | RtlCopyMemory(buffer, EventInfo->Buffer, EventInfo->BufferLength); 232 | 233 | // the written length 234 | info = EventInfo->BufferLength; 235 | 236 | status = EventInfo->Status; 237 | } 238 | 239 | 240 | irp->IoStatus.Status = status; 241 | irp->IoStatus.Information = info; 242 | IoCompleteRequest(irp, IO_NO_INCREMENT); 243 | 244 | DokanPrintNTStatus(status); 245 | DDbgPrint("<== DokanCompleteQueryVolumeInformation"); 246 | 247 | //FsRtlExitFileSystem(); 248 | } 249 | 250 | 251 | 252 | NTSTATUS 253 | DokanDispatchSetVolumeInformation( 254 | __in PDEVICE_OBJECT DeviceObject, 255 | __in PIRP Irp 256 | ) 257 | { 258 | NTSTATUS status = STATUS_INVALID_PARAMETER; 259 | 260 | //PAGED_CODE(); 261 | 262 | //FsRtlEnterFileSystem(); 263 | 264 | DDbgPrint("==> DokanSetVolumeInformation"); 265 | 266 | Irp->IoStatus.Status = status; 267 | Irp->IoStatus.Information = 0; 268 | IoCompleteRequest(Irp, IO_NO_INCREMENT); 269 | 270 | DDbgPrint("<== DokanSetVolumeInformation"); 271 | 272 | //FsRtlExitFileSystem(); 273 | 274 | return status; 275 | } 276 | 277 | --------------------------------------------------------------------------------