📄 speedcd_mfc.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 + -