📄 driverinterface.c
字号:
// Description:
// By Sarah Dean
// Email: sdean12@sdean12.org
// WWW: http://www.FreeOTFE.org/
//
// -----------------------------------------------------------------------------
//
#include "DriverInterface.h"
#include "DriverInterfaceCommon.h"
#include "FreeOTFEDebug.h"
#include "FreeOTFElib.h"
#include "FreeOTFE4PDARegistry.h"
#include "FreeOTFEGUIlib.h"
#include "FreeOTFE4PDAAPIConsts.h"
#include "SDUGeneral.h"
#include <stdio.h> // Needed for wcsncpy(...)
#include <StoreMgr.h> // Needed for BLOCK_DRIVER_GUID_STRING
// =========================================================================
// Forward declarations...
BOOL _driver_MountDIOC_DLLOption(DIOC_MOUNT* mountDetails, BOOL fullPath);
// =========================================================================
// Obtain driver version ID
// Note: Version ID taken from DLL's version info block
BOOL driver_VersionID(DWORD* versionID)
{
BOOL retval = FALSE;
WCHAR* DLLFilename;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_VersionID\n")));
DLLFilename = driver_AllocMainDLLFullFilename(TRUE);
if (DLLFilename == NULL)
{
// Do nothing; retval already set to FALSE
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("UNABLE TO GET FILENAME FOR MAIN DLL FILENAME")));
}
else
{
retval = SDUGetVersionInfoShort(DLLFilename, versionID);
SecZeroAndFreeWCHARMemory(DLLFilename);
}
if (!(retval))
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("FAILED TO GET VERSION ID\n")));
}
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Debug level : %d\n"), FreeOTFEDebugLevel));
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Driver version: 0x%08x (v%02d.%02d.%04d)\n"),
*versionID,
(*versionID & 0xFF000000) / 0x00FF0000,
(*versionID & 0x00FF0000) / 0x0000FF00,
(*versionID & 0x0000FFFF)
));
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("driver_VersionID\n")));
return retval;
}
// =========================================================================
BOOL driver_GetMountedCount(int* count)
{
BOOL retval = FALSE;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_GetMountedCount\n")));
(*count) = RegDetailsGetAllActive(0, NULL);
retval = ((*count) != -1);
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("driver_GetMountedCount\n")));
return retval;
}
// =========================================================================
// Retrieve details of all mounted volumes.
// detailsActiveSize - Size in bytes of detailsActive buffer.
// detailsActive - Actually an array of REGDETAILS_ACTIVE, this will be
// filled in as appropriate
// Note: On failure, the contents of detailsActive are undefined
// Note: This function will fail if detailsActiveSize doens't reflect the
// number of mounted volumes
// IMPORTANT: If this function succeeds, it is the caller's responsibility
// to free of the WCHAR*s, etc in each of the populated
// REGDETAILS_ACTIVE structures
BOOL driver_MountedVolumes(
int detailsActiveSize, // Size in bytes of detailsActive buffer
REGDETAILS_ACTIVE *detailsActive // Actually an array of REGDETAILS_ACTIVE
)
{
BOOL retval = FALSE;
int count;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_MountedVolumes\n")));
count = RegDetailsGetAllActive(
detailsActiveSize,
detailsActive
);
retval = (
(count != -1) &&
(count == (detailsActiveSize / sizeof(detailsActive[0])))
);
if (!(retval))
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to get mounted volumes\n")));
}
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("driver_MountedVolumes\n")));
return retval;
}
// =========================================================================
BOOL driver_GetVolumeInfo_DeviceName(
WCHAR* deviceName,
DIOC_DISK_DEVICE_STATUS* volumeDetails
)
{
BOOL retval = FALSE;
DWORD bytesReturned;
HANDLE fileHandle;
DWORD desiredAccess;
DWORD fileFlags;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_GetVolumeInfo_DeviceName\n")));
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Trying to open device: %ls...\n"), deviceName));
desiredAccess = 0; //(GENERIC_READ | GENERIC_WRITE);
// Note: FILE_ATTRIBUTE_NORMAL only valid if used *alone*
fileFlags = FILE_ATTRIBUTE_NORMAL;
fileHandle = CreateFile(
deviceName,
desiredAccess,
(FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL,
OPEN_EXISTING,
fileFlags,
NULL
);
if (fileHandle == INVALID_HANDLE_VALUE)
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to open device: %ls\n"), deviceName));
}
else
{
retval = DeviceIoControl(
fileHandle,
IOCTL_FREEOTFE_GET_DISK_DEVICE_STATUS,
NULL,
0,
volumeDetails,
sizeof(*volumeDetails),
&bytesReturned,
NULL
);
if (retval)
{
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("DIOC call OK\n")));
}
else
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("DIOC call failed\n")));
}
retval = (bytesReturned == sizeof(*volumeDetails));
// Slightly paranoid, but...
if (!(retval))
{
SecZeroMemory(volumeDetails, sizeof(*volumeDetails));
}
CloseHandle(fileHandle);
}
if (retval)
{
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Returning TRUE\n")));
}
else
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Returning FALSE\n")));
}
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("driver_GetVolumeInfo_DeviceName\n")));
return retval;
}
// =========================================================================
BOOL driver_GetVolumeInfo_Mountpoint(
WCHAR* mountpoint,
DIOC_DISK_DEVICE_STATUS* volumeDetails
)
{
BOOL retval = FALSE;
int cnt;
REGDETAILS_ACTIVE* mountedDetails;
BOOL found = FALSE;
BOOL allOK = FALSE;
int i;
int detailsByteSize;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_GetVolumeInfo_Mountpoint\n")));
detailsByteSize = 0;
// Get details for all volumes
allOK = driver_GetMountedCount(&cnt);
if (allOK)
{
detailsByteSize = (cnt * sizeof(*mountedDetails));
mountedDetails = malloc(detailsByteSize);
if (mountedDetails == NULL)
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to malloc memory for all volumes mounted\n")));
allOK = FALSE;
}
else
{
allOK = driver_MountedVolumes(detailsByteSize, mountedDetails);
if (!(allOK))
{
SecZeroAndFreeMemory(mountedDetails, detailsByteSize);
mountedDetails = NULL;
}
}
}
if (allOK)
{
for(i = 0; i < cnt; i++)
{
// Identify the volume we're interested in
if (wcscmp(
mountpoint,
mountedDetails[i].Mountpoint
) == 0)
{
found = TRUE;
allOK = driver_GetVolumeInfo_DeviceName(
mountedDetails[i].Name,
volumeDetails
);
break;
}
}
}
RegDetailsFreeAllActive(cnt, mountedDetails);
SecZeroAndFreeMemory(mountedDetails, detailsByteSize);
retval = (allOK && found);
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("driver_GetVolumeInfo_Mountpoint\n")));
return retval;
}
// =========================================================================
// Attempt to mount using the details supplied.
// First we attempt to mount passing the device manager the full path and
// filename to the main DLL in the registry key
// If that fails, we try again, but without the full path to the main DLL
// in which case, Windows Mobile *should* pick up the DLLs from the
// \Windows directory by default
BOOL _driver_MountDIOC(DIOC_MOUNT* mountDetails)
{
BOOL retval = FALSE;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("_driver_MountDIOC\n")));
retval = _driver_MountDIOC_DLLOption(mountDetails, TRUE);
if (!(retval))
{
retval = _driver_MountDIOC_DLLOption(mountDetails, FALSE);
}
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("_driver_MountDIOC\n")));
return retval;
}
// =========================================================================
// Debug - If the next line is uncommented, then debug messages will be
// displayed to the user during mounting
//#define _DEBUG_ACTIVATEDEVICEEX 1
BOOL _driver_MountDIOC_DLLOption(DIOC_MOUNT* mountDetails, BOOL fullPath)
{
BOOL retval = FALSE;
REGDETAILS_BUILTIN regdetailsBuiltin;
REGDETAILS_PROFILE regdetailsProfile;
WCHAR* keyBuiltin;
HANDLE hActiveDevice = NULL;
int regDeviceID;
#ifdef _DEBUG_ACTIVATEDEVICEEX
DWORD errorCode; // xxx - lplp
#endif
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("_driver_MountDIOC_DLLOption\n")));
regDeviceID = RegGetNextRegNumber();
regdetailsBuiltin.Prefix = DRIVER_PREFIX;
regdetailsBuiltin.Dll = driver_AllocMainDLLFullFilename(fullPath);
regdetailsBuiltin.FriendlyName = DRIVER_FRIENDLYNAME;
regdetailsBuiltin.Order = 0;
regdetailsBuiltin.Ioctl = 4;
regdetailsBuiltin.IClass = BLOCK_DRIVER_GUID_STRING;
regdetailsBuiltin.Profile = NULL; // Determined automatically
regdetailsProfile.Name = DRIVER_PROFILE_NAME;
regdetailsProfile.Folder = mountDetails->Mountpoint;
regdetailsProfile.AutoMount = 1;
regdetailsProfile.AutoPart = 1;
regdetailsProfile.AutoFormat = 1;
regdetailsProfile.MountFlags = 0;
// Create driver registry entries...
RegDetailsSetAll(regDeviceID, regdetailsBuiltin, regdetailsProfile);
// Activate driver...
RegKeyGenerate(regDeviceID, &keyBuiltin, NULL);
#ifdef _DEBUG_ACTIVATEDEVICEEX
MsgInfo(NULL, regdetailsBuiltin.Dll); // xxx - lplp
MsgInfo(NULL, TEXT("About to activate...")); // xxx - lplp
SetLastError(0); // xxx - lplp
#endif
hActiveDevice = ActivateDeviceEx(keyBuiltin, NULL, 0, mountDetails);
#ifdef _DEBUG_ACTIVATEDEVICEEX
// hActiveDevice = NULL; // xxx - lplp
errorCode = GetLastError(); // xxx - lplp
#endif
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("ActivateDeviceEx returned handle: 0x%0.8x\n"), hActiveDevice));
SecZeroAndFreeWCHARMemory(keyBuiltin);
// On mount failure, purge registry entries created
if (hActiveDevice == NULL)
{
#ifdef _DEBUG_ACTIVATEDEVICEEX
MsgError(NULL, TEXT("Activation failure")); // xxx - lplp
MsgErrorDWORD_AsHex(NULL, errorCode); // xxx - lplp
SDUDisplayLastError_TextForCode(errorCode); // xxx - lplp
#endif
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Mount failed; ActivateDeviceEx returned NULL handle\n")));
RegDetailsDeleteAllByID(regDeviceID, TRUE);
}
else
{
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Device activated OK\n")));
// Pass the active handle received to the driver to store
if (!(driver_SetUserAppHandle(
(WCHAR*)(mountDetails->Mountpoint),
hActiveDevice
)))
{
// Problem!
// <shrugs> Kill the device...
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to pass userspace device handle to device!\n")));
DeactivateDevice(hActiveDevice);
hActiveDevice = NULL;
}
}
retval = (hActiveDevice != NULL);
// Free DLL filename as it's no longer needed
driver_FreeMainDLLFullFilename(regdetailsBuiltin.Dll);
regdetailsBuiltin.Dll = NULL;
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("_driver_MountDIOC_DLLOption\n")));
return retval;
}
// =========================================================================
// Note: It it the *callers* responsibility to call CloseHandle(...) on the
// value returned after use
// Returns INVALID_HANDLE_VALUE on failure
HANDLE driver_GetDeviceHandle(WCHAR* deviceName)
{
DWORD desiredAccess;
DWORD fileFlags;
HANDLE fileHandle;
WCHAR pathMountpoint[FREEOTFE_MAX_FILENAME_LENGTH];
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_GetDeviceHandle\n")));
desiredAccess = 0; //(GENERIC_READ | GENERIC_WRITE);
// Note: FILE_ATTRIBUTE_NORMAL only valid if used *alone*
fileFlags = FILE_ATTRIBUTE_NORMAL;
fileHandle = CreateFile(
deviceName,
desiredAccess,
(FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL,
OPEN_EXISTING,
fileFlags,
NULL
);
if (fileHandle == INVALID_HANDLE_VALUE)
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to open device: %ls\n"), deviceName));
}
SecZeroMemory(pathMountpoint, sizeof(pathMountpoint));
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("driver_GetDeviceHandle\n")));
return fileHandle;
}
// =========================================================================
// Get handle returned by ActivateDeviceEx from device's internal store
HANDLE driver_GetUserAppHandle(WCHAR* mountpoint)
{
HANDLE retval = NULL;
DIOC_USER_DEVICE_HANDLE DIOCBuffer;
DWORD bytesReturned;
HANDLE fileHandle;
DIOC_DISK_DEVICE_STATUS volumeDetails;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_GetUserAppHandle\n")));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -