HANDLE DOKANAPI DokanOpenRequestorToken(PDOKAN_FILE_INFO FileInfo) { BOOL status; ULONG returnedLength; PDOKAN_INSTANCE instance; PDOKAN_OPEN_INFO openInfo; PEVENT_CONTEXT eventContext; PEVENT_INFORMATION eventInfo; HANDLE handle = INVALID_HANDLE_VALUE; ULONG eventInfoSize; WCHAR rawDeviceName[MAX_PATH]; openInfo = (PDOKAN_OPEN_INFO)(UINT_PTR)FileInfo->DokanContext; if (openInfo == NULL) { return INVALID_HANDLE_VALUE; } eventContext = openInfo->EventContext; if (eventContext == NULL) { return INVALID_HANDLE_VALUE; } instance = openInfo->DokanInstance; if (instance == NULL) { return INVALID_HANDLE_VALUE; } if (eventContext->MajorFunction != IRP_MJ_CREATE) { return INVALID_HANDLE_VALUE; } eventInfoSize = sizeof(EVENT_INFORMATION); eventInfo = (PEVENT_INFORMATION)malloc(eventInfoSize); if (eventInfo == NULL) { return INVALID_HANDLE_VALUE; } RtlZeroMemory(eventInfo, eventInfoSize); eventInfo->SerialNumber = eventContext->SerialNumber; status = SendToDevice( GetRawDeviceName(instance->DeviceName, rawDeviceName, MAX_PATH), IOCTL_GET_ACCESS_TOKEN, eventInfo, eventInfoSize, eventInfo, eventInfoSize, &returnedLength); if (status) { handle = eventInfo->Operation.AccessToken.Handle; } else { DbgPrintW(L"IOCTL_GET_ACCESS_TOKEN failed\n"); } free(eventInfo); return handle; }
BOOL DOKANAPI DokanResetTimeout(ULONG Timeout, PDOKAN_FILE_INFO FileInfo) { BOOL status; ULONG returnedLength; PDOKAN_INSTANCE instance; PDOKAN_OPEN_INFO openInfo; PEVENT_CONTEXT eventContext; PEVENT_INFORMATION eventInfo; ULONG eventInfoSize = sizeof(EVENT_INFORMATION); openInfo = (PDOKAN_OPEN_INFO)(UINT_PTR)FileInfo->DokanContext; if (openInfo == NULL) { return FALSE; } eventContext = openInfo->EventContext; if (eventContext == NULL) { return FALSE; } instance = openInfo->DokanInstance; if (instance == NULL) { return FALSE; } eventInfo = (PEVENT_INFORMATION)malloc(eventInfoSize); RtlZeroMemory(eventInfo, eventInfoSize); eventInfo->SerialNumber = eventContext->SerialNumber; eventInfo->ResetTimeout.Timeout = Timeout; status = SendToDevice( GetRawDeviceName(instance->DeviceName), IOCTL_RESET_TIMEOUT, eventInfo, eventInfoSize, NULL, 0, &returnedLength); free(eventInfo); return status; }
UINT WINAPI DokanKeepAlive( PDOKAN_INSTANCE DokanInstance) { HANDLE device; ULONG ReturnedLength; BOOL status; device = CreateFile( GetRawDeviceName(DokanInstance->DeviceName), GENERIC_READ | GENERIC_WRITE, // dwDesiredAccess FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode NULL, // lpSecurityAttributes OPEN_EXISTING, // dwCreationDistribution 0, // dwFlagsAndAttributes NULL // hTemplateFile ); while(device != INVALID_HANDLE_VALUE) { status = DeviceIoControl( device, // Handle to device IOCTL_KEEPALIVE, // IO Control code NULL, // Input Buffer to driver. 0, // Length of input buffer in bytes. NULL, // Output Buffer from driver. 0, // Length of output buffer in bytes. &ReturnedLength, // Bytes placed in buffer. NULL // synchronous call ); if (!status) { break; } Sleep(DOKAN_KEEPALIVE_TIME); } CloseHandle(device); _endthreadex(0); return 0; }
// ask driver to release all pending IRP to prepare for Unmount. BOOL SendReleaseIRP( LPCWSTR DeviceName) { ULONG returnedLength; DbgPrint("send release\n"); if (!SendToDevice( GetRawDeviceName(DeviceName), IOCTL_EVENT_RELEASE, NULL, 0, NULL, 0, &returnedLength) ) { DbgPrint("Failed to unmount device:%ws\n", DeviceName); return FALSE; } return TRUE; }
UINT WINAPI DokanLoop( PDOKAN_INSTANCE DokanInstance ) { HANDLE device; char buffer[EVENT_CONTEXT_MAX_SIZE]; BOOL status; ULONG returnedLength; DWORD result = 0; DWORD lastError = 0; RtlZeroMemory(buffer, sizeof(buffer)); device = CreateFile( GetRawDeviceName(DokanInstance->DeviceName), // 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) { DbgPrint("Dokan Error: CreateFile failed %ws: %d\n", GetRawDeviceName(DokanInstance->DeviceName), GetLastError()); result = (DWORD)-1; _endthreadex(result); return result; } status = TRUE; while (status) { status = DeviceIoControl( device, // Handle to device IOCTL_EVENT_WAIT, // IO Control code NULL, // Input Buffer to driver. 0, // Length of input buffer in bytes. buffer, // Output Buffer from driver. sizeof(buffer), // Length of output buffer in bytes. &returnedLength, // Bytes placed in buffer. NULL // synchronous call ); if (!status) { lastError = GetLastError(); DbgPrint("Ioctl failed for wait with code %d.\n", lastError); if (lastError == ERROR_NO_SYSTEM_RESOURCES) { DbgPrint("Processing will continue\n"); status = TRUE; Sleep(200); continue; } DbgPrint("Thread will be terminated\n"); break; } //printf("#%d got notification %d\n", (ULONG)Param, count++); if(returnedLength > 0) { PEVENT_CONTEXT context = (PEVENT_CONTEXT)buffer; if (context->MountId != DokanInstance->MountId) { DbgPrint("Dokan Error: Invalid MountId (expected:%d, acctual:%d)\n", DokanInstance->MountId, context->MountId); continue; } switch (context->MajorFunction) { case IRP_MJ_CREATE: DispatchCreate(device, context, DokanInstance); break; case IRP_MJ_CLEANUP: DispatchCleanup(device, context, DokanInstance); break; case IRP_MJ_CLOSE: DispatchClose(device, context, DokanInstance); break; case IRP_MJ_DIRECTORY_CONTROL: DispatchDirectoryInformation(device, context, DokanInstance); break; case IRP_MJ_READ: DispatchRead(device, context, DokanInstance); break; case IRP_MJ_WRITE: DispatchWrite(device, context, DokanInstance); break; case IRP_MJ_QUERY_INFORMATION: DispatchQueryInformation(device, context, DokanInstance); break; case IRP_MJ_QUERY_VOLUME_INFORMATION: DispatchQueryVolumeInformation(device ,context, DokanInstance); break; case IRP_MJ_LOCK_CONTROL: DispatchLock(device, context, DokanInstance); break; case IRP_MJ_SET_INFORMATION: DispatchSetInformation(device, context, DokanInstance); break; case IRP_MJ_FLUSH_BUFFERS: DispatchFlush(device, context, DokanInstance); break; case IRP_MJ_QUERY_SECURITY: DispatchQuerySecurity(device, context, DokanInstance); break; case IRP_MJ_SET_SECURITY: DispatchSetSecurity(device, context, DokanInstance); break; case IRP_MJ_SHUTDOWN: // this case is used before unmount not shutdown DispatchUnmount(device, context, DokanInstance); break; default: break; } } else { DbgPrint("ReturnedLength %d\n", returnedLength); } } CloseHandle(device); _endthreadex(result); return result; }