#include "resman.h"

void              HandleMsg(struct RMMessage *);
void              GetCRC(void);
int               Decrypt(char *inbuf, char *outbuf);
void              CleanUp(char *);
void TDebug(int, char *);

struct MsgPort   *rmctl;
struct MsgPort   *oldrmctl;
struct List       LangList;
struct List       ResourceList;
struct LangNode  *lbak;

long  rmsigbit;
long  oldrmsigbit;
long  signal;

unsigned long ports  = (ULONG)-1;
unsigned long locks  = (ULONG)-1;
unsigned long CRC    =  0x43524321;

long  __stack        =  8000;
long  __priority     =  3;
long  __BackGroundIO =  0;

char *__procname     = "DLGResMan";

static char version[]="$VER: DLG Resource Manager 2.2 © 1995-1997 by DLG Development ("__AMIGADATE__")";

struct FuncName internalfuncs[] =
{
   "DisplayMenu",
   "Help"
};

struct Library *DLGBase         =   NULL;

/// Main
void main(int argc,char **argv)
{
   struct RMMessage  *mymsg;
   struct OldRMMsg   *myoldmsg;

 Forbid();
 rmctl = FindPort(RMCONTROL);
 Permit();
 if (rmctl)  exit(5);

 if (!(DLGBase = OpenLibrary("dlg.library", 4L)))
       CleanUp("Unable to open DLG.library");

 System("Run DLG:BGChk",NULL);

 // Initialize and open control port, abort if it fails.
 if (!(rmctl = CreateMsgPort()))
   CleanUp("Error");

 rmctl->mp_Node.ln_Name = RMCONTROL;
 AddPort(rmctl);

// V2.1 -- added so that TPTRM calls can be interpreted.
 rmsigbit = 1 << rmctl->mp_SigBit;

 if (!(oldrmctl = CreateMsgPort()))
    CleanUp("Error");

 oldrmctl->mp_Node.ln_Name = "tptrm.control";
 AddPort(oldrmctl);
 oldrmsigbit = 1 << oldrmctl->mp_SigBit;
// End V2.1 Additions


 InitList(&LangList);
 InitList(&ResourceList);


 // Get CRC from handler.  This initiates a string of actions that polls the
 // handler for the serial number, stashes it, and returns.  If the serial number
 // and CRC do not agree, TpTRM terminates.
 Forbid();
 GetCRC();
 Permit();

 // This is the main loop of the program. We call HandleMsg() if we see
 // anything interesting.
 //do{WaitPort(rmctl);
 do{
      signal = Wait(rmsigbit | oldrmsigbit);

      if(signal & rmsigbit)
         while((mymsg = (struct RMMessage *)GetMsg(rmctl)))
         {
            HandleMsg(mymsg);
         }
//    Added 2.1
      if(signal & oldrmsigbit)
         while((myoldmsg = (struct OldRMMsg *)GetMsg(oldrmctl)))
         {
            myoldmsg->type=RMNOERR;
            ReplyMsg((struct Message *)myoldmsg);
         }
// end 2.1 additions
   } while(TRUE);
}
//-

/// HandleMsg
// This is the main part of the program in terms of handling messages to TpTRM.
void HandleMsg(struct RMMessage *message)
{
   switch(message->type)
   {
      // Shut down TpTRM
        case RMEXIT:          message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              CleanUp(NULL);
                              break;

        // Activate a port
        case ACTIVATEPORT:   {struct PortNode *port;
                              struct RootNode *rn;
                              struct DosInfo  *dosi;
                              struct DevInfo  *devi;
                              char            *dname;

                              // If the port is already active we return
                              // immediately.

                              if (IFindName(&ResourceList, message->port))
                                 {message->type = PORTACTIVE;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              Forbid();
                              rn   = (struct RootNode *)DOSBase->dl_Root;
                              dosi = (struct DosInfo *) BADDR(rn->rn_Info);
                              devi = (struct DevInfo *) BADDR(dosi->di_DevInfo);

                              while(devi)
                                   {if (devi->dvi_Type==DLT_DEVICE)
                                       {dname = (char *)BADDR(devi->dvi_Name);
                                        dname++;
                                        if (!Stricmp(dname, message->port))  break;
                                       }

                                    devi = (struct DevInfo *)BADDR(devi->dvi_Next);
                                   }

                              Permit();

                              if (!devi  ||  !ports)
                                 {message->type = GENERALERR;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              // Otherwise, let's set up the port.

                              port = malloc(sizeof(struct PortNode) + 5 + strlen(message->breakcommand));
                              port->mn.users        = 0;
                              port->mn.type         = 0;
                              port->mn.node.ln_Type = NODE_PORT;

                              port->mn.node.ln_Name = ((char *)port + sizeof(struct PortNode));
                              port->bgcommand = stpcpy(port->mn.node.ln_Name, message->port);
                                                strcpy(++port->bgcommand,     message->breakcommand);

                              InitList(&(port->mn.locklist));
                              InitList(&(port->mn.activelocks));

                              port->custnum = -1;
                              port->custnov = NULL;
                              port->custint = NULL;
                              AddTail(&ResourceList,(struct Node *)port);

                              port->ln   = NULL;
                              port->menu = NULL;

                              // If a background task is specified for this port, launch it.
                              if (*(port->bgcommand))  CronEvent(ADDEVENT, 0, port->bgcommand);

                              ports--;
                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        // Deactivate a port
        case DEACTIVATEPORT: {struct PortNode  *port;
                              struct PortLock  *pl;
                              struct RMMessage *tempmess;
                              port = (struct PortNode *)IFindName(&ResourceList,message->port);
                              // If port doesn't exist, we can't deactivate it.

                              if (!port)
                                 {message->type = BADPORT;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (!(pl=(struct PortLock *)RMFreeResource((struct MiscNode *)port,message)))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              free(pl->breakcommand);
                              free(pl);

                              // Fail on pending locks
                              while(pl=(struct PortLock *)RemHead(&(port->mn.locklist)))
                                   {tempmess = pl->ml.rm;

                                    free(pl->ml.node.ln_Name);
                                    free(pl->ml.reason);
                                    free(pl->breakcommand);
                                    free(pl);

                                    tempmess->type = BADPORT;
                                    ReplyMsg((struct Message *)tempmess);
                                   }

                              Remove((struct Node *)port);
                              if (port->ln) FreeLang(port->ln);
                              free(port);

                              ports++;
                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        // Lock a port
        case LOCKPORT:       {struct PortNode *port;
                              struct PortLock *pl;
                              struct PortLock *tpl;

                              port = (struct PortNode *)IFindName(&ResourceList,message->port);
                              if (!port)
                                 {message->type = BADPORT;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (Empty(&(port->mn.activelocks)))
                                 {if (!locks)
                                     {message->type = NOTLOCKED;
                                      ReplyMsg((struct Message *)message);
                                      break;
                                     }

                                  locks--;
                                 }

                              if (!(message->flags & PENDLOCK) && !CheckResource((struct MiscNode *)port,message))
                                 {tpl = (struct PortLock *)FirstNode(&(port->mn.activelocks));

                                  if (tpl && ((tpl->ml.node.ln_Pri>=0) || (message->priority<0)))
                                     {message->type = NOTLOCKED;
                                      ReplyMsg((struct Message *)message);
                                      break;
                                     }
                                 }

                              pl = malloc(sizeof(struct PortLock));
                              if (!pl)
                                 {message->type = RMNOMEM;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              pl->breakcommand = malloc(strlen(message->breakcommand)+1);
                              strcpy(pl->breakcommand, message->breakcommand);

                              if (RMLockResource((struct MiscNode *)port,(struct MiscLock *)pl,message))
                                 {message->type = RMNOERR;
                                  ReplyMsg((struct Message *)message);
                                 }
                               else
                                 {tpl = (struct PortLock *)FirstNode(&(port->mn.activelocks));

                                  if ((tpl->ml.node.ln_Pri<0)&&(pl->ml.node.ln_Pri>=0))
                                     {tpl->ml.node.ln_Pri = 0;
                                      if (*(tpl->breakcommand))
                                            CronEvent(ADDEVENT, 0, tpl->breakcommand);
                                     }
                                 }

                              break;
                             }

        // Free a port
        case FREEPORT:       {struct PortNode  *port;
                              struct PortLock  *pl;

                              port = (struct PortNode *)IFindName(&ResourceList,message->port);
                              if (!port)
                                 {message->type = BADPORT;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (!(pl = (struct PortLock *)RMFreeResource((struct MiscNode *)port,message)))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              free(pl->breakcommand);
                              free(pl);

                              if (Empty(&(port->mn.activelocks)))
                                 {if (*(port->bgcommand))  CronEvent(ADDEVENT, 0, port->bgcommand);
                                  locks++;
                                 }

                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        // Get info on a port.
        case GETPORTINFO:    {struct PortNode *port;
                              struct PortLock *pl;
                              struct PortInfo *pinfo;

                              port = (struct PortNode *)IFindName(&ResourceList,message->port);
                              if (!port)
                                 {message->type = BADPORT;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (Empty(&(port->mn.activelocks)))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              pinfo = (struct PortInfo *)message->dataptr;
                              pl    = (struct PortLock *)port->mn.activelocks.lh_Head;

                              pinfo->passwd       = malloc(strlen(pl->ml.node.ln_Name) + strlen(pl->ml.reason) + strlen(pl->breakcommand) + 3);
                              pinfo->reason       = stpcpy(pinfo->passwd,         pl->ml.node.ln_Name);
                              pinfo->breakcommand = stpcpy(++pinfo->reason,       pl->ml.reason);
                                                    strcpy(++pinfo->breakcommand, pl->breakcommand);
                              pinfo->priority     = pl->ml.node.ln_Pri;

                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case FREEPORTINFO:    free(((struct PortInfo *)message->dataptr)->passwd);
                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;

        // "TransferPort()"
        case TRANSFER:       {struct PortNode  *port;
                              struct PortLock  *pl;

                              port = (struct PortNode *)IFindName(&ResourceList,message->port);
                              if (!port)
                                 {message->type = BADPORT;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              pl = (struct PortLock *)IFindName(&(port->mn.activelocks),message->passwd);
                              if (!pl)
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              // Free old info
                              free(pl->ml.node.ln_Name);
                              free(pl->ml.reason);
                              free(pl->breakcommand);

                              // Replace with new info
                              pl->ml.node.ln_Pri  = message->priority;
                              pl->ml.node.ln_Name = malloc(strlen(message->newpasswd) + 1);
                              strcpy(pl->ml.node.ln_Name, message->newpasswd);
                              pl->ml.reason       = malloc(strlen(message->reason) + 1);
                              strcpy(pl->ml.reason, message->reason);
                              pl->breakcommand    = malloc(strlen(message->breakcommand)+1);
                              strcpy(pl->breakcommand, message->breakcommand);

                              if (!Empty(&(port->mn.locklist)) && (pl->ml.node.ln_Pri<0))
                                   if (*(pl->breakcommand))  CronEvent(ADDEVENT, 0, pl->breakcommand);

                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case LISTPORTS:      {char            *s;
                              struct Node     *nd;
                              struct PortNode *port;

                              nd = ResourceList.lh_Head;
                              s  = message->port;
                             *s  = 0;

                              while(nd->ln_Succ)
                                   {port = (struct PortNode *)nd;
                                    if ((port->mn.node.ln_Type==NODE_PORT)  &&
                                        (!message->passwd    ||
                                         !(*message->passwd) ||
                                         IFindName(&(port->mn.activelocks), message->passwd)))
                                        {s = stpcpy(s, port->mn.node.ln_Name);
                                        }

                                    nd = nd->ln_Succ;
                                   }

                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        // VERY IMPORTANT
        case LOCKAREA:       {struct AreaNode *area;
                              struct AreaLock *al;

                              // The CRC generated earlier on (on startup) is used
                              // here. The polling process sends a LOCKAREA message
                              // with QUICKLOCK set. To identify itself as the security
                              // checking process, it sends the CRC in the passwd field
                              // and the INVERSE of the CRC in the reason field.
                              // Otherwise, it's treated as a normal LockArea request.
         
                              // Is it from our security checker?
                              if ((message->flags&QUICKLOCK) &&
                                 ((long)message->passwd == ~((long)message->reason)))
                                 {// If it is, compare to the CRC.
                                  if (CRC == (long)message->passwd)
                                     {// If good, return no error.
                                      message->type=RMNOERR;
                                     }
                                   else
                                     {// Otherwise, return BADAREA (error).
                                      // Undoubtedly, the calling process will
                                      // now kill off TpTRM.
                                      message->type=BADAREA;
                                     }

                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              // End security checking.  The rest of this is
                              // straightforward.
                              area = FindTheArea(message, 1);
                              al   = malloc(sizeof(struct AreaLock));
                              if (!al)
                                 {message->type = RMNOMEM;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (RMLockResource((struct MiscNode *)area, (struct MiscLock *)al, message))
                                 {message->type = RMNOERR;
                                  ReplyMsg((struct Message *)message);
                                 }
                              break;
                             }

        case ENTERAREA:      {struct AreaNode *area;

                              area = FindTheArea(message, 1);
                              if (LockInQueue(&(area->mn.activelocks))  ||
                                 (LockInQueue(&(area->mn.locklist))))
                                 {message->type = AREAINUSE;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }
         
                              area->mn.users++;
                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case LEAVEAREA:     {struct AreaNode *area;

                             area = FindTheArea(message, 0);
                             if (!area)
                                 {message->type = BADAREA;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (area->mn.users)
                                 {area->mn.users--;
                                 }
                               else
                                 {message->type = AREAEMPTY;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (!area->mn.users  &&
                                 (Empty(&(area->mn.activelocks)) ||
                                  !(area->mn.type&WRITELOCK)))
                                 {HandlePending((struct MiscNode *)area);
                                  if (Empty(&(area->mn.activelocks)))
                                      RemoveArea(message);
                                 }

                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case FREEAREA:       {struct AreaNode *area;
                              struct AreaLock *al;

                              area = FindTheArea(message, 0);
                              if (!area)
                                 {message->type = BADAREA;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (!(al=(struct MiscLock *)RMFreeResource((struct MiscNode *)area,message)))
                                 {message->type=NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              free(al);
                              if (Empty(&(area->mn.activelocks)) && !area->mn.users)
                                  RemoveArea(message);

                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case GETAREAINFO:    {struct DLGAreaInfo *ainfo;
                              struct AreaNode    *area;
                              struct AreaLock    *al;

                              area = FindTheArea(message, 0);
                              if (!area)
                                 {message->type = BADAREA;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              ainfo = (struct DLGAreaInfo *)message->dataptr;
                              if (Empty(&(area->mn.activelocks)))
                                 {ainfo->passwd = (char *)malloc(22);
                                  ainfo->reason = stpcpy(ainfo->passwd,   "NOT LOCKED");
                                                  strcpy(++ainfo->reason, "NOT LOCKED");
                                  ainfo->priority = 0;
                                  ainfo->users    = area->mn.users;
                                 }
                               else
                                 {al = (struct AreaLock *)area->mn.activelocks.lh_Head;

                                  ainfo->passwd = malloc(strlen(al->node.ln_Name) + strlen(al->reason) + 2);
                                  ainfo->reason = stpcpy(ainfo->passwd,   al->node.ln_Name);
                                                  strcpy(++ainfo->reason, al->reason);
                                  ainfo->priority = al->node.ln_Pri;
                                  ainfo->users    = area->mn.users;
                                 }

                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case FREEAREAINFO:    free(((struct DLGAreaInfo *)message->dataptr)->passwd);
                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;

        case LOADLANG:       {struct PortNode  *port;

                              port = (struct PortNode *)IFindName(&ResourceList,message->port);

                              if (!port)
                                 {message->type = BADPORT;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (!port->ln || Stricmp(port->ln->ls.name, (char *)message->dataptr))
                                 {if (port->ln)
                                     {lbak = port->ln;
                                     }
                                   else
                                     {lbak = NULL;
                                     }

                                  if (port->ln = (struct LangNode *)RMLoadLang((char *)message->dataptr))
                                     {if (lbak)  FreeLang(lbak);
                                      message->type = RMNOERR;
                                     }
                                   else
                                     {if (lbak)  port->ln = lbak;
                                      message->type = NOLANG;
                                     }
                                 }
                               else
                                 {message->type = RMNOERR;
                                 }

                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case GETLANG:        {struct PortNode  *port;

                              port = (struct PortNode *)IFindName(&ResourceList,message->port);
                              if (!port)
                                 {message->type = BADPORT;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (port->ln)
                                 {message->dataptr = &(port->ln->ls);
                                  message->type    =   RMNOERR;
                                 }
                               else
                                 {message->dataptr = NULL;
                                  message->type    = NOLANG;
                                 }

                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case LOCKRESOURCE:   {struct MiscLock *ml;
                              struct MiscNode *mn;

                              if (!(mn=(struct MiscNode *)IFindName(&ResourceList,message->dataptr)))
                                 {mn = (struct MiscNode *)malloc(sizeof(struct MiscNode) + strlen(message->dataptr) + 1);
                                  if (!mn)
                                     {message->type = RMNOMEM;
                                      ReplyMsg((struct Message *)message);
                                      break;
                                     }

                                  mn->users        =  0;
                                  mn->type         =  0;
                                  mn->node.ln_Type =  NODE_MISC;
                                  mn->node.ln_Name = (char *)mn + sizeof(struct MiscNode);
                                  strcpy(mn->node.ln_Name, message->dataptr);

                                  InitList(&(mn->activelocks));
                                  InitList(&(mn->locklist));
                                  AddTail(&ResourceList,(struct Node *)mn);
                                 }

                              if (!(message->flags&PENDLOCK) && !CheckResource(mn,message))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              ml = (struct MiscLock *)malloc(sizeof(struct MiscLock));
                              if (!ml)
                                 {message->type = RMNOMEM;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (RMLockResource(mn, ml, message))
                                 {message->type = RMNOERR;
                                  ReplyMsg((struct Message *)message);
                                 }
                              break;
                             }

        case FREERESOURCE:   {struct MiscLock  *ml;
                              struct MiscNode  *mn;

                              if (!(mn = (struct MiscNode *)IFindName(&ResourceList, message->dataptr)))
                                 {message->type = BADRES;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (!(ml=(struct MiscLock *)RMFreeResource(mn, message)))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }
                              free(ml);

                              if (Empty(&(mn->activelocks)))
                                 {Remove((struct Node *)mn);
                                  free(mn);
                                 }

                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case LOCKMENU:       {struct PortNode  *port;
                              struct MiscLock  *ml;
                              struct MenuNode  *mun;
                              struct MenuStuff *ms;

                              ms = (struct MenuStuff *)message->dataptr;
                              if (*(message->port))
                                 {port = (struct PortNode *)IFindName(&ResourceList, message->port);
                                 }
                               else
                                 {port = NULL;
                                 }

                              if (!ms->name)
                                 {if (!port)
                                     {message->type = BADPORT;
                                      ReplyMsg((struct Message *)message);
                                      break;
                                     }

                                  if (port->menu)
                                     {mun = port->menu;
                                     }
                                   else
                                     {message->type = NOTLOCKED;
                                      ReplyMsg((struct Message *)message);
                                      break;
                                     }
                                 }
                               else
                                 {if (!(mun=(struct MenuNode *)IFindName(&ResourceList,ms->name)))
                                     {if (!(mun=(struct MenuNode *)LoadMenu(ms->name)))
                                         {message->type = NOLOADMENU;
                                          ReplyMsg((struct Message *)message);
                                          break;
                                         }
                                     }
                                 }


                              if (port)
                                 {if (mun!=port->menu  ||  message->area!=port->custnum)
                                      FreeCustomMenu(port);

                                  if (mun!=port->menu || message->area!=port->custnum)
                                      LoadCustomMenu(port,message->area,mun->mn.node.ln_Name);
                                 }
      
                              ms->custnum = port->custnum;
                              ms->custnov = port->custnov;
                              ms->custint = port->custint;

                              if (port)  port->menu = mun;

                              ms->mun = mun;
                              if (!(message->flags&PENDLOCK) && !CheckResource((struct MiscNode *)mun,message))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              ml = malloc(sizeof(struct MiscLock));
                              if (!ml)
                                 {message->type = RMNOMEM;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (RMLockResource((struct MiscNode *)mun,(struct MiscLock *)ml,message))
                                 {message->type = RMNOERR;
                                  ReplyMsg((struct Message *)message);
                                 }
                              break;
                             }

        case FREEMENU:       {struct PortNode  *port;
                              struct MiscLock  *ml;
                              struct MenuNode  *mun;

                              if (!message->dataptr)
                                 {port = (struct PortNode *)IFindName(&ResourceList,message->port);
                                  if (!port)
                                     {message->type = BADPORT;
                                      ReplyMsg((struct Message *)message);
                                      break;
                                     }

                                  if (!port->menu)
                                     {message->type = NOTLOCKED;
                                      ReplyMsg((struct Message *)message);
                                      break;
                                     }

                                  mun = port->menu;
                                 }
                               else
                                 {if (!(mun = (struct MenuNode *)IFindName(&ResourceList,message->dataptr)))
                                     {message->type = BADRES;
                                      ReplyMsg((struct Message *)message);
                                      break;
                                     }
                                 }

                              if (!(ml = (struct MiscLock *)RMFreeResource((struct MiscNode *)mun,message)))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              free(ml);
                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case PURGEMENU:      {struct PortNode  *port;
                              struct MiscLock  *ml;
                              struct MenuNode  *mun;

                              if (*(message->port))
                                 {port = (struct PortNode *)IFindName(&ResourceList,message->port);
                                 }
                               else
                                 {port = NULL;
                                 }

                              if (!message->dataptr)
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (!(mun = (struct MenuNode *)IFindName(&ResourceList,message->dataptr)))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }

                              if (!(ml = (struct MiscLock *)RMFreeResource((struct MiscNode *)mun,message)))
                                 {message->type = NOTLOCKED;
                                  ReplyMsg((struct Message *)message);
                                  break;
                                 }
                              free(ml);

                              RemFromPorts(mun);
                              RMFreeMenu(mun);
                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;
                             }

        case GETRESREPORT:    message->dataptr = RMGetResReport();
                              message->type    = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;

        case FREERESREPORT:   RMFreeResReport(message->dataptr);
                              message->type = RMNOERR;
                              ReplyMsg((struct Message *)message);
                              break;

        default:              message->type = RMBAD;
                              ReplyMsg((struct Message *)message);
                              break;
       }
}
//-

/// GetCRC
// This gets a CRC code generated from the serial number returned by TpT-Handler.
void GetCRC(void)
{
   char     *sn;
 char      buf[32];
 long      i;
 ULONG     serial;

 i      = 0;
 serial = 0;
 buf[0] = 0;
 while(i < 3)
      {Delay(250);

       sn = (char *)SendCtlMsg(99, 0, "TL0");
       if ((long)sn <= 0  &&  (long)sn >= -7)
          {i++;
           continue;
          }

       Decrypt(sn, buf);
       if (!(serial = atoi(buf+10)))
          {ports = 2;
           locks = 1;
          }

       CRC = CalcCRC(buf+8, 6, 0);
       break;
      }


 // Check to see if serial number is pirated.
 if ((!serial && Strnicmp(buf+8, "DEMO", 4))  ||
#include <dlg/dead.h>
    )
    {// If so, return a failure.
     CloseLibrary(DLGBase);
     exit(5);
    }
}
//-

/// Decrypt
int Decrypt(char *inbuf, char *outbuf)
{int    numchars;
 int    i;
 UBYTE  shift;

 Forbid();
 numchars = *inbuf++;
 shift    =  numchars;
 for(i=0; i < numchars; i++)
    {*outbuf++ = *inbuf - shift;
     shift     = *inbuf - CRYPTOFFSET;
     inbuf++;
    }
 Permit();

 return(numchars);
}
//-

/// CleanUp
void CleanUp(char *s)

{//if (rmsigbit) FreeSignal(rmsigbit);
 if (rmctl)    DeleteMsgPort(rmctl);
 //if (oldrmctl) DeleteMsgPort(oldrmctl);
 if (DLGBase)  CloseLibrary(DLGBase);

 exit(s?5:0);
}
//-


