int CheckMountPoint(LPCWSTR MountPoint) { size_t length = wcslen(MountPoint); if ((length == 1) || (length == 2 && MountPoint[1] == L':') || (length == 3 && MountPoint[1] == L':' && MountPoint[2] == L'\\')) { WCHAR driveLetter = MountPoint[0]; if (IsValidDriveLetter(driveLetter)) { return DOKAN_SUCCESS; } else { DokanDbgPrintW(L"Dokan Error: bad drive letter %s\n", MountPoint); return DOKAN_DRIVE_LETTER_ERROR; } } else if (length > 3) { HANDLE handle = CreateFile( MountPoint, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (handle == INVALID_HANDLE_VALUE) { DokanDbgPrintW(L"Dokan Error: bad mount point %s\n", MountPoint); return DOKAN_MOUNT_POINT_ERROR; } CloseHandle(handle); return DOKAN_SUCCESS; } return DOKAN_MOUNT_POINT_ERROR; }
BOOL CreateDriveLetter(WCHAR DriveLetter, LPCWSTR DeviceName) { WCHAR dosDevice[] = L"\\\\.\\C:"; WCHAR driveName[] = L"C:"; WCHAR rawDeviceName[MAX_PATH] = L"\\Device"; HANDLE device; dosDevice[4] = DriveLetter; driveName[0] = DriveLetter; wcscat_s(rawDeviceName, MAX_PATH, DeviceName); DokanDbgPrintW(L"DriveLetter: %c, DeviceName %s\n", DriveLetter, rawDeviceName); device = CreateFile( dosDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device != INVALID_HANDLE_VALUE) { DokanDbgPrintW(L"DokanControl Mount failed: %c: is alredy used\n", DriveLetter); CloseHandle(device); return FALSE; } if (!DefineDosDevice(DDD_RAW_TARGET_PATH, driveName, rawDeviceName)) { DokanDbgPrintW(L"DokanControl DefineDosDevice failed: %d\n", GetLastError()); return FALSE; } device = CreateFile( dosDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL ); if (device == INVALID_HANDLE_VALUE) { DokanDbgPrintW(L"DokanControl Mount %c failed:%d\n", DriveLetter, GetLastError()); DefineDosDevice(DDD_REMOVE_DEFINITION, dosDevice, NULL); return FALSE; } CloseHandle(device); return TRUE; }
static BOOL DokanServiceCheck(LPCWSTR ServiceName) { SC_HANDLE controlHandle; SC_HANDLE serviceHandle; controlHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (controlHandle == NULL) { DbgPrint("DokanServiceCheck: Failed to open Service Control Manager. error " "= %d\n", GetLastError()); return FALSE; } serviceHandle = OpenService(controlHandle, ServiceName, SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS); if (serviceHandle == NULL) { DokanDbgPrintW( L"DokanServiceCheck: Failed to open Service (%s). error = %d\n", ServiceName, GetLastError()); CloseServiceHandle(controlHandle); return FALSE; } CloseServiceHandle(serviceHandle); CloseServiceHandle(controlHandle); return TRUE; }
BOOL DOKANAPI DokanServiceInstall(LPCWSTR ServiceName, DWORD ServiceType, LPCWSTR ServiceFullPath) { SC_HANDLE controlHandle; SC_HANDLE serviceHandle; controlHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (controlHandle == NULL) { DokanDbgPrint("DokanServiceInstall: Failed to open Service Control " "Manager. error = %d\n", GetLastError()); return FALSE; } serviceHandle = CreateService(controlHandle, ServiceName, ServiceName, 0, ServiceType, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, ServiceFullPath, NULL, NULL, NULL, NULL, NULL); if (serviceHandle == NULL) { BOOL error = GetLastError(); if (error == ERROR_SERVICE_EXISTS) { DokanDbgPrintW( L"DokanServiceInstall: Service (%s) is already installed\n", ServiceName); } else { DokanDbgPrintW( L"DokanServiceInstall: Failed to install service (%s). error = %d\n", ServiceName, error); } CloseServiceHandle(controlHandle); return FALSE; } CloseServiceHandle(serviceHandle); CloseServiceHandle(controlHandle); DokanDbgPrintW(L"DokanServiceInstall: Service (%s) installed\n", ServiceName); if (DokanServiceControl(ServiceName, DOKAN_SERVICE_START)) { DokanDbgPrintW(L"DokanServiceInstall: Service (%s) started\n", ServiceName); return TRUE; } else { DokanDbgPrintW(L"DokanServiceInstall: Service (%s) start failed\n", ServiceName); return FALSE; } }
static BOOL CheckMount(WCHAR drive) { HANDLE pipe; DWORD readBytes; DWORD pipeMode; DOKAN_CONTROL control; ZeroMemory(&control, sizeof(DOKAN_CONTROL)); control.Type = DOKAN_CONTROL_CHECK; control.Check.Drive = drive; DokanDbgPrintW(L"CheckMount Drive: %c\n", drive); pipe = CreateFile(DOKAN_CONTROL_PIPE, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (pipe == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_ACCESS_DENIED) { DokanDbgPrintW(L"failed to connect DokanMounter service: access denied\n"); } else { DokanDbgPrintW(L"failed to connect DokanMounter service: %d\n", GetLastError()); } return FALSE; } pipeMode = PIPE_READMODE_MESSAGE|PIPE_WAIT; if(!SetNamedPipeHandleState(pipe, &pipeMode, NULL, NULL)) { DokanDbgPrintW(L"failed to set named pipe state\n"); return FALSE; } if(!TransactNamedPipe(pipe, &control, sizeof(DOKAN_CONTROL), &control, sizeof(DOKAN_CONTROL), &readBytes, NULL)) { DokanDbgPrintW(L"failed to transact named pipe\n"); } if(control.Status != DOKAN_CONTROL_FAIL) return TRUE; else return FALSE; }
static BOOL CheckMount2(LPCWSTR FileName) { std::wstring file = std::wstring(FileName) + L":SSHFSProperty.Permission"; DokanDbgPrintW(L"Check SSHFS file %s\n", file.c_str()); HANDLE handle = CreateFile( file.c_str(), FILE_GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (handle == INVALID_HANDLE_VALUE) { return FALSE; } CloseHandle(handle); return TRUE; }
int DOKANAPI DokanMain(PDOKAN_OPTIONS DokanOptions, PDOKAN_OPERATIONS DokanOperations) { ULONG threadNum = 0; ULONG i; int error; HANDLE device; HANDLE threadIds[DOKAN_MAX_THREAD]; BOOL useMountPoint = FALSE; PDOKAN_INSTANCE instance; g_DebugMode = DokanOptions->Options & DOKAN_OPTION_DEBUG; g_UseStdErr = DokanOptions->Options & DOKAN_OPTION_STDERR; if (g_DebugMode) { DbgPrintW(L"Dokan: debug mode on\n"); } if (g_UseStdErr) { DbgPrintW(L"Dokan: use stderr\n"); g_DebugMode = TRUE; } if (DokanOptions->ThreadCount == 0) { DokanOptions->ThreadCount = 5; } else if ((DOKAN_MAX_THREAD - 1) < DokanOptions->ThreadCount) { // DOKAN_MAX_THREAD includes DokanKeepAlive thread, so // available thread is DOKAN_MAX_THREAD -1 DokanDbgPrintW(L"Dokan Error: too many thread count %d\n", DokanOptions->ThreadCount); DokanOptions->ThreadCount = DOKAN_MAX_THREAD - 1; } if (DOKAN_MOUNT_POINT_SUPPORTED_VERSION <= DokanOptions->Version && DokanOptions->MountPoint) { error = CheckMountPoint(DokanOptions->MountPoint); if (error != DOKAN_SUCCESS) { return error; } useMountPoint = TRUE; } else if (!IsValidDriveLetter((WCHAR)DokanOptions->Version)) { // Older versions use the first 2 bytes of DokanOptions struct as DriveLetter. DokanDbgPrintW(L"Dokan Error: bad drive letter %wc\n", (WCHAR)DokanOptions->Version); return DOKAN_DRIVE_LETTER_ERROR; } device = CreateFile( DOKAN_GLOBAL_DEVICE_NAME, // lpFileName GENERIC_READ|GENERIC_WRITE, // dwDesiredAccess FILE_SHARE_READ|FILE_SHARE_WRITE, // dwShareMode NULL, // lpSecurityAttributes OPEN_EXISTING, // dwCreationDistribution 0, // dwFlagsAndAttributes NULL // hTemplateFile ); if (device == INVALID_HANDLE_VALUE){ DokanDbgPrintW(L"Dokan Error: CreatFile Failed %s: %d\n", DOKAN_GLOBAL_DEVICE_NAME, GetLastError()); return DOKAN_DRIVER_INSTALL_ERROR; } DbgPrint("device opened\n"); instance = NewDokanInstance(); instance->DokanOptions = DokanOptions; instance->DokanOperations = DokanOperations; if (useMountPoint) { wcscpy_s(instance->MountPoint, sizeof(instance->MountPoint) / sizeof(WCHAR), DokanOptions->MountPoint); } else { // Older versions use the first 2 bytes of DokanOptions struct as DriveLetter. instance->MountPoint[0] = (WCHAR)DokanOptions->Version; instance->MountPoint[1] = L':'; instance->MountPoint[2] = L'\\'; } if (!DokanStart(instance)) { CloseHandle(device); return DOKAN_START_ERROR; } if (!DokanMount(instance->MountPoint, instance->DeviceName)) { SendReleaseIRP(instance->DeviceName); DokanDbgPrint("Dokan Error: DefineDosDevice Failed\n"); return DOKAN_MOUNT_ERROR; } DbgPrintW(L"mounted: %s -> %s\n", instance->MountPoint, instance->DeviceName); //Start Keep Alive thread threadIds[threadNum++] = (HANDLE)_beginthreadex( NULL, // Security Attributes 0, //stack size DokanKeepAlive, (PVOID)instance, // param 0, // create flag NULL); for (i = 0; i < DokanOptions->ThreadCount; ++i) { threadIds[threadNum++] = (HANDLE)_beginthreadex( NULL, // Security Attributes 0, //stack size DokanLoop, (PVOID)instance, // param 0, // create flag NULL); } // wait for thread terminations WaitForMultipleObjects(threadNum, threadIds, TRUE, INFINITE); for (i = 0; i < threadNum; ++i) { CloseHandle(threadIds[i]); } CloseHandle(device); Sleep(1000); DbgPrint("\nunload\n"); DeleteDokanInstance(instance); return DOKAN_SUCCESS; }
static BOOL DokanServiceControl(LPCWSTR ServiceName, ULONG Type) { SC_HANDLE controlHandle; SC_HANDLE serviceHandle; SERVICE_STATUS ss; BOOL result = TRUE; controlHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (controlHandle == NULL) { DokanDbgPrint("DokanServiceControl: Failed to open Service Control " "Manager. error = %d\n", GetLastError()); return FALSE; } serviceHandle = OpenService(controlHandle, ServiceName, SERVICE_START | SERVICE_STOP | SERVICE_QUERY_STATUS | DELETE); if (serviceHandle == NULL) { DokanDbgPrintW( L"DokanServiceControl: Failed to open Service (%s). error = %d\n", ServiceName, GetLastError()); CloseServiceHandle(controlHandle); return FALSE; } QueryServiceStatus(serviceHandle, &ss); if (Type == DOKAN_SERVICE_DELETE) { if (DeleteService(serviceHandle)) { DokanDbgPrintW(L"DokanServiceControl: Service (%s) deleted\n", ServiceName); result = TRUE; } else { DokanDbgPrintW( L"DokanServiceControl: Failed to delete service (%s). error = %d\n", ServiceName, GetLastError()); result = FALSE; } } else if (ss.dwCurrentState == SERVICE_STOPPED && Type == DOKAN_SERVICE_START) { if (StartService(serviceHandle, 0, NULL)) { DokanDbgPrintW(L"DokanServiceControl: Service (%s) started\n", ServiceName); result = TRUE; } else { DokanDbgPrintW( L"DokanServiceControl: Failed to start service (%s). error = %d\n", ServiceName, GetLastError()); result = FALSE; } } else if (ss.dwCurrentState == SERVICE_RUNNING && Type == DOKAN_SERVICE_STOP) { if (ControlService(serviceHandle, SERVICE_CONTROL_STOP, &ss)) { DokanDbgPrintW(L"DokanServiceControl: Service (%s) stopped\n", ServiceName); result = TRUE; } else { DokanDbgPrintW( L"DokanServiceControl: Failed to stop service (%s). error = %d\n", ServiceName, GetLastError()); result = FALSE; } } CloseServiceHandle(serviceHandle); CloseServiceHandle(controlHandle); Sleep(100); return result; }
BOOL OnInitDialog(HWND hwnd, LPARAM lParam) { CSSHProperty::string_list* files; PROPSHEETPAGE* ppsp = (PROPSHEETPAGE*)lParam; files = (CSSHProperty::string_list*)ppsp->lParam; if (!files) return FALSE; // Store the filename in this window's user data area, for later use. SetWindowLong(hwnd, GWL_USERDATA, (LONG)files); CSSHProperty::string_list::iterator it = files->begin(); int reads[3]; int writes[3]; int execs[3]; ZeroMemory(reads, sizeof(reads)); ZeroMemory(writes, sizeof(writes)); ZeroMemory(execs, sizeof(execs)); for (; it != files->end(); ++it) { std::wstring file = *it; file += L":SSHFSProperty.Permission"; HANDLE hFile = CreateFile( file.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(hFile == INVALID_HANDLE_VALUE) continue; char buffer[32]; ZeroMemory(buffer, sizeof(buffer)); DWORD readBytes = 0; if (ReadFile(hFile, buffer, sizeof(buffer), &readBytes, NULL)) { int p = atoi(buffer); DokanDbgPrintW(L"%s, %d\n", file.c_str(), p); for(int i=0; i<3; ++i) { p = buffer[i] - '0'; if (p & 0x1) execs[i]++; if (p & 0x2) writes[i]++; if (p & 0x4) reads[i]++; } } CloseHandle(hFile); } int count = (int)files->size(); CheckDlgButton(hwnd, IDC_W_READ, reads[0] == 0 ? BST_UNCHECKED : (reads[0] == count ? BST_CHECKED : BST_INDETERMINATE)); CheckDlgButton(hwnd, IDC_W_WRITE, writes[0] == 0 ? BST_UNCHECKED : (writes[0] == count ? BST_CHECKED : BST_INDETERMINATE)); CheckDlgButton(hwnd, IDC_W_EXEC, execs[0] == 0 ? BST_UNCHECKED : (execs[0] == count ? BST_CHECKED : BST_INDETERMINATE)); CheckDlgButton(hwnd, IDC_G_READ, reads[1] == 0 ? BST_UNCHECKED : (reads[1] == count ? BST_CHECKED : BST_INDETERMINATE)); CheckDlgButton(hwnd, IDC_G_WRITE, writes[1] == 0 ? BST_UNCHECKED : (writes[1] == count ? BST_CHECKED : BST_INDETERMINATE)); CheckDlgButton(hwnd, IDC_G_EXEC, execs[1] == 0 ? BST_UNCHECKED : (execs[1] == count ? BST_CHECKED : BST_INDETERMINATE)); CheckDlgButton(hwnd, IDC_O_READ, reads[2] == 0 ? BST_UNCHECKED : (reads[2] == count ? BST_CHECKED : BST_INDETERMINATE)); CheckDlgButton(hwnd, IDC_O_WRITE, writes[2] == 0 ? BST_UNCHECKED : (writes[2] == count ? BST_CHECKED : BST_INDETERMINATE)); CheckDlgButton(hwnd, IDC_O_EXEC, execs[2] == 0 ? BST_UNCHECKED : (execs[2] == count ? BST_CHECKED : BST_INDETERMINATE)); return FALSE; // Take the default focus handling. }
STDMETHODIMP CSSHProperty::Initialize ( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID ) { TCHAR szFile[MAX_PATH]; UINT uNumFiles; HDROP hdrop; FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM stg; INITCOMMONCONTROLSEX iccex = { sizeof(INITCOMMONCONTROLSEX), ICC_DATE_CLASSES }; BOOL mounted = FALSE; // Init the common controls. InitCommonControlsEx ( &iccex ); // Read the list of folders from the data object. They're stored in HDROP // form, so just get the HDROP handle and then use the drag 'n' drop APIs // on it. if (FAILED(pDataObj->GetData(&etc, &stg))) return E_INVALIDARG; // Get an HDROP handle. hdrop = (HDROP)GlobalLock(stg.hGlobal); if (NULL == hdrop) { ReleaseStgMedium(&stg); return E_INVALIDARG; } // Determine how many files are involved in this operation. uNumFiles = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0); for (UINT uFile = 0; uFile < uNumFiles; uFile++ ) { // Get the next filename. if (0 == DragQueryFile(hdrop, uFile, szFile, MAX_PATH)) continue; if (!mounted && CheckMount2(szFile)) mounted = TRUE; // Skip over directories. We *could* handle directories, since they // keep the creation time/date, but I'm just choosing not to do so // in this example project. //if ( PathIsDirectory ( szFile ) ) // continue; // Add the filename to our list o' files to act on. DokanDbgPrintW(L"add %s\n", szFile); m_lsFiles.push_back(szFile); } // end for // Release resources. GlobalUnlock(stg.hGlobal); ReleaseStgMedium(&stg); // Check how many files were selected. If the number is greater than the // maximum number of property pages, truncate our list. if (m_lsFiles.size() > MAXPROPPAGES) m_lsFiles.resize(MAXPROPPAGES); // If we found any files we can work with, return S_OK. Otherwise, // return E_FAIL so we don't get called again for this right-click // operation. DokanDbgPrintW(mounted ? L"mounted\n" : L"not mounted\n"); return (m_lsFiles.size() > 0 && mounted) ? S_OK : E_FAIL; }