/* 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    <ctype.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 ];

    WORD    smh_TimesRead;
    WORD    smh_DestNode;
    WORD    smh_OrigNode;
    WORD    smh_Cost;
    WORD    smh_OrigNet;
    WORD    smh_DestNet;
    WORD    smh_DestZone;
    WORD    smh_OrigZone;
    WORD    smh_DestPoint;
    WORD    smh_OrigPoint;
    WORD    smh_ReplyTo;
    WORD    smh_Attribute;
    WORD    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()
{
/*    DisplayAlert( FileLock->ul_MsgNumber, FilePart(( char *) FileLock->ul_FileName + 1) - 3, 30); */

    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;

                    struct DateTime         MsgDateTime;

                    char    *MsgText;
                    char    *MsgSubject;
                    char    *MsgFromName;
                    char    *MsgToName;
                    char    *MsgOrigin;
                    long    *MsgDate;

                    long    MsgCounter;
                    long    StringLength;

                    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_ROrganization,   &MsgOrigin,
                                                        UMSTAG_RSubject,        &MsgSubject,
                                                        UMSTAG_RFromName,       &MsgFromName,
                                                        UMSTAG_RToName,         &MsgToName,
                                                        UMSTAG_RMsgDate,        &MsgDate,
                                                        TAG_DONE))
                                    {
                                        MsgCounter = strlen( MsgText);
                                        ufh->ufh_DataSize = sizeof( struct StoredMSGHeader) + MsgCounter + 4     + 80     + 2;
/*                                                                                            <MsgText>    \n--- <Origin> \n\0*/

                                        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);

                                            MsgDateTime.dat_Stamp.ds_Days      = ( int) MsgDate / 60 / 60 / 24;
                                            MsgDateTime.dat_Stamp.ds_Minute    = ( int) MsgDate / 60 - MsgDateTime.dat_Stamp.ds_Days * 24 * 60;
                                            MsgDateTime.dat_Stamp.ds_Tick      = ( int) ( MsgDate - MsgDateTime.dat_Stamp.ds_Days * 24 * 60 * 60 - MsgDateTime.dat_Stamp.ds_Minute * 60) * TICKS_PER_SECOND;

                                            MsgDateTime.dat_Format = FORMAT_DOS;
                                            MsgDateTime.dat_Flags  = 0;

                                            MsgDateTime.dat_StrDay     = 0;
                                            MsgDateTime.dat_StrDate    = ufh->ufh_Data->smh_DateTime;
                                            MsgDateTime.dat_StrTime    = ufh->ufh_Data->smh_DateTime + 11;

                                            DateToStr( &MsgDateTime);

                                            ufh->ufh_Data->smh_DateTime[ 2 ]  = 0x20;
                                            ufh->ufh_Data->smh_DateTime[ 6 ]  = 0x20;
                                            ufh->ufh_Data->smh_DateTime[ 9 ]  = 0x20;
                                            ufh->ufh_Data->smh_DateTime[ 10 ] = 0x20;

                                            memcpy( ufh->ufh_Data->smh_Text, MsgText, MsgCounter);

                                            memcpy( ufh->ufh_Data->smh_Text + MsgCounter, "\n---\n * Origin: ", 16);
                                            MsgCounter += 16;

                                            if(( StringLength = strlen( MsgOrigin)) > 68) StringLength = 68;
                                            memcpy( ufh->ufh_Data->smh_Text + MsgCounter, MsgOrigin, StringLength);

                                            MsgCounter += StringLength;
                                            memcpy( ufh->ufh_Data->smh_Text + MsgCounter, "\n\0", 4);
                                        }
                                        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;

                    char    *MsgSubject;
                    char    *MsgGroup;
                    char    *MsgText;
                    long    MsgDate;
                    long    Msgs;

                    if( FileLock = BTOC( Packet->dp_Arg1))
                    {
                        if( ResultFIB = BTOC( Packet->dp_Arg2))
                        {
                            ResultFIB->fib_DiskKey          = 0;
                            ResultFIB->fib_Protection       = 0;
                            ResultFIB->fib_FileName[ 0 ]    = 0;
                            ResultFIB->fib_Size             = 0;
                            ResultFIB->fib_NumBlocks        = 0;
                            ResultFIB->fib_Date.ds_Days     = 0;
                            ResultFIB->fib_Date.ds_Minute   = 0;
                            ResultFIB->fib_Date.ds_Tick     = 0;
                            ResultFIB->fib_Comment[ 0 ]     = 0;
                            ResultFIB->fib_Protection       = 0;

                            switch( FileLock->ul_LockType)
                            {
//+                               ST_USERDIR
                                case ST_USERDIR :
                                {
                                    if( FileLock->ul_MsgNumber = UMSSearchTags( FileLock->ul_Account,
                                                                                UMSTAG_SearchLocal, TRUE,
                                                                                UMSTAG_SearchLast,  FileLock->ul_MsgNumber,
                                                                                UMSTAG_SearchMask,  ( 1L<<0),
                                                                                UMSTAG_SearchMatch, ( 1L<<0),
                                                                                TAG_DONE))
                                    {
                                        if( ReadUMSMsgTags( FileLock->ul_Account,
                                                            UMSTAG_RMsgNum,     FileLock->ul_MsgNumber,
                                                            UMSTAG_RMsgText,    &MsgText,
                                                            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) + strlen( MsgText) + 4   + 80     + 2;
                                            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( FileLock->ul_Account, FileLock->ul_MsgNumber);
                                        }
                                        else Packet->dp_Res2 = ERROR_READ_PROTECTED;
                                    }
                                    else Packet->dp_Res2 = ERROR_NO_MORE_ENTRIES;
                                }
                                break;
//-
//+                               ST_ROOT
                                case ST_ROOT :
                                {
                                    if( FileLock->ul_MsgNumber = UMSSearchTags( FileLock->ul_Account,
                                                                                UMSTAG_SearchLocal, TRUE,
                                                                                UMSTAG_SearchLast,  FileLock->ul_MsgNumber,
                                                                                UMSTAG_SearchMask,  ( 1L<<0),
                                                                                UMSTAG_SearchMatch, ( 1L<<0),
                                                                                TAG_DONE))
                                    {
                                        if( ReadUMSMsgTags( FileLock->ul_Account,
                                                            UMSTAG_RMsgNum,     FileLock->ul_MsgNumber,
                                                            UMSTAG_RMsgDate,    &MsgDate,
                                                            UMSTAG_RGroup,      &MsgGroup,
                                                            TAG_DONE))
                                        {
                                            Msgs = UMSSelectTags( FileLock->ul_Account,
                                                                  UMSTAG_SelWriteLocal,   TRUE,
                                                                  UMSTAG_SelQuick,        TRUE,
                                                                  UMSTAG_SelSet,          0,
                                                                  UMSTAG_SelUnset,        ( 1L<<0),
                                                                  UMSTAG_WGroup,          MsgGroup,
                                                                  TAG_DONE);

                                            ResultFIB->fib_Protection   = 0;
                                            ResultFIB->fib_EntryType    = ResultFIB->fib_DirEntryType = ST_USERDIR;

                                            ResultFIB->fib_DiskKey      = 0;

                                            if( *MsgGroup)
                                            {
                                                strncpy( ResultFIB->fib_FileName + 1, MsgGroup, 29);
                                                *ResultFIB->fib_FileName = ( int) strlen( ResultFIB->fib_FileName + 1);
                                            }
                                            else
                                            {
                                                strcpy( ResultFIB->fib_FileName + 1, "Mail");
                                                *ResultFIB->fib_FileName = ( int) 4;
                                            }

                                            ResultFIB->fib_Size         = 0;
                                            ResultFIB->fib_NumBlocks    = 0;

                                            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;

                                            sprintf( ResultFIB->fib_Comment + 1, "Entries: %lu", Msgs);
                                            *ResultFIB->fib_Comment = ( int) strlen( ResultFIB->fib_Comment + 1);

                                            FreeUMSMsg( FileLock->ul_Account, FileLock->ul_MsgNumber);
                                        }
                                        else Packet->dp_Res2 = ERROR_READ_PROTECTED;
                                    }
                                    else Packet->dp_Res2 = ERROR_NO_MORE_ENTRIES;
                                }
                                break;
//-
//+                               default
                                default :
                                {
                                    Packet->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
                                }
                                break;
//-
                            }
                        }
                        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
                        {
                            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;
                            ResultLock->ul_Lock.fl_Access   = SHARED_LOCK;
                            ResultLock->ul_Lock.fl_Task     = DeviceNode->dn_Task;
                            ResultLock->ul_Lock.fl_Volume   = CTOB( DeviceNode);
                        }

                        if( !(( ResultLock->ul_Account = UMSRLogin( "", UserName, "")) > NULL))
                        {
                            FreeVec( ResultLock);
                            Packet->dp_Res2 = ERROR_NO_DISK;
                        }
                        else Packet->dp_Res1 = CTOB( ResultLock);
                    }
                    else Packet->dp_Res2 = ERROR_NO_FREE_STORE;
                }
                break;
//-
//+               ACTION_PARENT
                case ACTION_PARENT :
                {
                    struct UMSLock  *FileLock;
                    struct UMSLock  *ResultLock;

                    if( FileLock = BTOC( Packet->dp_Arg1))
                    {
                        if(( FileLock->ul_LockType == ST_FILE) || ( FileLock->ul_LockType == ST_USERDIR))
                        {
                            if( ResultLock = AllocVec( sizeof( struct UMSLock), MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR))
                            {
                                    memcpy( ResultLock, FileLock, sizeof( struct UMSLock));
                                if(( ResultLock->ul_Account = UMSRLogin( "", UserName, "")) > NULL)
                                {
                                   /*
                                char    *TempFileNamePointer = ResultLock->ul_FileName;

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

                                TempFileNamePointer[ 0 ]    = ( int) ( TempPointer - TempFileNamePointer - 1); */

                                    *ResultLock->ul_FileName = ( int) ( PathPart(( char *) FileLock->ul_FileName + 1) - FileLock->ul_FileName - 1);
                                    memcpy( ResultLock->ul_FileName + 1, FileLock->ul_FileName + 1, ( int) *ResultLock->ul_FileName);

                                    if( FileLock->ul_LockType == ST_USERDIR) ResultLock->ul_LockType = ST_ROOT;
                                    else                                     ResultLock->ul_LockType = ST_USERDIR;

                                    ResultLock->ul_Lock.fl_Access   = SHARED_LOCK;
                                    ResultLock->ul_Lock.fl_Task     = DeviceNode->dn_Task;
                                    ResultLock->ul_Lock.fl_Volume   = CTOB( DeviceNode);

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

//+               default
                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;
    }
} //-

//+ 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))
    {
        if(( ResultLock->ul_Account = UMSRLogin( "", UserName, "")) > NULL)
        {
            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;

                UMSSelectTags( ResultLock->ul_Account,
                               UMSTAG_SelWriteLocal,    TRUE,
                               UMSTAG_SelSet,           0,
                               UMSTAG_SelUnset,         ( 1L<<0) | ( 1L<<1),
                               TAG_DONE);

                if(( tolower( StartPointer[ 0 ]) == 'm') &&
                   ( tolower( StartPointer[ 1 ]) == 'a') &&
                   ( tolower( StartPointer[ 2 ]) == 'i') &&
                   ( tolower( StartPointer[ 3 ]) == 'l')) *StartPointer = 0;

                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
            {
                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;
            }
        }
        else DOSError = ERROR_NO_DISK;

        if( DOSError)
        {
            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 *FileLock)
void ActionFreeLock( struct UMSLock *FileLock)
{
    if( FileLock)
    {
        UMSLogout( FileLock->ul_Account);
        FileLock->ul_Lock.fl_Task = NULL;

        FreeVec( FileLock);
    }
} //-

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

    LONG    DOSError = 0;

    char    *StringPointer;
    char    *MsgSubject;
    char    *MsgText;
    long    MsgDate;
    long    Msgs;
    long    MsgNum;

    if( ResultFIB = BTOC( BCPLResultFIB))
    {
        ResultFIB->fib_DiskKey          = 0;
        ResultFIB->fib_FileName[ 0 ]    = 0;
        ResultFIB->fib_Size             = 0;
        ResultFIB->fib_NumBlocks        = 0;
        ResultFIB->fib_Date.ds_Days     = 0;
        ResultFIB->fib_Date.ds_Minute   = 0;
        ResultFIB->fib_Date.ds_Tick     = 0;
        ResultFIB->fib_Comment[ 0 ]     = 0;
        ResultFIB->fib_Protection       = 0;

        if( FileLock = BTOC( BCPLFileLock)) ResultFIB->fib_DirEntryType = FileLock->ul_LockType;
        else                                ResultFIB->fib_DirEntryType = ST_ROOT;

        ResultFIB->fib_EntryType = ResultFIB->fib_DirEntryType;

        switch( ResultFIB->fib_DirEntryType)
        {
//+           ST_FILE
            case ST_FILE :
            {
                if( ReadUMSMsgTags( FileLock->ul_Account,
                                    UMSTAG_RMsgNum,     FileLock->ul_MsgNumber,
                                    UMSTAG_RMsgText,    &MsgText,
                                    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) + strlen( MsgText) + 4   + 80     + 2;
                    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( FileLock->ul_Account, FileLock->ul_MsgNumber);
                }
                else DOSError = ERROR_READ_PROTECTED;
            }
            break;
//-
//+           ST_USERDIR
            case ST_USERDIR :
            {
                StringPointer = FilePart(( char *) FileLock->ul_FileName + 1);

                strncpy( ResultFIB->fib_FileName + 1, StringPointer, 29);
                *ResultFIB->fib_FileName = ( int) strlen( ResultFIB->fib_FileName + 1);

                FileLock->ul_MsgNumber = 0;

                UMSSelectTags( FileLock->ul_Account,
                               UMSTAG_SelWriteLocal,    TRUE,
                               UMSTAG_SelSet,           0,
                               UMSTAG_SelUnset,         ( 1L<<0),
                               TAG_DONE);

                if(( tolower( StringPointer[ 0 ]) == 'm') &&
                   ( tolower( StringPointer[ 1 ]) == 'a') &&
                   ( tolower( StringPointer[ 2 ]) == 'i') &&
                   ( tolower( StringPointer[ 3 ]) == 'l'))
                {
                    *ResultFIB->fib_FileName = ( char) 0;
                }

                Msgs = UMSSelectTags( FileLock->ul_Account,
                                      UMSTAG_SelWriteLocal,    TRUE,
                                      UMSTAG_SelQuick,         TRUE,
                                      UMSTAG_SelSet,           ( 1L<<0),
                                      UMSTAG_SelUnset,         0,
                                      UMSTAG_WGroup,           ResultFIB->fib_FileName + 1,
                                      TAG_DONE);

                if( !(( int) *ResultFIB->fib_FileName))
                {
                    strcpy( ResultFIB->fib_FileName + 1, "Mail");
                    *ResultFIB->fib_FileName = ( int) 4;
                }

                if( MsgNum = UMSSearchTags( FileLock->ul_Account,
                                            UMSTAG_SearchLocal,  TRUE,
                                            UMSTAG_SearchLast,   0,
                                            UMSTAG_SearchMask,   ( 1L<<0),
                                            UMSTAG_SearchMatch,  ( 1L<<0),
                                            TAG_DONE))
                {
                    if( ReadUMSMsgTags( FileLock->ul_Account,
                                        UMSTAG_RMsgNum,     MsgNum,
                                        UMSTAG_RMsgDate,    &MsgDate,
                                        TAG_DONE))
                    {
                        ResultFIB->fib_Protection   = 0;
                        ResultFIB->fib_DiskKey      = 0;

                        ResultFIB->fib_Size         = 0;
                        ResultFIB->fib_NumBlocks    = 0;

                        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;

                        sprintf( ResultFIB->fib_Comment + 1, "Entries: %lu", Msgs);
                        *ResultFIB->fib_Comment = ( int) strlen( ResultFIB->fib_Comment + 1);

                        FreeUMSMsg( FileLock->ul_Account, FileLock->ul_MsgNumber);
                    }
                    else DOSError = ERROR_READ_PROTECTED;
                }
                else DOSError = ERROR_NO_MORE_ENTRIES;
            }
            break;
//-
//+           ST_ROOT
            case ST_ROOT :
            {
                char    *TempFileNamePointer = BTOC( DeviceNode->dn_Name);
                memcpy( ResultFIB->fib_FileName, TempFileNamePointer, TempFileNamePointer[ 0 ] + 1);

                FileLock->ul_MsgNumber = 0;

                if( FileLock)
                {
                    UMSSelectTags( FileLock->ul_Account,
                                   UMSTAG_SelWriteLocal,    TRUE,
                                   UMSTAG_SelSet,           ( 1L<<0),
                                   UMSTAG_SelUnset,         0,
                                   TAG_DONE);
                }
            }
            break;
//-
//+           default
            default :
            {
                DOSError = ERROR_OBJECT_WRONG_TYPE;
            }
            break;
//-
        }
    }
    else DOSError = ERROR_INVALID_LOCK;

    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);
} //-
