/****************************************************************************/
/*
 *    PROGRAM NAME: USER32
 *    ------------
 *
 *    What this program does:  Creates a new user (password same as 
 *    userid, assigns user default resource domain, adds a file alias 
 *    as logon assignment (if specified).  Displays information about the
 *    user.  Deletes the user.         
 *
 *    Setup:
 *      If alias logon assigment used.
 *        - Create an alias for a file resource in the user's default
 *          resource domain.  ALIAS32.EXE could be used.
 *        - Give the user group of the resouce domain,
 *          "realms/<resourcedomainname>/USER", read access to the 
 *          alias resource if you plan to test user logon.       
 *
 *    SYNTAX:
 *    ------
 *    USER32 username /ADD //defaultresourcedomain [aliasname]
 *      creates user account, adds user default resource domain, adds 
 *      userid to "USER" group of resource domain, and adds alias as
 *      logon assignment (if specified)
 *
 *    USER32 username
 *      displays information about the user 'username'
 *
 *    USER32 username /DEL
 *      deletes the user account
 *
 *    REQUIRED FILES:
 *    --------------
 *    USER32.C       -  Source code for this program
 *
 *    REQUIRED LIBRARIES:
 *    ------------------
 *    NETAPI32.LIB   -  Netapi library (in \IBMLAN\NETSRC\LIB directory)
 *
 *    NetAPI32 functions used in this program:
 *    ---------------------------------------
 *    Net32UserAdd
 *    Net32UserDel
 *    Net32UserGetGroups
 *    Net32UserGetInfo
 *    Net32UserGetLogonAsn
 *    Net32UserSetLogonAsn
 *
 *    HOW TO COMPILE THIS PROGRAM:
 *    ---------------------------
 *    see makefile
 */
/****************************************************************************/

/**************   Defines   *************************************************/
#define    DISPLAY     0
#define    ADD         1
#define    DELETE      2
#define    BUFFER_LEN  4096
#define    INCL_DOSPROCESS
#define    INCL_DOSMEMMGR
#define    INCL_DOSERRORS

/**************   OS/2 include files ****************************************/
#include <os2.h>

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

/**************   LAN Server include files   ********************************/
#include <netcons.h>
#include <neterr.h>
#include <access.h>
#include <dcdb.h>
#include <lsdceerr.h>

/**************   Forward declarations of local functions   ******************/
VOID Error_Message(USHORT, PSZ);
VOID Syntax(VOID);
VOID AddUser(char *, char *, char *);
VOID DeleteUser(char *);
VOID DisplayUserDetails(char *);

/**************   Global Variables   *****************************************/
lsdce_err_stat_t  ErrStatus;

/**************   Main program   *********************************************/
/*
 * This function simply validates the command line arguments and
 * then calls a worker function, based on command line input.
 */
VOID
main(int argc, char *argv[])
{
    USHORT                 usFunction = DISPLAY;
    CHAR                   pUser[UNLEN+1];
    CHAR                   pDefResDom[256];
    CHAR                   pAliasName[ALIAS_LEN+1] = {'\0'};

    /* Validate command line input */
    if (argc < 2 || argc > 5)
        Syntax();

    /* Verify that username is not too long. */
    if (strlen(argv[1]) > UNLEN)
        Syntax();

    /* If a command line switch was specified, it must be "/ADD" or "/DELETE" */
    if (argc >= 3)
    {
        if (!stricmp(argv[2], "/ADD"))
        {

    /* For add, default resource domain name is required with double 
       leading forward slashes                                          */
            if ((argc == 3) || ( *(argv[3]) != '/' || *(argv[3]+1) != '/'))
                Syntax();     
            strcpy(pDefResDom, argv[3]);

    /* Is an alias name specified?                                      */
            if (argc == 5)
                strcpy(pAliasName,argv[4]);

            usFunction = ADD;
            
        }
        else if (!strnicmp(argv[2], "/DEL", strlen("/DEL")))
            usFunction = DELETE;
        else
            Syntax();
    }

    strcpy(pUser, argv[1]);

    /* Call the appropriate worker function. */
    if (usFunction == ADD)
        AddUser(pUser, pDefResDom, pAliasName);
    else if (usFunction == DELETE)
        DeleteUser(pUser);
    else
        DisplayUserDetails(pUser);

    DosExit(EXIT_PROCESS, 0);
}

/*
 * This function takes the username specified on the command line as
 * input and attempts to:
 *  - Create a user account.
 *  - Assign the default resource domain.
 *  - If specified, add alias as logon assignment.
 */
VOID
AddUser(char * pszUser, char * pszDefResDom, char * pszAliasName)
{
    USHORT                       usRc;
    PCHAR                        pBuffer;
    struct user32_info_201      *pUserInfo;
    PCHAR                        pszExtendedAliasName;
    struct logon_asn_info_200   *pLogInfo;
    struct logon_asn_list_200   *pLogList;
    CHAR                        SERVER_ANY[] = "\\\\*";

        /* Add a new user account */

    usRc = DosAllocMem((PPVOID)&pBuffer,
                       BUFFER_LEN,
                       PAG_WRITE | PAG_READ | PAG_COMMIT);

    if (usRc)
        Error_Message(usRc, "DosAllocMem");
    else
    {

        /* initialize user info structure                        */

        memset(pBuffer, 0, BUFFER_LEN);
        pUserInfo = (struct user32_info_201 *)pBuffer;

        strcpy(pUserInfo -> usri201_name, pszUser);

        /* user password same as userid */
        strcpy(pUserInfo -> usri201_password, pszUser);

        pUserInfo -> usri201_comment =
        pUserInfo -> usri201_usr_comment = 
                                   "userid added by USER sample program";

        pUserInfo -> usri201_priv = USER_PRIV_USER;
 
        pUserInfo -> usri201_flags = UF_SCRIPT;

        pUserInfo -> usri201_full_name = "This isn't a real user!";

        pUserInfo -> usri201_logon_server = SERVER_ANY;

        /* The user's account never expires. */
        pUserInfo -> usri201_acct_expires = TIMEQ_FOREVER;

        pUserInfo -> usri201_default_realm = pszDefResDom;

        pUserInfo -> usri201_pwstrength_server = "lspwsd";

        usRc = Net32UserAdd(pszDefResDom, 201, pBuffer, BUFFER_LEN, (UCHAR *)&ErrStatus);

        /* if user add successful then add logon assignment     */
        if (usRc)
        {
            Error_Message(usRc, "Net32UserAdd");
        }
        else
        {

        /* if an alias name was input then set it as a logon assignment */
            if (*pszAliasName) 
            {
                memset(pBuffer, 0, BUFFER_LEN);
                pLogInfo = (struct logon_asn_info_200 *)pBuffer;
                pLogList =
                   (struct logon_asn_list_200 *)(pBuffer + sizeof(struct logon_asn_info_200));
                pLogInfo -> lai200_count = 1;
        /* The lal200_global_name entry is used to specify the alias name.
           The format used here is extendedaliasname of the form
           "aliasname@resdomname"                                     */
                pszExtendedAliasName = pBuffer + (BUFFER_LEN -1024);
                strcpy(pszExtendedAliasName, pszAliasName);
                strcat(pszExtendedAliasName, "@");
        /* append the resource domain name without the leading forward
           slashes                                                    */
                strcat(pszExtendedAliasName, pszDefResDom+2);
                pLogList -> lal200_global_name = pszExtendedAliasName;
                strcpy(pLogList -> lal200_alias, pszAliasName);
                pLogList -> lal200_type = ALIAS_TYPE_FILE;

        /* note that the level 200 device entry is a pointer rather than
           and array                                                  */
                pLogList -> lal200_device = (pszExtendedAliasName +
                                            strlen(pszExtendedAliasName) + 1);
                strcpy(pLogList -> lal200_device, "M:");
           
           
                usRc = Net32UserSetLogonAsn(pszDefResDom,
                                        pszUser,
                                        200,
                                        pBuffer,
                                        BUFFER_LEN,
                                        (UCHAR *)&ErrStatus);
           
                if (usRc)
                {
                    Error_Message(usRc, "Net32UserSetLogonAsn");
                    DeleteUser(pszUser);
                }
            }
        }

        DosFreeMem((PVOID)pBuffer);

    }


    if (usRc)
        DosExit(EXIT_PROCESS, (ULONG)usRc);

    return;

}

/*
 * DeleteUser() calls the Net32UserDel API to delete a user account.
 */
void
DeleteUser(char *pszUser )
{
    USHORT             usRc;
    CHAR               pBuffer[GNLEN+1];
    ULONG              ulBytesAvailable;


    usRc = Net32UserDel((CHAR *)NULL,
                        pszUser,
                        (UCHAR *)&ErrStatus);

    if (usRc)
        Error_Message(usRc, "Net32UserDel");
    else
        printf("The definition of \"%s\" was successfully deleted.\n",
               strupr(pszUser));
    return;
}


void
DisplayUserDetails(char *pszUser)
{
    USHORT                      usRc,
                                usCount;
    ULONG                       ulTotalEntries,
                                ulAvailable;
    PCHAR                       pBuffer;
    struct user32_info_201     *pUserInfo;
    struct group_info_0        *pGroups;
    struct logon_asn_list_200  *pLogList;
    CHAR                        pszDC[UNCLEN + 1];

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

    if (usRc)
    {
        Error_Message(usRc, "DosAllocMem");
        return;
    }

    usRc = Net32UserGetInfo((char *)NULL,
                            pszUser,
                            201,
                            pBuffer,
                            4096,
                            &ulAvailable,
                            (UCHAR *)&ErrStatus);

    if (usRc)
        Error_Message(usRc, "Net32UserGetInfo");
    else
    {
        /* Display selected portions of the user32_info_201 structure... */
        pUserInfo = (struct user32_info_201 *)pBuffer;
        printf("Details for user %s:\n\n", pUserInfo -> usri201_name);
        printf("   Comment: %s\n", pUserInfo -> usri201_comment);
        printf("   User comment: %s\n", pUserInfo -> usri201_usr_comment);
        printf("   Full Name: %s\n", pUserInfo -> usri201_full_name);
        printf("   Privilege level: %s\n",
                (pUserInfo -> usri201_priv == USER_PRIV_USER ? "User" :
                 "Administrator"));
        printf("   Home directory: %s\n", pUserInfo -> usri201_home_dir);
        printf("   Preferred logon server: ");
        if (!pUserInfo -> usri201_logon_server ||
            *pUserInfo -> usri201_logon_server == '\0')
            printf("Domain controller\n");
        else if (strcmp(pUserInfo -> usri201_logon_server, "\\\\*"))
            printf("Any server\n");
        else
            printf("%s\n", pUserInfo -> usri201_logon_server);
        printf("   User default resource domain: %s\n", 
                                        pUserInfo -> usri201_default_realm);

        /* Now, get group membership information for this user. */
        usRc = Net32UserGetGroups((CHAR *)NULL,
                               pszUser,
                               0,
                               pBuffer,
                               4096,
                               &ulAvailable,
                               &ulTotalEntries,
                               (UCHAR *)&ErrStatus);

        if (usRc)
            Error_Message(usRc, "Net32UserGetGroups");
        else
        {
            /* print group memberships */
            usCount = (USHORT)ulAvailable;
            pGroups = (struct group_info_0 *)pBuffer;
            printf("\nUser \"%s\" belongs to the following groups:\n",
                    strupr(pszUser));
            while (usCount)
            {
                printf("\t%s\n", pGroups -> grpi0_name);
                --usCount;
                ++pGroups;
            }

            /*
             * print logon assignment information...get only
             * assignments to files aliases.
             */
            usRc = Net32UserGetLogonAsn((char *)NULL,
                                        pszUser,
                                        200,
                                        ALIAS_TYPE_FILE,
                                        pBuffer,
                                        4096,
                                        &ulAvailable,
                                        (UCHAR *)&ErrStatus);

            if (usRc == ERROR_PATH_NOT_FOUND)
                printf("The domain control database directory "\
                       "for \"%s\" was not found.\n", strupr(pszUser));
            else if (usRc)
                Error_Message(usRc, "Net32UserGetLogonAsn");
            else
            {
                usCount = ((struct logon_asn_info_200 *)pBuffer) -> lai200_count;
                if (usCount == 0)
                    printf("\n\"%s\" has no files logon assignments.\n",
                            strupr(pszUser));
                else
                {
                    pLogList =
                     (struct logon_asn_list_200 *)(pBuffer + sizeof(struct logon_asn_info_200));

                    printf("\nLogon assignments for user \"%s\":\n",
                           strupr(pszUser));
                    while (usCount)
                    {
                        printf("\t%-8.8s   %s\n",
                                pLogList -> lal200_device,
                                pLogList -> lal200_global_name);

                        ++pLogList;
                        --usCount;
                    }
                }
            }
        }
    }
    DosFreeMem((PVOID)pBuffer);
    return;
}

VOID
Syntax()
{
    printf("Usage:\n");
    printf("   The USER32 sample program creates a new user (password same as \n");
    printf("   userid, assigns user default resource domain, adds a file alias \n");
    printf("   as logon assignment (if desired).  Displays information about the \n");
    printf("   user.  Deletes the user. \n\n");
    printf("Syntax:\n");
    printf("   USER32 <username> /ADD <//defaultresourcedomain> [aliasname] \n");
    printf("      -- Creates <username> user account, adds user default resource domain,\n");
    printf("         adds <username> to ""USER"" group of resource domain, and adds alias \n");
    printf("         as logon assignment (if specified). \n");
    printf("   USER32 <username>  \n");
    printf("      -- Displays information about <username>  \n");
    printf("   USER32 <username> /DEL \n");
    printf("      -- deletes the user account for <username>. \n");
    DosExit(EXIT_PROCESS, 1);
}
