/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by MXM * * Name .....: LockDevice-Handler.c * Created ..: Tuesday 26-Jun-90 14:19 * Revision .: 1 * * Date Author Comment * ========= ======== ==================== * 26-Jun-90 Olsen Created this file! * * $Revision Header ********************************************************/ /* Arp cli arguments. */ char *CLI_Template = "Drive,L=Lock/K,K=Key/K,S=Show/S,Info/S,Q=Quit/S"; char *CLI_Help = "\nUsage: LockDevice [Lock ]\n [Key ] [Show] [Info] [Quit]\n"; /* Argument vector offsets. */ #define ARG_DRIVE 1 #define ARG_LOCK 2 #define ARG_KEY 3 #define ARG_SHOW 4 #define ARG_INFO 5 #define ARG_QUIT 6 /* Global lock segment. */ struct LockSeg *LSeg; /* Prototypes. */ char * FindDevice(char *DevName); struct Patch * FindPatch(char *DeviceName); VOID DiskChange(char *DeviceName); BYTE DeletePatch(char *DeviceName); BYTE DeleteLocks(VOID); BYTE DeleteSegment(VOID); BYTE CreateSegment(VOID); VOID main(int argc,char **argv); /* FindDevice(char *DevName): * * Find the device(s) associated with a device * driver. */ char * FindDevice(char *DevName) { static char Name[257]; static struct DeviceNode *DevInfo = NULL; static BYTE FirstThrough = TRUE; Forbid(); if(!DevInfo) { DevInfo = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct RootNode *)DOSBase -> dl_Root) -> rn_Info)) -> di_DevInfo); if(!FirstThrough) return(NULL); else FirstThrough = FALSE; } while(DevInfo) { if(DevInfo -> dn_Type == DLT_DEVICE && DevInfo -> dn_Task && !DevInfo -> dn_Handler) { struct FileSysStartupMsg *Startup = BADDR(DevInfo -> dn_Startup); if(!Strcmp((char *)((ULONG)BADDR(Startup -> fssm_Device) + 1),DevName)) { char *Pointer; SHORT i; Pointer = (char *)BADDR(DevInfo -> dn_Name); for(i = 0 ; i < Pointer[0] ; i++) Name[i] = Pointer[i + 1]; Name[Pointer[0] ] = ':'; Name[Pointer[0] + 1] = 0; DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next); Permit(); return(Name); } } DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next); } Permit(); return(NULL); } /* FindDriver(char *DevName): * * Find the device driver associated with a filing device. */ char * FindDriver(char *DevName) { static char Name[257]; struct DeviceNode *DevInfo = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(((struct RootNode *)DOSBase -> dl_Root) -> rn_Info)) -> di_DevInfo); Forbid(); while(DevInfo) { char *Pointer; SHORT i; Pointer = (char *)BADDR(DevInfo -> dn_Name); for(i = 0 ; i < Pointer[0] ; i++) Name[i] = Pointer[i + 1]; Name[Pointer[0] ] = ':'; Name[Pointer[0] + 1] = 0; if(DevInfo -> dn_Type == DLT_DEVICE && DevInfo -> dn_Task && !DevInfo -> dn_Handler) { if(!Strcmp(Name,DevName)) { struct FileSysStartupMsg *Startup = BADDR(DevInfo -> dn_Startup); strcpy(Name,(char *)((ULONG)BADDR(Startup -> fssm_Device) + 1)); DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next); Permit(); return(Name); } } DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next); } Permit(); return(NULL); } /* FindPatch(char *DeviceName): * * Find the patch created for a specific filing device. */ struct Patch * FindPatch(char *DeviceName) { struct Patch *Patch = LSeg -> RootPatch; while(Patch) { if(!Strcmp(Patch -> UnitName,DeviceName)) return(Patch); Patch = Patch -> NextPatch; } return(NULL); } /* DiskChange(char *DeviceName): * * Perform a kind of diskchange event for a filing * device. */ VOID DiskChange(char *DeviceName) { struct MsgPort *HandlerTask = DeviceProc(DeviceName); LONG Args[7]; if(HandlerTask) { Args[0] = DOSTRUE; if(SendPacket(ACTION_INHIBIT,Args,HandlerTask)) { Args[0] = DOSFALSE; SendPacket(ACTION_INHIBIT,Args,HandlerTask); } } } /* DeletePatch(char *DeviceName): * * Unlink and remove a patch from the linked system * list. */ BYTE DeletePatch(char *DeviceName) { if(DeviceName) { struct Patch *TempPatch = LSeg -> RootPatch,*OldPatch = NULL; Disable(); if(!Strcmp(TempPatch -> UnitName,DeviceName)) { OldPatch = TempPatch; LSeg -> RootPatch = TempPatch -> NextPatch; } else { while(TempPatch) { if(!Strcmp(TempPatch -> UnitName,DeviceName)) { OldPatch = TempPatch; break; } TempPatch = TempPatch -> NextPatch; } if(!OldPatch) return(FALSE); else { TempPatch = LSeg -> RootPatch; while(TempPatch) { if(TempPatch -> NextPatch == OldPatch) { TempPatch -> NextPatch = OldPatch -> NextPatch; break; } TempPatch = TempPatch -> NextPatch; } } } SetFunction((struct Library *)OldPatch -> Device,DEV_BEGINIO,OldPatch -> OldBeginIO); Enable(); CloseDevice(OldPatch -> Request); FreeMem(OldPatch -> Request,sizeof(struct IOExtTD)); FreeMem(OldPatch,sizeof(struct Patch)); DiskChange(DeviceName); return(TRUE); } return(FALSE); } /* DeleteLocks(): * * Delete all patches which are not protected by a * password. */ BYTE DeleteLocks() { struct Patch *Patch = LSeg -> RootPatch; while(Patch) { if(!Patch -> PassWord[0]) { DeletePatch(Patch -> UnitName); Patch = LSeg -> RootPatch; continue; } Patch = Patch -> NextPatch; } if(LSeg -> RootPatch) return(FALSE); else return(TRUE); } /* DeleteSegment(): * * Deallocate the lock segment. */ BYTE DeleteSegment() { if(LSeg) { if(DeleteLocks()) { LSeg -> HandShake = SIG_SHAKE; Signal(LSeg -> Child,SIG_QUIT); Wait(SIG_SHAKE); if(!LSeg -> Child) { RemPort(&LSeg -> SignalPort); FreeMem(LSeg -> SignalPort . mp_Node . ln_Name,sizeof(PORTNAME)); UnLoadSeg(LSeg -> HandlerSegment); FreeMem(LSeg,sizeof(struct LockSeg)); return(TRUE); } } } return(FALSE); } /* CreateSegment(): * * Create the lock segment. */ BYTE CreateSegment() { if(LSeg = (struct LockSeg *)AllocMem(sizeof(struct LockSeg),MEMF_PUBLIC | MEMF_CLEAR)) { LSeg -> SegSize = sizeof(struct LockSeg); LSeg -> Father = SysBase -> ThisTask; LSeg -> SignalPort . mp_Node . ln_Type = NT_MSGPORT; LSeg -> SignalPort . mp_Node . ln_Pri = 1; LSeg -> SignalPort . mp_Node . ln_Name = (char *)AllocMem(sizeof(PORTNAME),MEMF_PUBLIC); LSeg -> SignalPort . mp_Flags = PA_IGNORE; if(LSeg -> SignalPort . mp_Node . ln_Name) { strcpy(LSeg -> SignalPort . mp_Node . ln_Name,PORTNAME); if(!(LSeg -> HandlerSegment = LoadSeg("LockDevice-Handler"))) LSeg -> HandlerSegment = LoadSeg("L:LockDevice-Handler"); if(LSeg -> HandlerSegment) { LSeg -> HandShake = SIG_SHAKE; AddPort(&LSeg -> SignalPort); if(CreateProc(PORTNAME,5,LSeg -> HandlerSegment,4000)) { Wait(SIG_SHAKE); if(LSeg -> Child) return(TRUE); } RemPort(&LSeg -> SignalPort); UnLoadSeg(LSeg -> HandlerSegment); } FreeMem(LSeg -> SignalPort . mp_Node . ln_Name,sizeof(PORTNAME)); } FreeMem(LSeg,sizeof(struct LockSeg)); } return(FALSE); } /* main(int argc,char **argv): * * The main program. */ VOID main(int argc,char **argv) { LSeg = (struct LockSeg *)FindPort(PORTNAME); if(argc == 1) { Puts(CLI_Help); exit(RETURN_WARN); } /* Remove LockDevice? */ if(argv[ARG_QUIT]) { Printf("\nRemoving \33[33mLockDevice\33[31m, "); if(!DeleteSegment()) { Puts("FAILED!\a\n"); exit(RETURN_FAIL); } else { Puts("\33[3mOkay.\33[0m\n"); exit(RETURN_OK); } } /* Show program info? */ if(argv[ARG_INFO]) { Puts("This program installs patches to prevent write access to"); Puts("data media. Unlike the write protection simulated by the"); Puts("FastFileSystem, 'LockDevice' goes directly to the device"); Puts("driver itself which enables it to reject write/format"); Puts("requests even in situations in which FastFileSystem fails"); Puts("and the disk drive is still formatted."); Puts(" Furthermore, 'LockDevice' will work on any device and"); Puts("with any filing system.\n"); Puts("If you like this program and use it frequently, send a"); Puts("Share-Ware fee of at least 15 US$ or DM 20,- to:\n"); Puts(" Olaf Barthel, MXM"); Puts(" Brabeckstrasse 35"); Puts(" D-3000 Hannover 71\n"); Puts(" Federal Republic of Germany\n"); Puts("If you fail to pay this fee, then your conscience will haunt"); Puts("you for the rest of your life!\n"); exit(RETURN_OK); } /* Install the lock segment. */ if(!LSeg) { Printf("\nInstalling \33[33m\33[1mLockDevice\33[31m\33[0m, "); if(!CreateSegment()) { Puts("FAILED!\n\a"); exit(RETURN_FAIL); } else Printf("\33[3mOkay.\33[0m v1.%ld © Copyright 1990 by \33[4mMXM\33[0m, \33[1mSHARE-WARE\33[0m.\n\n",REVISION); } /* Install/remove a patch. */ if(argv[ARG_DRIVE]) { /* Remove a patch. */ if(!Strcmp(argv[ARG_LOCK],"OFF")) { struct Patch *Patch; if(!(Patch = FindPatch(argv[ARG_DRIVE]))) { Printf("\33[1mLockDevice:\33[0m Unable to find locked device '%s'.\a\n",argv[ARG_DRIVE]); exit(RETURN_FAIL); } /* Protected by a password? */ if(Patch -> PassWord[0]) { /* Password given? */ if(argv[ARG_KEY]) { /* Does it match? */ if(Strcmp(argv[ARG_KEY],(char *)Patch -> PassWord)) { Printf("\33[1mLockDevice:\33[0m Invalid access key for locked device '%s'.\a\n",argv[ARG_DRIVE]); exit(RETURN_FAIL); } else { DeletePatch(argv[ARG_DRIVE]); Printf("\33[1mLockDevice:\33[0m Device '%s' unlocked.\n",argv[ARG_DRIVE]); } } else { Printf("\33[1mLockDevice:\33[0m Device '%s' needs a key to be unlocked.\a\n",argv[ARG_DRIVE]); exit(RETURN_FAIL); } } else { DeletePatch(argv[ARG_DRIVE]); Printf("\33[1mLockDevice:\33[0m Device '%s' unlocked.\n",argv[ARG_DRIVE]); } } else { /* Lock a device. */ if(!Strcmp(argv[ARG_LOCK],"ON")) { struct LockMsg Message; char *LockOut[40],*Pointer,*DevName; SHORT NumLocked = 0; if(!(DevName = FindDriver(argv[ARG_DRIVE]))) { Printf("\33[1mLockDevice:\33[0m Unable to find driver for device '%s'!\a\n",argv[ARG_DRIVE]); exit(RETURN_FAIL); } /* Look how many filing devices this lock will affect. */ while(Pointer = FindDevice(DevName)) { if(!(LockOut[NumLocked] = ArpAlloc(strlen(Pointer) + 1))) { Printf("\33[1mLockDevice:\33[0m Out of memory!\a\n"); exit(RETURN_FAIL); } strcpy(LockOut[NumLocked++],Pointer); if(NumLocked == 40) break; } /* More than one device locked out? */ if(NumLocked > 1) { SHORT i; char Line[MaxInputBuf]; Printf("\33[33mWarning:\33[31m Locking '%s' will also lock the following device(s):\n\n\t\33[1m",argv[ARG_DRIVE]); for(i = 0 ; i < NumLocked ; i++) if(Strcmp(LockOut[i],argv[ARG_DRIVE])) Printf("%s ",LockOut[i]); Printf("\n\n\33[0mDo you wish to continue (\33[33my\33[31m/\33[33mN\33[31m) ? "); ReadLine(Line); if(Line[0] != 'y' && Line[0] != 'Y') exit(RETURN_WARN); } Message . ExecMessage . mn_Node . ln_Type = NT_MESSAGE; Message . ExecMessage . mn_Length = sizeof(struct LockMsg); Message . Success = FALSE; /* Ask the handler to lock the device(s). */ if(Message . ExecMessage . mn_ReplyPort = (struct MsgPort *)CreatePort(NULL,0)) { Message . DeviceName = argv[ARG_DRIVE]; Message . PassWord = argv[ARG_KEY]; PutMsg(&LSeg -> SignalPort,&Message); WaitPort(Message . ExecMessage . mn_ReplyPort); GetMsg(Message . ExecMessage . mn_ReplyPort); DeletePort(Message . ExecMessage . mn_ReplyPort); } if(!Message . Success) { Printf("\33[1mLockDevice:\33[0m Could not create lock for device '%s'.\a\n",argv[ARG_DRIVE]); exit(RETURN_FAIL); } else { Printf("\33[1mLockDevice:\33[0m Device '%s' locked.\n",argv[ARG_DRIVE]); DiskChange(argv[ARG_DRIVE]); } } else { Puts(CLI_Help); exit(RETURN_FAIL); } } } /* Show all locked devices. */ if(argv[ARG_SHOW]) { struct Patch *Patch = LSeg -> RootPatch; if(!Patch) { Puts("\33[1mLockDevice:\33[0m There are no locked devices."); exit(RETURN_WARN); } else { char *TempName; Puts("Name Driver \n-------- --------------------"); while(Patch) { while(TempName = FindDevice(Patch -> DriverName)) { if(!Strcmp(Patch -> UnitName,TempName)) Printf("\33[33m%-8.8s\33[31m %-20.20s\n",TempName,Patch -> DriverName); else Printf("%-8.8s %-20.20s\n",TempName,Patch -> DriverName); } Patch = Patch -> NextPatch; } } } exit(RETURN_OK); }