📄 tc9x.c
字号:
/* Copyright (C) 2004 TrueCrypt Team, truecrypt.org
This product uses components written by Paul Le Roux <pleroux@swprofessionals.com>
Majority of this code originally Copyright (C) 1998/9 by Aman. Used with
permission. Other parts originally Copyright (C) 1995 by Walter Oney used
with implied permission. */
#include "TCdefs.h"
#pragma VxD_LOCKED_CODE_SEG
#pragma VxD_LOCKED_DATA_SEG
#include "crypto.h"
#include "fat.h"
#include "volumes.h"
#include "cache.h"
#include "apidrvr.h"
#include "tc9x.h"
#include "queue.h"
#include "ifshook.h"
#include "ifsmgr.inc"
#define NUMSLOTS 8 /* Only up to 8 volumes at a time */
#define MAXBLOCK 128 /* 64k was 256.... */
#define MAX_MESSAGES 8 /* Max number of queued driver messages */
#define DEVICE_TYPE 0 /* We are a fixed disk (even files on
removables) */
#ifdef DEBUG
#define EXTRA_INFO 1
#endif
int halfseccount=0xc9;
char *transferbuffer = NULL; /* IO transfer buffer */
char *appaccessbuffer = NULL; /* win32 GUI IO buffer */
char *partitiontestbuffer = NULL; /* Buffer for the MBR */
int dcbcount = 0; /* DCB hack */
PDCB dcblist[128]; /* DCB hack */
PDCB dcb_boot; /* Boot device */
extern DRP theDRP; /* Device registration packet */
int bAllowFastShutdown = 0;
cryptvol cv1 =
{0, 0, 0, 0, 0, 0, 0, 0};
cryptvol cv2 =
{0, 0, 0, 0, 0, 0, 0, 0};
cryptvol cv3 =
{0, 0, 0, 0, 0, 0, 0, 0};
cryptvol cv4 =
{0, 0, 0, 0, 0, 0, 0, 0};
cryptvol cv5 =
{0, 0, 0, 0, 0, 0, 0, 0};
cryptvol cv6 =
{0, 0, 0, 0, 0, 0, 0, 0};
cryptvol cv7 =
{0, 0, 0, 0, 0, 0, 0, 0};
cryptvol cv8 =
{0, 0, 0, 0, 0, 0, 0, 0};
cryptvol *cryptvols[]=
{
&cv1,
&cv2,
&cv3,
&cv4,
&cv5,
&cv6,
&cv7,
&cv8
};
typedef struct MessageBox_t
{
char *MessageHdr;
char *MessageBody;
int PostPlease;
} MessageBox;
MessageBox Msgs[MAX_MESSAGES];
VOID
OnAsyncRequest (PAEP aep)
{
typedef USHORT (*PEF) (PAEP);
static PEF evproc[AEP_MAX_FUNC + 1] =
{(PEF) OnInitialize /* 0 AEP_INITIALIZE */
,NULL /* 1 AEP_SYSTEM_CRIT_SHUTDOWN */
,(PEF) OnBootComplete /* 2 AEP_BOOT_COMPLETE */
,(PEF) OnConfigDcb /* 3 AEP_CONFIG_DCB */
,(PEF) OnUnconfigDcb /* 4 AEP_UNCONFIG_DCB */
,NULL /* 5 AEP_IOP_TIMEOUT */
,NULL /* 6 AEP_DEVICE_INQUIRY */
,(PEF) OnHalfSec /* 7 AEP_HALF_SEC */
,NULL /* 8 AEP_1_SEC */
,NULL /* 9 AEP_2_SECS */
,NULL /* 10 AEP_4_SECS */
,NULL /* 11 AEP_DBG_DOT_CMD */
,NULL /* 12 AEP_ASSOCIATE_DCB */
,NULL /* 13 AEP_REAL_MODE_HANDOFF */
,(PEF) OnSystemExit /* 14 AEP_SYSTEM_SHUTDOWN */
,(PEF) OnUninitialize /* 15 AEP_UNINITIALIZE */
,NULL /* 16 AEP_DCB_LOCK */
,NULL /* 17 AEP_MOUNT_VERIFY */
,NULL /* 18 AEP_CREATE_VRP */
,NULL /* 19 AEP_DESTROY_VRP */
,NULL /* 20 AEP_REFRESH_DRIVE */
,NULL /* 21 AEP_PEND_UNCONFIG_DCB */
,NULL /* 22 AEP_1E_VEC_UPDATE */
,NULL /* 23 AEP_CHANGE_RPM */
};
PEF proc;
if (aep->AEP_func < arraysize (evproc) && (proc = evproc[aep->AEP_func]))
aep->AEP_result = proc (aep);
else
aep->AEP_result = (USHORT) AEP_FAILURE;
}
USHORT
OnInitialize (PAEP_bi_init aep)
{
/* allocate our (smaller) memory buffer..... */
static int initalready = 0;
if (initalready)
return AEP_SUCCESS;
initalready++;
transferbuffer = (char *) _PageAllocate (50, PG_SYS, 0, 0, 0, MBYTE16, NULL, PAGEZEROINIT | PAGEFIXED | PAGECONTIG | PAGEUSEALIGN);
partitiontestbuffer = (char *) transferbuffer + (265 * 512);
appaccessbuffer = transferbuffer + (265 * 512);
if (transferbuffer)
return AEP_SUCCESS;
return (USHORT) AEP_FAILURE;
}
USHORT
OnUninitialize (PAEP_bi_uninit aep)
{
return AEP_SUCCESS;
}
/* asks us if we want to stay loaded or not. */
USHORT
OnBootComplete (PAEP_boot_done aep)
{
installhook ();
return AEP_SUCCESS;
}
USHORT
OnConfigDcb (PAEP_dcb_config aep)
{
PDCB dcb = (PDCB) aep->AEP_d_c_dcb;
if (!(dcb->DCB_cmn.DCB_device_flags & DCB_DEV_PHYSICAL))
{
return AEP_SUCCESS;
}
/* Sadly for SCSI some port drivers have not set apparent_blk_shift
up at this point.. if ((dcb->DCB_cmn.DCB_apparent_blk_shift!=9)
&& (dcb->DCB_cmn.DCB_device_type!=DCB_type_cdrom) ) return
AEP_SUCCESS; */
if (dcbcount < 100)
{
if ((dcb->DCB_cmn.DCB_device_type == 0) || (dcb->DCB_cmn.DCB_device_type == DCB_type_cdrom))
{
if (cmpvend ((char *) &dcb->DCB_vendor_id, "JETICO", 6) != 0)
{
if (CheckDcbAlready (dcb))
return AEP_SUCCESS;
dcblist[dcbcount] = dcb;
dcblist[dcbcount + 1] = NULL;
dcbcount++;
}
}
}
if (dcb->DCB_cmn.DCB_device_type == 0)
((IspInsertCalldown (dcb, OnRequest, (PDDB) aep->AEP_d_c_hdr.AEP_ddb, 0,
dcb->DCB_cmn.DCB_dmd_flags, aep->AEP_d_c_hdr.AEP_lgn)));
return AEP_SUCCESS;
}
/* AEP_UNCONFIG_DCB informs us that the physical device represented by a DCB
is going away */
USHORT
OnUnconfigDcb (PAEP_dcb_unconfig aep)
{
return AEP_SUCCESS;
}
VOID
OnRequest (PIOP iop)
{
DoCallDown (iop); /* do normal unencryped disk stuff... */
}
int
cmpvend (char *a, char *b, int len)
{
int n;
for (n = 0; n < len; n++)
if (a[n] != b[n])
return 1;
return 0;
}
int
CheckDcbAlready (PDCB dcb)
{
int n;
/* sometimes the same dcb is passed more than once, on some drivers!! */
if (!dcbcount)
return 0;
for (n = 0; n < dcbcount; n++)
if (dcblist[n] == dcb)
return 1;
return 0;
}
/* DoCallDown passes a request to the next lower layer. Note that the
documentation about how to do this is totally wrong: you don't just add
sizeof(DCB_cd_entry) to the calldown pointer, you follow a linked list
from one calldown entry to the next. */
void
DoCallDown (PIOP iop)
{
_asm
{ /* call down to next layer */
pushfd
pushad
mov ecx,[iop]
mov eax,[ecx] IOP.IOP_calldown_ptr
mov eax,[eax] DCB_cd_entry.DCB_cd_next
mov[ecx] IOP.IOP_calldown_ptr, eax
push ecx
call[eax] DCB_cd_entry.DCB_cd_io_address
add esp, 4
popad
popfd
}
}
BOOL
OnSysDynamicDeviceInit ()
{
cv1.cryptsectorfirst = 0x7fffffff;
cv1.cryptsectorlast = 0;
cv2.cryptsectorfirst = 0x7fffffff;
cv2.cryptsectorlast = 0;
cv3.cryptsectorfirst = 0x7fffffff;
cv3.cryptsectorlast = 0;
cv4.cryptsectorfirst = 0x7fffffff;
cv4.cryptsectorlast = 0;
cv5.cryptsectorfirst = 0x7fffffff;
cv5.cryptsectorlast = 0;
cv6.cryptsectorfirst = 0x7fffffff;
cv6.cryptsectorlast = 0;
cv7.cryptsectorfirst = 0x7fffffff;
cv7.cryptsectorlast = 0;
cv8.cryptsectorfirst = 0x7fffffff;
cv8.cryptsectorlast = 0;
IOS_Register (&theDRP);
return TRUE; /* stay resident no matter what IOS says */
}
BOOL
OnSysDynamicDeviceExit ()
{
return TRUE;
}
DWORD
OnDeviceIoControl (PDIOCPARAMETERS p)
{
installhook (); /* make sure hook is installed */
InstallTCThread ();
/* select on IOCTL code */
switch (p->dwIoControlCode)
{
case 0: /* VWIN32 pinging us during CreateFile */
case -1: /* CloseHandle */
break;
case ALLOW_FAST_SHUTDOWN:
{
bAllowFastShutdown = 1;
break;
}
case DRIVER_VERSION:
{
LONG *tmp = (LONG *) p->lpvInBuffer;
LONG tmp2 = VERSION_NUM;
if (tmp == NULL)
return ERROR_GEN_FAILURE;
memcpy (tmp, &tmp2, 4);
break;
}
case WIPE_CACHE:
WipeCache ();
break;
case CACHE_STATUS:
return cacheEmpty ? ERROR_GEN_FAILURE : 0;
case DISKIO: /* Call to read and write sectors from
application */
{
DISKIO_STRUCT *dio = (DISKIO_STRUCT *) p->lpvInBuffer;
int s;
if (dio == NULL)
return ERROR_GEN_FAILURE;
s = AppAccessBlockDevice (dio->devicenum, dio->sectorstart, dio->sectorlen, dio->bufferad, dio->mode);
dio->nReturnCode = s;
break;
}
case OPEN_TEST:
{
OPEN_TEST_STRUCT *item = (OPEN_TEST_STRUCT *) p->lpvInBuffer;
unsigned long *tmp = (void *) partitiontestbuffer;
MOUNT_STRUCT mount;
if (item == NULL)
return ERROR_GEN_FAILURE;
strcpy ((char *) mount.wszVolume, (char *) item->wszFileName);
item->nReturnCode = ERR_BAD_DRIVE_LETTER;
readallpartitions (&mount, TRUE);
item->nReturnCode = mount.nReturnCode;
item->secstart = tmp[0];
item->seclast = tmp[1];
item->device = tmp[2];
break;
}
case MOUNT_LIST_N:
{
MOUNT_LIST_N_STRUCT *item = (MOUNT_LIST_N_STRUCT *) p->lpvInBuffer;
cryptvol *cv;
int c;
if (item == NULL)
return ERROR_GEN_FAILURE;
item->nReturnCode = ERR_BAD_DRIVE_LETTER;
for (c = 0; c < NUMSLOTS; c++)
{
cv = cryptvols[c];
if ((cv->booted == 0) && (cv->physdevDCB == 0))
continue;
if (item->nDosDriveNo == cv->drive)
{
/* 16/9/99 This is safe as
item->wszVolume is >
cv->mounted_file_name */
strcpy ((char *) item->wszVolume, cv->mounted_file_name);
item->nReturnCode = 0;
break;
}
}
break;
}
case RELEASE_TIME_SLICE:
ReleaseTimeSlice ();
break;
case MOUNT:
{
MOUNT_STRUCT *mount = (MOUNT_STRUCT *) p->lpvInBuffer;
char tmp[9];
if (mount == NULL)
return ERROR_GEN_FAILURE;
#if EXTRA_INFO
_Debug_Printf_Service ("MOUNT\n");
#endif
memcpy (tmp, (char *) mount->wszVolume, 8);
tmp[8] = 0;
if (strcmp (tmp, "\\Device\\") == 0)
readallpartitions (mount, FALSE);
else
mountdiskfileR0 (mount);
if (mount->nReturnCode == 0 && bAllowFastShutdown == 1)
{
IFSMgr_PNPEvent (DBT_DEVICEARRIVAL, mount->nDosDriveNo, PNPT_VOLUME | DBTF_MEDIA );
}
#if EXTRA_INFO
_Debug_Printf_Service ("MOUNT end\n");
#endif
break;
}
case UNMOUNT:
case UNMOUNT_PENDING:
{
UNMOUNT_STRUCT *unmount = (UNMOUNT_STRUCT *) p->lpvInBuffer;
cryptvol *cv;
int c;
if (unmount == NULL)
return ERROR_GEN_FAILURE;
unmount->nReturnCode = ERR_BAD_DRIVE_LETTER;
for (c = 0; c < NUMSLOTS; c++)
{
cv = cryptvols[c];
if ((cv->booted == 0) && (cv->physdevDCB == 0))
continue;
if (unmount->nDosDriveNo == cv->drive)
{
if (p->dwIoControlCode == UNMOUNT_PENDING)
{
if (closeCrDevice (cv, 0) != 0)
unmount->nReturnCode = ERR_FILES_OPEN;
else
unmount->nReturnCode = 0;
}
else
{
if (closeCrDevice (cv, 1) != 0)
unmount->nReturnCode = ERR_FILES_OPEN;
else
unmount->nReturnCode = 0;
}
break;
}
}
break;
}
case MOUNT_LIST:
{
MOUNT_LIST_STRUCT *list = (MOUNT_LIST_STRUCT *) p->lpvInBuffer;
cryptvol *cv;
int c;
if (list == NULL)
return ERROR_GEN_FAILURE;
list->ulMountedDrives = 0;
for (c = 0; c < NUMSLOTS; c++)
{
int nDosDriveNo;
cv = cryptvols[c];
if ((cv->booted == 0) && (cv->physdevDCB == 0))
continue;
nDosDriveNo = cv->drive;
list->ulMountedDrives |= 1 << nDosDriveNo;
if (strlen (cv->mounted_file_name) < 64)
{
strcpy ((char *) list->wszVolume[nDosDriveNo], cv->mounted_file_name);
}
else
{
memcpy ((char *) list->wszVolume[nDosDriveNo], cv->mounted_file_name, 60);
((char *) list->wszVolume[nDosDriveNo])[60] = '.';
((char *) list->wszVolume[nDosDriveNo])[61] = '.';
((char *) list->wszVolume[nDosDriveNo])[62] = '.';
((char *) list->wszVolume[nDosDriveNo])[63] = 0;
}
list->cipher[nDosDriveNo] = cv->cryptoInfo->cipher;
if(!cv->mountfilehandle)
list->diskLength[nDosDriveNo] = (cv->cryptsectorlast - cv->cryptsectorfirst) * 512I64;
else
list->diskLength[nDosDriveNo] = 0;
list->cipher[nDosDriveNo] = cv->cryptoInfo->cipher;
}
break;
}
case VOLUME_PROPERTIES:
{
VOLUME_PROPERTIES_STRUCT *prop = (VOLUME_PROPERTIES_STRUCT *) p->lpvInBuffer;
cryptvol *cv;
int c;
if (prop == NULL)
return ERROR_GEN_FAILURE;
for (c = 0; c < NUMSLOTS; c++)
{
int nDosDriveNo;
cv = cryptvols[c];
if ((cv->booted == 0) && (cv->physdevDCB == 0))
continue;
nDosDriveNo = cv->drive;
if (nDosDriveNo != prop->driveNo)
continue;
if (strlen (cv->mounted_file_name) < 64)
{
strcpy ((char *) prop->wszVolume, cv->mounted_file_name);
}
else
{
memcpy ((char *) prop->wszVolume, cv->mounted_file_name, 60);
((char *) prop->wszVolume)[60] = '.';
((char *) prop->wszVolume)[61] = '.';
((char *) prop->wszVolume)[62] = '.';
((char *) prop->wszVolume)[63] = 0;
}
prop->cipher = cv->cryptoInfo->cipher;
if(!cv->mountfilehandle)
prop->diskLength = (cv->cryptsectorlast - cv->cryptsectorfirst) * 512I64;
else
prop->diskLength = 0;
prop->cipher = cv->cryptoInfo->cipher;
prop->pkcs5 = cv->cryptoInfo->pkcs5;
prop->pkcs5Iterations = cv->cryptoInfo->noIterations;
prop->volumeCreationTime = cv->cryptoInfo->volume_creation_time;
prop->headerCreationTime = cv->cryptoInfo->header_creation_time;
return 0;
}
return ERROR_GEN_FAILURE;
}
default:
return ERROR_INVALID_FUNCTION;
}
return 0;
}
BOOL
Kill_Drive (cryptvol * cv)
{
BOOL result = FALSE;
if (cv->booted != 0 || cv->physdevDCB != 0)
{
if ((cv->drive >= 0) && (cv->drive < 26))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -