/****************************************************************************/
/*
 *    PROGRAM NAME: ALIAS32
 *    ------------
 *
 *    This program executes on a DSS client connected to a DSS cell.
 *    It does not support connection to an LS domain.
 *
 *    What this program does: Creates an alias for a files resource;
 *    shares it; attempts to add a directory space limit to the resource
 *    (but only if directory space limits are enabled).       
 *
 *    This progam does not set access control on the server resource.
 *    DCE sec_acl APIs could be used to provide this.
 *
 *    Execution of this program requires administrator rights in the
 *    resource domain where the alias is created and on the server of
 *    of the alias resource.
 *
 *    SYNTAX:
 *    ------
 *    ALIAS32 aliasname \\servername resourcename  [//resourcedomainname]
 *       where:
 *        - aliasname is the alias that the resource will be known by
 *          (an alias cannot be longer than 8 bytes)
 *        - \\servername is the name of the server where the resource
 *          physically resides. 
 *        - resourcename is a fully qualified path (beginning with a
 *          drive letter).
 *        - //resourcedomainname is optional and specifies the resource
 *          domain name of the cell where the alias is to reside.  If not
 *          specified, the resource domain of the server is used.
 *
 *        Note that adding an alias via this sample program will require
 *        some cleanup after the program runs: an administrator will need
 *        to: delete the alias, delete the share, and remove the
 *        directory limit, if one was added.  These tasks may be done
 *        with the following NET commands:
 *        - NET ALIAS <aliasname> /DEL  /DOMAIN:resourcedomainname
 *        - NET SHARE <netname (which is aliasname)> /DEL
 *          or, if the shared resource is on a remote server,
 *          NET ADMIN \\servername /C NET SHARE <aliasname> /DEL
 *        - NET DASD <resourcename> /DEL
 *          or
 *          NET ADMIN \\servername /C NET DASD <resourcename> /DEL
 *          if the resource resides on a remote server.
 *
 *    REQUIRED FILES:
 *    --------------
 *    ALIAS32.C        -  Source code for this program
 *
 *    REQUIRED LIBRARIES:
 *    ------------------
 *    NETAPI32.LIB     -  Netapi library (in \IBMLAN\NETSRC\LIB directory)
 *
 *    NetAPI functions used in this program:
 *    -------------------------------------
 *    Net32ServerGetInfo
 *    Net32AliasAdd
 *    Net32AliasDel
 *    Net32ShareAdd
 *    Net32DASDAdd
 *
 *    HOW TO COMPILE THIS PROGRAM:
 *    ---------------------------
 *       see sample makefile
 */
/****************************************************************************/

/*------- OS/2 include files -----------------------------------------------*/
#define INCL_DOSMEMMGR
#define INCL_DOSPROCESS
#include <os2.h>

/*------- NET APIs include files -------------------------------------------*/
#include <neterr.h>
#include <netcons.h>
#include <dasd.h>
#include <dcdb.h>
#include <server.h>
#include <shares.h>

/*------- C include files --------------------------------------------------*/
#include <stdio.h>
#include <string.h>

/*------- Function declaration ---------------------------------------------*/
VOID Syntax(VOID);
VOID Error_Message(USHORT, PSZ);


/*------- Main program -----------------------------------------------------*/
VOID
main(int argc, char *argv[])
{
    USHORT                      usRc = 0,
                                usCount;
    ULONG                       ulBytesAvailable,
                                ulEntriesRead;
    CHAR                        ServerName[UNCLEN+1];
    CHAR                        ResDomName[256];
    PCHAR                       pBuffer;
    BOOL                        AccessAdded = FALSE;
    struct alias_info_2        *pAliasInfo;
    struct share_info_2        *pShareInfo;
    struct dasd_info_0         *pDasdInfo;
    struct server_info_10      *pSrvInfo;
    ULONG Level =101L;  /* Level needed for LSE */


    /* There must be either 4 or 5 command line arguments */
    if (argc < 4 || argc > 5)
        Syntax();


    /*
     * Verify that the \\servername argument begins with two backslashes,
     * and that it's not too long.
     */
    if ( *(argv[2]) != '\\' || *(argv[2]+1) != '\\' ||
         strlen(argv[2]) > UNCLEN )
    {
         Syntax();
    }
    else
    {
            strcpy(ServerName, argv[2]);
    }

    /*
     * Check for the resource domain name and verify it begins with two
     * forward slashes and that it's not too long.
     */
    if (argc == 5)
    {
        if ( *(argv[4]) != '/' || *(argv[4]+1) != '/' ||
             strlen(argv[2]) > 256 )
        {
            Syntax();
        } 
        else
        {
            strcpy(ResDomName, argv[4]);
        }
    } 
    

    /* Make sure that the length of the alias name is acceptable. */
    if (strlen(argv[1]) > ALIAS_LEN)
        Syntax();

    /* allocate a buffer for the API calls */
    usRc = DosAllocMem((PPVOID)&pBuffer,
                       4096,
                       PAG_WRITE | PAG_READ | PAG_COMMIT);

    if (usRc)
    {
        Error_Message(usRc, "DosAllocMem");
        DosExit(EXIT_PROCESS, (ULONG)usRc);
    }

    /* Set the buffer to all zeroes. */
    memset(pBuffer, 0, 4096);

    /*
     * If no resource domain name specified, then interrogate the
     * server for it.
     */

    if (argc != 5)
    {
       pSrvInfo = (struct server_info_10 *)(pBuffer +3072);
        usRc =  Net32ServerGetInfo(ServerName,
                                   10,
                                   (unsigned char *)pSrvInfo,
                                   1024,
                             &ulBytesAvailable);
 
        if (usRc)
        {
            Error_Message(usRc, "NetServerGetInfo");
            (void)DosFreeMem((PVOID)pBuffer);
            DosExit(EXIT_PROCESS, (ULONG)usRc);
        }
        else
        {
           strcpy(ResDomName, "//");
           strcat(ResDomName, pSrvInfo -> sv10_resdom_name);
        }
    }

    /*
     * Set up the buffer for the call to Net32AliasAdd.
     * This will be an internal files alias that is shared
     * by administrator action.  The maximum number of
     * simultaneous users of this alias will be 10.
     */
    pAliasInfo = (struct alias_info_2 *)pBuffer;

    /*
     * Note that the ai2_queue, ai2_priority, and ai2_device_pool
     * elements of the alias_info_2 structure do not apply to files
     * aliases, so these elements are not initialized here.  Since
     * the buffer has been memset to 0, these elements all have a
     * value of 0.
     */
    strcpy(pAliasInfo -> ai2_alias, argv[1]);
    pAliasInfo -> ai2_remark = "Alias created by ALIAS sample program.";
    pAliasInfo -> ai2_type = ALIAS_TYPE_FILE;
    pAliasInfo -> ai2_location = ALIAS_LOCATION_INTERNAL;
    strcpy(pAliasInfo -> ai2_server, ServerName+2);
    pAliasInfo -> ai2_mode = ALIAS_MODE_BYADMIN;
    pAliasInfo -> ai2_maxuses = 10;
    pAliasInfo -> ai2_path = argv[3];

    /* The Net32AliasAdd api must be remoted to the domain controller. */
    usRc = Net32AliasAdd(ResDomName,
                         2,
                         (unsigned char *)pAliasInfo,
                         sizeof(struct alias_info_2),
                         NULL);

    if (usRc)
    {
        Error_Message(usRc, "Net32AliasAdd");
        (void)DosFreeMem((PVOID)pBuffer);
        DosExit(EXIT_PROCESS, (ULONG)usRc);
    }
    else
    {
        printf("The alias has been added successfully.\n");
    }


    /*
     * Set up the buffer to get the alias shared.
     */
    pShareInfo = (struct share_info_2 *)pBuffer;

    strcpy(pShareInfo -> shi2_netname, argv[1]);/* netname == aliasname */
    pShareInfo -> shi2_type = STYPE_DISKTREE;
    pShareInfo -> shi2_remark = "Share added by ALIAS32 sample program.";
    pShareInfo -> shi2_max_uses = 10;
    if (argc == 3)
        pShareInfo -> shi2_path = argv[2];
    else
        pShareInfo -> shi2_path = argv[3];
    *pShareInfo -> shi2_passwd = '\0';
    pShareInfo -> shi2_permissions = 0;
    pShareInfo -> shi2_current_uses = 0;

    usRc = Net32ShareAdd(ServerName,
                         2,
                         pBuffer,
                         4096);

    if (usRc)
    {
        Error_Message(usRc, "Net32ShareAdd");
        printf("Deleting alias definition for %s...\n", argv[1]);
        usRc = Net32AliasDel(ResDomName, argv[1], 0L, NULL);
        if (usRc)
        {
            printf("Deletion of alias %s failed.\n", argv[1]);
            Error_Message(usRc, "Net32AliasDel");
        }
        else
        {
            printf("Alias %s was deleted successfully.\n", argv[1]);
        }
        (void)DosFreeMem((PVOID)pBuffer);
        DosExit(EXIT_PROCESS, (ULONG)usRc);
    }
    else
    {
        printf("The alias was shared successfully.\n");
    }

    /*
     * Finally, attempt to add a directory limit to the resource.
     * We arbitrarily set the limit at 1MB and specify that alerts
     * are to be generated when the directory is 90% full.
     */
    pDasdInfo = (struct dasd_info_0 *)pBuffer;

    pDasdInfo -> d0_resource_name = argc == 3 ? argv[2] : argv[3];
    pDasdInfo -> d0_max = 1024;         /* 1024KB == 1Meg */
    pDasdInfo -> d0_use = 0;
    pDasdInfo -> d0_flag = DASD_VALIDATE_LIMIT_ON;
    pDasdInfo -> d0_thresh = 90;
    pDasdInfo -> d0_delta = 0;

    usRc = Net32DASDAdd(ServerName,
                        0,
                        pBuffer,
                        4096);

    if (usRc == NERR_Success)
    {
        printf("A directory limit of 1MB was set for directory %s.\n",
                argc == 3 ? argv[2] : argv[3]);
    }
    else
    {
        Error_Message(usRc, "Net32DASDAdd");
        (void)DosFreeMem((PVOID)pBuffer);
    }

    DosExit(EXIT_PROCESS, (ULONG)usRc);
}

/*
 * Display syntax information and exit.
 */
VOID
Syntax()
{
    printf("USAGE:\nThe ALIAS32 sample program adds a files alias, shares it, and\n");
    printf("adds a directory limit to the resource.\n\n");
    printf("Syntax:\n");
    printf("   ALIAS32 aliasname \\servername resourcename\n");
    printf("      OR\n");
    printf("   ALIAS32 aliasname \\\\servername resourcename //resourcedomainname \n");
    printf(" where:\n");
    printf("   - aliasname is an 8-byte name that is not currently in use.\n");
    printf("   - \\\\servername specifies the server that the alias resource\n");
    printf("     resides on.\n");
    printf("   - resourcename is a fully qualified path name.\n");
    printf("   - //resourcedomainname is the resource resource domain name \n");
    printf("     of the cell where the alias is to reside.  If not specified, \n");
    printf("     the resource doamin of the server is used. \n");
    DosExit(EXIT_PROCESS, 1);
}
