|
|
1.1 root 1: /* Copyright (C) 2004 TrueCrypt Team, truecrypt.org
2: This product uses components written by Paul Le Roux <[email protected]>
3: Majority of this code originally Copyright (C) 1998/9 by Aman. Used with
4: permission. Other parts originally Copyright (C) 1995 by Walter Oney used
5: with implied permission. */
6:
7: #include "TCdefs.h"
8:
9: #pragma VxD_LOCKED_CODE_SEG
10: #pragma VxD_LOCKED_DATA_SEG
11:
12: #include "crypto.h"
13: #include "fat.h"
14: #include "volumes.h"
15: #include "cache.h"
16: #include "apidrvr.h"
17: #include "tc9x.h"
18: #include "queue.h"
19:
20: #include "ifshook.h"
21: #include "ifsmgr.inc"
22:
23:
24: #define NUMSLOTS 8 /* Only up to 8 volumes at a time */
25: #define MAXBLOCK 128 /* 64k was 256.... */
26:
27: #define MAX_MESSAGES 8 /* Max number of queued driver messages */
28:
29: #define DEVICE_TYPE 0 /* We are a fixed disk (even files on
30: removables) */
31:
32: #ifdef DEBUG
33: #define EXTRA_INFO 1
34: #endif
35:
36: int halfseccount=0xc9;
37:
38: char *transferbuffer = NULL; /* IO transfer buffer */
39: char *appaccessbuffer = NULL; /* win32 GUI IO buffer */
40: char *partitiontestbuffer = NULL; /* Buffer for the MBR */
41: int dcbcount = 0; /* DCB hack */
42: PDCB dcblist[128]; /* DCB hack */
43:
44: PDCB dcb_boot; /* Boot device */
45:
46: extern DRP theDRP; /* Device registration packet */
47:
48: int bAllowFastShutdown = 0;
49:
50: cryptvol cv1 =
51: {0, 0, 0, 0, 0, 0, 0, 0};
52:
53: cryptvol cv2 =
54: {0, 0, 0, 0, 0, 0, 0, 0};
55:
56: cryptvol cv3 =
57: {0, 0, 0, 0, 0, 0, 0, 0};
58:
59: cryptvol cv4 =
60: {0, 0, 0, 0, 0, 0, 0, 0};
61:
62: cryptvol cv5 =
63: {0, 0, 0, 0, 0, 0, 0, 0};
64:
65: cryptvol cv6 =
66: {0, 0, 0, 0, 0, 0, 0, 0};
67:
68: cryptvol cv7 =
69: {0, 0, 0, 0, 0, 0, 0, 0};
70:
71: cryptvol cv8 =
72: {0, 0, 0, 0, 0, 0, 0, 0};
73:
74: cryptvol *cryptvols[]=
75: {
76: &cv1,
77: &cv2,
78: &cv3,
79: &cv4,
80: &cv5,
81: &cv6,
82: &cv7,
83: &cv8
84: };
85:
86: typedef struct MessageBox_t
87: {
88: char *MessageHdr;
89: char *MessageBody;
90: int PostPlease;
91: } MessageBox;
92:
93: MessageBox Msgs[MAX_MESSAGES];
94:
95:
96: VOID
97: OnAsyncRequest (PAEP aep)
98: {
99: typedef USHORT (*PEF) (PAEP);
100:
101: static PEF evproc[AEP_MAX_FUNC + 1] =
102: {(PEF) OnInitialize /* 0 AEP_INITIALIZE */
103: ,NULL /* 1 AEP_SYSTEM_CRIT_SHUTDOWN */
104: ,(PEF) OnBootComplete /* 2 AEP_BOOT_COMPLETE */
105: ,(PEF) OnConfigDcb /* 3 AEP_CONFIG_DCB */
106: ,(PEF) OnUnconfigDcb /* 4 AEP_UNCONFIG_DCB */
107: ,NULL /* 5 AEP_IOP_TIMEOUT */
108: ,NULL /* 6 AEP_DEVICE_INQUIRY */
109: ,(PEF) OnHalfSec /* 7 AEP_HALF_SEC */
110: ,NULL /* 8 AEP_1_SEC */
111: ,NULL /* 9 AEP_2_SECS */
112: ,NULL /* 10 AEP_4_SECS */
113: ,NULL /* 11 AEP_DBG_DOT_CMD */
114: ,NULL /* 12 AEP_ASSOCIATE_DCB */
115: ,NULL /* 13 AEP_REAL_MODE_HANDOFF */
116: ,(PEF) OnSystemExit /* 14 AEP_SYSTEM_SHUTDOWN */
117: ,(PEF) OnUninitialize /* 15 AEP_UNINITIALIZE */
118: ,NULL /* 16 AEP_DCB_LOCK */
119: ,NULL /* 17 AEP_MOUNT_VERIFY */
120: ,NULL /* 18 AEP_CREATE_VRP */
121: ,NULL /* 19 AEP_DESTROY_VRP */
122: ,NULL /* 20 AEP_REFRESH_DRIVE */
123: ,NULL /* 21 AEP_PEND_UNCONFIG_DCB */
124: ,NULL /* 22 AEP_1E_VEC_UPDATE */
125: ,NULL /* 23 AEP_CHANGE_RPM */
126: };
127: PEF proc;
128:
129: if (aep->AEP_func < arraysize (evproc) && (proc = evproc[aep->AEP_func]))
130: aep->AEP_result = proc (aep);
131: else
132: aep->AEP_result = (USHORT) AEP_FAILURE;
133: }
134:
135:
136: USHORT
137: OnInitialize (PAEP_bi_init aep)
138: {
139: /* allocate our (smaller) memory buffer..... */
140:
141: static int initalready = 0;
142:
143: if (initalready)
144: return AEP_SUCCESS;
145:
146: initalready++;
147:
148: transferbuffer = (char *) _PageAllocate (50, PG_SYS, 0, 0, 0, MBYTE16, NULL, PAGEZEROINIT | PAGEFIXED | PAGECONTIG | PAGEUSEALIGN);
149: partitiontestbuffer = (char *) transferbuffer + (265 * 512);
150: appaccessbuffer = transferbuffer + (265 * 512);
151:
152:
153: if (transferbuffer)
154: return AEP_SUCCESS;
155:
156: return (USHORT) AEP_FAILURE;
157: }
158:
159: USHORT
160: OnUninitialize (PAEP_bi_uninit aep)
161: {
162: return AEP_SUCCESS;
163: }
164:
165: /* asks us if we want to stay loaded or not. */
166:
167: USHORT
168: OnBootComplete (PAEP_boot_done aep)
169: {
170: installhook ();
171: return AEP_SUCCESS;
172: }
173:
174: USHORT
175: OnConfigDcb (PAEP_dcb_config aep)
176: {
177: PDCB dcb = (PDCB) aep->AEP_d_c_dcb;
178: if (!(dcb->DCB_cmn.DCB_device_flags & DCB_DEV_PHYSICAL))
179: {
180: return AEP_SUCCESS;
181: }
182:
183: /* Sadly for SCSI some port drivers have not set apparent_blk_shift
184: up at this point.. if ((dcb->DCB_cmn.DCB_apparent_blk_shift!=9)
185: && (dcb->DCB_cmn.DCB_device_type!=DCB_type_cdrom) ) return
186: AEP_SUCCESS; */
187:
188: if (dcbcount < 100)
189: {
190: if ((dcb->DCB_cmn.DCB_device_type == 0) || (dcb->DCB_cmn.DCB_device_type == DCB_type_cdrom))
191: {
192: if (cmpvend ((char *) &dcb->DCB_vendor_id, "JETICO", 6) != 0)
193: {
194: if (CheckDcbAlready (dcb))
195: return AEP_SUCCESS;
196: dcblist[dcbcount] = dcb;
197: dcblist[dcbcount + 1] = NULL;
198: dcbcount++;
199: }
200: }
201: }
202:
203:
204: if (dcb->DCB_cmn.DCB_device_type == 0)
205: ((IspInsertCalldown (dcb, OnRequest, (PDDB) aep->AEP_d_c_hdr.AEP_ddb, 0,
206: dcb->DCB_cmn.DCB_dmd_flags, aep->AEP_d_c_hdr.AEP_lgn)));
207:
208: return AEP_SUCCESS;
209: }
210:
211: /* AEP_UNCONFIG_DCB informs us that the physical device represented by a DCB
212: is going away */
213:
214: USHORT
215: OnUnconfigDcb (PAEP_dcb_unconfig aep)
216: {
217: return AEP_SUCCESS;
218: }
219:
220: VOID
221: OnRequest (PIOP iop)
222: {
223: DoCallDown (iop); /* do normal unencryped disk stuff... */
224: }
225:
226: int
227: cmpvend (char *a, char *b, int len)
228: {
229: int n;
230: for (n = 0; n < len; n++)
231: if (a[n] != b[n])
232: return 1;
233: return 0;
234: }
235:
236:
237: int
238: CheckDcbAlready (PDCB dcb)
239: {
240: int n;
241: /* sometimes the same dcb is passed more than once, on some drivers!! */
242: if (!dcbcount)
243: return 0;
244:
245: for (n = 0; n < dcbcount; n++)
246: if (dcblist[n] == dcb)
247: return 1;
248:
249: return 0;
250: }
251:
252: /* DoCallDown passes a request to the next lower layer. Note that the
253: documentation about how to do this is totally wrong: you don't just add
254: sizeof(DCB_cd_entry) to the calldown pointer, you follow a linked list
255: from one calldown entry to the next. */
256:
257: void
258: DoCallDown (PIOP iop)
259: {
260: _asm
261: { /* call down to next layer */
262: pushfd
263: pushad
264: mov ecx,[iop]
265: mov eax,[ecx] IOP.IOP_calldown_ptr
266: mov eax,[eax] DCB_cd_entry.DCB_cd_next
267: mov[ecx] IOP.IOP_calldown_ptr, eax
268: push ecx
269: call[eax] DCB_cd_entry.DCB_cd_io_address
270: add esp, 4
271: popad
272: popfd
273: }
274: }
275:
276: BOOL
277: OnSysDynamicDeviceInit ()
278: {
279: cv1.cryptsectorfirst = 0x7fffffff;
280: cv1.cryptsectorlast = 0;
281:
282: cv2.cryptsectorfirst = 0x7fffffff;
283: cv2.cryptsectorlast = 0;
284:
285: cv3.cryptsectorfirst = 0x7fffffff;
286: cv3.cryptsectorlast = 0;
287:
288: cv4.cryptsectorfirst = 0x7fffffff;
289: cv4.cryptsectorlast = 0;
290:
291: cv5.cryptsectorfirst = 0x7fffffff;
292: cv5.cryptsectorlast = 0;
293:
294: cv6.cryptsectorfirst = 0x7fffffff;
295: cv6.cryptsectorlast = 0;
296:
297: cv7.cryptsectorfirst = 0x7fffffff;
298: cv7.cryptsectorlast = 0;
299:
300: cv8.cryptsectorfirst = 0x7fffffff;
301: cv8.cryptsectorlast = 0;
302:
303: IOS_Register (&theDRP);
304: return TRUE; /* stay resident no matter what IOS says */
305: }
306:
307: BOOL
308: OnSysDynamicDeviceExit ()
309: {
310: return TRUE;
311: }
312:
313: DWORD
314: OnDeviceIoControl (PDIOCPARAMETERS p)
315: {
316: installhook (); /* make sure hook is installed */
317: InstallTCThread ();
318:
319: /* select on IOCTL code */
320: switch (p->dwIoControlCode)
321: {
322:
323: case 0: /* VWIN32 pinging us during CreateFile */
324: case -1: /* CloseHandle */
325: break;
326:
327: case ALLOW_FAST_SHUTDOWN:
328: {
329: bAllowFastShutdown = 1;
330: break;
331: }
332:
333: case DRIVER_VERSION:
334: {
335: LONG *tmp = (LONG *) p->lpvInBuffer;
336: LONG tmp2 = VERSION_NUM;
337:
338: if (tmp == NULL)
339: return ERROR_GEN_FAILURE;
340:
341: memcpy (tmp, &tmp2, 4);
342: break;
343: }
344:
345: case WIPE_CACHE:
346: WipeCache ();
347: break;
348:
349: case CACHE_STATUS:
350: return cacheEmpty ? ERROR_GEN_FAILURE : 0;
351:
352: case DISKIO: /* Call to read and write sectors from
353: application */
354: {
355: DISKIO_STRUCT *dio = (DISKIO_STRUCT *) p->lpvInBuffer;
356: int s;
357:
358: if (dio == NULL)
359: return ERROR_GEN_FAILURE;
360:
361: s = AppAccessBlockDevice (dio->devicenum, dio->sectorstart, dio->sectorlen, dio->bufferad, dio->mode);
362: dio->nReturnCode = s;
363:
364: break;
365: }
366:
367: case OPEN_TEST:
368: {
369: OPEN_TEST_STRUCT *item = (OPEN_TEST_STRUCT *) p->lpvInBuffer;
370: unsigned long *tmp = (void *) partitiontestbuffer;
371: MOUNT_STRUCT mount;
372:
373: if (item == NULL)
374: return ERROR_GEN_FAILURE;
375:
376: strcpy ((char *) mount.wszVolume, (char *) item->wszFileName);
377:
378: item->nReturnCode = ERR_BAD_DRIVE_LETTER;
379:
380: readallpartitions (&mount, TRUE);
381:
382: item->nReturnCode = mount.nReturnCode;
383:
384: item->secstart = tmp[0];
385: item->seclast = tmp[1];
386: item->device = tmp[2];
387:
388: break;
389: }
390:
391: case MOUNT_LIST_N:
392: {
393: MOUNT_LIST_N_STRUCT *item = (MOUNT_LIST_N_STRUCT *) p->lpvInBuffer;
394: cryptvol *cv;
395: int c;
396:
397: if (item == NULL)
398: return ERROR_GEN_FAILURE;
399:
400: item->nReturnCode = ERR_BAD_DRIVE_LETTER;
401:
402: for (c = 0; c < NUMSLOTS; c++)
403: {
404: cv = cryptvols[c];
405:
406: if ((cv->booted == 0) && (cv->physdevDCB == 0))
407: continue;
408:
409: if (item->nDosDriveNo == cv->drive)
410: {
411: /* 16/9/99 This is safe as
412: item->wszVolume is >
413: cv->mounted_file_name */
414: strcpy ((char *) item->wszVolume, cv->mounted_file_name);
415: item->nReturnCode = 0;
416: break;
417: }
418: }
419:
420: break;
421: }
422:
423: case RELEASE_TIME_SLICE:
424: ReleaseTimeSlice ();
425: break;
426:
427: case MOUNT:
428: {
429: MOUNT_STRUCT *mount = (MOUNT_STRUCT *) p->lpvInBuffer;
430: char tmp[9];
431:
432: if (mount == NULL)
433: return ERROR_GEN_FAILURE;
434:
435: #if EXTRA_INFO
436: _Debug_Printf_Service ("MOUNT\n");
437: #endif
438:
439: memcpy (tmp, (char *) mount->wszVolume, 8);
440: tmp[8] = 0;
441:
442: if (strcmp (tmp, "\\Device\\") == 0)
443: readallpartitions (mount, FALSE);
444: else
445: mountdiskfileR0 (mount);
446:
447: if (mount->nReturnCode == 0 && bAllowFastShutdown == 1)
448: {
449: IFSMgr_PNPEvent (DBT_DEVICEARRIVAL, mount->nDosDriveNo, PNPT_VOLUME | DBTF_MEDIA );
450: }
451:
452:
453: #if EXTRA_INFO
454: _Debug_Printf_Service ("MOUNT end\n");
455: #endif
456:
457: break;
458: }
459:
460: case UNMOUNT:
461: case UNMOUNT_PENDING:
462: {
463: UNMOUNT_STRUCT *unmount = (UNMOUNT_STRUCT *) p->lpvInBuffer;
464: cryptvol *cv;
465: int c;
466:
467: if (unmount == NULL)
468: return ERROR_GEN_FAILURE;
469:
470: unmount->nReturnCode = ERR_BAD_DRIVE_LETTER;
471:
472: for (c = 0; c < NUMSLOTS; c++)
473: {
474: cv = cryptvols[c];
475:
476: if ((cv->booted == 0) && (cv->physdevDCB == 0))
477: continue;
478:
479: if (unmount->nDosDriveNo == cv->drive)
480: {
481: if (p->dwIoControlCode == UNMOUNT_PENDING)
482: {
483: if (closeCrDevice (cv, 0) != 0)
484: unmount->nReturnCode = ERR_FILES_OPEN;
485: else
486: unmount->nReturnCode = 0;
487: }
488: else
489: {
490: if (closeCrDevice (cv, 1) != 0)
491: unmount->nReturnCode = ERR_FILES_OPEN;
492: else
493: unmount->nReturnCode = 0;
494: }
495:
496: break;
497: }
498: }
499:
500: break;
501: }
502:
503: case MOUNT_LIST:
504: {
505: MOUNT_LIST_STRUCT *list = (MOUNT_LIST_STRUCT *) p->lpvInBuffer;
506: cryptvol *cv;
507: int c;
508:
509: if (list == NULL)
510: return ERROR_GEN_FAILURE;
511:
512: list->ulMountedDrives = 0;
513:
514: for (c = 0; c < NUMSLOTS; c++)
515: {
516: int nDosDriveNo;
517:
518: cv = cryptvols[c];
519:
520: if ((cv->booted == 0) && (cv->physdevDCB == 0))
521: continue;
522:
523: nDosDriveNo = cv->drive;
524:
525: list->ulMountedDrives |= 1 << nDosDriveNo;
526:
527: if (strlen (cv->mounted_file_name) < 64)
528: {
529: strcpy ((char *) list->wszVolume[nDosDriveNo], cv->mounted_file_name);
530: }
531: else
532: {
533: memcpy ((char *) list->wszVolume[nDosDriveNo], cv->mounted_file_name, 60);
534: ((char *) list->wszVolume[nDosDriveNo])[60] = '.';
535: ((char *) list->wszVolume[nDosDriveNo])[61] = '.';
536: ((char *) list->wszVolume[nDosDriveNo])[62] = '.';
537: ((char *) list->wszVolume[nDosDriveNo])[63] = 0;
538: }
539:
540: list->cipher[nDosDriveNo] = cv->cryptoInfo->cipher;
541:
542: if(!cv->mountfilehandle)
543: list->diskLength[nDosDriveNo] = (cv->cryptsectorlast - cv->cryptsectorfirst) * 512I64;
544: else
545: list->diskLength[nDosDriveNo] = 0;
546:
547: list->cipher[nDosDriveNo] = cv->cryptoInfo->cipher;
548:
549: }
550:
551: break;
552: }
553:
554: case VOLUME_PROPERTIES:
555: {
556: VOLUME_PROPERTIES_STRUCT *prop = (VOLUME_PROPERTIES_STRUCT *) p->lpvInBuffer;
557: cryptvol *cv;
558: int c;
559:
560: if (prop == NULL)
561: return ERROR_GEN_FAILURE;
562:
563: for (c = 0; c < NUMSLOTS; c++)
564: {
565: int nDosDriveNo;
566:
567: cv = cryptvols[c];
568:
569: if ((cv->booted == 0) && (cv->physdevDCB == 0))
570: continue;
571:
572: nDosDriveNo = cv->drive;
573:
574: if (nDosDriveNo != prop->driveNo)
575: continue;
576:
577: if (strlen (cv->mounted_file_name) < 64)
578: {
579: strcpy ((char *) prop->wszVolume, cv->mounted_file_name);
580: }
581: else
582: {
583: memcpy ((char *) prop->wszVolume, cv->mounted_file_name, 60);
584: ((char *) prop->wszVolume)[60] = '.';
585: ((char *) prop->wszVolume)[61] = '.';
586: ((char *) prop->wszVolume)[62] = '.';
587: ((char *) prop->wszVolume)[63] = 0;
588: }
589:
590: prop->cipher = cv->cryptoInfo->cipher;
591:
592: if(!cv->mountfilehandle)
593: prop->diskLength = (cv->cryptsectorlast - cv->cryptsectorfirst) * 512I64;
594: else
595: prop->diskLength = 0;
596:
597: prop->cipher = cv->cryptoInfo->cipher;
598: prop->pkcs5 = cv->cryptoInfo->pkcs5;
599: prop->pkcs5Iterations = cv->cryptoInfo->noIterations;
600: prop->volumeCreationTime = cv->cryptoInfo->volume_creation_time;
601: prop->headerCreationTime = cv->cryptoInfo->header_creation_time;
602:
603: return 0;
604: }
605:
606: return ERROR_GEN_FAILURE;
607: }
608:
609:
610: default:
611: return ERROR_INVALID_FUNCTION;
612:
613: }
614:
615: return 0;
616: }
617:
618: BOOL
619: Kill_Drive (cryptvol * cv)
620: {
621: BOOL result = FALSE;
622:
623: if (cv->booted != 0 || cv->physdevDCB != 0)
624: {
625: if ((cv->drive >= 0) && (cv->drive < 26))
626: {
627: result = IspDisassociateDcb (cv->drive);
628: if (cv->mountfilehandle)
629: R0_CloseFile (cv->mountfilehandle);
630:
631: if (result == TRUE)
632: {
633: PDCB dcb;
634:
635: if (!cv->mountfilehandle)
636: unlockdrive (cv); /* files to be handled
637: by win32 app. */
638:
639: crypto_close (cv->cryptoInfo);
640:
641: dcb = cv->ldcb;
642: dcb->DCB_Port_Specific = 0;
643: memset (cv, 0, sizeof (cryptvol));
644: cv->cryptsectorfirst = 0x7fffffff;
645: }
646: }
647: }
648:
649: return result;
650: }
651:
652: int
653: closeCrDevice (cryptvol * cv, int mode)
654: {
655: if (mode == 0) /* pre flush volume call..... */
656: {
657: if (cv->drive != 0)
658: {
659: if (cv->booted <= 2)
660: {
661: _VolFlush (cv->drive, 0); /* flush stuff out
662: before the
663: dismount... */
664: //%% NotifyVolumeRemoval (cv->drive);
665: }
666: return 0;
667: }
668: else
669: return 1;
670: }
671: else
672: {
673: if (Kill_Drive (cv) == TRUE)
674: return 0;
675: else
676: return 0x42424242;
677: }
678: }
679:
680: int
681: installthread (void *t)
682: {
683: int id;
684: _asm
685: {
686: mov ecx, 4096
687: mov edi, 0
688: mov ebx,[t];
689: xor esi, esi
690: }
691:
692: VxDCall (_VWIN32_CreateRing0Thread)
693: _asm mov[id], eax
694: return id;
695: }
696:
697: void
698: sectorcopy (char *dest, char *source, int num)
699: {
700: _asm
701: {
702: pushad
703: mov edi,[dest]
704: mov esi,[source]
705: mov ecx,[num]
706: shl ecx, 9 /* *512 */
707: sar ecx, 4 /* 16 in pass... */
708: cpylp:
709: mov eax,[esi]
710: mov ebx,[esi + 4]
711: mov[edi], eax
712: mov[edi + 4], ebx
713: mov eax,[esi + 8]
714: mov ebx,[esi + 12]
715: mov[edi + 8], eax
716: mov[edi + 12], ebx
717: add edi, 16
718: add esi, 16
719: dec ecx
720: jnz cpylp
721: popad
722: }
723: }
724:
725: void
726: cryptproc (PIOP iop, cryptvol * cv)
727: {
728: PDCB dcbx;
729: unsigned int buffernum, totalsectors;
730: unsigned int sectorstart, sectorcount;
731: char *outbuffer, *bufadr, *buffercopy;
732: _BlockDev_Scatter_Gather *sgd;
733:
734: dcbx = (PDCB) iop->IOP_physical_dcb;
735: ior.IOR_status = 0;
736: if (ior.IOR_func == IOR_WRITEV)
737: {
738: ior.IOR_status = IORS_INVALID_COMMAND;
739: return;
740: }
741:
742: sectorcount = ior.IOR_xfer_count;
743:
744: if (!sectorcount)
745: {
746: ior.IOR_status = 0;
747: return;
748: }
749:
750: if ((ior.IOR_func == IOR_READ) || (ior.IOR_func == IOR_WRITE))
751: {
752: if (iop->IOP_ior.IOR_flags & IORF_CHAR_COMMAND)
753: {
754: ior.IOR_status = IORS_INVALID_COMMAND;
755: return; /* Char command NOT supported or needed.... */
756: }
757: }
758: else
759: {
760: ior.IOR_status = 0;
761: if (!cv->mountfilehandle)
762: DoCallDown (iop);
763: return;
764: }
765:
766: if (ior.IOR_func == IOR_READ)
767: {
768: sectorstart = ior.IOR_start_addr[0];
769: sectorcount = ior.IOR_xfer_count;
770: outbuffer = (char *) ior.IOR_buffer_ptr; /* may be scatter gather
771: pointer... */
772: if (ior.IOR_flags & IORF_SCATTER_GATHER)
773: {
774: sgd = (_BlockDev_Scatter_Gather *) outbuffer;
775: while ((sectorcount = sgd->BD_SG_Count))
776: {
777: outbuffer = (char *) sgd->BD_SG_Buffer_Ptr;
778: inblock (iop, outbuffer, sectorstart, sectorcount, cv);
779:
780: if (sectorstart == 0)
781: {
782: (unsigned char) outbuffer[0] = 0xeb;
783: outbuffer[1] = 0x3c;
784: (unsigned char) outbuffer[2] = 0x90;
785:
786: outbuffer[510] = 0x55; /* boot sector
787: bodge...... */
788: (unsigned char) outbuffer[511] = 0xAA;
789: }
790:
791: sectorstart += sectorcount;
792: ++sgd;
793: }
794: }
795: else
796: /* linear buffer */
797: {
798: inblock (iop, outbuffer, sectorstart, sectorcount, cv);
799:
800: /* The following code LIES to win98, who won't
801: otherwise mount disks created by earlier versions,
802: because the boot sector had stuff missing. (fixed
803: now...) */
804: if (sectorstart == 0)
805: {
806: (unsigned char) outbuffer[0] = 0xeb;
807: outbuffer[1] = 0x3c;
808: (unsigned char) outbuffer[2] = 0x90;
809: outbuffer[510] = 0x55;
810: (unsigned char) outbuffer[511] = 0xAA;
811: }
812: }
813: } /* end read op */
814: else if (ior.IOR_func == IOR_WRITE)
815: {
816: if (cv->booted == 0)
817: {
818: ior.IOR_status = 0;
819: return;
820: }
821:
822: buffernum = 0;
823:
824: bufadr = transferbuffer;
825: bufadr += (buffernum * (MAXBLOCK * 512));
826: sectorstart = ior.IOR_start_addr[0];
827: sectorcount = ior.IOR_xfer_count;
828: outbuffer = (char *) ior.IOR_buffer_ptr; /* may be scatter gather
829: pointer...; */
830: totalsectors = 0;
831: buffercopy = bufadr;
832:
833: if (ior.IOR_flags & IORF_SCATTER_GATHER)
834: {
835: sgd = (_BlockDev_Scatter_Gather *) outbuffer;
836: while ((sectorcount = sgd->BD_SG_Count))
837: {
838: outbuffer = (char *) sgd->BD_SG_Buffer_Ptr;
839: if ((totalsectors + sectorcount) <= MAXBLOCK)
840: {
841: sectorcopy (buffercopy, outbuffer, sectorcount);
842: totalsectors += sectorcount;
843: buffercopy += sectorcount * 512;
844: }
845: else
846: /* write any previous buffer..... */
847: {
848: if (totalsectors) /* was it too big to
849: start with ? */
850: {
851: outblock (iop, bufadr, sectorstart, totalsectors, cv, NULL);
852:
853: buffernum = 0;
854:
855: bufadr = transferbuffer;
856: bufadr += (buffernum * (MAXBLOCK * 512));
857: sectorstart += totalsectors;
858: totalsectors = 0;
859: buffercopy = bufadr;
860: --sgd; /* back to previous for
861: next pass..... */
862: }
863: else
864: { /* initial buffer was too
865: big, to start with! */
866: outblock (iop, outbuffer, sectorstart, sectorcount, cv, bufadr);
867:
868: buffernum = 0;
869:
870: bufadr = transferbuffer;
871: bufadr += (buffernum * (MAXBLOCK * 512));
872: sectorstart += sectorcount;
873: buffercopy = bufadr;
874: }
875:
876: }
877: ++sgd;
878: } /* end while */
879:
880: if (totalsectors)
881: outblock (iop, bufadr, sectorstart, totalsectors, cv, NULL); /* last one ? */
882: } /* end if scatter gather */
883: else
884: /* not scatter gather but is linear buffer */
885: {
886:
887: outblock (iop, outbuffer, sectorstart, sectorcount, cv, bufadr); /* get it to copy and do
888: large bit... */
889: }
890: } /* end write op */
891:
892: }
893:
894: /* DoCallBack handles completion of an I/O request by calling the previous
895: level's callback routine. */
896:
897: void
898: DoCallBack (PIOP iop)
899: {
900: _asm
901: { /* call back to previous layer */
902: pushfd
903: pushad
904: mov ecx,[iop]
905: sub[ecx] IOP.IOP_callback_ptr, size IOP_callback_entry
906: mov eax,[ecx] IOP.IOP_callback_ptr
907: push ecx
908: call[eax] IOP_callback_entry.IOP_CB_address
909: add esp, 4
910: popad
911: popfd
912:
913: }
914: }
915:
916: VOID
917: partfilerequest (PIOP iop)
918: {
919: PDCB dcb;
920: cryptvol *cv;
921:
922: dcb = (PDCB) iop->IOP_physical_dcb;
923: cv = (cryptvol *) dcb->DCB_Port_Specific;
924:
925:
926: if ((cv != &cv1) && (cv != &cv2) && (cv != &cv3) && (cv != &cv4) && (cv != &cv5) && (cv != &cv6) && (cv != &cv7) && (cv != &cv8))
927: {
928: DoCallDown (iop);
929: return;
930: }
931:
932: if (cv->booted > 2)
933: {
934: ior.IOR_status = IORS_NOT_READY; /* HW_FAILURE; */
935: DoCallBack (iop);
936: return;
937: }
938:
939: if (ior.IOR_func == IOR_COMPUTE_GEOM)
940: {
941: dcb->DCB_actual_sector_cnt[0] = cv->cryptsectorlast - cv->cryptsectorfirst;
942: dcb->DCB_actual_sector_cnt[0]++;
943: dcb->DCB_actual_sector_cnt[1] = 0;
944: dcb->DCB_actual_blk_size = 512;
945: dcb->DCB_actual_head_cnt = 1; /* number of heads */
946: dcb->DCB_actual_cyl_cnt = 1; /* number of cylinders */
947: dcb->DCB_cmn.DCB_apparent_blk_shift = 9;
948: dcb->DCB_cmn.DCB_TSD_Flags |= DCB_TSD_ACTUAL_PRE_SET;
949: ior.IOR_status = IORS_SUCCESS;
950: DoCallBack (iop);
951: return;
952: }
953:
954: if (ior.IOR_func == IOR_GEN_IOCTL)
955: {
956: iop->IOP_ior.IOR_ioctl_return = 01;
957: ior.IOR_status = IORS_INVALID_PARM; /* All the time now.... */
958: DoCallBack (iop);
959: return;
960: }
961:
962: if ((ior.IOR_func == IOR_READ) || (ior.IOR_func == IOR_WRITE))
963: {
964: dcb = (PDCB) iop->IOP_physical_dcb;
965: ior.IOR_status = IORS_CMD_IN_PROGRESS; /* 0 */
966:
967: dcb->DCB_cmn.DCB_device_flags |= DCB_DEV_IO_ACTIVE;
968: QueueMyIop (iop);
969: return;
970: }
971:
972: if ((ior.IOR_func == IOR_MEDIA_CHECK) || (ior.IOR_func == IOR_MEDIA_CHECK_RESET))
973: {
974: dcb = (PDCB) iop->IOP_original_dcb;
975:
976: ior.IOR_status = IORS_UNCERTAIN_MEDIA; /* IORS_SUCCESS; */
977: DoCallBack (iop);
978: return;
979: }
980:
981: ior.IOR_status = IORS_INVALID_COMMAND;
982: DoCallBack (iop);
983: return;
984: }
985:
986: int
987: Add_Drive (PDCB dcb, cryptvol * cv, int prefdrive)
988: {
989: int md = 0;
990: PDCB ldcb;
991: unsigned int flags;
992: unsigned int dmdbits;
993: ldcb = &cv->logicaldcb;
994: cv->ldcb = ldcb;
995:
996: #if EXTRA_INFO
997: _Debug_Printf_Service ("Add_Drive\n");
998: #endif
999:
1000: if (1)
1001: {
1002: ldcb = &cv->logicaldcb;
1003: flags = ldcb->DCB_cmn.DCB_device_flags;
1004:
1005: if (dcb)
1006: memcpy ((char *) ldcb, (char *) dcb, sizeof (DCB));
1007:
1008: ldcb->DCB_cmn.DCB_device_flags = flags;
1009: flags = dcb->DCB_cmn.DCB_device_flags;
1010: dmdbits = dcb->DCB_cmn.DCB_dmd_flags;
1011: dmdbits &= ~DCB_dmd_phys_sgd;
1012: cv->ldcb = ldcb;
1013: if (!cv->mountfilehandle)
1014: IspInsertCalldown (ldcb, partfilerequest, (PDDB) & cv->addb,
1015: (USHORT) dcb->DCB_cmn.DCB_expansion_length,
1016: dmdbits, (UCHAR) DRP_VSD_3);
1017: else
1018: IspInsertCalldown (ldcb, partfilerequest, (PDDB) & cv->addb, 0,
1019: 0, (UCHAR) DRP_VSD_3);
1020:
1021: ldcb->DCB_Port_Specific = (ULONG) cv;
1022: ldcb->DCB_cmn.DCB_physical_dcb = (ULONG) ldcb;
1023: ldcb->DCB_max_xfer_len = MAXBLOCK * 512; /* 256*512 */
1024:
1025: if ((dcb->DCB_max_xfer_len < MAXBLOCK * 512) && (cv->mountfilehandle == 0))
1026: ldcb->DCB_max_xfer_len = dcb->DCB_max_xfer_len;
1027:
1028: if (!cv->mountfilehandle)
1029: {
1030: ldcb->DCB_max_sg_elements = dcb->DCB_max_sg_elements; /* 1; */
1031: ldcb->DCB_cmn.DCB_expansion_length = dcb->DCB_cmn.DCB_expansion_length;
1032: ldcb->DCB_cmn.DCB_dmd_flags = dmdbits;
1033: }
1034: else
1035: ldcb->DCB_max_sg_elements = 17;
1036:
1037: ldcb->DCB_cmn.DCB_device_flags |= DCB_DEV_PHYSICAL;
1038: ldcb->DCB_cmn.DCB_device_flags2 = 0;
1039: ldcb->DCB_cmn.DCB_device_flags &= ~DCB_DEV_REMOVABLE; /* support removable as
1040: fixed... */
1041: ldcb->DCB_cmn.DCB_device_type = DEVICE_TYPE;
1042: ldcb->DCB_cmn.DCB_user_drvlet = (USHORT) md;
1043: ldcb->DCB_cmn.DCB_partition_type = 0;
1044: ldcb->DCB_cmn.DCB_Sstor_Host = 0;
1045: ldcb->DCB_actual_sector_cnt[0] = 0;
1046: ldcb->DCB_actual_sector_cnt[0]++;
1047: ldcb->DCB_actual_sector_cnt[1] = 0;
1048: ldcb->DCB_actual_blk_size = 512;
1049: ldcb->DCB_actual_head_cnt = 1; /* number of heads */
1050: ldcb->DCB_actual_cyl_cnt = 1; /* number of cylinders */
1051: ldcb->DCB_cmn.DCB_apparent_blk_shift = 9;
1052: ldcb->DCB_actual_spt = ldcb->DCB_actual_sector_cnt[0];
1053: ldcb->DCB_bdd.DCB_apparent_sector_cnt[0] = ldcb->DCB_actual_sector_cnt[0];
1054: ldcb->DCB_bdd.DCB_apparent_sector_cnt[1] = 0;
1055: ldcb->DCB_bdd.DCB_apparent_head_cnt = 1;
1056: ldcb->DCB_bdd.DCB_apparent_blk_size = 512;
1057: ldcb->DCB_bdd.DCB_apparent_cyl_cnt = 1;
1058: ldcb->DCB_bdd.DCB_apparent_spt = ldcb->DCB_actual_sector_cnt[0];
1059: }
1060:
1061: ldcb->DCB_cmn.DCB_drive_lttr_equiv = 0;
1062: ldcb->DCB_cmn.DCB_user_drvlet = 0;
1063: ldcb->DCB_cmn.DCB_device_type = DEVICE_TYPE;
1064:
1065: if (prefdrive != -1)
1066: md = IspDriveLetterPickPref (ldcb, (UCHAR) ISP_PDL_FL_USE_RANGE, (UCHAR) prefdrive);
1067: else
1068: md = (unsigned char) 255;
1069:
1070:
1071: if (md == 255)
1072: md = IspDriveLetterPick (ldcb, 0);
1073:
1074: ldcb->DCB_cmn.DCB_unit_number = (UCHAR) md;
1075: ldcb->DCB_cmn.DCB_vrp_ptr = 0; /* clear the copied VRP pointer...... */
1076: ldcb->DCB_cmn.DCB_device_flags |= DCB_DEV_WRITEABLE;
1077:
1078: if (!(flags & DCB_DEV_WRITEABLE))
1079: ldcb->DCB_cmn.DCB_device_flags &= ~DCB_DEV_WRITEABLE;
1080:
1081: ldcb->DCB_cmn.DCB_drive_lttr_equiv = md;
1082: ldcb->DCB_cmn.DCB_user_drvlet = (UCHAR) md;
1083: ldcb->DCB_cmn.DCB_unit_number = (UCHAR) md; /* 0; */
1084:
1085: cv->drive = (ULONG) md;
1086: ldcb->DCB_cmn.DCB_TSD_Flags = DCB_TSD_APPARENT_PRE_SET | DCB_TSD_MBPB_PBR;
1087: ldcb->DCB_cmn.DCB_partition_type = 0;
1088: ldcb->DCB_cmn.DCB_device_flags &= ~DCB_DEV_TSD_PROCESSED;
1089: ldcb->DCB_cmn.DCB_Partition_Start = 0;
1090: ldcb->DCB_cmn.DCB_device_flags |= DCB_DEV_LOGICAL | DCB_DEV_MEDIA_CHANGED | DCB_DEV_UNCERTAIN_MEDIA;
1091:
1092: ldcb->DCB_cmn.DCB_cAssoc = 1;
1093:
1094: ldcb->DCB_cmn.DCB_user_drvlet = 0xFF;
1095:
1096: #if EXTRA_INFO
1097: _Debug_Printf_Service ("Add_Drive end\n");
1098: #endif
1099:
1100: if ((md <= 26) && (md > 1))
1101: {
1102: IspAssociateDcb (ldcb, (char) md, ISP_D_A_FL_NOSHELLMSG);
1103:
1104: cv->notifytime = 2; /* 2 second to notify arrival of disk */
1105:
1106: return 0;
1107: }
1108:
1109: return 1;
1110: }
1111:
1112: #define FIRST_READ_SIZE SECTOR_SIZE
1113:
1114: int
1115: trymountfile (PDCB dcb, cryptvol * cv, MOUNT_STRUCT * mf)
1116: {
1117: USHORT offset;
1118: USHORT size;
1119: PIOP myiop;
1120: PIOR myior;
1121: int mounted = 0;
1122: char *readBuffer = NULL;
1123:
1124: if (dcb->DCB_cmn.DCB_device_type == DCB_type_disk)
1125: {
1126: int status;
1127:
1128: offset = (USHORT) (dcb->DCB_cmn.DCB_expansion_length + FIELDOFFSET (IOP, IOP_ior));
1129: size = offset + sizeof (IOR) + dcb->DCB_max_sg_elements * sizeof (SGD);
1130: myiop = IspCreateIop (size, offset, ISP_M_FL_MUST_SUCCEED | ISP_M_FL_SMART_ALLOC | ISP_M_FL_INTERRUPT_TIME | ISP_M_FL_PERSISTENT_IOP);
1131: myior = &myiop->IOP_ior;
1132: myior->IOR_private_client = offset;
1133:
1134: readBuffer = TCalloc (FIRST_READ_SIZE);
1135: if (readBuffer == NULL)
1136: goto error;
1137:
1138: dophysblock (myiop, cv->cryptsectorfirst, FIRST_READ_SIZE / 512, readBuffer, cv, IOR_READ);
1139:
1140: status = VolumeReadHeaderCache (mf->bCache, readBuffer, mf->szPassword,
1141: mf->nPasswordLen, &cv->cryptoInfo);
1142:
1143: if (status != 0)
1144: {
1145: memset (cv, 0, sizeof (cryptvol));
1146: cv->cryptsectorfirst = 0x7fffffff;
1147: mounted = 0;
1148: goto error;
1149: }
1150: else
1151: cv->booted = 1;
1152:
1153: if (Add_Drive (dcb, cv, mf->nDosDriveNo) == 0)
1154: {
1155: mounted = 1;
1156: }
1157: else
1158: {
1159: /* No Drive letter available */
1160: memset (cv, 0, sizeof (cryptvol));
1161: cv->cryptsectorfirst = 0x7fffffff;
1162: mounted = -1;
1163: }
1164:
1165: error:
1166: if (readBuffer != NULL)
1167: TCfree (readBuffer);
1168:
1169: IspDeallocMem ((PVOID) ((DWORD) myior - myior->IOR_private_client));
1170: return mounted;
1171: }
1172:
1173: return mounted;
1174: }
1175:
1176: void
1177: readnullfilesize (int hand)
1178: {
1179: int bytes;
1180: char buffer[512];
1181: R0_ReadFile (FALSE, hand, 0, 0, buffer, &bytes);
1182: }
1183:
1184: void
1185: mountdiskfileR0 (MOUNT_STRUCT * mf)
1186: {
1187: DWORD hfile;
1188: DWORD action;
1189: int tmf;
1190: int code;
1191: cryptvol *cv;
1192: int c;
1193: int writeable = 1;
1194: PDCB dcb;
1195: int flag = 0;
1196: unsigned char openflag = 0x81;
1197:
1198: char *fname = (char *) mf->wszVolume;
1199:
1200:
1201: installhook (); /* only installs if not done already... */
1202:
1203: for (c = 0; c < NUMSLOTS; c++)
1204: {
1205: cv = cryptvols[c];
1206: if (strcmp (fname, (char *) &cv->mounted_file_name) == 0)
1207: {
1208: flag = 3 + 128; /* already present */
1209: goto done;
1210: }
1211: }
1212:
1213: if (writeable)
1214: {
1215: code = R0_OpenCreateFile (FALSE, ACCESS_READWRITE | SHARE_DENYREADWRITE,
1216: 0, ACTION_OPENEXISTING, 0x81, fname, &hfile, &action); /* R0_NO_CACHE(UBYTE)
1217: ((R0_NO_CACHE)>>8) */
1218:
1219: if (code != 0)
1220: {
1221: writeable = 0;
1222: code = R0_OpenCreateFile (FALSE, ACCESS_READONLY | SHARE_DENYREAD,
1223: 0, ACTION_OPENEXISTING, 0x81, fname, &hfile, &action); /* R0_NO_CACHE(UBYTE)
1224: ((R0_NO_CACHE)>>8) */
1225: }
1226:
1227: if (code == 0)
1228: readnullfilesize (hfile);
1229: }
1230: else
1231: {
1232: code = R0_OpenCreateFile (FALSE, ACCESS_READONLY | SHARE_DENYREAD,
1233: 0, ACTION_OPENEXISTING, 0x81, fname, &hfile, &action); /* R0_NO_CACHE(UBYTE)
1234: ((R0_NO_CACHE)>>8) */
1235:
1236: if (code == 0)
1237: readnullfilesize (hfile);
1238: }
1239:
1240: if (code != 0)
1241: {
1242: flag = 1;
1243: goto done;
1244: }
1245:
1246: for (c = 0; c < NUMSLOTS; c++)
1247: {
1248: cv = cryptvols[c];
1249:
1250: if ((cv->booted == 0) && (cv->physdevDCB == 0))
1251: {
1252: cv->filehostdcb = 0;
1253: cv->mountfilehandle = hfile;
1254: cv->physdevDCB = &cv->logicaldcb;
1255: cv->cryptsectorfirst = 0x00000000;
1256: cv->cryptsectorlast = 0x7ffffff0;
1257: dcb = (PDCB) cv->physdevDCB;
1258: flag = 2;
1259:
1260: if (writeable != 0)
1261: dcb->DCB_cmn.DCB_device_flags = DCB_DEV_WRITEABLE;
1262:
1263: /* clears cv set above if failed.... */
1264: tmf = trymountfile (dcb, cv, mf);
1265:
1266: if (tmf)
1267: {
1268: _asm cli
1269: flag = 3;
1270:
1271: mf->nReturnCode = flag;
1272:
1273: if (tmf > 0) /* if tmg is -ve then no
1274: drive letter (already had
1275: blue screen..) */
1276: {
1277: mf->nReturnCode = flag;
1278:
1279: cv->booted = 2;
1280: strcpy ((char *) &cv->mounted_file_name, fname);
1281:
1282: goto done;
1283: }
1284: } /* trymountfile */
1285:
1286: } /* if cv->.... */
1287:
1288: if (flag)
1289: break; /* out of for loop */
1290: }
1291:
1292:
1293: R0_CloseFile (hfile);
1294:
1295: done:
1296:
1297: switch (flag)
1298: {
1299: case 3 + 128:
1300: mf->nReturnCode = ERR_VOL_ALREADY_MOUNTED;
1301: break;
1302: case 1:
1303: mf->nReturnCode = ERR_FILE_OPEN_FAILED;
1304: break;
1305: case 2:
1306: mf->nReturnCode = ERR_VOL_MOUNT_FAILED;
1307: break;
1308: case 3:
1309: if (tmf > 0)
1310: {
1311: mf->nReturnCode = 0;
1312: mf->nDosDriveNo = cv->drive;
1313: }
1314: else
1315: mf->nReturnCode = ERR_NO_FREE_DRIVES;
1316: break;
1317: case 0:
1318: mf->nReturnCode = ERR_NO_FREE_SLOTS;
1319: break;
1320: }
1321: }
1322:
1323:
1324: void
1325: outblock (PIOP iop, char *outbuffer, int sectorstart, int sectorcount, cryptvol * cv, char *workbuff)
1326: {
1327: int logsec = sectorstart + 1; /* get logical volume sector. */
1328:
1329: char *sendbuffer;
1330:
1331: if (!sectorcount)
1332: return;
1333:
1334: do
1335: {
1336: if (sectorcount <= MAXBLOCK)
1337: {
1338: sendbuffer = outbuffer;
1339:
1340: /* if copyflag 0, then buffer already set by caller. */
1341: ior.IOR_status = 0;
1342: if (workbuff)
1343: {
1344: sectorcopy (workbuff, outbuffer, sectorcount);
1345: sendbuffer = workbuff;
1346: }
1347:
1348: writelogical (iop, logsec, sectorcount, sendbuffer, cv);
1349:
1350: sectorcount = 0;
1351: return;
1352: }
1353: else
1354: {
1355: sendbuffer = outbuffer;
1356: if (workbuff)
1357: {
1358: sectorcopy (workbuff, outbuffer, MAXBLOCK);
1359: sendbuffer = workbuff;
1360: }
1361:
1362: writelogical (iop, logsec, MAXBLOCK, sendbuffer, cv);
1363: logsec += MAXBLOCK;
1364: sectorcount -= MAXBLOCK;
1365: outbuffer += (MAXBLOCK * 512);
1366: }
1367: }
1368: while ((sectorcount > 0) && (ior.IOR_status < 16));
1369: }
1370:
1371: void
1372: inblock (PIOP iop, char *outbuffer, int sectorstart, int sectorcount, cryptvol * cv)
1373: {
1374: int logsec = sectorstart + 1; /* get logical volume sector. */
1375:
1376: do
1377: {
1378: ior.IOR_status = 0;
1379: if (sectorcount < MAXBLOCK)
1380: {
1381: readlogical (iop, logsec, sectorcount, (char *) transferbuffer, cv);
1382: memcpy (outbuffer, transferbuffer, sectorcount * 512);
1383: sectorcount = 0;
1384: return;
1385: }
1386: else
1387: {
1388: readlogical (iop, logsec, MAXBLOCK, (char *) transferbuffer, cv);
1389: memcpy (outbuffer, transferbuffer, MAXBLOCK * 512);
1390: logsec += MAXBLOCK;
1391: sectorcount -= MAXBLOCK;
1392: outbuffer += (MAXBLOCK * 512);
1393: }
1394: }
1395: while ((sectorcount > 0) && (ior.IOR_status < 16));
1396: }
1397:
1398: int
1399: doR0fileio (int sector, int numsectors, char *buffer, cryptvol * cv, int iorop)
1400: {
1401: CLIENT_STRUCT sregs; /* static */
1402: PVRP v;
1403:
1404: int res;
1405: int bytes; /* static */
1406:
1407:
1408: if (iorop == IOR_READ)
1409: {
1410: if (numsectors)
1411: {
1412: SaveClientState ((CLIENT_STRUCT *) & sregs);
1413:
1414: res = R0_ReadFile (FALSE, cv->mountfilehandle, numsectors << 9, sector << 9, buffer, &bytes);
1415:
1416: RestoreClientState ((CLIENT_STRUCT *) & sregs);
1417: }
1418:
1419: return res;
1420: } /* IOR read */
1421:
1422: res = 0;
1423: if (iorop == IOR_WRITE)
1424: {
1425: if (numsectors)
1426: {
1427: SaveClientState ((CLIENT_STRUCT *) & sregs);
1428:
1429: res = R0_WriteFile (FALSE, cv->mountfilehandle, numsectors * 512, sector * 512, buffer, &bytes);
1430:
1431: RestoreClientState ((CLIENT_STRUCT *) & sregs);
1432: }
1433:
1434: if (res)
1435: {
1436: if (res == 5)
1437: res = 0x13; /* WHY ARE WE GETTING ACCESS
1438: DENIED 005 ON CD RATHER
1439: THAN WP ? */
1440:
1441: if (res == 0x13)
1442: {
1443: if (cv->booted >= 2)
1444: {
1445: v = (PVRP) cv->ldcb->DCB_cmn.DCB_vrp_ptr;
1446: if (v)
1447: {
1448: if ((v->VRP_event_flags & VRP_ef_write_protected) == 0)
1449: {
1450: v->VRP_event_flags |= VRP_ef_write_protected | VRP_ef_media_uncertain;
1451: }
1452: }
1453: } /* cv->booted */
1454: } /* res=13 */
1455: } /* res= something */
1456:
1457: return res;
1458: } /* IOR write */
1459:
1460: return 0;
1461: }
1462:
1463: int
1464: MapDosError (int error)
1465: {
1466: int e;
1467:
1468: if (error == 0x13)
1469: return (IORS_WRITE_PROTECT);
1470:
1471: e = IORS_NOT_READY; /* IORS_HW_FAILURE; */
1472: return e;
1473: }
1474:
1475: char fileerrorstr[]=
1476: {
1477: "TC has encountered an error reading a host file which\n"
1478: "it is using for a currently open scrambled disk volume.\n\n"
1479: "You should immediately dismount the file using the TC mount\n"
1480: "application, correct the error, and re mount the disk image file.\n\n\n"
1481: "The related disk will be unavailable, until you do, and you should\n"
1482: "save your work elsewhere."
1483: };
1484:
1485: int
1486: dophysblock2 (PIOP iop, int sector, int numsectors, char *buffr, cryptvol * cv, USHORT iorop)
1487: {
1488: int rstatus = 0; /* status return value.... */
1489: PIOP myiop;
1490: PIOR myior;
1491:
1492: _BlockDev_Scatter_Gather *sgd;
1493:
1494: PDCB mydcb = cv->physdevDCB; /* (PDCB) iop->IOP_physical_dcb; */
1495: USHORT offset;
1496: USHORT size;
1497:
1498: if (cv->mountfilehandle)
1499: {
1500: if (cv->booted <= 2)
1501: rstatus = doR0fileio (sector, numsectors, buffr, cv, iorop);
1502: else
1503: rstatus = 23;
1504:
1505: if ((rstatus) && (rstatus != 0x13))
1506: {
1507: iop->IOP_timer = iop->IOP_timer_orig = 32000;
1508: rstatus = MapDosError (rstatus);
1509:
1510: if (cv->booted <= 2 && (cv->booted))
1511: {
1512: Post_message (fileerrorstr, "TC: Mounted file error");
1513: cv->booted = 256;
1514: }
1515: }
1516:
1517: iop->IOP_ior.IOR_status = rstatus;
1518: return rstatus;
1519: }
1520:
1521: /* End up here, if we are handling a disk partition rather than
1522: container file */
1523: offset = (USHORT) (mydcb->DCB_cmn.DCB_expansion_length + FIELDOFFSET (IOP, IOP_ior));
1524: size = offset + sizeof (IOR) + (8 * sizeof (SGD));
1525: iop->IOP_timer = iop->IOP_timer_orig = 160;
1526:
1527: myiop = IspCreateIop (size, offset, ISP_M_FL_SMART_ALLOC);
1528:
1529: if (myiop == NULL)
1530: {
1531:
1532: iop->IOP_ior.IOR_status = IORS_MEMORY_ERROR;
1533: return IORS_MEMORY_ERROR;
1534: }
1535:
1536: myior = &myiop->IOP_ior;
1537:
1538: /* Be aware that Criteria routine reads it's dmd bits from THIS dcb! */
1539:
1540: myiop->IOP_original_dcb = (ULONG) mydcb; /* iop->IOP_original_dcb;
1541: (ULONG) mydcb; */
1542: myiop->IOP_physical_dcb = (ULONG) mydcb->DCB_cmn.DCB_physical_dcb;
1543: if (cv->booted == 1)
1544: cv->booted = 2; /* Irrelevant here..... */
1545: myior->IOR_next = 0;
1546: myior->IOR_start_addr[1] = 0;
1547: myior->IOR_flags = IORF_VERSION_002;
1548: myior->IOR_private_client = offset;
1549: myior->IOR_req_vol_handle = mydcb->DCB_cmn.DCB_vrp_ptr;
1550: myior->IOR_sgd_lin_phys = (ULONG) (myior + 1);
1551: myior->IOR_num_sgds = 0;
1552: myior->IOR_vol_designtr = mydcb->DCB_cmn.DCB_unit_number;
1553: myior->IOR_func = iorop;
1554: myior->IOR_flags |= IORF_BYPASS_VOLTRK | IORF_HIGH_PRIORITY | IORF_SCATTER_GATHER | IORF_SYNC_COMMAND | IORF_DONT_CACHE;
1555: if (iorop == IOR_READ)
1556: myior->IOR_flags |= IORF_DATA_IN;
1557: if (iorop == IOR_WRITE)
1558: myior->IOR_flags |= IORF_DATA_OUT;
1559: myior->IOR_start_addr[0] = sector;
1560: myior->IOR_xfer_count = numsectors;
1561: sgd = (_BlockDev_Scatter_Gather *) myior->IOR_sgd_lin_phys; /* scatter gather
1562: array... */
1563: sgd->BD_SG_Buffer_Ptr = (ULONG) buffr; /* Buffer in LOCKED ram,
1564: below 16mbyte, 4K
1565: boundary.. */
1566: sgd->BD_SG_Count = numsectors;
1567: myior->IOR_buffer_ptr = (ULONG) sgd; /* Implement as Scatter
1568: gather, with One block */
1569: sgd++;
1570: sgd->BD_SG_Buffer_Ptr = 0;
1571: sgd->BD_SG_Count = 0;
1572: sgd++;
1573: myior->IOR_sgd_lin_phys = (ULONG) sgd;
1574: rstatus = myior->IOR_status;
1575: sgd->BD_SG_Buffer_Ptr = 0;
1576: sgd->BD_SG_Count = 0;
1577: sgd++;
1578: sgd->BD_SG_Buffer_Ptr = 0;
1579: sgd->BD_SG_Count = 0;
1580: sgd++;
1581: sgd->BD_SG_Buffer_Ptr = 0;
1582: sgd->BD_SG_Count = 0;
1583: myiop->IOP_timer = 40;
1584: myiop->IOP_timer_orig = 40;
1585: /* Call criteria, to set phys SGDs physical addresses if needed..... */
1586: if (IlbIntIoCriteria (myiop))
1587: myior->IOR_flags |= IORF_DOUBLE_BUFFER; /* Double buffer, will
1588: also make no
1589: difference */
1590: IlbInternalRequest (myiop, mydcb, OnRequest);
1591: rstatus = myior->IOR_status;
1592: iop->IOP_ior.IOR_status = rstatus; /* myior->IOR_status; */
1593: IspDeallocMem ((PVOID) ((DWORD) myior - myior->IOR_private_client));
1594: return rstatus;
1595: }
1596:
1597: int
1598: dophysblock (PIOP iop, int sector, int numsectors, char *buffr, cryptvol * cv, USHORT iorop)
1599: {
1600: int s, c;
1601:
1602: for (c = 0; c < 3; c++)
1603: {
1604: s = dophysblock2 (iop, sector, numsectors, buffr, cv, iorop);
1605: if (s == IORS_SUCCESS_WITH_RETRY)
1606: return 0;
1607: if (!s)
1608: return 0;
1609: }
1610:
1611: return s;
1612: }
1613:
1614: void
1615: readlogical (PIOP iop, int temp_block, int num_sectors, char *buffer, cryptvol * cv)
1616: {
1617: int secNum;
1618:
1619: secNum = temp_block;
1620:
1621: #if EXTRA_INFO
1622: _Debug_Printf_Service ("secNum=%d,num_sectors=%d\n", secNum, num_sectors);
1623: #endif
1624:
1625: dophysblock (iop, secNum + cv->cryptsectorfirst, num_sectors, buffer, cv, IOR_READ);
1626:
1627: #if EXTRA_INFO
1628: _Debug_Printf_Service ("0x%08x\n", *((int *) buffer));
1629: #endif
1630:
1631: cv->cryptoInfo->decrypt_sector ((unsigned long *) buffer,
1632: (unsigned __int64) secNum, num_sectors,
1633: &cv->cryptoInfo->ks[0],
1634: cv->cryptoInfo->iv,
1635: cv->cryptoInfo->cipher);
1636:
1637: #if EXTRA_INFO
1638: _Debug_Printf_Service ("0x%08x\n", *((int *) buffer));
1639: #endif
1640:
1641: }
1642:
1643: void
1644: writelogical (PIOP iop, int temp_block, int num_sectors, char *buffer, cryptvol * cv)
1645: {
1646: int secNum;
1647:
1648: secNum = temp_block;
1649:
1650: #if EXTRA_INFO
1651: _Debug_Printf_Service ("0x%08x\n", *((int *) buffer));
1652: #endif
1653:
1654: cv->cryptoInfo->encrypt_sector ((unsigned long *) buffer,
1655: (unsigned __int64) secNum, num_sectors,
1656: &cv->cryptoInfo->ks[0],
1657: cv->cryptoInfo->iv,
1658: cv->cryptoInfo->cipher);
1659:
1660: #if EXTRA_INFO
1661: _Debug_Printf_Service ("0x%08x\n", *((int *) buffer));
1662: #endif
1663:
1664: dophysblock (iop, secNum + cv->cryptsectorfirst, num_sectors, buffer, cv, IOR_WRITE);
1665: }
1666:
1667:
1668: BOOL
1669: OnSystemExit (void)
1670: {
1671: /* Called when Win32 is about to die. We must close down the files,
1672: for any files mounted as encrypted disks. this call seems to be
1673: the only chance we get. the system pukes amd hangsif we don't.
1674: Corrupt screen etc. nd refuses to shut down..... */
1675:
1676: cryptvol *cv;
1677: int c;
1678:
1679: for (c = 0; c < NUMSLOTS; c++)
1680: {
1681: cv = cryptvols[c];
1682: unlockdrive (cv);
1683: if (cv->mountfilehandle)
1684: R0_CloseFile (cv->mountfilehandle);
1685: }
1686:
1687: killthread ();
1688: return AEP_SUCCESS;
1689: }
1690:
1691: void
1692: Post_message (char *msg, char *header)
1693: {
1694: MessageBox *m;
1695: int n;
1696:
1697: for (n = 0; n < MAX_MESSAGES - 1; n++)
1698: {
1699: m = &Msgs[n];
1700: if (m->PostPlease == 0)
1701: break;
1702:
1703: }
1704:
1705: m->PostPlease = 1;
1706: m->MessageHdr = header;
1707: m->MessageBody = msg;
1708: }
1709:
1710: void
1711: ProcessWinMessagesBlueScreen (void)
1712: {
1713: MessageBox *m;
1714: int n;
1715:
1716: for (n = 0; n < MAX_MESSAGES; n++)
1717: {
1718: m = &Msgs[n];
1719: if (m->PostPlease)
1720: {
1721: ShellMessageNCB (0, m->MessageBody, m->MessageHdr);
1722: m->PostPlease = 0;
1723: }
1724: }
1725: }
1726:
1727: /* The code below gets called by the IOS *every* 0.5 seconds... */
1728: USHORT
1729: OnHalfSec (PAEP_boot_done aep) /* dummy param */
1730: {
1731: #if 0
1732: cryptvol *cv;
1733: int c;
1734: int notified = 0;
1735: #endif
1736:
1737: halfseccount++;
1738:
1739: ProcessWinMessagesBlueScreen ();
1740:
1741: #if 0
1742: for (c = 0; c < 8; c++)
1743: {
1744: cv = cryptvols[c];
1745:
1746: if (cv->notifytime)
1747: {
1748: cv->notifytime--;
1749: if (cv->notifytime == 0)
1750: {
1751: cv->notifytime = 0x8000ffff;
1752: if (!notified) /* prevent multiple notifications */
1753: {
1754: notified++;
1755: SHELL_CallAtAppyTime ((APPY_CALLBACK) & drivearrived, 0, 0);
1756: }
1757: }
1758:
1759: }
1760: }
1761: #endif
1762:
1763: return AEP_SUCCESS;
1764: }
1765:
1766:
1767: /* ------------------------------------partition support
1768: ------------------------------------------- */
1769:
1770: /* go round every drive reading all the partitions.... */
1771: void
1772: readallpartitions (MOUNT_STRUCT * mf, BOOL bVerifyOnly)
1773: {
1774: int c = 0;
1775: PDCB dcb;
1776: USHORT offset;
1777: USHORT size;
1778: PIOP myiop;
1779: PIOR myior;
1780: int x, disks, z;
1781: char *vol = (char *) mf->wszVolume;
1782:
1783: mf->nReturnCode = ERR_INVALID_DEVICE; /* Assume failure */
1784:
1785: if (strlen ((char *) mf->wszVolume) < 28)
1786: return;
1787:
1788: x = vol[16] - '0'; /* Disk number starting from 0 */
1789: z = vol[27] - '0'; /* Partition number start from 1 */
1790: disks = 0; /* Count of disks */
1791:
1792: if (x < 0 || z < 1)
1793: return;
1794:
1795: #if EXTRA_INFO
1796: _Debug_Printf_Service ("readallpartitions\n");
1797: #endif
1798:
1799: while (dcb = dcblist[++c])
1800: {
1801: if ((dcb->DCB_cmn.DCB_device_type == 0) && (dcb->DCB_cmn.DCB_apparent_blk_shift == 9))
1802: {
1803: if (x != disks++)
1804: continue;
1805:
1806: offset = (USHORT) (dcb->DCB_cmn.DCB_expansion_length + FIELDOFFSET (IOP, IOP_ior));
1807: size = offset + sizeof (IOR) + dcb->DCB_max_sg_elements * sizeof (SGD);
1808: myiop = IspCreateIop (size, offset, ISP_M_FL_MUST_SUCCEED | ISP_M_FL_SMART_ALLOC | ISP_M_FL_INTERRUPT_TIME | ISP_M_FL_PERSISTENT_IOP);
1809: myior = &myiop->IOP_ior;
1810: myior->IOR_private_client = offset;
1811:
1812: DiskRead (dcb, myiop, 0, 1, partitiontestbuffer, IOR_READ); /* ;single read in case
1813: of media change... */
1814: memset (partitiontestbuffer, 0, 512);
1815:
1816: if (!DiskRead (dcb, myiop, 0, 1, partitiontestbuffer, IOR_READ)) /* +32768 */
1817: {
1818: UsePartitionInfo (dcb, myiop, partitiontestbuffer, 0, 0, &z, mf, bVerifyOnly); /* +32768 */
1819: }
1820:
1821: IspDeallocMem ((PVOID) ((DWORD) myior - myior->IOR_private_client));
1822:
1823: }
1824: }
1825:
1826: #if EXTRA_INFO
1827: _Debug_Printf_Service ("readallpartitions end\n");
1828: #endif
1829:
1830: }
1831:
1832:
1833: int
1834: DiskRead (PDCB mydcb, PIOP myiop, unsigned int sector, unsigned int numsectors, char *buffr, USHORT iorop)
1835: {
1836: int rstatus = 0; /* status return value.... */
1837: unsigned long *errnl = (unsigned long *) buffr; /* no load test... */
1838: PIOR myior;
1839: _BlockDev_Scatter_Gather *sgd;
1840:
1841: myior = &myiop->IOP_ior;
1842: myiop->IOP_original_dcb = (ULONG) mydcb;
1843: myiop->IOP_physical_dcb = (ULONG) mydcb->DCB_cmn.DCB_physical_dcb;
1844: myior->IOR_next = 0;
1845: myior->IOR_start_addr[1] = 0;
1846: myior->IOR_flags = IORF_VERSION_002;
1847: myior->IOR_req_vol_handle = mydcb->DCB_cmn.DCB_vrp_ptr;
1848: myior->IOR_sgd_lin_phys = (ULONG) (myior + 1);
1849: myior->IOR_num_sgds = 0;
1850: myior->IOR_vol_designtr = mydcb->DCB_cmn.DCB_unit_number;
1851: myior->IOR_func = iorop;
1852: myior->IOR_flags |= IORF_BYPASS_VOLTRK | IORF_HIGH_PRIORITY | IORF_SCATTER_GATHER | IORF_SYNC_COMMAND;
1853: if (iorop == IOR_READ)
1854: {
1855: myior->IOR_flags |= IORF_DATA_IN;
1856: memset (buffr, 0, numsectors * 512);
1857: errnl[0] = 0xACE01DE4;
1858: errnl[1] = 0xEDB0CD01;
1859: errnl[2] = 0x4caf3321;
1860: errnl[3] = 0xa35a32c4;
1861: }
1862:
1863: if (iorop == IOR_WRITE)
1864: myior->IOR_flags |= IORF_DATA_OUT;
1865: myior->IOR_start_addr[0] = sector;
1866: myior->IOR_xfer_count = numsectors;
1867: myior->IOR_buffer_ptr = (ULONG) buffr;
1868:
1869: sgd = (_BlockDev_Scatter_Gather *) myior->IOR_sgd_lin_phys; /* scatter gather
1870: array... */
1871: sgd->BD_SG_Buffer_Ptr = (ULONG) buffr; /* Buffer in LOCKED ram,
1872: below 16mbyte, 4K
1873: boundary.. */
1874: sgd->BD_SG_Count = numsectors;
1875: myior->IOR_buffer_ptr = (ULONG) sgd; /* Implement as Scatter
1876: gather, with One block */
1877: sgd++;
1878: sgd->BD_SG_Buffer_Ptr = 0;
1879: sgd->BD_SG_Count = 0;
1880:
1881: sgd++;
1882: myior->IOR_sgd_lin_phys = (ULONG) sgd;
1883: rstatus = myior->IOR_status;
1884:
1885: myiop->IOP_timer = 40;
1886: myiop->IOP_timer_orig = 40;
1887:
1888: if (mydcb->DCB_cmn.DCB_Sstor_Host == FALSE)
1889: {
1890: if (IlbIntIoCriteria (myiop))
1891: myior->IOR_flags |= IORF_DOUBLE_BUFFER;
1892: IlbInternalRequest (myiop, mydcb, 0);
1893: rstatus = myior->IOR_status;
1894:
1895: if (iorop == IOR_READ)
1896: {
1897: /* checks for partion reads of simulated drives that
1898: dont return either data or error.... */
1899: if ((errnl[0] == 0xACE01DE4) &&
1900: (errnl[1] == 0xEDB0CD01) &&
1901: (errnl[2] == 0x4caf3321) &&
1902: (errnl[3] == 0xa35a32c4))
1903:
1904: rstatus = 16;
1905:
1906: }
1907:
1908: return rstatus;
1909: }
1910:
1911: return 16;
1912:
1913:
1914: }
1915:
1916: /* This routine finds partitions */
1917:
1918: void
1919: UsePartitionInfo (PDCB dcb, PIOP myiop, char *diskbuffer, unsigned int relative, int recursed, int *partnum,
1920: MOUNT_STRUCT * mf, BOOL bVerifyOnly)
1921: {
1922: /* Note that this is recursive..... */
1923: partitionrec *pr;
1924: char *c;
1925: char *ndb;
1926: int flag = 0;
1927: cryptvol *cv = NULL;
1928:
1929: unsigned int ComputedStartSector;
1930: unsigned int ComputedEndSector;
1931: unsigned int cyl;
1932: unsigned int cylsize;
1933: unsigned int headsize;
1934:
1935: #if EXTRA_INFO
1936: _Debug_Printf_Service ("UsePartitionInfo\n");
1937: #endif
1938:
1939: c = diskbuffer;
1940: ndb = c + 512; /* next disk buffer */
1941: c += 0x1be;
1942:
1943: headsize = dcb->DCB_bdd.DCB_apparent_spt;
1944: cylsize = dcb->DCB_bdd.DCB_apparent_head_cnt;
1945: cylsize = cylsize * headsize;
1946:
1947: c = diskbuffer;
1948: c += 0x1be;
1949: pr = (partitionrec *) c;
1950:
1951:
1952: cyl = (pr->ss) & (128 + 64);
1953: cyl = cyl << 2;
1954: cyl += pr->sc;
1955: cyl *= cylsize; /* 16065; */
1956:
1957: ComputedStartSector = pr->sh * headsize; /* 63; */
1958: ComputedStartSector += (((pr->ss) & 63) - 1);
1959: ComputedStartSector += cyl;
1960:
1961:
1962: cyl = (pr->es) & (128 + 64);
1963: cyl = cyl << 2;
1964: cyl += pr->ec;
1965: cyl *= cylsize; /* 16065; */
1966:
1967: ComputedEndSector = pr->eh * headsize; /* 63 */
1968: ComputedEndSector += (((pr->es) & 63) - 1);
1969: ComputedEndSector += cyl;
1970: ComputedEndSector = ComputedEndSector - ComputedStartSector;
1971: ComputedEndSector += 1; /* allow for inclusive sectors... */
1972:
1973:
1974: pr = (partitionrec *) c;
1975:
1976: if (pr->boot == 0x80)
1977: dcb_boot = dcb;
1978:
1979: if ((pr->system == 5) || (pr->system == 0xF))
1980: {
1981: if (!recursed)
1982: relative = pr->StartSector;
1983: else
1984: pr->StartSector += relative;
1985:
1986:
1987: memset (ndb, 0, 512);
1988: DiskRead (dcb, myiop, pr->StartSector, 1, ndb, IOR_READ);
1989: UsePartitionInfo (dcb, myiop, ndb, relative, pr->StartSector, partnum, mf, bVerifyOnly); /* recursed, and also
1990: offset */
1991: }
1992: else
1993: {
1994: if (recursed)
1995: pr->StartSector += recursed;
1996:
1997: if (--(*partnum) == 0)
1998: {
1999: if (bVerifyOnly == TRUE)
2000: flag = 1;
2001: else
2002: flag = tryvol (dcb, myiop, pr, mf, &cv); /* partition 1 */
2003: goto error;
2004: }
2005: }
2006:
2007: pr++;
2008:
2009: if (pr->boot == 0x80)
2010: dcb_boot = dcb;
2011:
2012: if ((pr->system == 5) || (pr->system == 0xF))
2013: {
2014: if (!recursed)
2015: relative = pr->StartSector;
2016: else
2017: pr->StartSector += relative;
2018:
2019: memset (ndb, 0, 512);
2020: DiskRead (dcb, myiop, pr->StartSector, 1, ndb, IOR_READ);
2021: UsePartitionInfo (dcb, myiop, ndb, relative, pr->StartSector, partnum, mf, bVerifyOnly); /* recursed, and also
2022: offset */
2023: }
2024: else if (!recursed)
2025: {
2026: if (--(*partnum) == 0)
2027: {
2028: if (bVerifyOnly == TRUE)
2029: flag = 1;
2030: else
2031: flag = tryvol (dcb, myiop, pr, mf, &cv); /* partition 2 */
2032: goto error;
2033: }
2034: }
2035:
2036: if (recursed)
2037: goto error;
2038:
2039: pr++;
2040:
2041: if (pr->boot == 0x80)
2042: dcb_boot = dcb;
2043:
2044: if ((pr->system == 5) || (pr->system == 0xF))
2045: {
2046: if (!recursed)
2047: relative = pr->StartSector;
2048: else
2049: pr->StartSector += relative;
2050:
2051: memset (ndb, 0, 512);
2052: DiskRead (dcb, myiop, pr->StartSector, 1, ndb, IOR_READ);
2053: UsePartitionInfo (dcb, myiop, ndb, relative, pr->StartSector, partnum, mf, bVerifyOnly); /* recursed, and also
2054: offset */
2055: }
2056: else if (!recursed)
2057: {
2058: if (--(*partnum) == 0)
2059: {
2060: if (bVerifyOnly == TRUE)
2061: flag = 1;
2062: else
2063: flag = tryvol (dcb, myiop, pr, mf, &cv); /* partition 3 */
2064: goto error;
2065: }
2066: }
2067:
2068: pr++;
2069:
2070: if (pr->boot == 0x80)
2071: dcb_boot = dcb;
2072:
2073: if ((pr->system == 5) || (pr->system == 0xF))
2074: {
2075: if (!recursed)
2076: relative = pr->StartSector;
2077: else
2078: pr->StartSector += relative;
2079:
2080: memset (ndb, 0, 512);
2081: DiskRead (dcb, myiop, pr->StartSector, 1, ndb, IOR_READ);
2082: UsePartitionInfo (dcb, myiop, ndb, relative, pr->StartSector, partnum, mf, bVerifyOnly); /* recursed, and also
2083: offset */
2084: }
2085: else if (!recursed)
2086: {
2087: if (--(*partnum) == 0)
2088: {
2089: if (bVerifyOnly == TRUE)
2090: flag = 1;
2091: else
2092: flag = tryvol (dcb, myiop, pr, mf, &cv); /* partition 4 */
2093: goto error;
2094: }
2095: }
2096:
2097: error:
2098:
2099: #if EXTRA_INFO
2100: _Debug_Printf_Service ("UsePartitionInfo end\n");
2101: #endif
2102:
2103: if (bVerifyOnly == TRUE)
2104: {
2105: if (flag == 1)
2106: {
2107: /* Return partition info in the 'diskbuffer' buffer */
2108:
2109: char *peek = (char *) &pr->system;
2110: unsigned long *tmp = (void *) partitiontestbuffer;
2111: unsigned long secstart, seclast;
2112:
2113: mf->nReturnCode = 0;
2114:
2115: peek -= 4;
2116: peek += 8; /* point at starting sector... */
2117: secstart = *(unsigned long *) peek;
2118: peek += 4;
2119:
2120: seclast = (secstart + *(unsigned long *) peek);
2121:
2122: if (pr->boot == 0x80)
2123: {
2124: /* For safety reasons we return 0 length for
2125: the boot device */
2126: seclast = secstart;
2127: }
2128:
2129: tmp[0] = secstart;
2130: tmp[1] = seclast;
2131: tmp[2] = (unsigned long) dcb; /* device */
2132:
2133: }
2134: }
2135: else if (cv != NULL)
2136: {
2137: /* cv is only set by tryvol, flag is set only when cv is set */
2138: switch (flag)
2139: {
2140: case 0:
2141: mf->nReturnCode = ERR_VOL_MOUNT_FAILED;
2142: break;
2143: case 1:
2144: mf->nReturnCode = 0;
2145: mf->nDosDriveNo = cv->drive;
2146: strcpy (cv->mounted_file_name, (char *) mf->wszVolume);
2147: break;
2148: case -1:
2149: mf->nReturnCode = ERR_NO_FREE_DRIVES;
2150: break;
2151: }
2152: }
2153: }
2154:
2155: int
2156: tryvol (PDCB dcb, PIOP myiop, partitionrec * pr, MOUNT_STRUCT * mf, cryptvol ** pcv)
2157: {
2158: cryptvol *cv;
2159: char *readBuffer;
2160: int mounted = 0;
2161:
2162: readBuffer = TCalloc (FIRST_READ_SIZE);
2163: if (readBuffer == NULL)
2164: goto error;
2165:
2166: if (cv = checkpartition (myiop, pr))
2167: {
2168: if (cv->booted == 0)
2169: {
2170: int status;
2171:
2172: dophysblock (myiop, cv->cryptsectorfirst, FIRST_READ_SIZE / 512, readBuffer, cv, IOR_READ);
2173:
2174: status = VolumeReadHeaderCache (mf->bCache, readBuffer, mf->szPassword,
2175: mf->nPasswordLen, &cv->cryptoInfo);
2176:
2177: if (status != 0)
2178: {
2179: memset (cv, 0, sizeof (cryptvol));
2180: cv->cryptsectorfirst = 0x7fffffff;
2181: mounted = 0;
2182: goto error;
2183: }
2184: else
2185: cv->booted = 1;
2186:
2187: if (Add_Drive (dcb, cv, mf->nDosDriveNo) == 0)
2188: {
2189: cv->filehostdcb = dcb;
2190: lockdrive (cv->filehostdcb, myiop, 1);
2191: mounted = 1;
2192: }
2193: else
2194: {
2195: /* No Drive letter available */
2196: memset (cv, 0, sizeof (cryptvol));
2197: cv->cryptsectorfirst = 0x7fffffff;
2198: mounted = -1;
2199: }
2200: }
2201: }
2202: else
2203: {
2204: /* If the checkpartition fails it could be because the
2205: partitions is already mounted or because there are no free
2206: slots */
2207: mounted = 0;
2208: }
2209:
2210: error:
2211: if (readBuffer != NULL)
2212: TCfree (readBuffer);
2213:
2214: *pcv = cv;
2215:
2216: return mounted;
2217:
2218: }
2219:
2220: struct cryptvol *
2221: checkpartition (PIOP iop, partitionrec * pr)
2222: {
2223:
2224: cryptvol *flag = 0;
2225: cryptvol *cv;
2226: PDCB dcb = (PDCB) iop->IOP_physical_dcb;
2227:
2228: char *peek = (char *) &pr->system;
2229:
2230: pr->system = 0x74;
2231:
2232: if (pr->system == 0x74)
2233: {
2234: if (cv = addcryptedpartition (iop, peek))
2235: {
2236: flag = cv;
2237: }
2238: }
2239:
2240: return flag;
2241:
2242: }
2243:
2244: int
2245: cmppart (PDCB dcb, unsigned int secstart, cryptvol * cv)
2246: {
2247: if (cv->physdevDCB != dcb)
2248: return 0;
2249: if (cv->cryptsectorfirst != secstart)
2250: return 0;
2251: return 1;
2252: }
2253:
2254: struct cryptvol *
2255: addcryptedpartition (PIOP iop, char *peek)
2256: {
2257:
2258: unsigned int secstart;
2259: unsigned int seclast;
2260: PDCB device;
2261: int d;
2262: peek -= 4;
2263: peek += 8; /* point at starting sector... */
2264: secstart = *(unsigned long *) peek;
2265: peek += 4;
2266:
2267: seclast = (secstart + *(unsigned long *) peek);
2268: device = (PDCB) iop->IOP_physical_dcb;
2269:
2270: /* have we got it already ? */
2271: if (cmppart (device, secstart, (cryptvol *) & cv1))
2272: return NULL;
2273: if (cmppart (device, secstart, (cryptvol *) & cv2))
2274: return NULL;
2275: if (cmppart (device, secstart, (cryptvol *) & cv3))
2276: return NULL;
2277: if (cmppart (device, secstart, (cryptvol *) & cv4))
2278: return NULL;
2279: if (cmppart (device, secstart, (cryptvol *) & cv5))
2280: return NULL;
2281: if (cmppart (device, secstart, (cryptvol *) & cv6))
2282: return NULL;
2283: if (cmppart (device, secstart, (cryptvol *) & cv7))
2284: return NULL;
2285: if (cmppart (device, secstart, (cryptvol *) & cv8))
2286: return NULL;
2287:
2288: d = tryaddpart ((cryptvol *) & cv1, secstart, seclast, device);
2289: if (d == 1)
2290: return &cv1;
2291: if (d == 2)
2292: return 0;
2293:
2294: d = tryaddpart ((cryptvol *) & cv2, secstart, seclast, device);
2295: if (d == 1)
2296: return &cv2;
2297: if (d == 2)
2298: return 0;
2299:
2300: d = tryaddpart ((cryptvol *) & cv3, secstart, seclast, device);
2301: if (d == 1)
2302: return &cv3;
2303: if (d == 2)
2304: return 0;
2305:
2306: d = tryaddpart ((cryptvol *) & cv4, secstart, seclast, device);
2307: if (d == 1)
2308: return &cv4;
2309: if (d == 2)
2310: return 0;
2311:
2312: d = tryaddpart ((cryptvol *) & cv5, secstart, seclast, device);
2313: if (d == 1)
2314: return &cv5;
2315: if (d == 2)
2316: return 0;
2317:
2318: d = tryaddpart ((cryptvol *) & cv6, secstart, seclast, device);
2319: if (d == 1)
2320: return &cv6;
2321: if (d == 2)
2322: return 0;
2323:
2324: d = tryaddpart ((cryptvol *) & cv7, secstart, seclast, device);
2325: if (d == 1)
2326: return &cv7;
2327: if (d == 2)
2328: return 0;
2329:
2330: d = tryaddpart ((cryptvol *) & cv8, secstart, seclast, device);
2331: if (d == 1)
2332: return &cv8;
2333: if (d == 2)
2334: return 0;
2335:
2336: return NULL;
2337: }
2338:
2339: int
2340: tryaddpart (cryptvol * cv, unsigned int secstart, unsigned int seclast, PDCB device)
2341: {
2342: /* THIS if CAN NEVER BE TRUE because cmppart does this job before
2343: this func is called */
2344: if ((cv->physdevDCB == device) && (cv->cryptsectorfirst == secstart))
2345: return (2);
2346:
2347: if (cv->physdevDCB == 0)
2348: {
2349: cv->physdevDCB = device;
2350: cv->cryptsectorfirst = secstart;
2351: cv->cryptsectorlast = seclast;
2352:
2353: return (1);
2354: }
2355:
2356: return (0);
2357: }
2358:
2359: int
2360: unlockdrive (cryptvol * cv)
2361: {
2362: PDCB dcb = cv->filehostdcb; /* physdevDCB; */
2363: PIOP myiop;
2364: PIOR myior;
2365: USHORT offset;
2366: USHORT size;
2367:
2368: if (!dcb)
2369: return -1;
2370:
2371: offset = (USHORT) (dcb->DCB_cmn.DCB_expansion_length + FIELDOFFSET (IOP, IOP_ior));
2372: size = offset + sizeof (IOR) + dcb->DCB_max_sg_elements * sizeof (SGD);
2373: myiop = IspCreateIop (size, offset, ISP_M_FL_MUST_SUCCEED | ISP_M_FL_SMART_ALLOC | ISP_M_FL_INTERRUPT_TIME | ISP_M_FL_PERSISTENT_IOP);
2374: myior = &myiop->IOP_ior;
2375: myior->IOR_private_client = offset;
2376: lockdrive (dcb, myiop, 0); /* unlock it! */
2377: IspDeallocMem ((PVOID) ((DWORD) myior - myior->IOR_private_client));
2378: return 1;
2379: }
2380:
2381: int
2382: lockdrive (PDCB mydcb, PIOP myiop, int lockmode)
2383: {
2384: PIOR myior;
2385: int rstatus;
2386: int iorop;
2387:
2388: if (!mydcb)
2389: return -1;
2390:
2391: if (lockmode)
2392: iorop = IOR_LOCK_MEDIA;
2393: else
2394: iorop = IOR_UNLOCK_MEDIA;
2395:
2396: if ((mydcb->DCB_cmn.DCB_device_flags & DCB_DEV_REMOVABLE) == 0)
2397: return -1;
2398:
2399: myior = &myiop->IOP_ior;
2400: myiop->IOP_original_dcb = (ULONG) mydcb;
2401: myiop->IOP_physical_dcb = (ULONG) mydcb->DCB_cmn.DCB_physical_dcb;
2402: myior->IOR_next = 0;
2403: myior->IOR_start_addr[1] = 0;
2404: myior->IOR_flags = IORF_VERSION_002;
2405: myior->IOR_req_vol_handle = 0;
2406: myior->IOR_vol_designtr = 0xff;
2407: myior->IOR_func = iorop;
2408: myior->IOR_flags |= IORF_BYPASS_VOLTRK | IORF_HIGH_PRIORITY | IORF_SYNC_COMMAND;
2409: myior->IOR_start_addr[0] = 0;
2410: myior->IOR_xfer_count = 0;
2411: myior->IOR_buffer_ptr = 0;
2412:
2413: myiop->IOP_timer = 40;
2414: myiop->IOP_timer_orig = 40;
2415:
2416: IlbInternalRequest (myiop, mydcb, 0);
2417: rstatus = myior->IOR_status;
2418: return rstatus;
2419: }
2420:
2421:
2422: /* the ring 0 code to allow win32 gui to access disk sectors */
2423:
2424: int
2425: AppAccessBlockDevice (unsigned int devicenum, unsigned int sectorstart, unsigned int sectorlen, char *buffer, int mode)
2426: {
2427: PDCB dcb;
2428: USHORT offset;
2429: USHORT size;
2430: PIOP myiop;
2431: PIOR myior;
2432: int status;
2433: USHORT diskop;
2434:
2435: if (mode == 0)
2436: diskop = IOR_READ;
2437: else
2438: diskop = IOR_WRITE;
2439:
2440: if (devicenum < 128)
2441: dcb = dcblist[devicenum + 1];
2442: else
2443: dcb = (PDCB) devicenum;
2444:
2445: if (diskop == IOR_WRITE && dcb == dcb_boot)
2446: {
2447: if (sectorstart == 0)
2448: {
2449: return ERR_ACCESS_DENIED;
2450: }
2451: }
2452:
2453: offset = (USHORT) (dcb->DCB_cmn.DCB_expansion_length + FIELDOFFSET (IOP, IOP_ior));
2454: size = offset + sizeof (IOR) + dcb->DCB_max_sg_elements * sizeof (SGD);
2455: myiop = IspCreateIop (size, offset, ISP_M_FL_MUST_SUCCEED | ISP_M_FL_SMART_ALLOC | ISP_M_FL_INTERRUPT_TIME | ISP_M_FL_PERSISTENT_IOP);
2456: myior = &myiop->IOP_ior;
2457: myior->IOR_private_client = offset;
2458:
2459: if (diskop == IOR_WRITE)
2460: memcpy (appaccessbuffer, buffer, sectorlen * 512);
2461:
2462: status = DiskRead (dcb, myiop, sectorstart, sectorlen, appaccessbuffer, diskop); /* mode later...... */
2463:
2464: if (diskop == IOR_READ)
2465: memcpy (buffer, appaccessbuffer, sectorlen * 512);
2466:
2467: IspDeallocMem ((PVOID) ((DWORD) myior - myior->IOR_private_client));
2468:
2469: if (status != 0)
2470: {
2471: if (mode == 0)
2472: status = ERR_VOL_READING;
2473: else
2474: status = ERR_VOL_WRITING;
2475: }
2476:
2477: return status;
2478: }
2479:
2480: /* This code informs Windows of a drives arrival, this code
2481: crashes windows 95 for some cd's; so it's currently never called */
2482:
2483: void
2484: drivearrived (void)
2485: {
2486: cryptvol *cv;
2487: int c;
2488:
2489: for (c = 0; c < 8; c++)
2490: {
2491: cv = cryptvols[c];
2492:
2493: if (cv->notifytime & 0x80000000)
2494: {
2495: cv->notifytime = 0;
2496:
2497: IFSMgr_PNPEvent (DBT_DEVICEARRIVAL, cv->drive, PNPT_VOLUME | DBTF_MEDIA );
2498: }
2499: }
2500: }
2501:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.