/* Handler fuer UMS */

//+ includes, defines, structs
#include    <exec/types.h>
#include    <exec/nodes.h>
#include    <exec/ports.h>
#include    <exec/memory.h>
#include    <dos/dos.h>
#include    <dos/dosextens.h>
#include    <dos/filehandler.h>
#include    <intuition/intuition.h>

#include    <clib/dos_protos.h>
#include    <clib/exec_protos.h>
#include    <clib/intuition_protos.h>
#include    <clib/alib_protos.h>
#include    <clib/ums_protos.h>

#include    <stdio.h>
#include    <stdarg.h>
#include    <stdlib.h>
#include    <string.h>

#include    "libraries/UMS.h"
#include    "DLIB:UMSMatchConfigTags.c"
#include    "DLIB:UMSReadMsgTags.c"
#include    "DLIB:UMSWriteMsgTags.c"
#include    "DLIB:UMSReadConfigTags.c"
#include    "DLIB:UMSWriteConfigTags.c"
#include    "DLIB:UMSSearchTags.c"
#include    "DLIB:UMSSelectTags.c"

#define     DOS_TRUE    -1
#define     DOS_FALSE   0

#define     CTOB( x)    ( BPTR)(( ULONG)( x) >> 2)
#define     BTOC( x)    ( APTR)(( ULONG)( x) << 2)

struct  UMSFileHandle
{
    struct StoredMSGHeader  *ufh_Data;

    long    ufh_DataSeek;
    long    ufh_DataSize;
    long    ufh_MsgNumber;

    struct UMSLock  *ufh_Lock;

    UMSUserAccount  ufh_Account;
};

struct  UMSLock
{
    struct FileLock     ul_Lock;

    long    ul_MsgNumber;
    long    ul_LockType;

    BSTR    ul_FileName[ 108 ];

    UMSUserAccount  ul_Account;
};

struct  StoredMSGHeader
{
    char    smh_FromUserName[ 36 ];
    char    smh_ToUserName[ 36 ];
    char    smh_Subject[ 72 ];
    char    smh_DateTime[ 20 ];

    long    smh_TimesRead;
    long    smh_DestNode;
    long    smh_OrigNode;
    long    smh_Cost;
    long    smh_OrigNet;
    long    smh_DestNet;
    long    smh_DestZone;
    long    smh_OrigZone;
    long    smh_DestPoint;
    long    smh_OrigPoint;
    long    smh_ReplyTo;
    long    smh_Attribute;
    long    smh_NextReply;

    char    smh_Text[ 0 ];
};

#define     STRING_LENGTH       60
#define     FILE_NAME_LENGTH    216
//-
//+ vars, defs
void CreateFileName( char *, BPTR, BPTR);

LONG ActionLocateObject( BPTR, BPTR, LONG, BPTR *);
void ActionFreeLock( struct UMSLock *);

LONG ActionExamineLock( BPTR, BPTR);

void ReturnPacket( struct DosPacket *);
void Initialize( void);
void UnInitialize( void);

struct DeviceNode   *DeviceNode;
struct MsgPort      *PacketPort;
struct Library      *UMSBase    = NULL;

const char  *Version    = "$VER: UMS-handler 1.01 (30.08.95)";

char    UserName[ STRING_LENGTH ];
//-

//+ void _main()
void _main()
{
    struct DosPacket  *Packet;

    {
        struct Process *ThisProcess = FindTask( NULL);
        PacketPort = &ThisProcess->pr_MsgPort;
    }

    Initialize();

    while( TRUE)
    {
        {
            struct Message *PaketMsg;

            while(( PaketMsg = GetMsg( PacketPort)) == NULL)            /* auf Msg warten */
                Wait( 1 << PacketPort->mp_SigBit);

            Packet = ( struct DosPacket *) PaketMsg->mn_Node.ln_Name;       /* ln_Name = Zeiger auf Paket! */
        }

        if( Packet)
        {
            Packet->dp_Res1 = DOS_TRUE;
            Packet->dp_Res2 = 0;

            switch( Packet->dp_Type)
            {
//+               ACTION_DIE
                case ACTION_DIE :
                {
                    ReturnPacket( Packet);

                    UnInitialize();
                    _exit( 0);
                }
                break;

//-
/*                case ACTION_FINDOUTPUT:
                case ACTION_FINDUPDATE: */
//+               ACTION_FINDINPUT
                case ACTION_FINDINPUT :
                {
                    struct FileHandle       *fh     = BTOC( Packet->dp_Arg1);
                    struct UMSFileHandle    *ufh    = NULL;

                    char    *MsgText;
                    char    *MsgSubject;
                    char    *MsgFromName;
                    char    *MsgToName;

                    if( fh->fh_Arg1 = ufh = AllocVec( sizeof( struct UMSFileHandle), MEMF_ANY|MEMF_CLEAR))
                    {
                        if( !( Packet->dp_Res2 = ActionLocateObject(( BPTR) Packet->dp_Arg2, ( BPTR) Packet->dp_Arg3, ( LONG) Packet->dp_Arg3, ( BPTR *) &ufh->ufh_Lock)))
                        {
                            ufh->ufh_Lock = BTOC( ufh->ufh_Lock);

                            if( ufh->ufh_Lock->ul_LockType == ST_FILE)
                            {
                                fh->fh_Port = ( struct MsgPort *) DOS_FALSE;

                                if(( ufh->ufh_Account = UMSRLogin( "", UserName, "")) > NULL)
                                {
                                    ufh->ufh_MsgNumber = ufh->ufh_Lock->ul_MsgNumber;

                                    if( ReadUMSMsgTags( ufh->ufh_Account,
                                                        UMSTAG_RMsgNum,     ufh->ufh_MsgNumber,
                                                        UMSTAG_RMsgText,    &MsgText,
                                                        UMSTAG_RSubject,    &MsgSubject,
                                                        UMSTAG_RFromName,   &MsgFromName,
                                                        UMSTAG_RToName,     &MsgToName,
                                                        TAG_DONE))
                                    {
                                        ufh->ufh_DataSize = sizeof( struct StoredMSGHeader) + strlen( MsgText) + 1;

                                        if( ufh->ufh_Data = AllocVec( ufh->ufh_DataSize, MEMF_ANY|MEMF_CLEAR))
                                        {
                                            strncpy( ufh->ufh_Data->smh_Subject,        MsgSubject,     71);
                                            strncpy( ufh->ufh_Data->smh_FromUserName,   MsgFromName,    35);
                                            strncpy( ufh->ufh_Data->smh_ToUserName,     MsgToName,      35);

                                            strcpy( ufh->ufh_Data->smh_Text, MsgText);
                                        }
                                        else Packet->dp_Res2 = ERROR_NO_FREE_STORE;
                                    }
                                    else Packet->dp_Res2 = ERROR_READ_PROTECTED;
                                }
                                else Packet->dp_Res2 = ERROR_NO_DISK;
                            }
                            else Packet->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
                        }
                        else Packet->dp_Res2 = ERROR_OBJECT_NOT_FOUND;

                        if( Packet->dp_Res2)
                        {
                            if( ufh->ufh_Lock)
                            {
                                ActionFreeLock( ufh->ufh_Lock);

                                if( ufh->ufh_Account > NULL)
                                {
                                    if( ufh->ufh_Data) FreeVec( ufh->ufh_Data);

                                    FreeUMSMsg( ufh->ufh_Account, ufh->ufh_MsgNumber);
                                    UMSLogout( ufh->ufh_Account);
                                }
                            }

                            FreeVec( ufh);
                            fh->fh_Arg1 = NULL;
                        }
                    }
                    else Packet->dp_Res2 = ERROR_NO_FREE_STORE;
                }
                break;
//-
//+               ACTION_READ
                case ACTION_READ :
                {
                    struct UMSFileHandle    *ufh = ( struct UMSFileHandle *) Packet->dp_Arg1;

                    if( Packet->dp_Arg3 > ufh->ufh_DataSize - ufh->ufh_DataSeek)
                        Packet->dp_Res1 = ufh->ufh_DataSize - ufh->ufh_DataSeek;
                    else
                        Packet->dp_Res1 = Packet->dp_Arg3;

                    memcpy(( void *) Packet->dp_Arg2, ufh->ufh_Data + ufh->ufh_DataSeek, Packet->dp_Res1);

                    ufh->ufh_DataSeek += Packet->dp_Res1;
                }
                break;
//-
/*                case ACTION_WRITE :
                {
                    struct FileHandle   *fh = BTOC( Packet->dp_Arg1);
                }
                break; */

//+               ACTION_SEEK
                case ACTION_SEEK :
                {
                    struct UMSFileHandle    *ufh = ( struct UMSFileHandle *) Packet->dp_Arg1;

                    Packet->dp_Res1 = ufh->ufh_DataSeek;

                    switch( Packet->dp_Arg3)
                    {
                        case OFFSET_BEGINNING :
                        {
                            if( ufh->ufh_DataSize >= Packet->dp_Arg2 >= 0) ufh->ufh_DataSeek = Packet->dp_Arg2;
                            else Packet->dp_Res1 = -1;
                        }
                        break;

                        case OFFSET_CURRENT :
                        {
                            if( ufh->ufh_DataSize >= ufh->ufh_DataSeek + Packet->dp_Arg2 >= 0) ufh->ufh_DataSeek += Packet->dp_Arg2;
                            else Packet->dp_Res1 = -1;
                        }
                        break;

                        case OFFSET_END :
                        {
                            if( ufh->ufh_DataSize >= -( Packet->dp_Arg2) >= 0) ufh->ufh_DataSeek = ufh->ufh_DataSize - Packet->dp_Arg2;
                            else Packet->dp_Res1 = -1;
                        }
                        break;
                    }

                    if( Packet->dp_Res1 == -1) Packet->dp_Res2 = ERROR_SEEK_ERROR;
                }
                break;

//-
//+               ACTION_END
                case ACTION_END :
                {
                    struct UMSFileHandle    *ufh = ( struct UMSFileHandle *) Packet->dp_Arg1;

                    ActionFreeLock( ufh->ufh_Lock);
                    FreeUMSMsg( ufh->ufh_Account, ufh->ufh_MsgNumber);
                    UMSLogout( ufh->ufh_Account);

                    FreeVec( ufh->ufh_Data);
                    FreeVec( ufh);
                }
                break;
//-

//+               ACTION_LOCATE_OBJECT
                case ACTION_LOCATE_OBJECT :
                {
                    Packet->dp_Res2 = ActionLocateObject(( BPTR) Packet->dp_Arg1, ( BPTR) Packet->dp_Arg2, ( LONG) Packet->dp_Arg3, ( BPTR *) &( Packet->dp_Res1));
                }
                break;
//-
//+               ACTION_FREE_LOCK
                case ACTION_FREE_LOCK :
                {
                    ActionFreeLock( BTOC( Packet->dp_Arg1));
                }
                break;
//-

//+               ACTION_EXAMINE_OBJECT
                case ACTION_EXAMINE_OBJECT :
                {
                    Packet->dp_Res2 = ActionExamineLock(( BPTR) Packet->dp_Arg1, ( BPTR) Packet->dp_Arg2);
                }
                break;
//-
//+               ACTION_EXAMINE_FH
                case ACTION_EXAMINE_FH :
                {
                    Packet->dp_Res2 = ActionExamineLock( CTOB((( struct UMSFileHandle *) Packet->dp_Arg1)->ufh_Lock), ( BPTR) Packet->dp_Arg2);
                }
                break;
//-
//+               ACTION_EXAMINE_NEXT
                case ACTION_EXAMINE_NEXT :
                {
                    struct UMSLock          *FileLock;
                    struct FileInfoBlock    *ResultFIB;

                    UMSUserAccount  Account;

                    char    *MsgSubject;
                    long    MsgDate;

                    if( FileLock = BTOC( Packet->dp_Arg1))
                    {
                        if( ResultFIB = BTOC( Packet->dp_Arg2))
                        {
                            if(( Account = UMSRLogin( "", UserName, "")) > NULL)
                            {
                                if( FileLock->ul_LockType == ST_USERDIR)
                                {
                                    UMSSelectTags( Account,
                                                   UMSTAG_SelWriteLocal,    TRUE,
                                                   UMSTAG_SelSet,           0,
                                                   UMSTAG_SelUnset,         ( 1L<<0),
                                                   TAG_DONE);

                                    UMSSelectTags( Account,
                                                   UMSTAG_SelWriteLocal,    TRUE,
                                                   UMSTAG_SelQuick,         TRUE,
                                                   UMSTAG_SelSet,           ( 1L<<0),
                                                   UMSTAG_SelUnset,         0,
                                                   UMSTAG_WGroup,           FilePart(( char *) FileLock->ul_FileName + 1),
                                                   TAG_DONE);

                                    if( FileLock->ul_MsgNumber = UMSSearchTags( Account,
                                                                                UMSTAG_SearchLocal, TRUE,
                                                                                UMSTAG_SearchLast,  FileLock->ul_MsgNumber,
                                                                                UMSTAG_SearchMask,  ( 1L<<0),
                                                                                UMSTAG_SearchMatch, ( 1L<<0),
                                                                                TAG_DONE))
                                    {
                                        if( ReadUMSMsgTags( Account,
                                                            UMSTAG_RMsgNum,     FileLock->ul_MsgNumber,
                                                            UMSTAG_RTextLength, &ResultFIB->fib_Size,
                                                            UMSTAG_RSubject,    &MsgSubject,
                                                            UMSTAG_RMsgDate,    &MsgDate,
                                                            TAG_DONE))
                                        {
                                            ResultFIB->fib_Protection   = 0;
                                            ResultFIB->fib_EntryType    = ResultFIB->fib_DirEntryType = ST_FILE;

                                            ResultFIB->fib_DiskKey      = FileLock->ul_MsgNumber;

                                            sprintf( ResultFIB->fib_FileName + 1, "%lu.msg", FileLock->ul_MsgNumber);
                                            *ResultFIB->fib_FileName = ( int) strlen( ResultFIB->fib_FileName + 1);

                                            ResultFIB->fib_Size         += sizeof( struct StoredMSGHeader) + 1;
                                            ResultFIB->fib_NumBlocks    = ResultFIB->fib_Size / 512;

                                            ResultFIB->fib_Date.ds_Days     = MsgDate / 60 / 60 / 24;
                                            ResultFIB->fib_Date.ds_Minute   = MsgDate / 60 - ResultFIB->fib_Date.ds_Days * 24 * 60;
                                            ResultFIB->fib_Date.ds_Tick     = ( MsgDate - ResultFIB->fib_Date.ds_Days * 24 * 60 * 60 - ResultFIB->fib_Date.ds_Minute * 60) * TICKS_PER_SECOND;

                                            strncpy( ResultFIB->fib_Comment + 1, MsgSubject, 79);
                                            *ResultFIB->fib_Comment = ( int) strlen( ResultFIB->fib_Comment + 1);

                                            FreeUMSMsg( Account, FileLock->ul_MsgNumber);
                                        }
                                        else Packet->dp_Res2 = ERROR_READ_PROTECTED;
                                    }
                                    else Packet->dp_Res2 = ERROR_NO_MORE_ENTRIES;
                                }
                                else Packet->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;

                                UMSLogout( Account);
                            }
                            else Packet->dp_Res2 = ERROR_NO_DISK;
                        }
                        else Packet->dp_Res2 = ERROR_INVALID_LOCK;
                    }
                    else Packet->dp_Res2 = ERROR_INVALID_LOCK;
                }
                break;
//-

//+               ACTION_COPY_DIR
                case ACTION_COPY_DIR :
                {
                    struct UMSLock          *FileLock;
                    struct UMSLock          *ResultLock;

                    if( ResultLock = AllocVec( sizeof( struct UMSLock), MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR))
                    {
                        if( FileLock = BTOC( Packet->dp_Arg1))
                        {
                            memcpy( ResultLock, FileLock, sizeof( struct UMSLock));
                        }
                        else
                        {
                            ResultLock->ul_Lock.fl_Access   = SHARED_LOCK;
                            ResultLock->ul_Lock.fl_Task     = DeviceNode->dn_Task;
                            ResultLock->ul_Lock.fl_Volume   = CTOB( DeviceNode);
                            ResultLock->ul_LockType         = ST_ROOT;

                            char    *TempFileNamePointer = BTOC( DeviceNode->dn_Name);
                            memcpy( ResultLock->ul_FileName, TempFileNamePointer, TempFileNamePointer[ 0 ] + 1);
                        }
                    }
                    else Packet->dp_Res2 = ERROR_NO_FREE_STORE;

                    Packet->dp_Res1 = CTOB( ResultLock);
                }
                break;
//-
//+               ACTION_PARENT
                case ACTION_PARENT :
                {
                    struct UMSLock  *FileLock;
                    struct UMSLock  *ResultLock;

                    char    *TempPointer;

                    if( FileLock = BTOC( Packet->dp_Arg1))
                    {
                        if( FileLock->ul_LockType != ST_ROOT)
                        {
                            if( ResultLock = AllocVec( sizeof( struct UMSLock), MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR))
                            {
                                memcpy( ResultLock, FileLock, sizeof( struct UMSLock));

                                char    *TempFileNamePointer = ResultLock->ul_FileName;

                                TempPointer = PathPart( TempFileNamePointer + 1);
                                TempPointer[ 0 ] = 0;

                                TempFileNamePointer[ 0 ]    = ( int) ( TempPointer - TempFileNamePointer - 1);
                                ResultLock->ul_Lock.fl_Access   = SHARED_LOCK;

                                switch( ResultLock->ul_LockType)
                                {
                                    case ST_USERDIR :
                                    {
                                        ResultLock->ul_LockType = ST_ROOT;
                                    }
                                    break;

                                    case ST_FILE :
                                    {
                                        ResultLock->ul_LockType = ST_USERDIR;
                                    }
                                    break;
                                }

                                Packet->dp_Res1 = CTOB( ResultLock);
                            }
                            else Packet->dp_Res2 = ERROR_NO_FREE_STORE;
                        }
                        else Packet->dp_Res1 = 0;
                    }
                    else Packet->dp_Res1 = 0;
                }
                break;
//-

                default:
                {
                    Packet->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
                }
                break;
            }

            if( Packet->dp_Res2) Packet->dp_Res1 = DOS_FALSE;

            ReturnPacket( Packet);
        }
    }
} //-

//+ void CreateFileName( char *FileName, BPTR BCPLSourceLock, BPTR BCPLSourceString)
void CreateFileName( char *FileName, BPTR BCPLSourceLock, BPTR BCPLSourceString)
{
    struct UMSLock  *SourceLock;
    char    *TempPointer;
    char    *PrePartPointer;

    FileName[ 1 ] = 0;

    if( SourceLock = BTOC( BCPLSourceLock)) strncpy( FileName + 1, ( char *) SourceLock->ul_FileName + 1, FILE_NAME_LENGTH);
    if( BCPLSourceString)                   AddPart( FileName + 1, ( char *) BTOC( BCPLSourceString) + 1, FILE_NAME_LENGTH);

    TempPointer = FileName + 1;
    while( *TempPointer != ':') TempPointer++;
    PrePartPointer = TempPointer;

    while( *TempPointer)
    {
        if(( *TempPointer == '/') || ( *TempPointer == ':'))
        {
            if( *( TempPointer + 1) == '/')
            {
                strcpy( PrePartPointer + 1, TempPointer + 2);

                TempPointer = FileName + 1;
                while( *TempPointer != ':') TempPointer++;
                PrePartPointer = TempPointer;
            }
            else PrePartPointer = TempPointer++;
        }
        else TempPointer++;
    }

    FileName[ 0 ] = ( int) strlen( FileName + 1);

    if( FileName[ FileName[ 0 ]] == '/')
    {
        FileName[ FileName[ 0 ]--] = 0x00;
    }

/*    DisplayAlert( 0, FileName - 2, 30); */
} //-

//+ LONG ActionLocateObject( BPTR FileLock, BPTR ObjectName, LONG AccessMode, BPTR *Res1)
LONG ActionLocateObject( BPTR FileLock, BPTR ObjectName, LONG AccessMode, BPTR *Res1)
{
    struct UMSLock  *ResultLock;

    LONG    DOSError = 0;

    char    FileName[ FILE_NAME_LENGTH ];

    char    *StartPointer;
    char    *EndPointer;

    if( ResultLock = AllocVec( sizeof( struct UMSLock), MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR))
    {
        ResultLock->ul_Lock.fl_Access   = AccessMode;
        ResultLock->ul_Lock.fl_Task     = DeviceNode->dn_Task;
        ResultLock->ul_Lock.fl_Volume   = CTOB( DeviceNode);

        CreateFileName( FileName, FileLock, ObjectName);

        StartPointer = FileName + 1;

        while( *StartPointer && *StartPointer++ != ':');

        if( *StartPointer)                      /* Mehr als nur Volume? */
        {
            memcpy( ResultLock->ul_FileName, FileName, FileName[ 0 ] + 1);

            EndPointer = StartPointer;

            while( *EndPointer && *EndPointer != '/') EndPointer++;

            if( *EndPointer) *EndPointer++ = 0x00;

            if(( ResultLock->ul_Account = UMSRLogin( "", UserName, "")) > NULL)
            {
                UMSSelectTags( ResultLock->ul_Account,
                               UMSTAG_SelWriteLocal,    TRUE,
                               UMSTAG_SelSet,           0,
                               UMSTAG_SelUnset,         ( 1L<<0) | ( 1L<<1),
                               TAG_DONE);

                if( UMSSelectTags( ResultLock->ul_Account,
                                   UMSTAG_SelWriteLocal,    TRUE,
                                   UMSTAG_SelSet,           ( 1L<<0),
                                   UMSTAG_SelUnset,         0,
                                   UMSTAG_SelMask,          UMSUSTATF_ReadAccess |
                                                            UMSUSTATF_ViewAccess,
                                   UMSTAG_SelMatch,         UMSUSTATF_ReadAccess |
                                                            UMSUSTATF_ViewAccess,
                                   UMSTAG_WGroup,           StartPointer,
                                   TAG_DONE))

                {
                    if( *EndPointer)        /* noch mehr als nur Dir? */
                    {
                        ResultLock->ul_MsgNumber = atol( EndPointer);

                        if( UMSSelectTags( ResultLock->ul_Account,
                                           UMSTAG_SelWriteLocal,    TRUE,
                                           UMSTAG_SelSet,           ( 1L<<1),
                                           UMSTAG_SelUnset,         0,
                                           UMSTAG_SelMask,          UMSUSTATF_ReadAccess |
                                                                    UMSUSTATF_ViewAccess,
                                           UMSTAG_SelMatch,         UMSUSTATF_ReadAccess |
                                                                    UMSUSTATF_ViewAccess,
                                           UMSTAG_SelMsg,           ResultLock->ul_MsgNumber,
                                           TAG_DONE))
                        {
                            if( UMSSelectTags( ResultLock->ul_Account,
                                               UMSTAG_SelReadLocal,    TRUE,
                                               UMSTAG_SelSet,           0,
                                               UMSTAG_SelUnset,         0,
                                               UMSTAG_SelMask,          ( 1L<<0) | ( 1L<<1),
                                               UMSTAG_SelMatch,         ( 1L<<0) | ( 1L<<1),
                                               TAG_DONE))
                            {
                                ResultLock->ul_LockType = ST_FILE;
                            }
                            else DOSError = ERROR_OBJECT_NOT_FOUND;
                        }
                        else DOSError = ERROR_OBJECT_NOT_FOUND;
                    }
                    else ResultLock->ul_LockType = ST_USERDIR;
                }
                else DOSError = ERROR_OBJECT_NOT_FOUND;
            }
            else DOSError = ERROR_NO_DISK;
        }
        else
        {
            char    *TempFileNamePointer;

            TempFileNamePointer = BTOC( DeviceNode->dn_Name);

            memcpy( ResultLock->ul_FileName, TempFileNamePointer, TempFileNamePointer[ 0 ] + 1);

            TempFileNamePointer = ResultLock->ul_FileName;
            TempFileNamePointer[ ++TempFileNamePointer[ 0 ]] = ':';

            ResultLock->ul_LockType = ST_ROOT;
        }

        if( DOSError)
        {
            if( ResultLock)
            {
                if( ResultLock->ul_Account > NULL)
                {
                    UMSLogout( ResultLock->ul_Account);
                }

                FreeVec( ResultLock);
                ResultLock = NULL;
            }
        }
    }
    else DOSError = ERROR_NO_FREE_STORE;

    *Res1 = CTOB( ResultLock);

    return( DOSError);
} //-
//+ void ActionFreeLock( struct UMSLock *ResultLock)
void ActionFreeLock( struct UMSLock *ResultLock)
{
    if( ResultLock)
    {
        UMSLogout( ResultLock->ul_Account);
        ResultLock->ul_Lock.fl_Task = NULL;

        FreeVec( ResultLock);
    }
} //-

//+ LONG ActionExamineLock( BPTR BCPLFileLock, BPTR BCPLResultFIB)
LONG ActionExamineLock( BPTR BCPLFileLock, BPTR BCPLResultFIB)
{
    struct UMSLock          *FileLock;
    struct FileInfoBlock    *ResultFIB;

    LONG    DOSError = 0;

    char    *MsgSubject;
    long    MsgDate;

    UMSUserAccount  Account;

    if(( Account = UMSRLogin( "", UserName, "")) > NULL)
    {
        if( ResultFIB = BTOC( BCPLResultFIB))
        {
            if( FileLock = BTOC( BCPLFileLock))
            {
                char    *TempFileNamePointer = ResultFIB->fib_FileName;

                strncpy( TempFileNamePointer + 1, FilePart(( char *) FileLock->ul_FileName + 1), 29);
                *TempFileNamePointer = ( int) strlen( TempFileNamePointer + 1);

                ResultFIB->fib_DirEntryType = FileLock->ul_LockType;
            }
            else
            {
                char    *TempFileNamePointer = BTOC( DeviceNode->dn_Name);
                memcpy( ResultFIB->fib_FileName, TempFileNamePointer, TempFileNamePointer[ 0 ] + 1);

                ResultFIB->fib_DirEntryType = ST_ROOT;
            }

            ResultFIB->fib_DiskKey      = 0;
            ResultFIB->fib_Protection   = 0;
            ResultFIB->fib_Size         = 0;
            ResultFIB->fib_NumBlocks    = 0;
            ResultFIB->fib_Comment[ 0 ] = 0;
            ResultFIB->fib_EntryType    = ResultFIB->fib_DirEntryType;

            if( ResultFIB->fib_DirEntryType == ST_FILE)
            {
                if( ReadUMSMsgTags( Account,
                                    UMSTAG_RMsgNum,     FileLock->ul_MsgNumber,
                                    UMSTAG_RTextLength, &ResultFIB->fib_Size,
                                    UMSTAG_RSubject,    &MsgSubject,
                                    UMSTAG_RMsgDate,    &MsgDate,
                                    TAG_DONE))
                {
                    ResultFIB->fib_DiskKey  = FileLock->ul_MsgNumber;

                    sprintf( ResultFIB->fib_FileName + 1, "%lu.msg", FileLock->ul_MsgNumber);
                    *ResultFIB->fib_FileName = ( int) strlen( ResultFIB->fib_FileName + 1);

                    ResultFIB->fib_Size         += sizeof( struct StoredMSGHeader) + 1;
                    ResultFIB->fib_NumBlocks    = ResultFIB->fib_Size / 512;

                    ResultFIB->fib_Date.ds_Days     = MsgDate / 60 / 60 / 24;
                    ResultFIB->fib_Date.ds_Minute   = MsgDate / 60 - ResultFIB->fib_Date.ds_Days * 24 * 60;
                    ResultFIB->fib_Date.ds_Tick     = ( MsgDate - ResultFIB->fib_Date.ds_Days * 24 * 60 * 60 - ResultFIB->fib_Date.ds_Minute * 60) * TICKS_PER_SECOND;

                    strncpy( ResultFIB->fib_Comment + 1, MsgSubject, 79);
                    *ResultFIB->fib_Comment = ( int) strlen( ResultFIB->fib_Comment + 1);

                    FreeUMSMsg( Account, FileLock->ul_MsgNumber);
                }
                else DOSError = ERROR_READ_PROTECTED;
            }
        }
        else DOSError = ERROR_INVALID_LOCK;

        UMSLogout( Account);
    }
    else DOSError = ERROR_NO_DISK;

    return( DOSError);
} //-

//+ void ReturnPacket( struct DosPacket *Packet)
void ReturnPacket( struct DosPacket *Packet)
{
    struct Message *Msg;
    struct MsgPort *ReplyPort;

    ReplyPort                = Packet->dp_Port;
    Msg                      = Packet->dp_Link;
    Packet->dp_Port          = PacketPort;
    Msg->mn_Node.ln_Name     = ( char *) Packet;
    PutMsg( ReplyPort, Msg);
}//-

//+ void Initialize()
void Initialize()
{
    struct DosPacket   *Packet;

    char    *String;

    {
        struct Message  *InitialMsg;

        WaitPort( PacketPort);
        InitialMsg = GetMsg( PacketPort);
        Packet = ( struct DosPacket *) InitialMsg->mn_Node.ln_Name;
    }

    DeviceNode = BTOC( Packet->dp_Arg3);
    DeviceNode->dn_Task = PacketPort;
/*    DeviceNode->dn_Task = NULL;       */

    Packet->dp_Res2 = 0;

    if( UMSBase = ( struct Library *) OpenLibrary( "ums.library", 11L))
    {
        String = BTOC( Packet->dp_Arg2);

        memcpy( UserName, String + 1, ( int) *String);
        UserName[ ( int) *String ] = 0x00;
    }
    else Packet->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED;

    if( Packet->dp_Res2) Packet->dp_Res1 = DOS_FALSE;
    else                 Packet->dp_Res1 = DOS_TRUE;

    ReturnPacket( Packet);
}
//-
//+ void UnInitialize( void)
void UnInitialize( void)
{
    {
        DeviceNode->dn_Task    = NULL;
        DeviceNode->dn_SegList = NULL;
    }

    if( UMSBase)    CloseLibrary( UMSBase);
}
//-
