⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 speedcd_mfc.cpp

📁 虚拟光驱程序
💻 CPP
字号:


#include "stdafx.h"
#include "SPEEDcd_mfc.h"

#include "dynamic.h"

#include <winioctl.h>
#include <ntddcdrm.h>
#include <winsvc.h>
#include <dbt.h>


//
// Defining private IOCTLs and structures.
//
#define IOCTL_SPEEDCD_GET_DUBUG_LOG CTL_CODE( \
	FILE_DEVICE_CD_ROM, \
	0x801, \
	METHOD_BUFFERED, \
	FILE_ANY_ACCESS )

#define IOCTL_SPEEDCD_ADD_DEVICE CTL_CODE( \
	FILE_DEVICE_CD_ROM, \
	0x802, \
	METHOD_BUFFERED, \
	FILE_ANY_ACCESS )

#define IOCTL_SPEEDCD_REMOVE_DEVICE CTL_CODE( \
	FILE_DEVICE_CD_ROM, \
	0x803, \
	METHOD_BUFFERED, \
	FILE_ANY_ACCESS )

// Previous version did not support this IOCTL
// V 1.31 was the last version that had no support for it.
#define IOCTL_SPEEDCD_GET_VERSION CTL_CODE( \
	FILE_DEVICE_CD_ROM, \
	0x804, \
	METHOD_BUFFERED, \
	FILE_ANY_ACCESS )

typedef struct {     
	WCHAR     wcDriveLetter; 
	WCHAR     szFileName[500]; 
} SPEEDCD_ADD_DEVICE;


HANDLE AttachToDriver()
{
	// TODO: Add your control notification handler code here
	HANDLE h;
	h = CreateFile(
		"\\\\.\\SPEEDCD",
		GENERIC_READ,
		FILE_SHARE_READ/*|FILE_SHARE_WRITE*/ /*FILE_SHARE_READ*/,
		NULL,
		OPEN_EXISTING,
		0,
		NULL);
	// Driver not started or not installed
	if (h == INVALID_HANDLE_VALUE )
	{
		// Open Service Control Manager on the local machine...
		SC_HANDLE hSCManager = OpenSCManager(NULL, NULL,
							   GENERIC_READ|GENERIC_WRITE);

		CString sSystemDirectory;
		// Assume driver is in the same directory as the DLL.

		GetSystemDirectory( sSystemDirectory.GetBuffer(500) ,500);
		sSystemDirectory.ReleaseBuffer();
		
		CString sDest, sSource;
		sDest = sSystemDirectory+"\\Drivers\\SPEEDCD.SYS";
		sSource = "SPEEDCD.SYS";
		
		CFileFind cff;

		BOOL bFound = cff.FindFile("SPEEDCD.SYS");

		/*if (!bFound)
			AfxMessageBox("Warning: speedcd.sys not found in application directory."
			              );
	   */
		if (!CopyFile(sSource,sDest,FALSE))
		{
			/*CString s;
			s.Format("Warning: Unable to copy file %s to %s\nError #%i",
					sSource, sDest, GetLastError());
			AfxMessageBox(s);
			// Keep going and hope for the best.
			*/
		}

		// Install and Start the driver so that we can use it
		if (!InstallAndStartDriver(hSCManager, "SPEEDCD","System32\\DRIVERS\\SPEEDCD.SYS"))
		{
			// Close Service Control Manager
			CloseServiceHandle(hSCManager);
			AfxMessageBox("Warning: Unable to install or start driver.");
			// Keep going and hope for the best.

		}else
		{
			// Close Service Control Manager
			CloseServiceHandle(hSCManager);
		}

		h = CreateFile(
			"\\\\.\\SPEEDCD",
			GENERIC_READ,
			FILE_SHARE_READ/*|FILE_SHARE_WRITE*/ /*FILE_SHARE_READ*/,
			NULL,
			OPEN_EXISTING,
			0,
			NULL);
	}
	return h;
}

ULONG GetSPEEDCDDriverVer(HANDLE h)
{
    ULONG ver;
    DWORD dwBytes = sizeof(ULONG);

	DWORD rr = DeviceIoControl(  h,        // handle to device of interest
		  IOCTL_SPEEDCD_GET_VERSION ,   // dwIoControlCode, control code
									// of operation to perform
		  NULL,                     // lpInBuffer is not used; must be NULL
		  0,                        // nInBufferSize is not used; must be zero
		  &ver, // pointer to output buffer
		  dwBytes,  // size, in bytes, of lpOutBuffer
		  &dwBytes,				    // pointer to variable to receive
									// output byte count
		  FALSE					    // pointer to OVERLAPPED structure
									// for asynchronous operation
		);

    if (!rr)
        ver = 0;
    return ver;
}

BOOL UninstallCleanup()
{
	// Open Service Control Manager on the local machine...
	SC_HANDLE hSCManager = OpenSCManager(NULL, NULL,
						   GENERIC_READ|GENERIC_WRITE);

    BOOL r = UninstallDriver(hSCManager, "SPEEDCD");
	// Close Service Control Manager
	CloseServiceHandle(hSCManager);
//			AfxMessageBox("Driver not installed or unable to uninstall driver.");
	// delete the file from the system directory
	CString sSystemDirectory;
	// Assume driver is in the system directory under drivers
	GetSystemDirectory( sSystemDirectory.GetBuffer(500) ,500);
	sSystemDirectory.ReleaseBuffer();

	DeleteFile(sSystemDirectory+"\\drivers\\speedcd.sys");

    return r;
}

BOOL AddPersistant(char cLetter, CString sPath)
{
    CString sValueName;
    sValueName.Format(
        "SYSTEM\\CurrentControlSet\\Services\\SPEEDCD\\Parameters\\%c",cLetter);

    LONG r = RegSetValueEx(
    HKEY_LOCAL_MACHINE,           // handle to key to set value for
    sValueName, // name of the value to set
    0,      // reserved
    REG_SZ,        // flag for value type
    (const unsigned char *)sPath.GetBuffer(1),  // address of value data
    sPath.GetLength()+1         // size in bytes of value data + NULL
    );
    return (r == ERROR_SUCCESS);
}
//
//   sPath can be a fully qualified UNC path 
//   \\server\share or a normal full path D:\file.ext
//
//   sLetter is the letter A: or b:
//
BOOL Mount(HANDLE h,CString sPath, char cLetter, BOOL bPersist)
{

    // Convert UNC names to explicit UNC paths
    if (sPath.Left(2) == "\\\\")
        sPath = "UNC\\" +sPath.Right(sPath.GetLength()-2);
	DWORD dwIoCtl = IOCTL_SPEEDCD_ADD_DEVICE;
	DWORD dwBytes = sizeof(SPEEDCD_ADD_DEVICE);
    SPEEDCD_ADD_DEVICE vacdBuf;
    BYTE * pBuf = (BYTE *) &vacdBuf;
    CString sLetter;
    sLetter.Format("%c",cLetter);
	sLetter.MakeUpper();
	char * pString;
	int iLengthString = sLetter.GetLength();
	pString = sLetter.GetBuffer(1);
    WCHAR szDriveLetter[10];
	int rr = MultiByteToWideChar(  
		  CP_ACP ,         // code page
		  MB_PRECOMPOSED,         // character-type options
		  pString, // address of string to map
		  iLengthString+1,      // number of bytes in string
		  szDriveLetter,  // address of wide-character buffer
		  10*sizeof(WCHAR)        // size of buffer
		  );
    vacdBuf.wcDriveLetter = szDriveLetter[0];
	sLetter.ReleaseBuffer();
	if (rr == 0)
        return FALSE;
	CString sFile = sPath;
	pString = sFile.GetBuffer(1);
	iLengthString = sFile.GetLength();
	rr = MultiByteToWideChar(  
		  CP_ACP ,         // code page
		  MB_PRECOMPOSED,         // character-type options
		  pString, // address of string to map
		  iLengthString+1,      // number of bytes in string
		  vacdBuf.szFileName,  // address of wide-character buffer
		  500*sizeof(WCHAR)      // size of buffer
		  );
	if (rr == 0)
		return FALSE;
//
//   Path names must be specified as follows... in Unicode.
//
//   B:\myfile.dat
//   UNC\server\share
//
//   Length of the path is limited to MAX_PATH.
//
	// fill in the array of structures for the media types
	rr = DeviceIoControl(  h,        // handle to device of interest
		  dwIoCtl ,   // dwIoControlCode, control code
									// of operation to perform
		  NULL,                     // lpInBuffer is not used; must be NULL
		  0,                        // nInBufferSize is not used; must be zero
		  pBuf, // pointer to output buffer
		  dwBytes,  // size, in bytes, of lpOutBuffer
		  &dwBytes,				    // pointer to variable to receive
									// output byte count
		  FALSE					    // pointer to OVERLAPPED structure
									// for asynchronous operation
		);
    if (rr && bPersist)
    {
        // Save in persistant list if success and we were told to make it persistant
        AddPersistant(cLetter, sPath);
    }
    
	if (rr)
	{ // Here's how you call the function when you've added a drive letter
      // In this call, DriveLetter is the drive letter that you added
      BroadcastVolumeDeviceChange(DBT_DEVICEARRIVAL, (WCHAR)cLetter);
	}    
	return rr;
}

BOOL RemovePersistant(char cLetter)
{
    CString sValueName;
    sValueName.Format(
        "%c",cLetter);
    HKEY hkResult;
    LONG r = RegOpenKeyEx(
        HKEY_LOCAL_MACHINE,         // handle to open key
        "SYSTEM\\CurrentControlSet\\Services\\SPEEDCD\\Parameters",
        0, KEY_SET_VALUE, &hkResult);
    if  (r != ERROR_SUCCESS)
        return FALSE;

    LONG rr = RegDeleteValue(
        hkResult, // handle to key
        sValueName   // address of value name
        );
    return (r == ERROR_SUCCESS);
}

BOOL Unmount(char cLetter)
{
    // Always remove from persistant list.
    RemovePersistant(cLetter);

	HANDLE h;
	CString sDevice;

	sDevice.Format("\\\\.\\%c:",cLetter);
	h = CreateFile(
		sDevice,
		GENERIC_READ,
		FILE_SHARE_READ/*|FILE_SHARE_WRITE*/ /*FILE_SHARE_READ*/,
		NULL,
		OPEN_EXISTING,
		0,
		NULL);

	if (h == NULL || h == INVALID_HANDLE_VALUE )
	{
		return FALSE;
	}

	DWORD dwBytes = 0;
	// fill in the array of structures for the media types
	DWORD r = DeviceIoControl(  h,        // handle to device of interest
		  IOCTL_SPEEDCD_REMOVE_DEVICE ,   // dwIoControlCode, control code
									// of operation to perform
		  NULL,                     // lpInBuffer is not used; must be NULL
		  0,                        // nInBufferSize is not used; must be zero
		  NULL, // pointer to output buffer
		  0,  // size, in bytes, of lpOutBuffer
		  &dwBytes,				    // pointer to variable to receive
									// output byte count
		  FALSE					    // pointer to OVERLAPPED structure
									// for asynchronous operation
		);
   if (r)
   {	// Here's how you call the function when you've removed a drive letter
       // In this call, DriveLetter is the drive letter that you removed
       BroadcastVolumeDeviceChange(DBT_DEVICEREMOVECOMPLETE,(WCHAR) cLetter);
   }
   return r;
}
 
// Call this function when you've added/removed a drive letter symbolic
// link in kernel mode.  When using Win32 alone to create your symbolic
// link (using DefineDosDevice()), you'll end up with symbolic links in
// the session namespace (which you probably don't want) rather than
// the global namespace.  The solution is to create the drive letter
// symbolic links in kernel mode, but then you'll discover (as you did)
// that DefineDosDevice() does more than just create symbolic links... it
// also notifies everybody that a drive letter assignment was made.  So
// if you create your symbolic links in kernel mode you'll need to add this
// extra functionality, and as far as I can tell this function is sufficient.
HRESULT BroadcastVolumeDeviceChange(WPARAM notification, WCHAR DriveLetter)
{
	static PDEV_BROADCAST_VOLUME pMyDevHdr = NULL;
	DWORD dwFlag = BSM_ALLCOMPONENTS;
	DWORD volumeMask =  1<<(DriveLetter - L'A');

	// Allocate our broadcast header and keep it around (static)
	// We have to keep it around because if we post the broadcast the buffers that we
	// pass into the broadcast have to stick around after this call returns.
	if (NULL == pMyDevHdr)
	{
		pMyDevHdr = new DEV_BROADCAST_VOLUME;
	}

	// Initialize our broadcast header
	pMyDevHdr->dbcv_devicetype = DBT_DEVTYP_VOLUME;
	pMyDevHdr->dbcv_size = sizeof(DEV_BROADCAST_VOLUME);
	pMyDevHdr->dbcv_flags = DBTF_NET;
	pMyDevHdr->dbcv_unitmask = volumeMask;
	// Broadcast the device change notification
	BroadcastSystemMessage(BSF_IGNORECURRENTTASK,
	                       &dwFlag,
	                       WM_DEVICECHANGE,
	                       notification,
    					   (LPARAM)pMyDevHdr);

	if (DBT_DEVICEARRIVAL!=notification)
	    BroadcastSystemMessage(BSF_IGNORECURRENTTASK,
	                       &dwFlag,
	                       WM_DEVICECHANGE,
	                       notification,
                             (LPARAM)pMyDevHdr);
	return S_OK;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -