BOOL DokanMount( ULONG DeviceNumber, WCHAR DriveLetter) { HANDLE pipe; DOKAN_CONTROL control; ZeroMemory(&control, sizeof(DOKAN_CONTROL)); control.Type = DOKAN_CONTROL_MOUNT; control.Mount.Device = DeviceNumber; control.Mount.Drive = DriveLetter; return DokanControl(&control); }
BOOL DOKANAPI DokanUnmount( WCHAR DriveLetter) { HANDLE pipe; DOKAN_CONTROL control; SendReleaseIRP(DriveLetter); ZeroMemory(&control, sizeof(DOKAN_CONTROL)); control.Type = DOKAN_CONTROL_UNMOUNT; control.Unmount.Drive = DriveLetter; if (DokanControl(&control)) { return TRUE; } else { return FALSE; } }
static VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { DWORD eventNo; HANDLE pipe, device; HANDLE eventConnect, eventUnmount; HANDLE eventArray[3]; DOKAN_CONTROL control, unmount; OVERLAPPED ov, driver; ULONG returnedBytes; EVENT_CONTEXT eventContext; SECURITY_ATTRIBUTES sa; UNREFERENCED_PARAMETER(dwArgc); UNREFERENCED_PARAMETER(lpszArgv); InitializeCriticalSectionAndSpinCount(&g_CriticalSection, 4000); InitializeListHead(&g_MountList); g_StatusHandle = RegisterServiceCtrlHandlerEx(L"DokanMounter", HandlerEx, NULL); // extend completion time g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwWin32ExitCode = NO_ERROR; g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; g_ServiceStatus.dwServiceSpecificExitCode = 0; g_ServiceStatus.dwWaitHint = 30000; g_ServiceStatus.dwCheckPoint = 1; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); BuildSecurityAttributes(&sa); pipe = CreateNamedPipe(DOKAN_CONTROL_PIPE, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, sizeof(control), sizeof(control), 1000, &sa); if (pipe == INVALID_HANDLE_VALUE) { // TODO: should do something DbgPrintW(L"DokanMounter: failed to create named pipe: %d\n", GetLastError()); } device = CreateFile( DOKAN_GLOBAL_DEVICE_NAME, // lpFileName GENERIC_READ | GENERIC_WRITE, // dwDesiredAccess FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode NULL, // lpSecurityAttributes OPEN_EXISTING, // dwCreationDistribution FILE_FLAG_OVERLAPPED, // dwFlagsAndAttributes NULL // hTemplateFile ); if (device == INVALID_HANDLE_VALUE) { // TODO: should do something DbgPrintW(L"DokanMounter: failed to open device: %d\n", GetLastError()); } eventConnect = CreateEvent(NULL, FALSE, FALSE, NULL); eventUnmount = CreateEvent(NULL, FALSE, FALSE, NULL); g_EventControl = CreateEvent(NULL, TRUE, FALSE, NULL); g_ServiceStatus.dwWaitHint = 0; g_ServiceStatus.dwCheckPoint = 0; g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); for (;;) { ZeroMemory(&ov, sizeof(OVERLAPPED)); ZeroMemory(&driver, sizeof(OVERLAPPED)); ZeroMemory(&eventContext, sizeof(EVENT_CONTEXT)); ov.hEvent = eventConnect; driver.hEvent = eventUnmount; ConnectNamedPipe(pipe, &ov); if (!DeviceIoControl(device, IOCTL_SERVICE_WAIT, NULL, 0, &eventContext, sizeof(EVENT_CONTEXT), NULL, &driver)) { DWORD error = GetLastError(); if (error != 997) { DbgPrintW(L"DokanMounter: DeviceIoControl error: %d\n", error); } } eventArray[0] = eventConnect; eventArray[1] = eventUnmount; eventArray[2] = g_EventControl; eventNo = WaitForMultipleObjects(3, eventArray, FALSE, INFINITE) - WAIT_OBJECT_0; DbgPrintW(L"DokanMounter: get an event\n"); if (eventNo == 0) { DWORD result = 0; ZeroMemory(&control, sizeof(control)); if (ReadFile(pipe, &control, sizeof(control), &result, NULL)) { DokanControl(&control); WriteFile(pipe, &control, sizeof(control), &result, NULL); } FlushFileBuffers(pipe); DisconnectNamedPipe(pipe); } else if (eventNo == 1) { if (GetOverlappedResult(device, &driver, &returnedBytes, FALSE)) { if (returnedBytes == sizeof(EVENT_CONTEXT)) { DbgPrintW(L"DokanMounter: Unmount\n"); ZeroMemory(&unmount, sizeof(DOKAN_CONTROL)); unmount.Type = DOKAN_CONTROL_UNMOUNT; unmount.Option = eventContext.Operation.Unmount.Option; wcscpy_s(unmount.DeviceName, sizeof(unmount.DeviceName) / sizeof(WCHAR), eventContext.Operation.Unmount.DeviceName); DokanControl(&unmount); } else { DbgPrintW(L"DokanMounter: Unmount error\n", control.Type); } } } else if (eventNo == 2) { DbgPrintW(L"DokanMounter: stop mounter service\n"); g_ServiceStatus.dwWaitHint = 0; g_ServiceStatus.dwCheckPoint = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_StatusHandle, &g_ServiceStatus); break; } else break; } CloseHandle(pipe); CloseHandle(eventConnect); CloseHandle(g_EventControl); CloseHandle(device); CloseHandle(eventUnmount); DeleteCriticalSection(&g_CriticalSection); return; }