Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

771 lines
23 KiB

/*++
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) {
NetpKdPrint(( PREFIX_PORTUAS "PortUasGetString: "
" output string is '" FORMAT_LPWSTR "'.\n", BufferW ));
}
NetpKdPrint(( 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:
NetpKdPrint(( 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