// // Close the current image // VOID VfdCloseImage ( IN PDEVICE_EXTENSION DeviceExtension) { VFDTRACE(0, ("[VFD] VfdCloseImage - IN\n")); ASSERT(DeviceExtension); DeviceExtension->MediaType = VFD_MEDIA_NONE; DeviceExtension->MediaFlags = 0; DeviceExtension->FileType = 0; DeviceExtension->ImageSize = 0; DeviceExtension->FileName.Length = 0; DeviceExtension->Sectors = 0; if (DeviceExtension->FileHandle) { ZwClose(DeviceExtension->FileHandle); DeviceExtension->FileHandle = NULL; } if (DeviceExtension->FileBuffer) { ExFreePool(DeviceExtension->FileBuffer); DeviceExtension->FileBuffer = NULL; } VFDTRACE(0, ("[VFD] VfdCloseImage - OUT\n")); }
// // Handle IO control requests in the device thread // VOID VfdIoCtlThread( IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN ULONG ControlCode) { switch (ControlCode) { case IOCTL_VFD_OPEN_IMAGE: // open the file from the caller's security context // -- this allows this driver to open network files if (DeviceExtension->SecurityContext) { SeImpersonateClient(DeviceExtension->SecurityContext, NULL); } Irp->IoStatus.Status = VfdOpenImage(DeviceExtension, (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer); PsRevertToSelf(); break; case IOCTL_VFD_CLOSE_IMAGE: case IOCTL_DISK_EJECT_MEDIA: case IOCTL_STORAGE_EJECT_MEDIA: VfdCloseImage(DeviceExtension); Irp->IoStatus.Status = STATUS_SUCCESS; break; case IOCTL_DISK_FORMAT_TRACKS: case IOCTL_DISK_FORMAT_TRACKS_EX: Irp->IoStatus.Status = VfdFormatTrack(DeviceExtension, (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer); break; default: // This shouldn't happen... VFDTRACE(0, ("[VFD] %s passed to the device thread\n", GetIoControlName(ControlCode))); Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; } #if DBG if ((NT_SUCCESS(Irp->IoStatus.Status) && (TraceFlags & VFDINFO) == VFDINFO) || (TraceFlags & VFDWARN) == VFDWARN) { VFDTRACE(0,("[VFD] %-40s - %s\n", GetIoControlName(ControlCode), GetStatusName(Irp->IoStatus.Status))); } #endif }
STDMETHODIMP CVfdShExt::GetCommandString( UINT idCmd, UINT uFlags, UINT *reserved, LPSTR pszName, UINT cchMax) { VFDTRACE(0, ("CVfdShExt::GetCommandString(%u,...)\n", idCmd)); UNREFERENCED_PARAMETER(reserved); if (idCmd >= sizeof(g_VfdMenu) / sizeof(g_VfdMenu[0])) { return S_FALSE; } switch (uFlags) { case GCS_HELPTEXTA: FormatMessageA( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, g_hDllModule, g_VfdMenu[idCmd].helpid, 0, pszName, cchMax, NULL); VFDTRACE(0, ("HELPTEXTA: %s\n", pszName)); break; case GCS_HELPTEXTW: FormatMessageW( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, g_hDllModule, g_VfdMenu[idCmd].helpid, 0, (LPWSTR)pszName, cchMax, NULL); VFDTRACE(0, ("HELPTEXTW: %ws\n", pszName)); break; case GCS_VERBA: lstrcpynA(pszName, g_VfdMenu[idCmd].verbA, cchMax); break; case GCS_VERBW: lstrcpynW((LPWSTR)pszName, g_VfdMenu[idCmd].verbW, cchMax); break; } return NOERROR; }
// // Enable/disable media write protection // DWORD CVfdShExt::DoVfdProtect( HWND hParent) { HANDLE hDevice; DWORD ret; UNREFERENCED_PARAMETER(hParent); VFDTRACE(0, ("CVfdShExt::DoVfdProtect()\n")); hDevice = VfdOpenDevice(m_nDevice); if (hDevice == INVALID_HANDLE_VALUE) { return GetLastError(); } ret = VfdGetMediaState(hDevice); if (ret == ERROR_SUCCESS) { ret = VfdWriteProtect(hDevice, TRUE); } else if (ret == ERROR_WRITE_PROTECT) { ret = VfdWriteProtect(hDevice, FALSE); } if (ret == ERROR_SUCCESS) { ret = VfdGetMediaState(hDevice); } CloseHandle(hDevice); return ret; }
// // IClassFactory methods // STDMETHODIMP CVfdFactory::CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) { VFDTRACE(0, ("CVfdFactory::CreateInstance()\n")); *ppvObj = NULL; // Shell extensions typically don't support // aggregation (inheritance) if (pUnkOuter) { return CLASS_E_NOAGGREGATION; } // Create the main shell extension object. // The shell will then call QueryInterface with IID_IShellExtInit // -- this is how shell extensions are initialized. LPCVFDSHEXT pVfdShExt = new CVfdShExt; if (!pVfdShExt) { return E_OUTOFMEMORY; } return pVfdShExt->QueryInterface(riid, ppvObj); }
// // constructor // CVfdFactory::CVfdFactory() { VFDTRACE(0, ("CVfdFactory::CVfdFactory()\n")); m_cRefCnt = 0L; g_cDllRefCnt++; }
STDMETHODIMP_(ULONG) CVfdFactory::Release() { VFDTRACE(0, ("CVfdFactory::Release()\n")); if (--m_cRefCnt) { return m_cRefCnt; } delete this; return 0L; }
STDMETHODIMP_(ULONG) CVfdFactory::Release() { VFDTRACE(0, ("CVfdFactory::Release()\n")); if (--m_cRefCnt) { return m_cRefCnt; } #ifndef __REACTOS__ delete this; #endif return 0L; }
// // IUnknown methods // STDMETHODIMP CVfdFactory::QueryInterface( REFIID riid, LPVOID *ppv) { VFDTRACE(0, ("CVfdFactory::QueryInterface()\n")); *ppv = NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) { *ppv = (LPCLASSFACTORY)this; AddRef(); return NOERROR; } return E_NOINTERFACE; }
// // append a text string to the message control // void AppendLogMessage(DWORD err, DWORD msg, ...) { TCHAR buf[200]; DWORD len; DWORD max; DWORD cur; HWND hEdit; // get edit control handle hEdit = GetDlgItem(hMainWnd, IDC_LOG_MESSAGE); if (hEdit == NULL) { VFDTRACE(0,("AppendMessage : GetDlgItem - %s", GetSystemMessage(GetLastError()))); return; } // max length of text the edit control can store max = SendMessage(hEdit, EM_GETLIMITTEXT, 0, 0); if (max == 0) { VFDTRACE(0,("AppendMessage : EM_GETLIMITTEXT - %s", GetSystemMessage(GetLastError()))); return; } // current length of text in the edit control cur = SendMessage(hEdit, WM_GETTEXTLENGTH, 0, 0); // format the message len = 0; if (msg) { va_list args; va_start(args, msg); len = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, hAppInst, msg, 0, buf, sizeof(buf), &args); va_end(args); } if (err) { len += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, buf + len, sizeof(buf) - len, NULL); } if (cur + len >= max) { // remove first half of text in the edit control SendMessage(hEdit, EM_SETSEL, 0, cur / 2); SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)""); cur -= (cur / 2); } // append the new text at the end SendMessage(hEdit, EM_SETSEL, cur, cur); SendMessage(hEdit, EM_REPLACESEL, FALSE, (LPARAM)buf); }
// // Application entry point // int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { HACCEL hAccel; MSG msg = { 0 }; DWORD err; UNREFERENCED_PARAMETER(hPrevInst); UNREFERENCED_PARAMETER(nCmdShow); // // Reports memory leaks at process termination // _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); // // Check the Operating System version // /*if (!VfdIsValidPlatform()) { ShowErrorMessage(0, MSG_ERR_WRONG_PLATFORM); return -1; }*/ // // Save the application instance handle // hAppInst = hInstance; // // Process command line parameters // if (lpCmdLine && *lpCmdLine) { CommandLine(); return 0; } // // register the custom dialog window class // { WNDCLASS wc; GetClassInfo(hInstance, WC_DIALOG, &wc); wc.lpszClassName = VFDWIN_APP_BASENAME; RegisterClass(&wc); } // // Find if another instance of VfdWin is running // { HWND hWnd; hWnd = FindWindow(VFDWIN_APP_BASENAME, NULL); if (hWnd) { // bring to the foreground ShowWindow(hWnd, SW_RESTORE); SetForegroundWindow(hWnd); return 0; } } // // Store application executable file path // err = GetModuleFileName(NULL, sAppPath, sizeof(sAppPath)); if (err == 0) { err = GetLastError(); VFDTRACE(0,("WinMain : GetModuleFileName() - %s", GetSystemMessage(err))); ShowErrorMessage(err, MSG_ERR_APP_INTERNAL); goto cleanup; } pAppBase = sAppPath + err; while (pAppBase > sAppPath && *(pAppBase - 1) != '\\') { pAppBase--; } // // initialize ole and common controls // if (!SUCCEEDED(CoInitialize(NULL))) { err = GetLastError(); VFDTRACE(0,("WinMain : CoInitialize() - %s", GetSystemMessage(err))); ShowErrorMessage(err, MSG_ERR_APP_INTERNAL); goto cleanup; } InitCommonControls(); // // Create the main dialog window // hMainWnd = CreateDialog( hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainProc); if (hMainWnd == NULL) { err = GetLastError(); VFDTRACE(0,("WinMain : CreateDialog - %s", GetSystemMessage(err))); ShowErrorMessage(err, MSG_ERR_APP_INTERNAL); goto cleanup; } hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR)); if (hAccel == NULL) { VFDTRACE(0,("WinMain : LoadAccelerators - %s", GetSystemMessage(GetLastError()))); } // // Message loop // for (;;) { BOOL ret = GetMessage(&msg, NULL, 0, 0); if (ret == 0) { break; } else if (ret == -1) { err = GetLastError(); VFDTRACE(0,("WinMain: GetMessage - %s", GetSystemMessage(err))); ShowErrorMessage(err, MSG_ERR_APP_INTERNAL); break; } if (!TranslateAccelerator(hMainWnd, hAccel, &msg) && !IsDialogMessage(hMainWnd, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } cleanup: CoUninitialize(); return msg.wParam; }
// // Close the current image and open the new image // void CommandLine() { ULONG target = '0'; PSTR file_name = NULL; VFD_DISKTYPE disk_type = VFD_DISKTYPE_FILE; VFD_MEDIA media_type = VFD_MEDIA_NONE; VFD_FLAGS image_flags = 0; VFD_FILETYPE file_type; BOOL five_inch = FALSE; CHAR protect = 0; BOOL open_folder = TRUE; BOOL close_only = FALSE; HANDLE hDevice; CHAR letter; DWORD driver_state; DWORD ret; // // process command line parameters // while (*(++__argv)) { // Open switch if (_stricmp(*__argv, VFD_OPEN_SWITCH) == 0) { close_only = FALSE; } // Close switch else if (_stricmp(*__argv, "/close") == 0) { close_only = TRUE; } // Quiet mode switch else if (stricmp(*__argv, "/q") == 0) { open_folder = FALSE; } // Disk type options else if (_stricmp(*__argv, "/ram") == 0) { disk_type = VFD_DISKTYPE_RAM; } // Protect options else if (_stricmp(*__argv, "/p") == 0 || _stricmp(*__argv, "/w") == 0) { protect = (CHAR)toupper(*(*__argv + 1)); } // media type options /*else if (strcmp(*__argv, "/160") == 0) { media_type = VFD_MEDIA_F5_160; } else if (strcmp(*__argv, "/180") == 0) { media_type = VFD_MEDIA_F5_180; } else if (strcmp(*__argv, "/320") == 0) { media_type = VFD_MEDIA_F5_320; } else if (strcmp(*__argv, "/360") == 0) { media_type = VFD_MEDIA_F5_360; } else if (strcmp(*__argv, "/640") == 0) { media_type = VFD_MEDIA_F3_640; }*/ else if (strcmp(*__argv, "/720") == 0) { media_type = VFD_MEDIA_F3_720; } /*else if (strcmp(*__argv, "/820") == 0) { media_type = VFD_MEDIA_F3_820; } else if (strcmp(*__argv, "/120") == 0 || strcmp(*__argv, "/1.20") == 0) { media_type = VFD_MEDIA_F3_1P2; }*/ else if (strcmp(*__argv, "/144") == 0 || strcmp(*__argv, "/1.44") == 0) { media_type = VFD_MEDIA_F3_1P4; } /*else if (strcmp(*__argv, "/168") == 0 || strcmp(*__argv, "/1.68") == 0) { media_type = VFD_MEDIA_F3_1P6; } else if (strcmp(*__argv, "/172") == 0 || strcmp(*__argv, "/1.72") == 0) { media_type = VFD_MEDIA_F3_1P7; } else if (strcmp(*__argv, "/288") == 0 || strcmp(*__argv, "/2.88") == 0) { media_type = VFD_MEDIA_F3_2P8; }*/ // 5.25 inch else if (strcmp(*__argv, "/5") == 0 || strcmp(*__argv, "/525") == 0 || strcmp(*__argv, "/5.25") == 0) { five_inch = TRUE; } // target drive else if (isalnum(**__argv) && *(*__argv + 1) == ':' && *(*__argv + 2) == '\0') { target = toupper(**__argv); } else if (**__argv == '*' && *(*__argv + 1) == ':' && *(*__argv + 2) == '\0') { target = (ULONG)-1; } // image filename else if (**__argv != '/') { file_name = *__argv; if (*file_name == '\"' && *(file_name + strlen(file_name) - 1) == '\"') { // remove quote characters if the path is quoted *(file_name + strlen(file_name) - 1) = '\0'; file_name++; } } // unknown options else { ShowErrorMessage(0, MSG_ERR_INVALID_PARAM, *__argv); return; } } // check parameter consistency if (target == (ULONG)-1 && !close_only) { ShowErrorMessage(0, MSG_ERR_INVALID_PARAM, "*:"); return; } // Get the current driver state ret = VfdGetDriverState(&driver_state); if (ret != ERROR_SUCCESS) { ShowErrorMessage(ret, MSG_ERR_APP_INTERNAL); return; } if (close_only && driver_state != SERVICE_RUNNING) { // nothing to do... return; } // ensure that the driver is running if (driver_state == VFD_NOT_INSTALLED) { ret = VfdInstallDriver(NULL, SERVICE_DEMAND_START); if (ret != ERROR_SUCCESS) { ShowErrorMessage(ret, MSG_ERR_DRIVER_INSTALL); return; } } // ensure that the driver is started if (driver_state != SERVICE_RUNNING) { ret = VfdStartDriver(&driver_state); if (ret != ERROR_SUCCESS || driver_state != SERVICE_RUNNING) { ShowErrorMessage(ret, MSG_ERR_DRIVER_START); return; } } // // close the current image (if any) // if (target == (ULONG)-1) { int i; for (i = 0; i < VFD_MAXIMUM_DEVICES; i++) { ret = VfdGuiClose(NULL, i); if (ret != ERROR_SUCCESS && ret != ERROR_NOT_READY) { ShowErrorMessage(ret, MSG_ERR_IMAGE_CLOSE, i + '0'); } } return; } ret = VfdGuiClose(NULL, target); if (ret != ERROR_SUCCESS && ret != ERROR_NOT_READY) { ShowErrorMessage(ret, MSG_ERR_IMAGE_CLOSE, target); return; } if (close_only) { return; } // // check target image file // if (file_name) { DWORD file_attr; ULONG image_size; ret = VfdCheckImageFile( file_name, &file_attr, &file_type, &image_size); if (ret == ERROR_FILE_NOT_FOUND) { // If file does not exist, create a new image file if (media_type == VFD_MEDIA_NONE) { media_type = VFD_MEDIA_F3_1P4; } ret = VfdCreateImageFile( file_name, media_type, VFD_FILETYPE_RAW, FALSE); if (ret != ERROR_SUCCESS) { ShowErrorMessage(ret, MSG_ERR_FILE_CREATE, file_name); return; } ret = VfdCheckImageFile( file_name, &file_attr, &file_type, &image_size); if (ret != ERROR_SUCCESS) { ShowErrorMessage(ret, MSG_ERR_FILE_OPEN, file_name); return; } } else if (ret == ERROR_SUCCESS) { // check file size / media size ULONG media_size; VFD_MEDIA def_media; media_size = VfdGetMediaSize(media_type); if (media_size > image_size) { ShowErrorMessage(0, MSG_ERR_IMAGE_TOO_SMALL); return; } def_media = VfdLookupMedia(image_size); if (def_media == VFD_MEDIA_NONE) { ShowErrorMessage(0, MSG_ERR_IMAGE_TOO_SMALL); return; } if (media_type == VFD_MEDIA_NONE) { media_type = def_media; } // check file type if (file_type == VFD_FILETYPE_ZIP || (file_attr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED))) { disk_type = VFD_DISKTYPE_RAM; } } else { ShowErrorMessage(ret, MSG_ERR_FILE_OPEN, file_name); return; } if (disk_type != VFD_DISKTYPE_FILE) { if (protect != 'W') { protect = 'P'; } } } else { disk_type = VFD_DISKTYPE_RAM; if (media_type == VFD_MEDIA_NONE) { media_type = VFD_MEDIA_F3_1P4; } } if (protect == 'P') { image_flags |= VFD_FLAG_WRITE_PROTECTED; } if (five_inch && VfdGetMediaSize(media_type) == VfdGetMediaSize((VFD_MEDIA)(media_type + 1))) { media_type = (VFD_MEDIA)(media_type + 1); } // Open the target device hDevice = VfdOpenDevice(target); if (hDevice == INVALID_HANDLE_VALUE) { ShowErrorMessage(GetLastError(), MSG_ERR_DEVICE_OPEN, target); return; } // assign a drive letter if the drive has none VfdGetGlobalLink(hDevice, &letter); if (!isalpha(letter)) { VfdGetLocalLink(hDevice, &letter); } if (!isalpha(letter)) { letter = VfdChooseLetter(); VfdSetLocalLink(hDevice, letter); } // Open the image file ret = VfdOpenImage(hDevice, file_name, disk_type, media_type, image_flags); CloseHandle(hDevice); if (ret != ERROR_SUCCESS) { ShowErrorMessage(ret, MSG_ERR_FILE_OPEN, file_name ? file_name : "<RAM>"); return; } // // Unless otherwise specified, open the drive // if (open_folder && isalpha(letter)) { CHAR drive[] = "A:\\"; CHAR verb[20] = {0}; LONG size = sizeof(verb); drive[0] = (CHAR)toupper(letter); // get the default verb for folder object from the registry RegQueryValue(HKEY_CLASSES_ROOT, "Folder\\shell", verb, &size); ret = (DWORD)ShellExecute( NULL, verb[0] ? verb : NULL, drive, NULL, NULL, SW_SHOWNORMAL); if (ret <= 32) { VFDTRACE(0, ("OpenImage : ShellExecute - %s", GetSystemMessage(GetLastError()))); } } return; }
// // Write sectors from write buffer into image file or RAM image buffer // VOID VfdWriteData( IN PDEVICE_EXTENSION DeviceExtension, IN OUT PIRP Irp, IN ULONG Length, IN PLARGE_INTEGER Offset) { PVOID buf; VFDTRACE(VFDINFO,("[VFD] VfdWriteData - IN\n")); buf = MmGetSystemAddressForMdlPrettySafe( Irp->MdlAddress, NormalPagePriority); if (!buf) { VFDTRACE(0, ("[VFD] MmGetSystemAddressForMdlPrettySafe\n")); Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; return; } if (DeviceExtension->FileHandle) { // Write into image file Irp->IoStatus.Status = ZwWriteFile( DeviceExtension->FileHandle, NULL, NULL, NULL, &Irp->IoStatus, buf, Length, Offset, NULL); if (NT_SUCCESS(Irp->IoStatus.Status)) { Irp->IoStatus.Information = Length; } else { VFDTRACE(0, ("[VFD] ZwWriteFile - %s\n", GetStatusName(Irp->IoStatus.Status))); } } else if (DeviceExtension->FileBuffer) { // Deal with the modify flag if (RtlCompareMemory( DeviceExtension->FileBuffer + Offset->QuadPart, buf, Length) != Length) { DeviceExtension->MediaFlags |= VFD_FLAG_DATA_MODIFIED; } // Copy into RAM image buffer RtlMoveMemory( DeviceExtension->FileBuffer + Offset->QuadPart, buf, Length); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = Length; } else { // no image opened Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE; } VFDTRACE(VFDINFO,("[VFD] VfdWriteData - %s\n", GetStatusName(Irp->IoStatus.Status))); return; }
// // Read sectors from image file or RAM disk buffer into read buffer // VOID VfdReadData( IN PDEVICE_EXTENSION DeviceExtension, IN OUT PIRP Irp, IN ULONG Length, IN PLARGE_INTEGER Offset) { PVOID buf; VFDTRACE(VFDINFO,("[VFD] VfdReadData - IN\n")); buf = MmGetSystemAddressForMdlPrettySafe( Irp->MdlAddress, NormalPagePriority); if (!buf) { VFDTRACE(0, ("[VFD] MmGetSystemAddressForMdlPrettySafe\n")); Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; return; } if (DeviceExtension->FileHandle) { // Read from image file Irp->IoStatus.Status = ZwReadFile( DeviceExtension->FileHandle, NULL, NULL, NULL, &Irp->IoStatus, buf, Length, Offset, NULL); if (NT_SUCCESS(Irp->IoStatus.Status)) { Irp->IoStatus.Information = Length; } else { VFDTRACE(0, ("[VFD] ZwReadFile - %s\n", GetStatusName(Irp->IoStatus.Status))); } } else if (DeviceExtension->FileBuffer) { // Copy from RAM disk buffer RtlMoveMemory( buf, DeviceExtension->FileBuffer + Offset->QuadPart, Length); Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = Length; } else { // no image opened Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE; } VFDTRACE(VFDINFO,("[VFD] VfdReadData - %s\n", GetStatusName(Irp->IoStatus.Status))); return; }
NTSTATUS VfdReadWrite ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDEVICE_EXTENSION device_extension; PIO_STACK_LOCATION io_stack; NTSTATUS status; device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; io_stack = IoGetCurrentIrpStackLocation(Irp); #if DBG if (DeviceObject && DeviceObject->DeviceExtension && ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer) { VFDTRACE(VFDINFO, ("[VFD] %-40s %ws\n", GetMajorFuncName(io_stack->MajorFunction), ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceName.Buffer)); } else { VFDTRACE(VFDINFO, ("[VFD] %-40s %p\n", GetMajorFuncName(io_stack->MajorFunction), DeviceObject)); } #endif // DBG #ifdef VFD_PNP if (device_extension->DeviceState != VFD_WORKING) { // Device is not yet started or being removed, reject any IO request // TODO: Queue the IRPs VFDTRACE(VFDWARN, ("[VFD] Device not ready\n")); status = STATUS_INVALID_DEVICE_STATE; goto complete_request; } else { status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp); if (!NT_SUCCESS(status)) { VFDTRACE(0, ("[VFD] Acquire RemoveLock failed: %s\n", GetStatusName(status))); goto complete_request; } } #endif // VFD_PNP /* // Check if volume verification is required if ((DeviceObject->Flags & DO_VERIFY_VOLUME) && !(io_stack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) { status = STATUS_VERIFY_REQUIRED; goto complete_request; } */ // Check if an image is opened if (!device_extension->FileHandle && !device_extension->FileBuffer) { status = STATUS_NO_MEDIA_IN_DEVICE; goto complete_request; } // Check if write operation is allowed if (io_stack->MajorFunction == IRP_MJ_WRITE && (device_extension->MediaFlags & VFD_FLAG_WRITE_PROTECTED)) { status = STATUS_MEDIA_WRITE_PROTECTED; goto complete_request; } // Check for invalid parameters. It is an error for the starting offset // + length to go past the end of the partition, or for the length or // offset to not be a proper multiple of the sector size. // // Others are possible, but we don't check them since we trust the // file system and they aren't deadly. if ((IO_READ_OFF(io_stack) + IO_READ_LEN(io_stack)) > VFD_SECTOR_TO_BYTE(device_extension->Sectors)) { VFDTRACE(VFDWARN, ("[VFD] Offset:%I64u + Length:%u goes past the media size %lu\n", IO_READ_OFF(io_stack), IO_READ_LEN(io_stack), VFD_SECTOR_TO_BYTE(device_extension->Sectors))); status = STATUS_INVALID_PARAMETER; goto complete_request; } if (!VFD_SECTOR_ALIGNED((IO_READ_LEN(io_stack))) || !VFD_SECTOR_ALIGNED((IO_READ_OFF(io_stack)))) { VFDTRACE(VFDWARN, ("[VFD] Invalid Alignment Offset:%I64u Length:%u\n", IO_READ_OFF(io_stack), IO_READ_LEN(io_stack))); status = STATUS_INVALID_PARAMETER; goto complete_request; } // If read/write data length is 0, we are done if (IO_READ_LEN(io_stack) == 0) { status = STATUS_SUCCESS; goto complete_request; } // It seems that actual read/write operation is going to take place // so mark the IRP as pending, insert the IRP into queue list // then signal the device thread to perform the operation IoMarkIrpPending(Irp); ExInterlockedInsertTailList( &device_extension->ListHead, &Irp->Tail.Overlay.ListEntry, &device_extension->ListLock); KeSetEvent( &device_extension->RequestEvent, (KPRIORITY) 0, FALSE); VFDTRACE(VFDINFO,("[VFD] %-40s - STATUS_PENDING\n", GetMajorFuncName(io_stack->MajorFunction))); return STATUS_PENDING; complete_request: // complete the request immediately Irp->IoStatus.Status = status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); VFDTRACE(VFDWARN,("[VFD] %-40s - %s\n", GetMajorFuncName(io_stack->MajorFunction), GetStatusName(status))); return status; }
// // FUNCTION: CVfdShExt::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT) // // PURPOSE: Called by the shell just before the context menu is displayed. // This is where you add your specific menu items. // // PARAMETERS: // hMenu - Handle to the context menu // indexMenu - Index of where to begin inserting menu items // idCmdFirst - Lowest value for new menu ID's // idCmtLast - Highest value for new menu ID's // uFlags - Specifies the context of the menu event // STDMETHODIMP CVfdShExt::QueryContextMenu( HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { UNREFERENCED_PARAMETER(idCmdLast); VFDTRACE(0, ("CVfdShExt::QueryContextMenu()\n")); // // Check if menu items should be added // if ((CMF_DEFAULTONLY & uFlags) || !m_pDataObj || m_nDevice == (ULONG)-1) { VFDTRACE(0, ("Don't add any items.\n")); return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); } // // Drag & Drop handler? // if (m_bDragDrop) { VFDTRACE(0, ("Invoked as the Drop handler.\n")); if (GetFileAttributes(m_sTarget) & FILE_ATTRIBUTE_DIRECTORY) { // if the dropped item is a directory, nothing to do here VFDTRACE(0, ("Dropped object is a directory.\n")); return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); } // Add a drop context menu item AddMenuItem( hMenu, indexMenu, MF_BYPOSITION | MF_STRING, idCmdFirst + VFD_CMD_DROP, g_VfdMenu[VFD_CMD_DROP].textid); return MAKE_HRESULT(SEVERITY_SUCCESS, 0, VFD_CMD_DROP + 1); } // // Context menu handler // VFDTRACE(0, ("Invoked as the context menu handler.\n")); // // Get the VFD media state // HANDLE hDevice = VfdOpenDevice(m_nDevice); if (hDevice == INVALID_HANDLE_VALUE) { VFDTRACE(0, ("device open failed.\n")); return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0); } DWORD status = VfdGetMediaState(hDevice); CloseHandle(hDevice); // // Add context menu items // InsertMenu(hMenu, indexMenu++, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); if (status == ERROR_SUCCESS || status == ERROR_WRITE_PROTECT) { // An image is opened // insert the "save" menu item AddMenuItem( hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, idCmdFirst + VFD_CMD_SAVE, g_VfdMenu[VFD_CMD_SAVE].textid); // insert the "close" menu item AddMenuItem( hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, idCmdFirst + VFD_CMD_CLOSE, g_VfdMenu[VFD_CMD_CLOSE].textid); // insert the "protect" menu item AddMenuItem( hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, idCmdFirst + VFD_CMD_PROTECT, g_VfdMenu[VFD_CMD_PROTECT].textid); // check "protect" menu item if (status == ERROR_WRITE_PROTECT) { CheckMenuItem(hMenu, indexMenu - 1, MF_BYPOSITION | MF_CHECKED); } } else { // The drive is empty // insert the "open" menu item AddMenuItem( hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, idCmdFirst + VFD_CMD_OPEN, g_VfdMenu[VFD_CMD_OPEN].textid); } // Insert the "proterty" menu item AddMenuItem( hMenu, indexMenu++, MF_BYPOSITION | MF_STRING, idCmdFirst + VFD_CMD_PROP, g_VfdMenu[VFD_CMD_PROP].textid); // Insert a separator InsertMenu(hMenu, indexMenu, MF_BYPOSITION | MF_SEPARATOR, 0, NULL); return MAKE_HRESULT(SEVERITY_SUCCESS, 0, VFD_CMD_PROP + 1); }
// // Open dropped file with VFD // DWORD CVfdShExt::DoVfdDrop( HWND hParent) { HANDLE hDevice; DWORD file_attr; ULONG file_size; VFD_FILETYPE file_type; VFD_DISKTYPE disk_type; VFD_MEDIA media_type; DWORD ret; VFDTRACE(0, ("CVfdShExt::DoVfdDropOpen()\n")); // check if dropped file is a valid image ret = VfdCheckImageFile( m_sTarget, &file_attr, &file_type, &file_size); if (ret != ERROR_SUCCESS) { return ret; } // check file size media_type = VfdLookupMedia(file_size); if (!media_type) { PSTR msg = ModuleMessage(MSG_FILE_TOO_SMALL); MessageBox(hParent, msg ? msg : "Bad size", VFD_MSGBOX_TITLE, MB_ICONSTOP); if (msg) { LocalFree(msg); } return ERROR_CANCELLED; } if ((file_type == VFD_FILETYPE_ZIP) || (file_attr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED))) { disk_type = VFD_DISKTYPE_RAM; } else { disk_type = VFD_DISKTYPE_FILE; } // close current image (if opened) ret = DoVfdClose(hParent); if (ret != ERROR_SUCCESS && ret != ERROR_NOT_READY) { return ret; } // open dropped file hDevice = VfdOpenDevice(m_nDevice); if (hDevice == INVALID_HANDLE_VALUE) { return GetLastError(); } ret = VfdOpenImage( hDevice, m_sTarget, disk_type, media_type, FALSE); CloseHandle(hDevice); return ret; }
// // destructor // CVfdFactory::~CVfdFactory() { VFDTRACE(0, ("CVfdFactory::~CVfdFactory()\n")); g_cDllRefCnt--; }
STDMETHODIMP CVfdShExt::InvokeCommand( LPCMINVOKECOMMANDINFO lpcmi) { VFDTRACE(0, ("CVfdShExt::InvokeCommand()\n")); BOOL unicode = FALSE; UINT id; DWORD ret; CMINVOKECOMMANDINFOEX *excmi = (CMINVOKECOMMANDINFOEX *)lpcmi; if (lpcmi->cbSize >= sizeof(CMINVOKECOMMANDINFOEX) && (lpcmi->fMask & CMIC_MASK_UNICODE)) { unicode = TRUE; } if (!unicode && HIWORD(lpcmi->lpVerb)) { VFDTRACE(0, ("ANSI: %s\n", lpcmi->lpVerb)); // ANSI verb for (id = 0; id < sizeof(g_VfdMenu) / sizeof(g_VfdMenu[0]); id++) { if (!lstrcmpi(lpcmi->lpVerb, g_VfdMenu[id].verbA)) { break; } } } else if (unicode && HIWORD(excmi->lpVerbW)) { VFDTRACE(0, ("UNICODE: %ws\n", excmi->lpVerbW)); // UNICODE verb for (id = 0; id < sizeof(g_VfdMenu) / sizeof(g_VfdMenu[0]); id++) { if (!lstrcmpiW(excmi->lpVerbW, g_VfdMenu[id].verbW)) { break; } } } else { VFDTRACE(0, ("Command: %u\n", LOWORD(lpcmi->lpVerb))); // Command ID id = LOWORD(lpcmi->lpVerb); } VFDTRACE(0, ("MenuItem: %u\n", id)); switch (id) { case VFD_CMD_OPEN: ret = DoVfdOpen(lpcmi->hwnd); if (ret == ERROR_SUCCESS) { VfdImageTip(lpcmi->hwnd, m_nDevice); } break; case VFD_CMD_SAVE: ret = DoVfdSave(lpcmi->hwnd); break; case VFD_CMD_CLOSE: ret = DoVfdClose(lpcmi->hwnd); break; case VFD_CMD_PROTECT: ret = DoVfdProtect(lpcmi->hwnd); if (ret == ERROR_SUCCESS) { VfdImageTip(lpcmi->hwnd, m_nDevice); } else if (ret == ERROR_WRITE_PROTECT) { VfdImageTip(lpcmi->hwnd, m_nDevice); ret = ERROR_SUCCESS; } break; case VFD_CMD_DROP: ret = DoVfdDrop(lpcmi->hwnd); if (ret == ERROR_SUCCESS) { VfdImageTip(lpcmi->hwnd, m_nDevice); } break; case VFD_CMD_PROP: { SHOBJECTPROPERTIES pSHObjectProperties; WCHAR path[4] = L" :\\"; pSHObjectProperties = (SHOBJECTPROPERTIES)GetProcAddress( LoadLibrary("shell32"), "SHObjectProperties"); if (!pSHObjectProperties) { pSHObjectProperties = (SHOBJECTPROPERTIES)GetProcAddress( LoadLibrary("shell32"), (LPCSTR)SHOP_EXPORT_ORDINAL); } if (pSHObjectProperties) { path[0] = m_sTarget[0]; pSHObjectProperties(lpcmi->hwnd, SHOP_FILEPATH, path, L"VFD"); } } ret = ERROR_SUCCESS; break; default: return E_INVALIDARG; } if (ret != ERROR_SUCCESS && ret != ERROR_CANCELLED) { MessageBox(lpcmi->hwnd, SystemMessage(ret), VFD_MSGBOX_TITLE, MB_ICONSTOP); } return NOERROR; }
STDMETHODIMP CVfdFactory::LockServer(BOOL fLock) { VFDTRACE(0, ("CVfdFactory::LockServer()\n")); UNREFERENCED_PARAMETER(fLock); return NOERROR; }
// // IOCTL commands handler // NTSTATUS VfdDeviceControl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PDEVICE_EXTENSION device_extension; PIO_STACK_LOCATION io_stack; NTSTATUS status; device_extension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; io_stack = IoGetCurrentIrpStackLocation(Irp); Irp->IoStatus.Information = 0; VFDTRACE(VFDINFO, ("[VFD] %-40s %ws\n", GetIoControlName(IO_CTRLCODE(io_stack)), device_extension->DeviceName.Buffer)); #ifdef VFD_PNP status = IoAcquireRemoveLock(&device_extension->RemoveLock, Irp); if (!NT_SUCCESS(status)) { VFDTRACE(0, ("Acquire RemoveLock failed %s\n", NtStatusToStr(status))); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } #endif // VFD_PNP /* // Check if volume verification is required if ((DeviceObject->Flags & DO_VERIFY_VOLUME) && !(io_stack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) { VFDTRACE(VFDWARN, ("[VFD] %-40s - %s\n", GetIoControlName(IO_CTRLCODE(io_stack)), GetStatusName(STATUS_VERIFY_REQUIRED))); Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_VERIFY_REQUIRED; } */ switch (IO_CTRLCODE(io_stack)) { case IOCTL_VFD_OPEN_IMAGE: // Open an image file or create an empty RAM disk. // Only a few checks are done here. // Actual operation is done in device thread status = VfdOpenCheck( device_extension, (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer, IO_INPUTLEN(io_stack)); if (!NT_SUCCESS(status)) { break; } // Pass the task to the device thread status = STATUS_PENDING; break; case IOCTL_VFD_CLOSE_IMAGE: case IOCTL_DISK_EJECT_MEDIA: case IOCTL_STORAGE_EJECT_MEDIA: // Close the current image file or delete the RAM disk // Only status check is done here. // Actual operation is done in device thread. if (!device_extension->FileHandle && !device_extension->FileBuffer) { status = STATUS_NO_MEDIA_IN_DEVICE; break; } // Pass the task to the device thread status = STATUS_PENDING; break; case IOCTL_VFD_QUERY_IMAGE: // Returns current image file information status = VfdQueryImage( device_extension, (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer, IO_OUTPUTLEN(io_stack), &Irp->IoStatus.Information); break; case IOCTL_VFD_SET_LINK: // Create / remove a persistent drive letter // and store it in the registry if (IO_INPUTLEN(io_stack) < sizeof(CHAR)) { status = STATUS_INVALID_PARAMETER; break; } #ifdef VFD_MOUNT_MANAGER if (OsMajorVersion >= 5) { // Windows 2000/XP // Create a drive letter via the mount manager status = VfdMountMgrMountPoint(device_extension, *(PCHAR)Irp->AssociatedIrp.SystemBuffer); // The new drive letter will be stored in the device extension // and the registry when IOCTL_MOUNTDEV_LINK_CREATED or // IOCTL_MOUNTDEV_LINK_DELETED is issued from the mount manager. } else #else // VFD_MOUNT_MANAGER { // Windows NT style drive letter assignment // Simply create a symbolic link and store the new value status = VfdSetLink(device_extension, *(PCHAR)Irp->AssociatedIrp.SystemBuffer); if (NT_SUCCESS(status)) { // Store the new drive letter into the registry status = VfdStoreLink(device_extension); } } #endif // VFD_MOUNT_MANAGER break; case IOCTL_VFD_QUERY_LINK: // Return the current persistent drive letter if (IO_OUTPUTLEN(io_stack) < sizeof(CHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } *(PCHAR)Irp->AssociatedIrp.SystemBuffer = device_extension->DriveLetter; Irp->IoStatus.Information = sizeof(CHAR); status = STATUS_SUCCESS; break; case IOCTL_VFD_SET_PROTECT: // Set media protect flag if (!device_extension->FileHandle && !device_extension->FileBuffer) { status = STATUS_NO_MEDIA_IN_DEVICE; break; } device_extension->MediaFlags |= VFD_FLAG_WRITE_PROTECTED; status = STATUS_SUCCESS; break; case IOCTL_VFD_CLEAR_PROTECT: // Clear media protect flag if (!device_extension->FileHandle && !device_extension->FileBuffer) { status = STATUS_NO_MEDIA_IN_DEVICE; break; } device_extension->MediaFlags &= ~VFD_FLAG_WRITE_PROTECTED; status = STATUS_SUCCESS; break; case IOCTL_VFD_RESET_MODIFY: // Reset the data modify flag if (!device_extension->FileHandle && !device_extension->FileBuffer) { status = STATUS_NO_MEDIA_IN_DEVICE; break; } device_extension->MediaFlags &= ~VFD_FLAG_DATA_MODIFIED; status = STATUS_SUCCESS; break; case IOCTL_VFD_QUERY_NUMBER: // Return VFD device number (\??\VirtualFD<n>) if (IO_OUTPUTLEN(io_stack) < sizeof(ULONG)) { status = STATUS_BUFFER_TOO_SMALL; break; } *(PULONG)Irp->AssociatedIrp.SystemBuffer= device_extension->DeviceNumber; Irp->IoStatus.Information = sizeof(ULONG); status = STATUS_SUCCESS; break; case IOCTL_VFD_QUERY_NAME: // Return VFD device name (\Device\Floppy<n>) // counted unicode string (not null terminated) if (IO_OUTPUTLEN(io_stack) < sizeof(USHORT)) { status = STATUS_BUFFER_TOO_SMALL; break; } { PUSHORT p = (PUSHORT)Irp->AssociatedIrp.SystemBuffer; *p = device_extension->DeviceName.Length; if (IO_OUTPUTLEN(io_stack) < sizeof(USHORT) + *p) { Irp->IoStatus.Information = sizeof(USHORT); status = STATUS_BUFFER_OVERFLOW; break; } RtlCopyMemory(p + 1, device_extension->DeviceName.Buffer, *p); Irp->IoStatus.Information = sizeof(USHORT) + *p; } status = STATUS_SUCCESS; break; case IOCTL_VFD_QUERY_VERSION: // Return the VFD driver version if (IO_OUTPUTLEN(io_stack) < sizeof(ULONG)) { status = STATUS_BUFFER_TOO_SMALL; break; } *(PULONG)Irp->AssociatedIrp.SystemBuffer = (VFD_DRIVER_MAJOR << 16) | VFD_DRIVER_MINOR | VFD_DEBUG_FLAG; Irp->IoStatus.Information = sizeof(ULONG); status = STATUS_SUCCESS; break; // // standard disk and storage I/O control requests // case IOCTL_DISK_CHECK_VERIFY: case IOCTL_STORAGE_CHECK_VERIFY: case IOCTL_STORAGE_CHECK_VERIFY2: if (IO_OUTPUTLEN(io_stack) >= sizeof(ULONG)) { *(PULONG)Irp->AssociatedIrp.SystemBuffer = device_extension->MediaChangeCount; Irp->IoStatus.Information = sizeof(ULONG); } status = STATUS_SUCCESS; break; case IOCTL_DISK_FORMAT_TRACKS: case IOCTL_DISK_FORMAT_TRACKS_EX: // Only parameter checks are performed here // Actual operation is done by the device thread status = VfdFormatCheck( device_extension, (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer, IO_INPUTLEN(io_stack), IO_CTRLCODE(io_stack)); if (!NT_SUCCESS(status)) { break; } // Pass the task to the device thread status = STATUS_PENDING; break; case IOCTL_DISK_GET_DRIVE_GEOMETRY: // Returns the geometry of current media if (!device_extension->FileHandle && !device_extension->FileBuffer) { status = STATUS_NO_MEDIA_IN_DEVICE; break; } // fall through case IOCTL_DISK_GET_MEDIA_TYPES: case IOCTL_STORAGE_GET_MEDIA_TYPES: // Return *the last mounted* disk geometry, although xxx_GET_MEDIA_TYPES // commands are supposed to return all supported media types. // This makes the matter much simpler...;-) // If no image has been mounted yet, 1.44MB media is assumed. if (IO_OUTPUTLEN(io_stack) < sizeof(DISK_GEOMETRY)) { return STATUS_BUFFER_TOO_SMALL; } // Copy appropriate DISK_GEOMETRY into the output buffer if (device_extension->Geometry) { RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, device_extension->Geometry, sizeof(DISK_GEOMETRY)); } else { // default = 3.5" 1.44 MB media RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &geom_tbl[VFD_MEDIA_F3_1P4], sizeof(DISK_GEOMETRY)); } Irp->IoStatus.Information = sizeof(DISK_GEOMETRY); status = STATUS_SUCCESS; break; case IOCTL_DISK_GET_LENGTH_INFO: // Return disk length information // (Windows XP requires this request to be handled) if (!device_extension->FileHandle && !device_extension->FileBuffer) { status = STATUS_NO_MEDIA_IN_DEVICE; break; } if (IO_OUTPUTLEN(io_stack) < sizeof(GET_LENGTH_INFORMATION)) { status = STATUS_BUFFER_TOO_SMALL; break; } ((PGET_LENGTH_INFORMATION)Irp->AssociatedIrp.SystemBuffer)->Length.QuadPart = VFD_SECTOR_TO_BYTE(device_extension->Sectors); Irp->IoStatus.Information = sizeof(GET_LENGTH_INFORMATION); status = STATUS_SUCCESS; break; case IOCTL_DISK_IS_WRITABLE: // Checks if current media is writable if (!device_extension->FileHandle && !device_extension->FileBuffer) { status = STATUS_NO_MEDIA_IN_DEVICE; } else if (device_extension->MediaFlags & VFD_FLAG_WRITE_PROTECTED) { status = STATUS_MEDIA_WRITE_PROTECTED; } else { status = STATUS_SUCCESS; } break; /* case IOCTL_DISK_MEDIA_REMOVAL: case IOCTL_STORAGE_MEDIA_REMOVAL: // Since removal lock is irrelevant for virtual disks, // there's really nothing to do here... status = STATUS_SUCCESS; break; case IOCTL_STORAGE_GET_HOTPLUG_INFO: { PSTORAGE_HOTPLUG_INFO hotplug; if (IO_OUTPUTLEN(io_stack) < sizeof(STORAGE_HOTPLUG_INFO)) { status = STATUS_BUFFER_TOO_SMALL; break; } hotplug = (PSTORAGE_HOTPLUG_INFO)Irp->AssociatedIrp.SystemBuffer; RtlZeroMemory(hotplug, sizeof(STORAGE_HOTPLUG_INFO)); hotplug->Size = sizeof(STORAGE_HOTPLUG_INFO); hotplug->MediaRemovable = 1; Irp->IoStatus.Information = sizeof(STORAGE_HOTPLUG_INFO); status = STATUS_SUCCESS; } break; */ #ifdef VFD_MOUNT_MANAGER // // IO control requests received from the mount manager // (on Windows 2000 / XP) // case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: // Returns a unique ID for the target device status = VfdMountDevUniqueId( device_extension, Irp->AssociatedIrp.SystemBuffer, IO_OUTPUTLEN(io_stack), &Irp->IoStatus); break; // case IOCTL_MOUNTDEV_UNIQUE_ID_CHANGE_NOTIFY: case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: // Returns the device name of the target device status = VfdMountDevDeviceName( device_extension, Irp->AssociatedIrp.SystemBuffer, IO_OUTPUTLEN(io_stack), &Irp->IoStatus); break; case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: // Returns the drive letter link which we want the mount manager // to create. This request is issued in response to the volume // arrival notification, and the mount manager will create the // symbolic link. status = VfdMountDevSuggestedLink( device_extension, Irp->AssociatedIrp.SystemBuffer, IO_OUTPUTLEN(io_stack), &Irp->IoStatus); break; case IOCTL_MOUNTDEV_LINK_CREATED: case IOCTL_MOUNTDEV_LINK_DELETED: // Issued after the mount manager created/deleted a symbolic link status = VfdMountDevLinkModified( device_extension, Irp->AssociatedIrp.SystemBuffer, IO_INPUTLEN(io_stack), IO_CTRLCODE(io_stack)); break; /* case IOCTL_MOUNTDEV_QUERY_STABLE_GUID: { PMOUNTDEV_STABLE_GUID guid; if (IO_OUTPUTLEN(io_stack) < sizeof(MOUNTDEV_STABLE_GUID)) { status = STATUS_INVALID_PARAMETER; break; } guid = Irp->AssociatedIrp.SystemBuffer; RtlCopyMemory( &guid->StableGuid, &VFD_GUID, sizeof(GUID)); Irp->IoStatus.Information = sizeof(guid); status = STATUS_SUCCESS; } break; */ #endif // VFD_MOUNT_MANAGER default: // Unknown IOCTL request status = STATUS_INVALID_DEVICE_REQUEST; break; } #if DBG if ((NT_SUCCESS(status) && (TraceFlags & VFDINFO) == VFDINFO) || (TraceFlags & VFDWARN) == VFDWARN) { VFDTRACE(0,("[VFD] %-40s - %s\n", GetIoControlName(IO_CTRLCODE(io_stack)), GetStatusName(status))); } #endif if (status == STATUS_PENDING) { // Let the device thread perform the operation IoMarkIrpPending(Irp); ExInterlockedInsertTailList( &device_extension->ListHead, &Irp->Tail.Overlay.ListEntry, &device_extension->ListLock); KeSetEvent( &device_extension->RequestEvent, (KPRIORITY) 0, FALSE); } else { // complete the operation Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); #ifdef VFD_PNP IoReleaseRemoveLock(&device_extension->RemoveLock, Irp); #endif // VFD_PNP } return status; }
STDMETHODIMP_(ULONG) CVfdFactory::AddRef() { VFDTRACE(0, ("CVfdFactory::AddRef()\n")); return ++m_cRefCnt; }
// // Check IOCTL_VFD_OPEN_IMAGE input parameters // NTSTATUS VfdOpenCheck( PDEVICE_EXTENSION DeviceExtension, PVFD_IMAGE_INFO ImageInfo, ULONG InputLength) { // Check media status if (DeviceExtension->FileHandle || DeviceExtension->FileBuffer) { VFDTRACE(VFDWARN, ("[VFD] image already opened.\n")); return STATUS_DEVICE_BUSY; } // Check input parameter length if (InputLength < sizeof(VFD_IMAGE_INFO) || InputLength < sizeof(VFD_IMAGE_INFO) + ImageInfo->NameLength) { return STATUS_INVALID_PARAMETER; } // Check input parameters if (ImageInfo->MediaType == VFD_MEDIA_NONE || ImageInfo->MediaType >= VFD_MEDIA_MAX) { VFDTRACE(VFDWARN, ("[VFD] invalid MediaType - %u.\n", ImageInfo->MediaType)); return STATUS_INVALID_PARAMETER; } if (ImageInfo->DiskType == VFD_DISKTYPE_FILE && ImageInfo->NameLength == 0) { VFDTRACE(VFDWARN, ("[VFD] File name required for VFD_DISKTYPE_FILE.\n")); return STATUS_INVALID_PARAMETER; } // create a security context to match the calling process' context // the driver thread uses this context to impersonate the client // to open the specified image file // if (ImageInfo->DiskType == VFD_DISKTYPE_FILE) { SECURITY_QUALITY_OF_SERVICE sqos; if (DeviceExtension->SecurityContext != NULL) { SeDeleteClientSecurity(DeviceExtension->SecurityContext); } else { DeviceExtension->SecurityContext = (PSECURITY_CLIENT_CONTEXT)ExAllocatePoolWithTag( NonPagedPool, sizeof(SECURITY_CLIENT_CONTEXT), VFD_POOL_TAG); } RtlZeroMemory(&sqos, sizeof(SECURITY_QUALITY_OF_SERVICE)); sqos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE); sqos.ImpersonationLevel = SecurityImpersonation; sqos.ContextTrackingMode = SECURITY_STATIC_TRACKING; sqos.EffectiveOnly = FALSE; SeCreateClientSecurity( PsGetCurrentThread(), &sqos, FALSE, DeviceExtension->SecurityContext); } return STATUS_SUCCESS; }
// // Open a virtual floppy image file or create an empty ram disk // NTSTATUS VfdOpenImage ( IN PDEVICE_EXTENSION DeviceExtension, IN PVFD_IMAGE_INFO ImageInfo) { IO_STATUS_BLOCK io_status; NTSTATUS status = STATUS_SUCCESS; const DISK_GEOMETRY *geometry; ULONG sectors; ULONG alignment; VFDTRACE(0, ("[VFD] VfdOpenImage - IN\n")); // // Store file name in the device extension // if (ImageInfo->NameLength) { if (ImageInfo->NameLength + 1 > DeviceExtension->FileName.MaximumLength) { // expand the filename buffer if (DeviceExtension->FileName.Buffer) { ExFreePool(DeviceExtension->FileName.Buffer); RtlZeroMemory( &DeviceExtension->FileName, sizeof(ANSI_STRING)); } DeviceExtension->FileName.Buffer = (PCHAR)ExAllocatePoolWithTag( NonPagedPool, ImageInfo->NameLength + 1, VFD_POOL_TAG); if (!DeviceExtension->FileName.Buffer) { VFDTRACE(0, ("[VFD] Can't allocate memory for image path\n")); return STATUS_INSUFFICIENT_RESOURCES; } DeviceExtension->FileName.MaximumLength = (USHORT)(ImageInfo->NameLength + 1); RtlZeroMemory( DeviceExtension->FileName.Buffer, DeviceExtension->FileName.MaximumLength); } if (DeviceExtension->FileName.Buffer) { RtlCopyMemory( DeviceExtension->FileName.Buffer, ImageInfo->FileName, ImageInfo->NameLength); DeviceExtension->FileName.Buffer[ImageInfo->NameLength] = '\0'; } } DeviceExtension->FileName.Length = ImageInfo->NameLength; // // Get DISK_GEOMETRY and calculate the media capacity // -- validity of the ImageInfo->MediaType value is assured in // the VfdOpenCheck function // geometry = &geom_tbl[ImageInfo->MediaType]; sectors = geometry->Cylinders.LowPart * geometry->TracksPerCylinder * geometry->SectorsPerTrack; if (ImageInfo->ImageSize != 0 && ImageInfo->ImageSize < VFD_SECTOR_TO_BYTE(sectors)) { VFDTRACE(0, ("[VFD] Image is smaller than the media\n")); return STATUS_INVALID_PARAMETER; } // // Prepare a virtual media according to the ImageInfo // if (ImageInfo->DiskType == VFD_DISKTYPE_FILE) { // // open an existing image file // HANDLE file_handle; OBJECT_ATTRIBUTES attributes; UNICODE_STRING unicode_name; FILE_STANDARD_INFORMATION file_standard; FILE_BASIC_INFORMATION file_basic; FILE_ALIGNMENT_INFORMATION file_alignment; PFILE_OBJECT file_object; BOOLEAN network_drive; // convert the filename into a unicode string status = RtlAnsiStringToUnicodeString( &unicode_name, &DeviceExtension->FileName, TRUE); if (!NT_SUCCESS(status)) { VFDTRACE(0, ("[VFD] Failed to convert filename to UNICODE\n")); return status; } VFDTRACE(VFDINFO, ("[VFD] Opening %s\n", DeviceExtension->FileName.Buffer)); // prepare an object attribute to open InitializeObjectAttributes( &attributes, &unicode_name, OBJ_CASE_INSENSITIVE, NULL, NULL); // open the target file status = ZwCreateFile( &file_handle, GENERIC_READ | GENERIC_WRITE, &attributes, &io_status, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_NO_INTERMEDIATE_BUFFERING | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); RtlFreeUnicodeString(&unicode_name); if (!NT_SUCCESS(status)) { VFDTRACE(0, ("[VFD] ZwCreateFile - %s\n", GetStatusName(status))); return status; } // Check the file size status = ZwQueryInformationFile( file_handle, &io_status, &file_standard, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); if (!NT_SUCCESS(status)) { VFDTRACE(0, ("[VFD] ZwQueryInformationFile - FILE_STANDARD_INFORMATION\n")); ZwClose(file_handle); goto exit_func; } // Actual file size can be larger than the media capacity if (file_standard.EndOfFile.QuadPart < VFD_SECTOR_TO_BYTE(sectors)) { VFDTRACE(0, ("[VFD] file is smaller than the media.\n")); status = STATUS_INVALID_PARAMETER; ZwClose(file_handle); goto exit_func; } DeviceExtension->ImageSize = file_standard.EndOfFile.LowPart; // Find out whether the file is on a local disk or a network drive network_drive = FALSE; status = ObReferenceObjectByHandle( file_handle, GENERIC_READ, NULL, KernelMode, &file_object, NULL); if (NT_SUCCESS(status)) { if (file_object && file_object->DeviceObject) { VFDTRACE(VFDINFO, ("[VFD] Device type is 0x%08x\n", file_object->DeviceObject->DeviceType)); if (file_object->DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) { network_drive = TRUE; } // how about these types ? // FILE_DEVICE_NETWORK // FILE_DEVICE_NETWORK_BROWSER // FILE_DEVICE_NETWORK_REDIRECTOR } else { VFDTRACE(VFDWARN, ("[VFD Cannot decide the device type\n")); } ObDereferenceObject(file_object); } else { VFDTRACE(0, ("[VFD] ObReferenceObjectByHandle - %s\n", GetStatusName(status))); } if (!network_drive) { // The NT cache manager can deadlock if a filesystem that is using // the cache manager is used in a virtual disk that stores its file // on a file systemthat is also using the cache manager, this is // why we open the file with FILE_NO_INTERMEDIATE_BUFFERING above, // however if the file is compressed or encrypted NT will not honor // this request and cache it anyway since it need to store the // decompressed/unencrypted data somewhere, therefor we put an // extra check here and don't alow disk images to be compressed/ // encrypted. status = ZwQueryInformationFile( file_handle, &io_status, &file_basic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(status)) { VFDTRACE(0, ("[VFD] ZwQueryInformationFile - FILE_BASIC_INFORMATION\n")); ZwClose(file_handle); goto exit_func; } if (file_basic.FileAttributes & (FILE_ATTRIBUTE_COMPRESSED | FILE_ATTRIBUTE_ENCRYPTED)) { VFDTRACE(0, ("[VFD] Image file is compressed and/or encrypted\n")); status = STATUS_ACCESS_DENIED; ZwClose(file_handle); goto exit_func; } } // Retrieve the file alignment requirement status = ZwQueryInformationFile( file_handle, &io_status, &file_alignment, sizeof(FILE_ALIGNMENT_INFORMATION), FileAlignmentInformation); if (!NT_SUCCESS(status)) { VFDTRACE(0, ("[VFD] ZwQueryInformationFile - FILE_ALIGNMENT_INFORMATION\n")); ZwClose(file_handle); goto exit_func; } DeviceExtension->FileHandle = file_handle; alignment = file_alignment.AlignmentRequirement; VFDTRACE(0, ("[VFD] Opened an image file\n")); } else { // // Create an empty RAM disk // DeviceExtension->FileBuffer = (PUCHAR)ExAllocatePoolWithTag( NonPagedPool, VFD_SECTOR_TO_BYTE(sectors), VFD_POOL_TAG); if (!DeviceExtension->FileBuffer) { VFDTRACE(0, ("[VFD] Can't allocate memory for RAM disk\n")); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory( DeviceExtension->FileBuffer, VFD_SECTOR_TO_BYTE(sectors)); if (ImageInfo->ImageSize) { DeviceExtension->ImageSize = ImageInfo->ImageSize; } else { DeviceExtension->ImageSize = VFD_SECTOR_TO_BYTE(sectors); } alignment = FILE_WORD_ALIGNMENT; VFDTRACE(0, ("[VFD] Created an empty RAM disk\n")); } DeviceExtension->MediaChangeCount++; DeviceExtension->MediaType = ImageInfo->MediaType; DeviceExtension->MediaFlags = ImageInfo->MediaFlags; DeviceExtension->FileType = ImageInfo->FileType; DeviceExtension->Geometry = geometry; DeviceExtension->Sectors = sectors; VFDTRACE(0, ("[VFD] Media:%d Flag:0x%02x Size:%lu Capacity:%lu\n", DeviceExtension->MediaType, DeviceExtension->MediaFlags, DeviceExtension->ImageSize, DeviceExtension->Sectors)); DeviceExtension->DeviceObject->AlignmentRequirement = alignment; exit_func: VFDTRACE(0, ("[VFD] VfdOpenImage - %s\n", GetStatusName(status))); return status; }