Пример #1
0
//
//	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"));
}
Пример #2
0
//
//	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
}
Пример #3
0
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;
}
Пример #4
0
//
//	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;
}
Пример #5
0
//
// 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);
}
Пример #6
0
//
//	constructor
//
CVfdFactory::CVfdFactory()
{
	VFDTRACE(0, ("CVfdFactory::CVfdFactory()\n"));

	m_cRefCnt = 0L;

	g_cDllRefCnt++;
}
Пример #7
0
STDMETHODIMP_(ULONG) CVfdFactory::Release()
{
	VFDTRACE(0, ("CVfdFactory::Release()\n"));

	if (--m_cRefCnt) {
		return m_cRefCnt;
	}

	delete this;

	return 0L;
}
Пример #8
0
STDMETHODIMP_(ULONG) CVfdFactory::Release()
{
	VFDTRACE(0, ("CVfdFactory::Release()\n"));

	if (--m_cRefCnt) {
		return m_cRefCnt;
	}

#ifndef __REACTOS__
	delete this;
#endif

	return 0L;
}
Пример #9
0
//
//	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;
}
Пример #10
0
//
//	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);
}
Пример #11
0
//
//	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;
}
Пример #12
0
//
//	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;
}
Пример #13
0
//
//	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;
}
Пример #14
0
//
//	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;
}
Пример #15
0
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;
}
Пример #16
0
//
//	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);
}
Пример #17
0
//
//	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;
}
Пример #18
0
//
//	destructor
//
CVfdFactory::~CVfdFactory()
{
	VFDTRACE(0, ("CVfdFactory::~CVfdFactory()\n"));

	g_cDllRefCnt--;
}
Пример #19
0
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;
}
Пример #20
0
STDMETHODIMP CVfdFactory::LockServer(BOOL fLock)
{
	VFDTRACE(0, ("CVfdFactory::LockServer()\n"));
	UNREFERENCED_PARAMETER(fLock);
	return NOERROR;
}
Пример #21
0
//
//	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;
}
Пример #22
0
STDMETHODIMP_(ULONG) CVfdFactory::AddRef()
{
	VFDTRACE(0, ("CVfdFactory::AddRef()\n"));

	return ++m_cRefCnt;
}
Пример #23
0
//
//	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;
}
Пример #24
0
//
//	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;
}