/*++

Copyright (c) 1992-1993  Microsoft Corporation

Module Name:

    Prompt.c

Abstract:

    PortUasDefaultPromptForNewName.

Author:

    John Rogers (JohnRo) 29-Oct-1992

Environment:

    Portable to any flat, 32-bit environment.  (Uses Win32 typedefs.)
    Requires that sizeof(DWORD) >= sizeof(pointer) (for FormatMessageW).
    Requires ANSI C extensions: slash-slash comments, long external names.

Revision History:

    29-Oct-1992 JohnRo
        Created for RAID 9020: setup: PortUas fails ("prompt on conflicts"
        version).
    26-Jan-1993 JohnRo
        RAID 8683: PortUAS should set primary group from Mac parms.
    30-Jul-1993 JohnRo
        RAID NTISSUE 2260: PortUAS returns a NetUserAdd error=1379 with local
        group.
        Do a little checking on values set by FormatMessageA().
        Made changes suggested by PC-LINT 5.0
    24-Aug-1993 JohnRo
        RAID 2822: PortUAS maps chars funny.  (Work around FormatMessageA bug.)
    01-Sep-1993 JohnRo
        Add PortUAS /log:filename switch for Cheetah.
        PC-LINT found a bug: PUAS_GROUP_EXISTS_AS_A_LOCALGROUP wasn't used yet.
        Fix output intended to stderr.
        Made more changes suggested by PC-LINT 5.0

--*/


// These must be included first:

#include <nt.h>         // Needed by <portuasp.h>
#include <ntrtl.h>      // (Needed with nt.h and windows.h)
#include <nturtl.h>     // (Needed with ntrtl.h and windows.h)
#include <windows.h>    // IN, LPWSTR, BOOL, etc.
#include <lmcons.h>     // NET_API_STATUS, UNLEN, GNLEN.

// These may be included in any order:

#include <lmapibuf.h>
#include <names.h>      // NetpIsUserNameValid(), etc.
#include <netdebug.h>   // NetpAssert(), FORMAT_ equates, etc.
#include <netlib.h>     // NetpErrNoToApiStatus(), MAX_NETLIB_MESSAGE_ARG, etc.
//#include <io.h>         // write
#include <stdarg.h>     // va_list, va_start(), va_end(), va_arg().
#include <stdio.h>      // feof(), ferror(), printf(), stdin, etc.
#include <portuas.h>    // REASON_ equates.
#include <portuasp.h>   // My prototype, Verbose.
#include <tstring.h>    // NetpAllocWStrFromWStr().
#include <tchar.h>      // iswdigit(), wcsncmp(), etc.
#include <winerror.h>   // ERROR_ equates, NO_ERROR.

#include "nlstxt.h"     // NLS message ID's.

extern	TCHAR	ConBuf[];
extern	int	MyWriteConsole(int fOutOrErr, int cch);
extern	int	FileIsConsole(HANDLE fh);

//
// Globals (may also be set by PortUasParseCommandLine):
//

HANDLE PortUasGlobalLogFileHandle = INVALID_HANDLE_VALUE;


/***    NlsPutMsg - Print a message to a handle
 *
 *  Purpose:
 *      PutMsg takes the given message number from the
 *      message table resource, and displays it on the requested
 *      handle with the given parameters (optional)
 *
 *   unsigned PutMsg(unsigned Handle, unsigned MsgNum, ... )
 *
 *  Args:
 *      Handle          - the handle to print to  (must be STDOUT or STDERR)
 *      MsgNum          - the number of the message to print
 *      Arg1 [Arg2...]  - additonal arguments for the message as necessary
 *
 *  Returns:
 *      The number of characters printed.
 *
 */

/*lint -save -e579 */  // Don't complain about unwidened before ...
USHORT NlsPutMsg(USHORT Handle, USHORT usMsgNum, ... )
{
    LPTSTR          AllocatedStrings[ MAX_NETLIB_MESSAGE_ARG+1 ]; // 0 unused.
    NET_API_STATUS ApiStatus;
    va_list        arglist;
    BOOL           ArgListInUse = FALSE;
    LPWSTR         FormattedOutput = NULL;
    DWORD          Index;
    DWORD          ModifiedArgs[ MAX_NETLIB_MESSAGE_ARG+1 ];  // 0 ignored.
    DWORD          msglen;
    LPSTR          NarrowFormat = NULL;
    LPWSTR         UnicodeFormat = NULL;  // Unicode format, modified as we go.

    NetpAssert( (Handle == STDOUT) || (Handle == STDERR) );

    va_start(arglist, usMsgNum);
    ArgListInUse = TRUE;

    for (Index=0; Index <= MAX_NETLIB_MESSAGE_ARG; ++Index) {
        AllocatedStrings[Index] = NULL;
    }

    //
    // As of this writing (19-Aug-1993), there is a bug below FormatMessageA(),
    // where the "Unicode-to-ANSI translation" just truncates Unicode chars to
    // 8 bits.  So, we need to avoid that by using FormatMessageA to get the
    // message, convert it to Unicode, and use FormatMessageW to do the actual
    // formatting.
    //
    // Get the format string (as NarrowFormat).
    //

    msglen = FormatMessageA(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_IGNORE_INSERTS |
            FORMAT_MESSAGE_FROM_HMODULE,
            NULL,                               // source
            usMsgNum,
            (DWORD) 0,                          // Default country ID.
            (LPVOID) &NarrowFormat,             // Alloc and set pointer.
            0,
            &arglist );

    if (msglen == 0) {
        ApiStatus = GetLastError();
        (VOID) WriteToCon(
                TEXT("PortUAS.exe: FormatMessageA failed: ") TEXT(FORMAT_API_STATUS) TEXT("\n"),
                ApiStatus );
        NetpAssert( ApiStatus != NO_ERROR );
        goto Cleanup;
    }

    NetpAssert( NarrowFormat != NULL );
    if (NarrowFormat == NULL) {
        msglen = 0;
        goto Cleanup;
    }

    //
    // OK, Now convert the format string to Unicode.
    // We'll modify the Unicode format string (in place) below...
    //

    UnicodeFormat = NetpAllocWStrFromStr( NarrowFormat );
    if (UnicodeFormat == NULL) {
        // Rats, probably ran out of memory.  Well, we tried.
        msglen = 0;
        goto Cleanup;
    }

    // 
    // FormatMessageA() just walked the va_list.  We're going to walk it
    // again, looking for args to convert.  So, tell C runtime...
    //

    NetpAssert( ArgListInUse );
    va_end(arglist);
    va_start(arglist, usMsgNum);

    //
    // For each numbered arg (1..MAX_NETLIB_MESSAGE_ARG), perhaps modify UnicodeFormat in
    // place and come up with a narrow string for its arg.  For other args,
    // just copy from va_list format to an array we can pass to
    // FormatMessageW().
    //
    // Things we handle:
    //     %1!lu!
    //     %2
    //     %5!08lX!
    //     %16!ws!
    //

    for (Index=1; Index <= MAX_NETLIB_MESSAGE_ARG; ++Index) {
        LPWSTR ThisFormat;

        ThisFormat = (LPWSTR) NetpFindNumberedFormatInWStr(
                UnicodeFormat,
                Index );      // Arg number (1=first).
        if (ThisFormat == NULL) {
            break;  // Just last numbered arg (if any).
        }

        NetpAssert( ThisFormat[0] == L'%' );
        NetpAssert( ThisFormat[1] != L'0' );      // Leading zero would confuse.
        NetpAssert( iswdigit( ThisFormat[1] ) );
        NetpAssert( wcslen( ThisFormat ) >= 2 );  // At least "%1".

        // Skip "%1" or "%16"...
        ++ThisFormat;  // Skip percent sign.
        NetpSkipWDigits( ThisFormat );

        // Parse format itself.
        if (ThisFormat[0] == L'!') {
            ++ThisFormat;  // Skip leading BANG.

            // Skip possible leading digits in "08lX"...
            NetpSkipWDigits( ThisFormat );

            if ( wcsncmp( ThisFormat, (LPWSTR) L"ws", 2 ) == 0 ) {

                LPWSTR OriginalArg;
                OriginalArg = va_arg( arglist, LPWSTR );
                AllocatedStrings[ Index ] = OriginalArg;

                // Modify format AND arg for this one.
                ThisFormat[0] = TEXT('h');
                ModifiedArgs[ Index ] = (DWORD) AllocatedStrings[ Index ];
                ThisFormat += 2;  // Skip "hs".

            } else if ( ThisFormat[0] == TEXT('l') ) {

                DWORD TempDword;
                if ( wcsncmp( ThisFormat, (LPWSTR) L"lu", 2 ) == 0 ) {
                    TempDword = va_arg( arglist, DWORD );
                    ModifiedArgs[ Index ] = TempDword;
                } else if ( wcsncmp( ThisFormat, (LPWSTR) L"lX", 2 ) == 0 ) {
                    TempDword = va_arg( arglist, DWORD );
                    ModifiedArgs[ Index ] = TempDword;
                } else if ( wcsncmp( ThisFormat, (LPWSTR) L"lx", 2 ) == 0 ) {
                    TempDword = va_arg( arglist, DWORD );
                    ModifiedArgs[ Index ] = TempDword;
                } else {
                    NetpAssert( FALSE );
                    msglen = 0;
                    goto Cleanup;
                }
                ThisFormat += 2;  // Skip "lu", etc.
            } else if ( wcsncmp( ThisFormat, (LPWSTR) L"s", 1 ) == 0 ) {
                LPTSTR OriginalArg = va_arg( arglist, LPTSTR );
                //FARBUGBUG  '%s' is Unicode to FormatMessageW.
                ModifiedArgs[ Index ] = (DWORD) OriginalArg;
                ThisFormat += 1;  // Skip "s", etc.
            } else if ( wcsncmp( ThisFormat, (LPWSTR) L"hs", 2 ) == 0 ) {
                LPTSTR OriginalArg = va_arg( arglist, LPTSTR );
                ModifiedArgs[ Index ] = (DWORD) OriginalArg;
                ThisFormat += 2;  // Skip "hs", etc.
            } else {
                NetpAssert( FALSE );
                msglen = 0;
                goto Cleanup;
            }

            // Must be to trailing BANG here.
            NetpAssert( L'!' == *ThisFormat );
            if (*ThisFormat != BANG) {
                msglen = 0;
                goto Cleanup;
            }
            ++ThisFormat;  // Skip trailing BANG
        } else {
	    //FARBUGBUG  '%s' is Unicode to FormatMessageW.
            LPTSTR OriginalArg = va_arg( arglist, LPTSTR );
            ModifiedArgs[ Index ] = (DWORD) OriginalArg;
            ThisFormat += 1;  // Skip "s", etc.
        }
    }

    //
    // Use modified Unicode format string and modified args, to format the
    // message.
    //

    msglen = FormatMessageW(
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_STRING |
            FORMAT_MESSAGE_ARGUMENT_ARRAY,
            UnicodeFormat,                      // source of format string
            usMsgNum,
            (DWORD) 0,                          // Default country ID.
            (LPVOID) &FormattedOutput,          // Alloc and set pointer.
            0,
            (LPVOID) &ModifiedArgs[1] );        // Array of 32-bit args.
    if (msglen == 0) {
        ApiStatus = GetLastError();
        (VOID) WriteToCon(
                TEXT("PortUAS.exe: FormatMessageW failed: ") TEXT(FORMAT_API_STATUS) TEXT("\n"),
                ApiStatus );
        NetpAssert( ApiStatus != NO_ERROR );
        // BUGBUG: Event log this?
        goto Cleanup;
    }

    NetpAssert( FormattedOutput != NULL );
    if (FormattedOutput == NULL) {
        msglen = 0;
        goto Cleanup;
    }

    //
    // Print the message.
    //

    {
        if (Handle == STDOUT) {
	    msglen = WriteToCon(TFORMAT_LPWSTR, FormattedOutput);
        } else {
	    msglen = _stprintf( ConBuf, TFORMAT_LPWSTR, FormattedOutput);
	    if (msglen >= 0)
		msglen = MyWriteConsole(STDERR, msglen);
	    else
		msglen = 0;
        }
    }
    if ( msglen == ((USHORT)-1) ) {
        msglen = 0;
    }

    //
    // If we're logging stuff, then log a copy of this message too.
    //

    if (PortUasGlobalLogFileHandle != INVALID_HANDLE_VALUE) {
        ApiStatus = PortUasWriteToLogFile(
                PortUasGlobalLogFileHandle,
                (LPCTSTR) FormattedOutput );
        if (ApiStatus != NO_ERROR) {
            msglen = 0;
        }
    }

Cleanup:

    if (msglen == 0) {
        // BUGBUG: event log this?
        (VOID) WriteToCon( TEXT("PortUAS.exe: UNEXPECTED ERROR.\n") );
    }

    for (Index=0; Index<=MAX_NETLIB_MESSAGE_ARG; ++Index) {
        if (AllocatedStrings[Index] != NULL) {
            (VOID) NetApiBufferFree( AllocatedStrings[Index] );
        }
    }

    if (FormattedOutput != NULL) {
        (VOID) LocalFree( FormattedOutput );
    }
    if (NarrowFormat != NULL) {
        (VOID) LocalFree( NarrowFormat );
    }
    if (UnicodeFormat != NULL) {
        (VOID) LocalFree( UnicodeFormat );
    }
    if (ArgListInUse) {
        va_end(arglist);
    }
    return( (USHORT) msglen);
}
/*lint -restore */


DBGSTATIC NET_API_STATUS
PortUasGetString(
    OUT LPWSTR BufferW,
    IN DWORD BufLenW    // number of chars for string and NULLC.
    )
{
    NET_API_STATUS ApiStatus;
    char * BufferA = NULL;
    DWORD BufLenA = BufLenW + 1;        // room for str, \n, \0
    char * NewLine;
    char * Result;

    NetpAssert( BufferW != NULL );
    NetpAssert( BufLenW > 0 );

    if (FileIsConsole(GetStdHandle(STD_INPUT_HANDLE))) {
	ApiStatus = ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
			BufferW, BufLenW, &BufLenA, 0);
	if (ApiStatus) {
	    //
	    // Get rid of cr/lf
	    //
	    if (wcschr(BufferW, RETURN) == NULL) {
		if (wcschr(BufferW, NEWLINE))
		    *wcschr(BufferW, NEWLINE) = NULLC;
	    }
	    else
		*wcschr(BufferW, RETURN) = NULLC;
	    ApiStatus = NO_ERROR;
	    goto Cleanup;
	}
	else {
	    ApiStatus = GetLastError();
	}
    }

    //
    // Allocate an 8-bit version.
    //
    ApiStatus = NetApiBufferAllocate(
            BufLenA,                    // byte count
            (LPVOID *) (LPVOID) & BufferA);
    if (ApiStatus != NO_ERROR) {
       NetpAssert( BufferA == NULL );
       goto Cleanup;
    } else {
       NetpAssert( BufferA != NULL );
    }

    //
    // Read user's input (from stdin).
    // fgets will return a buffer of the form "flarp\n\0".
    //
    Result = fgets(
            BufferA,
            (int) BufLenA,
            stdin);

    //
    // Check for end of file or error.
    //
    if (Result == NULL) {
        if (ferror(stdin)) {
            ApiStatus = NetpErrNoToApiStatus( errno );
            NetpAssert( ApiStatus != NO_ERROR );
            goto Cleanup;
        } else {
            NetpAssert( feof(stdin) );
            ApiStatus = ERROR_HANDLE_EOF;
            goto Cleanup;
        }
    }

    //
    // Make sure string isn't too long, and get rid of newline.
    //
    NewLine = strchr( BufferA, '\n');
    if (NewLine == NULL) {
        ApiStatus = ERROR_INVALID_DATA; // string was too long.
        goto Cleanup;
    }

    NetpAssert( *(NewLine+1) == '\0' );
    *NewLine = '\0';

    //
    // copy and convert to UNICODE.
    //
    NetpCopyStrToWStr(
            BufferW,            // dest: unicode
            (LPVOID) BufferA ); // src: string in default LAN codepage

    ApiStatus = NO_ERROR;

Cleanup:
    if (BufferA != NULL) {
        (VOID) NetApiBufferFree( BufferA );
    }
    if (Verbose) {
        if (ApiStatus==NO_ERROR) {
            NetpDbgPrint( PREFIX_PORTUAS "PortUasGetString: "
                    " output string is '" FORMAT_LPWSTR "'.\n", BufferW );
        }
        NetpDbgPrint( PREFIX_PORTUAS "PortUasGetString: "
                " returning status " FORMAT_API_STATUS ".\n", ApiStatus );
    }
    return (ApiStatus);

} // PortUasGetString


NET_API_STATUS
PortUasComplainAboutBadName(
    IN LPWSTR OldName,
    IN BOOL ThisIsUserName,     // TRUE for user name, FALSE for group name
    IN DWORD Reason             // REASON_ equates from PortUAS.h
    )
{
    NET_API_STATUS ApiStatus;
    //LPTSTR ReasonText = NULL;
    USHORT ReasonText = 0;

    //
    // Come up with reason text (WriteToCon format string).
    //
    switch (Reason) {
    case REASON_BAD_NAME_SYNTAX:
        //ReasonText = "bad name syntax '" FORMAT_LPWSTR "'";
        ReasonText = PUAS_BAD_NAME_SYNTAX;
        break;

    case REASON_CONFLICT_WITH_DOMAIN:
        //ReasonText = "name '" FORMAT_LPWSTR "' conflicts with a domain name";
        ReasonText = PUAS_NAME_CONFLICTS_WITH_A_DOMAIN_NAME;
        break;

    case REASON_CONFLICT_WITH_GROUP:
        //ReasonText = "User '" FORMAT_LPWSTR "' exists as a group";
        ReasonText = PUAS_USER_EXISTS_AS_A_GROUP;
        break;

    case REASON_CONFLICT_WITH_USERNAME:
        //ReasonText = "group '" FORMAT_LPWSTR "' exists as a user";
        ReasonText = PUAS_GROUP_EXISTS_AS_A_USER;
        break;

#ifdef FAT8
    case REASON_NAME_LONG_FOR_TEMP_REG:
        //ReasonText = "group '" FORMAT_LPWSTR "' name too long.";
        ReasonText = PUAS_GROUP_NAME_TOO_LONG;
        break;
#endif

    case REASON_CONFLICT_WITH_LOCALGROUP:
        if (ThisIsUserName) {
            //ReasonText = "User '" FORMAT_LPWSTR "' exists as a local group";
            ReasonText = PUAS_USER_EXISTS_AS_A_LOCALGROUP;
        } else {
            ReasonText = PUAS_GROUP_EXISTS_AS_A_LOCALGROUP;
        }
        break;

    default:
        NetpDbgPrint( PREFIX_PORTUAS "PortUasComplainAboutBadName: "
                "got invalid value " FORMAT_DWORD " for reason.\n",
                Reason );
        ApiStatus = ERROR_INVALID_PARAMETER;
        goto Cleanup;
    }
    //NetpAssert( ReasonText != NULL );
    NetpAssert( ReasonText != 0 );

    //(VOID) WriteToCon( TEXT("\n\n*** Bad %s name *** "),
    //       ( ThisIsUserName ? TEXT("user") : TEXT("group") ) );
    if (ThisIsUserName) {
         (VOID) NlsPutMsg(STDOUT, PUAS_BAD_USER_NAME);
    }
    else {
         (VOID) NlsPutMsg(STDOUT, PUAS_BAD_GROUP_NAME);
    }
    //(VOID) WriteToCon( ReasonText, OldName );
    (VOID)NlsPutMsg(STDOUT, ReasonText, OldName);
    ApiStatus = NO_ERROR;

Cleanup:
    return (ApiStatus);
}

DBGSTATIC BOOL
IsCharInString (
    IN WCHAR wch,
    IN WCHAR * wszString
    )
{
    WCHAR * wszTemp = wszString;

    while (*wszTemp != (WCHAR)NULLC) {
        if (*wszTemp == wch) {
            return(TRUE);
        }
        ++wszTemp;
    }
    return(FALSE);
}

NET_API_STATUS
PortUasDefaultPromptForNewName(
    IN LPWSTR OldName,
    IN BOOL ThisIsUserName,     // TRUE for user name, FALSE for group name
    IN DWORD Reason,            // REASON_ equates from PortUAS.h
    OUT LPWSTR * NewName,       // alloc w/ NetApiBufferAllocate().
    OUT BOOL * IgnoreThis,
    OUT BOOL * ForceIgnoreFromNowOn
    )
{
    NET_API_STATUS ApiStatus;
    WCHAR Flag[3];
    LPWSTR NameToComplainAbout = OldName;  // OldName first time, but...
    WCHAR TempName[UNLEN+2];  // space for user name or group name

    static WCHAR * szYesNoForceChars[3] = {NULL, NULL, NULL}; // 0(Yes), 1(No), 2(Force)
    UINT i;
    BOOL Valid;

    // Get the localised yes, no and force characters.

    // IMPORTANT!!! Yes, No, and Force characters must be
    //              stored in sequentially-numbered messages in
    //              the MSGTABLE resource!

    for (i=0; i<=2; ++i) {
        if (szYesNoForceChars[i] == NULL) {
            if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
                  FORMAT_MESSAGE_IGNORE_INSERTS |
                  FORMAT_MESSAGE_FROM_HMODULE,
                  NULL,
                  (PUAS_YES_CHARS + i),
                  0L,                // Default country ID.
                  (LPTSTR)&(szYesNoForceChars[i]),
                  0,
                  NULL ) == 0) {

                UNEXPECTED_MSG( "FormatMessage", GetLastError() );
            }
        }
    }

    NetpAssert( OldName != NULL );
    NetpAssert( (ThisIsUserName==TRUE) || (ThisIsUserName==FALSE) );
    NetpAssert( NewName != NULL );
    NetpAssert( IgnoreThis != NULL );
    NetpAssert( ForceIgnoreFromNowOn != NULL );
    NetpAssert( UNLEN >= GNLEN );       // Make TempName larger if this fails.

    *NewName = NULL;   // don't confuse caller on error.

    Valid = FALSE;
    while ( !Valid ) {

        //
        // Explain what's wrong...
        //
        ApiStatus = PortUasComplainAboutBadName(
                OldName,
                ThisIsUserName,
                Reason );
        if (ApiStatus != NO_ERROR) {
            UNEXPECTED_MSG( "PortUasComplainAboutBadName", ApiStatus );
            goto Cleanup;
        }

        //
        // Prompt explaining what's wrong and what they can do...
        //
        //(VOID) WriteToCon(
        //       TEXT("\n")
        //       TEXT("Do you want to enter a new name?\n")
        //       TEXT("Enter Y for yes, N to ignore this name, or F to force ")
        //       TEXT("ignore from now on.\n") );
        (VOID)NlsPutMsg(STDOUT, PUAS_DO_YOU_WANT_A_NEW_NAME);

        ApiStatus = PortUasGetString( Flag, 3 );  // get str (max 1 char & nul)
        switch (ApiStatus) {
        case NO_ERROR:
            break;

        case ERROR_INVALID_DATA:        // Name too long gets this.
            Valid = FALSE;
            continue;       // loop again.

        case ERROR_HANDLE_EOF:
            *IgnoreThis = TRUE;
            *ForceIgnoreFromNowOn = TRUE;
            ApiStatus = NO_ERROR;
            goto Cleanup;

        default:
            UNEXPECTED_MSG( "PortUasGetString(flag)", ApiStatus );
            goto Cleanup;
        }

        NetpAssert( ApiStatus == NO_ERROR );

        //switch (Flag[0]) {
        //
        //case TEXT('Y'):  /*FALLTHROUGH*/
        //case TEXT('y'):
        if (IsCharInString(Flag[0],szYesNoForceChars[0]))
          {
            //(VOID) WriteToCon( TEXT("Enter a new name:\n") );
            (VOID)NlsPutMsg(STDOUT, PUAS_ENTER_A_NEW_NAME);

            ApiStatus = PortUasGetString( TempName, UNLEN+2 );

            switch (ApiStatus) {
            case NO_ERROR:
                break;

            case ERROR_INVALID_DATA:    // Name too long gets this.
                NameToComplainAbout = TempName;
                Reason = REASON_BAD_NAME_SYNTAX;
                Valid = FALSE;
                continue;               // Loop again.

            case ERROR_HANDLE_EOF:
                *IgnoreThis = TRUE;
                *ForceIgnoreFromNowOn = TRUE;
                ApiStatus = NO_ERROR;
                goto Cleanup;

            default:
                UNEXPECTED_MSG( "PortUasGetString(name)", ApiStatus );
                goto Cleanup;
            }

            if (TempName[0] == NULLC) {
                NameToComplainAbout = TempName;
                Reason = REASON_BAD_NAME_SYNTAX;
                Valid = FALSE;
                continue;               // Loop again.
            }

            if (ThisIsUserName) {
                if ( !NetpIsUserNameValid( TempName ) ) {
                    NameToComplainAbout = TempName;
                    Reason = REASON_BAD_NAME_SYNTAX;
                    Valid = FALSE;
                    continue;               // Loop again.
                }
            } else {
                if ( !NetpIsGroupNameValid( TempName ) ) {
                    NameToComplainAbout = TempName;
                    Reason = REASON_BAD_NAME_SYNTAX;
                    Valid = FALSE;
                    continue;               // Loop again.
                }
            }

            Valid = TRUE;
            *IgnoreThis = FALSE;
            *ForceIgnoreFromNowOn = FALSE;

            *NewName = NetpAllocWStrFromWStr( TempName );
            if (*NewName == NULL) {
                ApiStatus = ERROR_NOT_ENOUGH_MEMORY;
                goto Cleanup;
            }
            break;
        }
        //case TEXT('N'):  /*FALLTHROUGH*/
        //case TEXT('n'):
        else if (IsCharInString(Flag[0],szYesNoForceChars[1]))
          {
            Valid = TRUE;
            *IgnoreThis = TRUE;
            *ForceIgnoreFromNowOn = FALSE;
            break;
          }
        //case TEXT('F'):  /*FALLTHROUGH*/
        //case TEXT('f'):
        else if (IsCharInString(Flag[0],szYesNoForceChars[2]))
          {
            Valid = TRUE;
            *IgnoreThis = TRUE;
            *ForceIgnoreFromNowOn = TRUE;
            break;
          }
        //default:               // Handle empty string here.
        else
          {
            Valid = FALSE;      // Repeat prompt for flag and ask again.
          }

    }  // while !Valid

Cleanup:

    return (ApiStatus);

} // PortUasDefaultPromptForNewName
