diff options
Diffstat (limited to '')
62 files changed, 35877 insertions, 0 deletions
diff --git a/private/utils/ulib/src/achkmsg.cxx b/private/utils/ulib/src/achkmsg.cxx new file mode 100644 index 000000000..c20c2811e --- /dev/null +++ b/private/utils/ulib/src/achkmsg.cxx @@ -0,0 +1,550 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "achkmsg.hxx" +#include "basesys.hxx" +#include "rtmsg.h" + +extern "C" { +#include <ntddkbd.h> +} + +BOOLEAN +IsSuppressedMessage( + MSGID MessageId + ) +/*++ + +Routine Description: + + This function determines whether the specified message ID + should be suppressed, i.e. not recorded in the message log. + +Arguments: + + MessageId -- Supplies the Message ID in question. + +Return Value: + + TRUE if this message ID is in the set which is not recorded + in the message log. + +--*/ +{ + BOOLEAN result; + + switch( MessageId ) { + + case MSG_HIDDEN_STATUS : + case MSG_PERCENT_COMPLETE : + case MSG_CHK_NTFS_CHECKING_FILES : + case MSG_CHK_NTFS_CHECKING_INDICES : + case MSG_CHK_NTFS_INDEX_VERIFICATION_COMPLETED : + case MSG_CHK_NTFS_FILE_VERIFICATION_COMPLETED : + case MSG_CHK_NTFS_CHECKING_SECURITY : + case MSG_CHK_NTFS_SECURITY_VERIFICATION_COMPLETED : + case MSG_CHK_VOLUME_CLEAN : + case MSG_CHK_CHECKING_FILES : + case MSG_CHK_DONE_CHECKING : + + result = TRUE; + break; + + default: + result = FALSE; + break; + } + + return result; +} + +DEFINE_CONSTRUCTOR(AUTOCHECK_MESSAGE, MESSAGE); + + +AUTOCHECK_MESSAGE::~AUTOCHECK_MESSAGE( + ) +/*++ + +Routine Description: + + Destructor for AUTOCHECK_MESSAGE. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + Destroy(); +} + + +VOID +AUTOCHECK_MESSAGE::Construct( + ) +/*++ + +Routine Description: + + This routine initializes the object to a default initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _msgid = 0; + _logged_chars = 0; + _next_message_offset = 0; + _logging_enabled = FALSE; +} + + +VOID +AUTOCHECK_MESSAGE::Destroy( + ) +/*++ + +Routine Description: + + This routine returns the object to a default initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _msgid = 0; + _logged_chars = 0; + _next_message_offset = 0; + _logging_enabled = FALSE; +} + + +BOOLEAN +AUTOCHECK_MESSAGE::Initialize( + IN BOOLEAN DotsOnly + ) +/*++ + +Routine Description: + + This routine initializes the class to a valid initial state. + +Arguments: + + DotsOnly - Autochk should produce only dots instead of messages. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + Destroy(); + + _dots_only = DotsOnly; + + return( _log_buffer.Initialize() ); +} + + +BOOLEAN +AUTOCHECK_MESSAGE::DisplayV( + IN PCSTR Format, + IN va_list VarPointer + ) +/*++ + +Routine Description: + + This routine displays the message with the specified parameters. + + The format string supports all printf options. + +Arguments: + + Format - Supplies a printf style format string. + VarPointer - Supplies a varargs pointer to the arguments. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + CHAR buffer[256]; + DSTRING display_string; + UNICODE_STRING unicode_string; + PWSTR dis_str; + UNICODE_STRING uDot; + + RtlInitUnicodeString(&uDot, L"."); + + if (!BASE_SYSTEM::QueryResourceStringV(&display_string, _msgid, Format, + VarPointer)) { + return FALSE; + } + + if (!(dis_str = display_string.QueryWSTR())) { + return FALSE; + } + + unicode_string.Length = (USHORT)display_string.QueryChCount()*sizeof(WCHAR); + unicode_string.MaximumLength = unicode_string.Length; + unicode_string.Buffer = dis_str; + + if (!_dots_only && MSG_HIDDEN_STATUS != _msgid) { + NtDisplayString(&unicode_string); + } + + if (IsLoggingEnabled() && !IsSuppressedMessage(_msgid)) { + LogMessage(&display_string); + } + + // If we're printing dots only, we print a dot for each interesting + // message. The interesting messages are those that aren't suppressed + // except VOLUME_CLEAN and FILE_SYSTEM_TYPE, which we want to print a + // dot for regardless. + + if (_dots_only && (!IsSuppressedMessage(_msgid) || + MSG_CHK_VOLUME_CLEAN == _msgid || MSG_FILE_SYSTEM_TYPE == _msgid)) { + + NtDisplayString(&uDot); + } + + // Send the output to the debug port, too. + // + if (MSG_HIDDEN_STATUS != _msgid && + display_string.QuerySTR( 0, TO_END, buffer, 256, TRUE ) ) { + + DebugPrint( buffer ); + } + + DELETE(dis_str); + + return TRUE; +} + + +BOOLEAN +AUTOCHECK_MESSAGE::IsYesResponse( + IN BOOLEAN Default + ) +/*++ + +Routine Description: + + This routine queries a response of yes or no. + +Arguments: + + Default - Supplies a default in the event that a query is not possible. + +Return Value: + + FALSE - The answer is no. + TRUE - The answer is yes. + +--*/ +{ + PWSTR dis_str; + UNICODE_STRING unicode_string; + DSTRING string; + + if (!BASE_SYSTEM::QueryResourceString(&string, Default ? MSG_YES : MSG_NO, "")) { + return Default; + } + + if (!(dis_str = string.QueryWSTR())) { + return Default; + } + + unicode_string.Length = (USHORT)string.QueryChCount()*sizeof(WCHAR); + unicode_string.MaximumLength = unicode_string.Length; + unicode_string.Buffer = dis_str; + + NtDisplayString(&unicode_string); + + if (!IsSuppressedMessage(_msgid)) { + LogMessage(&string); + } + + DELETE(dis_str); + + return Default; +} + + +PMESSAGE +AUTOCHECK_MESSAGE::Dup( + ) +/*++ + +Routine Description: + + This routine returns a new MESSAGE of the same type. + +Arguments: + + None. + +Return Value: + + A pointer to a new MESSAGE object. + +--*/ +{ + PAUTOCHECK_MESSAGE p; + + if (!(p = NEW AUTOCHECK_MESSAGE)) { + return NULL; + } + + if (!p->Initialize()) { + DELETE(p); + return NULL; + } + + return p; +} + +BOOLEAN +AUTOCHECK_MESSAGE::IsLoggingEnabled( + ) +{ + return _logging_enabled; +} + + +VOID +AUTOCHECK_MESSAGE::ResetLoggingIterator( + ) +{ + _next_message_offset = 0; +} + + +BOOLEAN +AUTOCHECK_MESSAGE::QueryNextLoggedMessage( + OUT PFSTRING MessageText + ) +{ + PWCHAR Buffer = (PWCHAR)_log_buffer.GetBuf(); + BOOLEAN Result; + + if( _next_message_offset >= _logged_chars ) { + + // No more logged messages. + // + return FALSE; + } + + Result = (MessageText->Initialize( Buffer + _next_message_offset ) != NULL) ? + TRUE : FALSE; + + // Push _next_message_offset to the next message. Note + // that _next_message_offset is also incremented if this + // loop terminates because a zero was found, so that it + // will be one character past the next NULL character. + // + while( _next_message_offset < _logged_chars && + Buffer[_next_message_offset++] ); + + return Result; +} + + +BOOLEAN +AUTOCHECK_MESSAGE::LogMessage( + PCWSTRING Message + ) +{ + ULONG NewBufferSize; + PWCHAR Buffer; + + // The buffer must be large enough to accept this message plus + // a trailing null. To cut down the number of memory allocation + // calls, grow the buffer by 1K chunks. + // + NewBufferSize = (_logged_chars + Message->QueryChCount() + 1) * sizeof(WCHAR); + + // Don't allow the buffer to grow more than 0.5MB + // otherwise we may use up all the pages. + + if (NewBufferSize > 512000) + return FALSE; + + if( _log_buffer.QuerySize() < NewBufferSize && + !_log_buffer.Resize( (NewBufferSize + 1023)/1024 * 1024, 0x1 ) ) { + return FALSE; + } + + Buffer = (PWCHAR)_log_buffer.GetBuf(); + + // QueryWSTR will append a trailing NULL. + // + Message->QueryWSTR( 0, TO_END, + Buffer + _logged_chars, + _log_buffer.QuerySize()/sizeof(WCHAR) - _logged_chars ); + + _logged_chars += Message->QueryChCount() + 1; + + return TRUE; +} + +BOOLEAN +AUTOCHECK_MESSAGE::SetDotsOnly( + IN BOOLEAN DotsOnlyState + ) +/*++ + +Routine Description: + + This routine modifies the output mode, changing whether full + output is printed, or just dots. + +Arguments: + + DotsOnlyState - TRUE if only dots should be printed. + +Return Value: + + The previous state. + +--*/ +{ + BOOLEAN b; + + b = _dots_only; + + _dots_only = DotsOnlyState; + + if (b && !_dots_only) { + // + // Going from dots-only to full output, want to reset to the + // beginning of the next output line. + // + + Set(MSG_BLANK_LINE); + Display(); + } + return b; +} + + +VOID +AUTOCHECK_MESSAGE::SetLoggingEnabled( + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + + This routine allows a *_SA::VerifyAndFix routine to note that + there were interesting messages for a volume check. Before + autochk exits it will call the corresponding IsLoggingEnabled() + method to determine whether to save log information. + +Arguments: + + Enable - TRUE if logging should be enabled. + +Return Value: + + None. + +--*/ +{ + _logging_enabled = Enable; +} + +BOOLEAN +AUTOCHECK_MESSAGE::WaitForUserSignal( + ) +/*++ + +Routine Description: + + Open the keyboard directly and wait to read something. + +Arguments: + + None: + +Return Value: + + TRUE - Something was successfully read. + FALSE - An error occured while attempting to open or read. + +--*/ +{ + UNICODE_STRING u; + NTSTATUS Status; + IO_STATUS_BLOCK Iosb; + OBJECT_ATTRIBUTES ObjAttr; + HANDLE h; + UCHAR buf[120]; + + // + // The device we want to open is "\Device\KeyboardClass0" + // + + RtlInitUnicodeString(&u, DD_KEYBOARD_DEVICE_NAME_U L"0"); + + InitializeObjectAttributes(&ObjAttr, + &u, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtCreateFile(&h, + SYNCHRONIZE | GENERIC_READ, + &ObjAttr, + &Iosb, + NULL, /* AllocationSize */ + 0, /* FileAttributes */ + FILE_SHARE_READ|FILE_SHARE_WRITE, /* ShareAccess */ + FILE_OPEN, /* CreateDisposition */ + FILE_SYNCHRONOUS_IO_ALERT, /* CreateOptions */ + NULL, /* EaBuffer */ + 0); /* EaLength */ + + + if (!NT_SUCCESS(Status)) { + + DebugPrintf("ULIB: WaitForUserSignal: create status %x\n", Status); + return FALSE; + } + + Status = NtReadFile(h, NULL, NULL, NULL, + &Iosb, (PVOID)&buf, sizeof(buf), + NULL, NULL); + + if (!NT_SUCCESS(Status)) { + + DebugPrint("ULIB WaitForUserSignal: read status %x\n", Status); + return FALSE; + } + + return TRUE; +} + diff --git a/private/utils/ulib/src/arg.cxx b/private/utils/ulib/src/arg.cxx new file mode 100644 index 000000000..5f93094ad --- /dev/null +++ b/private/utils/ulib/src/arg.cxx @@ -0,0 +1,2707 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + argument classes + +Abstract: + + These classes implement the command line parsing for all utilities. + +Author: + + steve rowe stever 2/45/91 + +Revision History: + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +extern "C" { + #include <ctype.h> +}; + +#include "ulib.hxx" +#include "arg.hxx" +#include "array.hxx" +#include "arrayit.hxx" +#include "wstring.hxx" + +#if !defined( _AUTOCHECK_ ) + +#include "path.hxx" +#include "dir.hxx" +#include "filter.hxx" +#include "system.hxx" + +#endif + +// +// Prototypes for the matching functions +// +STATIC +BOOLEAN +Match( + OUT PARGUMENT Argument, + OUT PARGUMENT_LEXEMIZER ArgumentLexemizer, + IN BOOLEAN CaseSensitive + ); + +STATIC +BOOLEAN +TailMatch( + IN PWSTRING Pattern, + IN PWSTRING String, + IN CHNUM chn, + OUT PCHNUM chnEnd, + IN BOOLEAN CaseSensitive + ); + + + +// +// Increment size of the _CharPos array +// +#define CHARPOS_INCREMENT 64 + + + +DEFINE_EXPORTED_CONSTRUCTOR( ARGUMENT_LEXEMIZER, OBJECT, ULIB_EXPORT ); + +VOID +ARGUMENT_LEXEMIZER::Construct ( + ) +{ + _CharPos = NULL; +} + + +ULIB_EXPORT +ARGUMENT_LEXEMIZER::~ARGUMENT_LEXEMIZER ( + ) +{ + if ( _CharPos ) { + FREE( _CharPos ); + } +} + + + +ULIB_EXPORT +BOOLEAN +ARGUMENT_LEXEMIZER::Initialize ( + IN PARRAY LexemeArray + ) +/*++ + +Routine Description: + + Initialization for ARGUMENT_LEXEMIZER. ARGUMENT_LEXEMIZER holds the + container for lexed parameters from the command line. + +Arguments: + + LexemeArray - Supplies pointer to a general array container. + +Return Value: + + TRUE - If initialization succeeds + FALSE - If failed to construct the different character sets used + to lex out the argument strings. + +--*/ +{ + + DebugPtrAssert( LexemeArray ); + + // + // Initialize our counts and pointer to the array of lexemes + // + _ConsumedCount = 0; + _LexemeCount = 0; + _parray = LexemeArray; + _CharPosSize = CHARPOS_INCREMENT; + + if ( !(_CharPos = (PCHNUM)MALLOC( (unsigned int)(_CharPosSize * sizeof(CHNUM)) ))) { + return FALSE; + } + + + + // + // Setup the character sets used in lexing. + // + // Switch defines the general character used to a switch. This + // is needed to seperate /a/b into /a /b + // + // White space is all characters that are not of interest + // + // MultipleSwitches are specific switch values that can be grouped + // together under 1 switch. Appear as /a/b or /ab + // + // EscapeChars are chars that negate any special meaning of a char. + // + // StartQuote and EndQuote define the opening and closing of quoted strings + // + if ((_SwitchChars.Initialize( (PWSTR) L"/" )) && + (_WhiteSpace.Initialize( (PWSTR) L" \t")) && + (_MultipleSwitches.Initialize()) && + (_StartQuote.Initialize()) && + (_EndQuote.Initialize()) && + (_MetaChars.Initialize())) { + + // + // Separator is a combo of other characters that can terminate + // a token. + // + _Separators.Initialize(); + _SeparatorString.Initialize( &_Separators ); + _SeparatorString.Strcat(&_WhiteSpace); + _SeparatorString.Strcat(&_SwitchChars); + _SeparatorString.Strcat(&_StartQuote); + + _CaseSensitive = TRUE; + _AllowGlomming = FALSE; + _NoSpcBetweenDstAndSwitch = FALSE; + + return TRUE; + } + + // + // Something went wrong + // + return FALSE; +} + +VOID +ARGUMENT_LEXEMIZER::PutMetaChars ( + IN PCSTR MetaChars + ) +/*++ + +Routine Description: + + Initializes Meta-characters + +Arguments: + + MetaChars - Supplies pointer to string of metacharacters + +Return Value: + + none +--*/ +{ + DebugPtrAssert( MetaChars ); + _MetaChars.Initialize(MetaChars); +} + +VOID +ARGUMENT_LEXEMIZER::PutMetaChars ( + IN PCWSTRING MetaChars + ) +/*++ + +Routine Description: + + Initializes Meta-characters + +Arguments: + + MetaChars - Supplies pointer to string of metacharacters + +Return Value: + + none +--*/ +{ + DebugPtrAssert( MetaChars ); + _MetaChars.Initialize(MetaChars); +} + +ULIB_EXPORT +VOID +ARGUMENT_LEXEMIZER::PutMultipleSwitch ( + IN PCSTR MultipleSwitches + ) +/*++ + +Routine Description: + + initializes Multiple-switches + +Arguments: + + MultipleSwitches - Supplies pointer to string of multiple switches + +Return Value: + + none +--*/ +{ + DebugPtrAssert( MultipleSwitches ); + _MultipleSwitches.Initialize(MultipleSwitches); +} + +ULIB_EXPORT +VOID +ARGUMENT_LEXEMIZER::PutMultipleSwitch ( + IN PCWSTRING MultipleSwitches + ) +/*++ + +Routine Description: + + initializes Multiple-switches + +Arguments: + + MultipleSwitches - Supplies pointer to string of multiple switches + +Return Value: + + none +--*/ +{ + DebugPtrAssert( MultipleSwitches ); + _MultipleSwitches.Initialize(MultipleSwitches); +} + +ULIB_EXPORT +VOID +ARGUMENT_LEXEMIZER::PutSeparators ( + IN PCSTR Separators + ) +/*++ + +Routine Description: + + Initializes Separators + +Arguments: + + pSeparators - Supplies pointer to string of separators + +Return Value: + + none +--*/ +{ + DebugPtrAssert( Separators ); + _Separators.Initialize(Separators); + _SeparatorString.Initialize( &_Separators ); + //_SeparatorString += _WhiteSpace; + //_SeparatorString += _SwitchChars; +} + +VOID +ARGUMENT_LEXEMIZER::PutSeparators ( + IN PCWSTRING Separators + ) +/*++ + +Routine Description: + + Initializes Separators + +Arguments: + + Separators - Supplies pointer to string of separators + +Return Value: + + none +--*/ +{ + DebugPtrAssert( Separators ); + _Separators.Initialize(Separators); + _SeparatorString.Initialize( &_Separators ); + _SeparatorString.Strcat(&_WhiteSpace); + _SeparatorString.Strcat(&_SwitchChars); +} + +ULIB_EXPORT +VOID +ARGUMENT_LEXEMIZER::PutSwitches ( + IN PCSTR Switches + ) +/*++ + +Routine Description: + + Initializes Switches + +Arguments: + + Switches - Supplies pointer to string of switches + +Return Value: + + none +--*/ +{ + DebugPtrAssert( Switches ); + _SwitchChars.Initialize(Switches); + _SeparatorString.Initialize( &_Separators ); + _SeparatorString.Strcat(&_WhiteSpace); + _SeparatorString.Strcat(&_SwitchChars); +} + +ULIB_EXPORT +VOID +ARGUMENT_LEXEMIZER::PutSwitches ( + IN PCWSTRING Switches + ) +/*++ + +Routine Description: + + Initializes Switches + +Arguments: + + Switches - Supplies pointer to string of switches + +Return Value: + + none +--*/ +{ + DebugPtrAssert( Switches ); + _SwitchChars.Initialize(Switches); + _SeparatorString.Initialize( &_Separators ); + _SeparatorString.Strcat(&_WhiteSpace); + _SeparatorString.Strcat(&_SwitchChars); +} + +ULIB_EXPORT +PWSTRING +ARGUMENT_LEXEMIZER::QueryInvalidArgument ( + ) +/*++ + +Routine Description: + + Returns the lexeme tha could not be matched against any argument + +Arguments: + + none + +Return Value: + + pointer to string initialized with the offending lexeme + +--*/ +{ + PWSTRING String; + + if ( _ConsumedCount == _LexemeCount) { + // + // There was no error + // + return NULL; + } + + if ( ((String = NEW DSTRING) == NULL) || + !String->Initialize( GetLexemeAt( _ConsumedCount )) ) { + DebugAssert( FALSE ); + + DELETE( String ); + return NULL; + } + + return String; + +} + +BOOLEAN +ARGUMENT_LEXEMIZER::PutCharPos ( + IN ULONG Index, + IN CHNUM CharPos + ) +/*++ + +Routine Description: + + Puts a character position into the character position array + +Arguments: + + Index - Supplies the Index within the CharPos array + + CharPos - Supplies the character + +Return Value: + + TRUE - If done, FALSE otherwise + +--*/ + +{ + PCHNUM pTmp; + ULONG NewSize = _CharPosSize; + + if ( Index >= _CharPosSize ) { + + NewSize += CHARPOS_INCREMENT; + + if ( !(pTmp = (PCHNUM)REALLOC( _CharPos, (unsigned int)(NewSize * sizeof(CHNUM)) ))) { + return FALSE; + } + + _CharPos = pTmp; + _CharPosSize = NewSize; + } + + _CharPos[ Index ] = CharPos; + + return TRUE; +} + + + +ULIB_EXPORT +BOOLEAN +ARGUMENT_LEXEMIZER::PrepareToParse ( + IN PWSTRING CommandLine + ) +/*++ + +Routine Description: + + Lexes command line into strings and puts in array container held + with object. + +Arguments: + + CommandLine - Supplies command line + +Return Value: + + TRUE - If Command line lex'd correctly + FALSE - If error in lexing. FALSE will be returned if there are + quote characters defined and the user types a command line with + an open quote without a corresponding close quote. + +--*/ + +{ + PWSTRING pEndSet; // End Set for token + PWSTRING pCur; // Current token + PWSTRING pTmp; // Temporary string + CHNUM chnStart; // Start of token + CHNUM chnEnd; // End of token + CHNUM SwitchAt; // Switch character position + CHNUM SwitchSpan; // Switches expand up to this position + CHNUM QuoteOffset; // Offset of beg. quote char in _StartQuote + WCHAR EndQuoteChar; // end of quote char + CHNUM NextMeta; + CHNUM NextSeparator; + + + if ( CommandLine == NULL ) { + +#if defined( _AUTOCHECK_ ) + + return FALSE; +#else + if (!_CmdLine.Initialize( GetCommandLine() )) { + DebugAssert( FALSE ); + return FALSE; + } +#endif + + } else { + + if (!_CmdLine.Initialize( CommandLine )) { + DebugAssert( FALSE ); + return FALSE; + } + } + + chnStart = 0; + + // + // Set _Switch to any permissible switch character + // + DebugAssert( _SwitchChars.QueryChCount() > 0 ); + _Switch = _SwitchChars.QueryChAt( 0 ); + + // + // If we are case-insensitive, then we expand our multiple switches + // to include lower and upper case. + // + if (!_CaseSensitive && _MultipleSwitches.QueryChCount() > 0) { + + pTmp = NEW DSTRING; + + _MultipleSwitches.Strupr(); + + pTmp->Initialize(&_MultipleSwitches); + pTmp->DeleteChAt(0); + pTmp->Strlwr(); + _MultipleSwitches.Strcat(pTmp); + + DELETE( pTmp ); + } + + // + // Loop till Command line is exhausted of tokens. + // + while ( TRUE ) { + + // + // move to first character not part of white space. This will + // always be the case for the start char. position since lexing + // will always be interested in anything that is not white space. + // + chnStart = _CmdLine.Strspn( &_WhiteSpace, chnStart ); + + // + // Check of any tokens left to lex. Note that we have to + // recheck the actual char. count each time through since + // we may have deleted meta characters + // + if (chnStart == INVALID_CHNUM) { + + // + // Have exhausted the command line of tokens. Get out of here + // + break; + } + + // + // if escape character, skip it and try again + // + if (_MetaChars.Strchr( _CmdLine.QueryChAt( chnStart)) != INVALID_CHNUM) { + + chnStart++; + continue; + } + + // + // we've skipped over the leading whitespace so we're at the + // beginning of the token. + // + chnEnd = chnStart; + + if ( chnEnd < _CmdLine.QueryChCount() ) { + + pEndSet = &_SeparatorString; + + while ( chnEnd < _CmdLine.QueryChCount() ) { + + // if the current character is a separator and not + // the first character in the token, we're done. + // It can also be that there is no space between switches + if( chnEnd != chnStart && + ((_SeparatorString.Strchr(_CmdLine.QueryChAt(chnEnd)) != INVALID_CHNUM) || + (_NoSpcBetweenDstAndSwitch && + (_SwitchChars.Strchr(_CmdLine.QueryChAt(chnEnd)) != INVALID_CHNUM) && + ((chnEnd+1) < _CmdLine.QueryChCount()) && + !isdigit(_CmdLine.QueryChAt(chnEnd+1))))) { + + // If this token so far is two consecutive separators, + // keep going. Otherwise, it's the end of the token. + // + if( chnStart + 1 == chnEnd && + (_SwitchChars.Strchr( _CmdLine.QueryChAt( chnStart ) ) != INVALID_CHNUM ) && + (_SwitchChars.Strchr( _CmdLine.QueryChAt( chnEnd ) ) != INVALID_CHNUM ) ) { + + chnEnd++; + continue; + } + + break; + } + + // if the current character is a meta character, delete + // the meta character and accept the following character + // without reservation. + // + if( _MetaChars.Strchr( _CmdLine.QueryChAt(chnEnd) ) != INVALID_CHNUM ) { + + _CmdLine.DeleteChAt(chnEnd); + + if( chnEnd < _CmdLine.QueryChCount() ) { + chnEnd++; + } + continue; + } + + // if the current character is a start-quote, accept everything + // until an end-quote is found (or we run out of string). + // + if( (QuoteOffset = _StartQuote.Strchr( _CmdLine.QueryChAt(chnEnd) )) != INVALID_CHNUM ) { + + // + // Set the end of quote char to the corresponding char in + // the _EndQuote string. (ie. if the opening quote char + // is the first char in _StartQuote then use the first + // char in _EndQuote) + // + EndQuoteChar = _EndQuote.QueryChAt(QuoteOffset); + chnEnd++; + + while( TRUE ) { + // + // locate potential end of token by looking for the + // EndQuoteChar. + // + // check if next char is the EndQuoteChar--if it is, + // then the user is 'quoting' the endquotechar, so + // remove the 'quoting' char. Otherwise, this is + // the end of the quoted string. + // + if( (chnEnd = _CmdLine.Strchr(EndQuoteChar, chnEnd )) + != INVALID_CHNUM ) { + + // + // bump up chnEnd to check the character + // after the quote char. If it's another + // quote char then, delete the first quote. + // Otherwise, we're at the end of the quoted + // string. + // + if( _CmdLine.QueryChAt(++chnEnd) == EndQuoteChar ) { + + _CmdLine.DeleteChAt(chnEnd - 1); + continue; + + } else { + + break; + } + + } else { + + // + // we reached the end of the string w/o finding the + // endQuoteChar (chnEnd == INVALID_CHNUM) + // + // return FALSE because an open quote is being + // considered a lex error because this is easier and + // does what is required. If someone wants to + // handle quote characters they could change this + // by setting chnEnd to the last char of the first + // token, ignoring the quote. eg: if cmd line was + // cmd "arg1 arg2 arg3 + // + // chnEnd could be set to the position of '1'. + // + return FALSE; + + } + } + + // Keep accepting characters. + // + continue; + } + + // It's not a separator, a meta-character, or a start quote; + // accept it. + // + chnEnd++; + } + } + + + // + // we have a valid token to put in string array. + // + if ((pCur = _CmdLine.QueryString(chnStart, chnEnd - chnStart)) == NULL) { + + // + // Could not create a new substring. Error out. + // + return FALSE; + } + + SwitchSpan = pCur->Strspn( &_MultipleSwitches, 1 ); + + // + // Ramonsa - We must not replace the original switch character used, + // because if we do then we won't be able to retrieve it. + // + //if ((SwitchAt = _SwitchChars.Strchr( pCur->QueryChAt(0))) != INVALID_CHNUM ) { + // + // // + // // The first character is a switch + // // + // pCur->SetChAt( _Switch, 0); + // + // + //} + SwitchAt = _SwitchChars.Strchr( pCur->QueryChAt(0) ); + + // + // Check for multiple switch arguments by seeing if any of the + // characters in the token are not in the multiple switch set. + // Also, if the token is only one character then it can't be + // multiple switches. + if (( SwitchAt == INVALID_CHNUM ) || + ( SwitchSpan != INVALID_CHNUM ) || + pCur->QueryChCount() == 1) { + + // + // Non-multiple characters were found, throw the entire + // thing into the string array container + // + + if (!_parray->Put( pCur ) || + !PutCharPos( _LexemeCount, chnStart ) + ) { + + // + // Error out we could not insert the value + // + return FALSE; + + } else { + + // + // Setup to fetch next token and go to outer loop + // + _LexemeCount++; + chnStart = chnEnd; + continue; + } + + } else { + + // + // All characters in the string are multiple switches. + // + for ( CHNUM chn = 1; chn < pCur->QueryChCount(); chn++ ) { + + // + // If glomming is allowed then we want to handle pCur when + // it looks like "/s/f/i/d" by splitting up each argument. + // We skip over the slashes and treat this string the same + // as "/sfid". (See arg.hxx at "GLOMMING".) + // + + if (_AllowGlomming && chn >= 2 && + pCur->QueryChAt(chn) == pCur->QueryChAt(0)) { + continue; + } + + // + // Pull out a switch and put in new switch string. + // + pTmp = NEW DSTRING(); + + pTmp->Initialize((PWSTR) L" "); + + pTmp->SetChAt( pCur->QueryChAt(0), 0 ); + pTmp->SetChAt( pCur->QueryChAt(chn), 1 ); + + if (!_parray->Put( pTmp ) || + !PutCharPos( _LexemeCount, chnStart ) + ) { + + // + // ERROR out we could not put the token + // + DELETE( pTmp ); + return FALSE; + + } else { + + _LexemeCount++; + } + } + + // + // pCur not needed anymore + // + DELETE( pCur ); + + // + // Setup to fetch next token and go to outer loop + // + chnStart = chnEnd; + continue; + } + } + + return TRUE; +} + +ULIB_EXPORT +BOOLEAN +ARGUMENT_LEXEMIZER::DoParsing ( + IN PARRAY ArgumentArray + ) +/*++ + +Routine Description: + + Parses the arguments passed. + +Arguments: + + ArgumentArray - Supplies pointer to array of arguments to set + + +Return Value: + + TRUE if all argument strings matched + FALSE otherwise. + + +--*/ +{ + + PARRAY_ITERATOR Iterator; + PARGUMENT arg; + BOOLEAN DoAgain = TRUE; + + DebugPtrAssert( ArgumentArray ); + + while (DoAgain) { + + DoAgain = FALSE; + + Iterator = (PARRAY_ITERATOR)ArgumentArray->QueryIterator(); + + DebugAssert( Iterator ); + + if ( Iterator ) { + + arg = (PARGUMENT)Iterator->GetNext(); + + while( arg ) { + + // + // Check that the argument hasn't already found its + // match. + // + if (!arg->IsValueSet()) { + + // + // If the first character of the pattern is a switch, + // we change the switch character. + // + if (( _SwitchChars.Strchr(arg->GetPattern()->QueryChAt(0))) != INVALID_CHNUM) { + + arg->GetPattern()->SetChAt( _Switch, 0); + + } + + // + // Try to match it + // + if (arg->SetIfMatch( this, _CaseSensitive )) { + + // + // Found a match, start over with first argument + // if there are more lexemes to match. + // + DoAgain = (BOOLEAN)( _ConsumedCount != _LexemeCount ); + + break; + } + } + + arg = (PARGUMENT)Iterator->GetNext(); + } + + DELETE( Iterator ); + } + } + + return ( _ConsumedCount == _LexemeCount ); +} + +ULIB_EXPORT +PWSTRING +ARGUMENT_LEXEMIZER::GetLexemeAt ( + IN ULONG Index + ) +/*++ + +Routine Description: + + Gets the Lexeme at the specified index + +Arguments: + + Index - Supplies the index of the lexeme desired + +Return Value: + + Pointer to the lexeme + +--*/ +{ + return (PWSTRING)_parray->GetAt(Index); +} + + +CHNUM +ARGUMENT_LEXEMIZER::QueryCharPos ( + IN ULONG LexemeNumber + ) +/*++ + +Routine Description: + + Queries the character position of a particular lexeme + +Arguments: + + LexemeNumber - Supplies the lexeme number + +Return Value: + + Returns the character position of the lexeme + +--*/ +{ + DebugAssert( LexemeNumber < _LexemeCount ); + DebugAssert( LexemeNumber < _CharPosSize ); + + return _CharPos[ LexemeNumber ]; +} + + +ULIB_EXPORT +VOID +ARGUMENT_LEXEMIZER::SetCaseSensitive ( + IN BOOLEAN CaseSensitive + ) +/*++ + +Routine Description: + + Sets case sensitivity ON/OFF + +Arguments: + + CaseSensitive - Supplies case sensitivity flag + +Return Value: + + none + +--*/ +{ + _CaseSensitive = CaseSensitive; +} + + +ULIB_EXPORT +VOID +ARGUMENT_LEXEMIZER::SetAllowSwitchGlomming ( + IN BOOLEAN AllowGlomming + ) +/*++ + +Routine Description: + + Sets whether swith glomming (as in "/s/f/i/d") is allowed + or not. See note in <arg.hxx> at "GLOMMING". + +Arguments: + + AllowGlomming - Supplies glomming allowed flag. + +Return Value: + + none + +--*/ +{ + _AllowGlomming = AllowGlomming; +} + + +ULIB_EXPORT +VOID +ARGUMENT_LEXEMIZER::SetNoSpcBetweenDstAndSwitch ( + IN BOOLEAN NoSpcBetweenDstAndSwitch + ) +/*++ + +Routine Description: + + Sets whether a separator is required between + tokens. This is specifically for xcopy that + a space should not be required to separate the + destination and the specified options. + +Arguments: + + NoSpcBetweenDstAndSwitch - Supplies the flag + +Return Value: + + none + +--*/ +{ + _NoSpcBetweenDstAndSwitch = NoSpcBetweenDstAndSwitch; +} + + +DEFINE_CONSTRUCTOR( ARGUMENT, OBJECT ); + +VOID +ARGUMENT::Construct ( + ) +{ + UNREFERENCED_PARAMETER( (void)this); + _Lexeme = NULL; +} + +BOOLEAN +ARGUMENT::Initialize ( + IN PSTR Pattern + ) +/*++ + +Routine Description: + + Create an ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + // + // Make sure that we have an associated pattern + // + DebugAssert(Pattern); + + // + // Initially we don't have a value + // + _fValueSet = FALSE; + + // + // Initialize the pattern + // + return _Pattern.Initialize(Pattern); +} + +BOOLEAN +ARGUMENT::Initialize ( + IN PWSTRING Pattern + ) +/*++ + +Routine Description: + + Create an ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + // + // Make sure that we have an associated pattern + // + DebugAssert(Pattern); + + // + // Initially we don't have a value + // + _fValueSet = FALSE; + + // + // Initialize the pattern + // + return _Pattern.Initialize(Pattern); +} + +ULIB_EXPORT +PWSTRING +ARGUMENT::GetLexeme ( + ) +/*++ + +Routine Description: + + Gets the lexeme matched by this Argument. + +Arguments: + + none + +Return Value: + + Pointer to Lexeme + +--*/ +{ + //DebugAssert( _fValueSet ); + + return _Lexeme; +} + +ULIB_EXPORT +PWSTRING +ARGUMENT::GetPattern ( + ) +/*++ + +Routine Description: + + Gets the pattern associated with this Argument. + +Arguments: + + none + +Return Value: + + Pointer to pattern + +--*/ +{ + return &_Pattern; +} + +BOOLEAN +ARGUMENT ::SetIfMatch( + OUT PARGUMENT_LEXEMIZER ArgumentLexemizer, + IN BOOLEAN CaseSensitive + ) +/*++ + +Routine Description: + + Determines if the current argument string is recognized by + this ARGUMENT object, and setst the value if there is a match. + +Arguments: + + ArgumentLexemizer - Supplies container holding command line + lex'd into strings + CaseSensitive - Supplies case sensitivity flag + +Return Value: + + TRUE - argument recognized and value set. + FALSE - argument not recognized and/or value not set. + +--*/ +{ + // + // Match will try to match the current argument pattern (Pattern) + // with one of the string from the lexemizer. If a match occurs + // then it will callback through the this pointer passed to + // the SetValue routine for this argument object. + // + return Match( this, ArgumentLexemizer, CaseSensitive ); +}; + +ULIB_EXPORT +BOOLEAN +ARGUMENT::IsValueSet ( + ) +/*++ + +Routine Description: + + Checks if the argument has been found and set. + + This method is used to determine if the ARGUMENT object has had + its value set without having to know what type of ARGUMENT object + it is. This is used mainly in ARGUMENT_LIST to avoid repeated calling + IsArgument once the argument has been recognized and the value + set. + +Arguments: + +Return Value: + + TRUE - if value has already been set. + FALSE - if the value has not been set and it is ok to call IsArgument + +--*/ +{ + return _fValueSet; +}; + +BOOLEAN +ARGUMENT::SetValue( + IN PWSTRING Arg, + IN CHNUM chnIdx, + IN CHNUM chnEnd, + IN PARGUMENT_LEXEMIZER ArgumentLexemizer + ) +/*++ + +Routine Description: + + Default method for setting the value of an argument. Sets + fValueSet to false. + +Arguments: + + Arg - Supplies current argument string + chnIdx - Supplies index within Arg + ArgumentLexemizer - Supplies list of lexed strings + +Return Value: + + FALSE + +--*/ +{ + + UNREFERENCED_PARAMETER( this ); + UNREFERENCED_PARAMETER( (void)Arg ); + UNREFERENCED_PARAMETER( (void)chnIdx ); + UNREFERENCED_PARAMETER( (void)ArgumentLexemizer ); + UNREFERENCED_PARAMETER( (void)chnEnd ); + + + return _fValueSet = FALSE ; +} + + + + + + + + +DEFINE_EXPORTED_CONSTRUCTOR( FLAG_ARGUMENT, ARGUMENT, ULIB_EXPORT); + +VOID +FLAG_ARGUMENT::Construct ( + ) +{ + UNREFERENCED_PARAMETER( this ); +} + +ULIB_EXPORT +BOOLEAN +FLAG_ARGUMENT::Initialize ( + IN PSTR Pattern + ) +/*++ + +Routine Description: + + Create a FLAG_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + // + // Set our initial value + // + _flag = FALSE; + + // + // Initialize the pattern + // + return ARGUMENT::Initialize(Pattern); + +} + +ULIB_EXPORT +BOOLEAN +FLAG_ARGUMENT::Initialize ( + IN PWSTRING Pattern + ) +/*++ + +Routine Description: + + Create a FLAG_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + // + // Set our initial value + // + _flag = FALSE; + + // + // Initialize the pattern + // + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +FLAG_ARGUMENT::SetValue( + IN PWSTRING Arg, + IN CHNUM chnIdx, + IN CHNUM chnEnd, + IN PARGUMENT_LEXEMIZER ArgumentLexemizer + ) +/*++ + +Routine Description: + + Sets the flag to TRUE + +Arguments: + + Arg - Supplies current argument string + chnIdx - Supplies index within Arg + ArgumentLexemizer - Supplies list of lexed strings + +Return Value: + + FALSE + +--*/ +{ + + UNREFERENCED_PARAMETER( this ); + UNREFERENCED_PARAMETER( (void)Arg ); + UNREFERENCED_PARAMETER( (void)chnIdx ); + UNREFERENCED_PARAMETER( (void)ArgumentLexemizer ); + + _Lexeme = Arg; + return _flag = _fValueSet = TRUE; + +} + + + +DEFINE_EXPORTED_CONSTRUCTOR( STRING_ARGUMENT, ARGUMENT, ULIB_EXPORT); + +VOID +STRING_ARGUMENT::Construct ( + ) +{ + _String = NULL; +} + +ULIB_EXPORT +STRING_ARGUMENT::~STRING_ARGUMENT ( + ) +/*++ + +Routine Description: + + Destructor for String Arguments + +Arguments: + + +Return Value: + + none + +--*/ +{ + DELETE( _String ); +} + +ULIB_EXPORT +BOOLEAN +STRING_ARGUMENT::Initialize ( + IN PSTR Pattern + ) +/*++ + +Routine Description: + + Create a FLAG_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + // + // Set our initial value + // + _String = NULL; + + // + // Initialize the pattern + // + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +STRING_ARGUMENT::Initialize ( + IN PWSTRING Pattern + ) +/*++ + +Routine Description: + + Create a FLAG_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + // + // Set our initial value + // + _String = NULL; + + // + // Initialize the pattern + // + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +STRING_ARGUMENT::SetValue( + IN PWSTRING Arg, + IN CHNUM chnIdx, + IN CHNUM chnEnd, + IN PARGUMENT_LEXEMIZER ArgumentLexemizer + ) + +/*++ + +Routine Description: + + Sets the value of a STRING_ARGUMENT argument + +Arguments: + + Arg - Supplies current argument string + chnIdx - Supplies index within Arg + ArgumentLexemizer - Supplies list of lexed strings + +Return Value: + + TRUE if value set + FALSE otherwise + +--*/ +{ + + DebugPtrAssert( Arg ); + + _fValueSet = FALSE; + + DebugAssert( Arg->QueryChCount() >= chnEnd ); + + if ((_String=Arg->QueryString(chnIdx, chnEnd - chnIdx )) != NULL) { + ArgumentLexemizer->IncrementConsumedCount( ); + + _Lexeme = Arg; + _fValueSet = TRUE; + } + + return _fValueSet; +} + + + + + + +DEFINE_EXPORTED_CONSTRUCTOR( LONG_ARGUMENT, ARGUMENT, ULIB_EXPORT); + +VOID +LONG_ARGUMENT::Construct ( + ) +{ + UNREFERENCED_PARAMETER( this ); +} + +ULIB_EXPORT +BOOLEAN +LONG_ARGUMENT::Initialize ( + IN PSTR Pattern + ) +/*++ + +Routine Description: + + Create a FLAG_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + // + // Set our initial value + // + _value = 0; + + // + // Initialize the pattern + // + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +LONG_ARGUMENT::Initialize ( + IN PWSTRING Pattern + ) +/*++ + +Routine Description: + + Create a FLAG_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + // + // Set our initial value + // + _value = 0; + + // + // Initialize the pattern + // + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +LONG_ARGUMENT::SetValue ( + IN PWSTRING Arg, + IN CHNUM chnIdx, + IN CHNUM chnEnd, + IN PARGUMENT_LEXEMIZER ArgumentLexemizer + ) + +/*++ + +Routine Description: + + Sets the value of a LONG_ARGUMENT argument + +Arguments: + + Arg - Supplies current argument string + chnIdx - Supplies index within Arg + ArgStrings - Supplies list of lexed strings + +Return Value: + + TRUE if value set + FALSE otherwise + +--*/ +{ + DebugPtrAssert( Arg ); + + DebugAssert( Arg->QueryChCount() >= chnEnd ); + + if ( Arg->QueryNumber( &_value, chnIdx, chnEnd - chnIdx )) { + ArgumentLexemizer->IncrementConsumedCount(); + + _Lexeme = Arg; + return _fValueSet = TRUE; + } + + return FALSE; +} + + + +#if !defined( _AUTOCHECK_ ) + + + +DEFINE_EXPORTED_CONSTRUCTOR( TIMEINFO_ARGUMENT, ARGUMENT, ULIB_EXPORT); + +VOID +TIMEINFO_ARGUMENT::Construct ( + ) +{ + UNREFERENCED_PARAMETER( this ); +} + +ULIB_EXPORT +TIMEINFO_ARGUMENT::~TIMEINFO_ARGUMENT ( + ) +/*++ + +Routine Description: + + Destructor for Timeinfo Arguments + +Arguments: + + +Return Value: + + none + +--*/ +{ + DELETE( _TimeInfo ); +} + +ULIB_EXPORT +BOOLEAN +TIMEINFO_ARGUMENT::Initialize ( + IN PSTR Pattern + ) +/*++ + +Routine Description: + + Create a TIMEINFO_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + _TimeInfo = NULL; + + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +TIMEINFO_ARGUMENT::Initialize ( + IN PWSTRING Pattern + ) +/*++ + +Routine Description: + + Create a TIMEINFO_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with command line + parameter + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + _TimeInfo = NULL; + + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +TIMEINFO_ARGUMENT::SetValue ( + IN PWSTRING Arg, + IN CHNUM chnIdx, + IN CHNUM chnEnd, + IN PARGUMENT_LEXEMIZER ArgumentLexemizer + ) + +/*++ + +Routine Description: + + Sets the value of a TIMEINFO_ARGUMENT argument + +Arguments: + + Arg - Supplies current argument string + chnIdx - Supplies index within Arg + ArgStrings - Supplies list of lexed strings + +Return Value: + + TRUE if value set + FALSE otherwise + +--*/ +{ + + DSTRING String; + + DebugPtrAssert( Arg ); + + if ( ( Arg) && + String.Initialize( Arg, chnIdx, chnEnd - chnIdx ) && + ((_TimeInfo = NEW TIMEINFO) != NULL) && + _TimeInfo->Initialize() && + _TimeInfo->SetDateAndTime( &String ) ) { + + ArgumentLexemizer->IncrementConsumedCount(); + + _Lexeme = Arg; + return _fValueSet = TRUE; + } + + return FALSE; +} + +#endif // _AUTOCHECK_ + + +#if !defined( _AUTOCHECK_ ) + +DEFINE_EXPORTED_CONSTRUCTOR( PATH_ARGUMENT, ARGUMENT, ULIB_EXPORT); + +VOID +PATH_ARGUMENT::Construct ( + ) +{ + _Path = NULL; +} + +ULIB_EXPORT +PATH_ARGUMENT::~PATH_ARGUMENT( + ) +/*++ + +Routine Description: + + Destructor for Path Arguments + +Arguments: + + none + +Return Value: + + none + +--*/ +{ + Destroy(); +} + +VOID +PATH_ARGUMENT::Destroy( + ) +/*++ + +Routine Description: + + Destroys a path argument + +Arguments: + + none + +Return Value: + + none + +--*/ +{ + DELETE( _Path ); +} + +ULIB_EXPORT +BOOLEAN +PATH_ARGUMENT::Initialize ( + IN PSTR Pattern, + IN BOOLEAN Canonicalize + ) +/*++ + +Routine Description: + + Create a PATH_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with + command line parameter + Canonicalize - Supplies the canonicalization flag + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + // + // Destroy the path, in case we are re-initializing + // + Destroy(); + + _Canonicalize = Canonicalize; + + // + // Initialize the pattern + // + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +PATH_ARGUMENT::Initialize ( + IN PWSTRING Pattern, + IN BOOLEAN Canonicalize + ) +/*++ + +Routine Description: + + Create a PATH_ARGUMENT object and setup for parsing + +Arguments: + + Pattern - Supplies string used in matching argument with + command line parameter + Canonicalize - Supplies the canonicalization flag + +Return Value: + + TRUE - If arg. initialized. + FALSE - If failed to initialize. + +--*/ +{ + + // + // Destroy the path, in case we are re-initializing + // + Destroy(); + + _Canonicalize = Canonicalize; + + // + // Initialize the pattern + // + return ARGUMENT::Initialize(Pattern); + +} + +BOOLEAN +PATH_ARGUMENT::SetValue( + IN PWSTRING Arg, + IN CHNUM chnIdx, + IN CHNUM chnEnd, + IN PARGUMENT_LEXEMIZER ArgumentLexemizer + ) +/*++ + +Routine Description: + + Sets the value of a PATH_ARGUMENT argument + +Arguments: + + Arg - Supplies current argument string + chnIdx - Supplies index within Arg + ArgumentLexemizer - Supplies list of lexed strings + +Return Value: + + TRUE if value set + FALSE otherwise + +--*/ +{ + + PWSTRING pT; + + DebugPtrAssert( Arg ); + + + _fValueSet = FALSE; + + DebugAssert( Arg->QueryChCount() >= chnEnd ); + + pT = Arg->QueryString(chnIdx, chnEnd - chnIdx); + + if (NULL != pT) { + + // + // Remove double quotes from the path string. We assume + // that there will never be a valid double-quote in an + // actual path. + // + + for (ULONG i = 0; i < pT->QueryChCount(); ++i) { + if ('\"' == pT->QueryChAt(i)) { + pT->DeleteChAt(i); + i--; + continue; + } + } + + if( (_Path = NEW PATH) != NULL) { + if ( _Path->Initialize( pT, _Canonicalize )) { + + // + // check the first char to see if it's a switch char + // (it can't be if it's a path) + // + if( (ArgumentLexemizer->GetSwitches()->Strchr(pT->QueryChAt(0)) + == INVALID_CHNUM) ) { + ArgumentLexemizer->IncrementConsumedCount(); + + _Lexeme = Arg; + _fValueSet = TRUE; + } + + } else { + + DebugAssert( FALSE ); + DELETE( _Path ); + } + } + + DELETE( pT ); + + } + + return _fValueSet; +} + + +#endif // _AUTOCHECK_ + + + +#if !defined( _AUTOCHECK_ ) + + +DEFINE_EXPORTED_CONSTRUCTOR( MULTIPLE_PATH_ARGUMENT, PATH_ARGUMENT, ULIB_EXPORT); + +VOID +MULTIPLE_PATH_ARGUMENT::Construct ( + ) +{ + _PathArray = NULL; +} + +ULIB_EXPORT +MULTIPLE_PATH_ARGUMENT::~MULTIPLE_PATH_ARGUMENT( + ) + +/*++ + +Routine Description: + + Destructor for Path Arguments + +Arguments: + + none + + +Return Value: + + none + +--*/ + +{ + Destroy(); +} + +VOID +MULTIPLE_PATH_ARGUMENT::Destroy( + ) + +/*++ + +Routine Description: + + Destroys a multiple-path argument + +Arguments: + + none + + +Return Value: + + none + +--*/ + +{ + DELETE( _PathArray ); +} + +ULIB_EXPORT +BOOLEAN +MULTIPLE_PATH_ARGUMENT::Initialize ( + IN PSTR Pattern, + IN BOOLEAN Canonicalize, + IN BOOLEAN ExpandWildCards + ) +/*++ + +Routine Description: + + Initializes a MULTIPLE_PATH_ARGUMENT + +Arguments: + + Pattern - Supplies the argument pattern + Canonicalize - Supplies canonicalization flag + ExpandWildCards - Supplies wildcard expansion flag + +Return Value: + + TRUE if correctly initialized + FALSE otherwise + +--*/ + +{ + + // + // Destroy, in case we are re-initializing + // + Destroy(); + + // + // Initialize the argument + // + if (PATH_ARGUMENT::Initialize( Pattern, Canonicalize ) ) { + + // + // Argument correctly initialized, create our array object + // + if ((_PathArray = NEW ARRAY) != NULL) { + + // + // Ok, so initialize it + // + if (_PathArray->Initialize() ) { + + // + // Everything's cool + // + _PathCount = 0; + _ExpandWildCards = ExpandWildCards; + _WildCardExpansionFailed = FALSE; + return TRUE ; + } + + DELETE( _PathArray ); + } + } + + return FALSE; +} + +BOOLEAN +MULTIPLE_PATH_ARGUMENT::Initialize ( + IN PWSTRING Pattern, + IN BOOLEAN Canonicalize, + IN BOOLEAN ExpandWildCards + ) +/*++ + +Routine Description: + + Initializes a MULTIPLE_PATH_ARGUMENT + +Arguments: + + Pattern - Supplies the argument pattern + Canonicalize - Supplies canonicalization flag + ExpandWildCards - Supplies wildcard expansion flag + +Return Value: + + TRUE if correctly initialized + FALSE otherwise + +--*/ + +{ + // + // Destroy, in case we are re-initializing + // + Destroy(); + + // + // Initialize the argument + // + if (PATH_ARGUMENT::Initialize( Pattern, Canonicalize ) ) { + + // + // Argument correctly initialized, create our array object + // + if ((_PathArray = NEW ARRAY) != NULL) { + + // + // Ok, so initialize it + // + if (_PathArray->Initialize() ) { + + // + // Everything's cool + // + _PathCount = 0; + _ExpandWildCards = ExpandWildCards; + _WildCardExpansionFailed = FALSE; + return TRUE ; + } + + DELETE( _PathArray ); + } + } + + return FALSE; +} + +BOOLEAN +MULTIPLE_PATH_ARGUMENT::SetValue ( + IN PWSTRING pwcArg, + IN CHNUM chnIdx, + IN CHNUM chnEnd, + IN PARGUMENT_LEXEMIZER ArgumentLexemizer + ) +/*++ + +Routine Description: + + Sets the value of a MULTIPLE_PATH_ARGUMENT argument + +Arguments: + + pwcArg - Supplies current argument string + chnIdx - Supplies index within pwcArg + ArgumentLexemizer - Supplies list of lexed strings + +Return Value: + + TRUE if value set + FALSE otherwise + +--*/ +{ + + PPATH FullPath = NULL; + PWSTRING TmpName = NULL; + PFSN_DIRECTORY Directory = NULL; + PARRAY NodeArray = NULL; + PARRAY_ITERATOR Iterator = NULL; + PFSNODE Node; + PPATH Path; + CHNUM BaseLength; + DSTRING Name; + FSN_FILTER Filter; + CHNUM PrefixLength; + BOOLEAN Ok = FALSE; + + DebugPtrAssert( _PathArray ); + + // + // Try to set the path value + // + if (PATH_ARGUMENT::SetValue(pwcArg, chnIdx, chnEnd, ArgumentLexemizer)) { + + // + // If we have to expand wildcards, we get an array of paths and put + // the elements in our array, otherwise we just put the path that we + // have. + // + if ( _ExpandWildCards && PATH_ARGUMENT::_Path->HasWildCard() ) { + + // + // Expand the path that we have, remember its name portion + // and truncate it so that we are left with a directory + // path. Then get a directory object from the path and a filter + // for the wildcard. + // + // Then do the wildcard expansion. + // + if ( ( FullPath = PATH_ARGUMENT::_Path->QueryFullPath() ) && + ( TmpName = FullPath->QueryName() ) && + Name.Initialize( TmpName ) && + FullPath->TruncateBase() && + (Directory = SYSTEM::QueryDirectory( FullPath )) && + Filter.Initialize() && + Filter.SetFileName( &Name ) && + ( NodeArray = Directory->QueryFsnodeArray( &Filter )) && + ( Iterator = (PARRAY_ITERATOR)NodeArray->QueryIterator() ) + ) { + + Ok = TRUE; + + + // + // If no files matched the wildcard, we remember the pattern + // and set the failure flag. + // + if ( !_WildCardExpansionFailed && + (NodeArray->QueryMemberCount() == 0 ) ) { + + _WildCardExpansionFailed = TRUE; + _LexemeThatFailed.Initialize( pwcArg ); + + } else { + + // + // Now that we have done the wildcard expansion, extract + // all the paths and put them in our array + // + while ( Node = (PFSNODE)Iterator->GetNext() ) { + + Path = NULL; + + DELETE( TmpName ); + + if ( (Path = NEW PATH) && + Path->Initialize( PATH_ARGUMENT::_Path ) && + Path->TruncateBase() && + (TmpName = ((PPATH) Node->GetPath())->QueryName()) && + Path->AppendBase( TmpName ) && + _PathArray->Put( Path ) + ) { + + DELETE( TmpName ); + + _PathCount++; + + } else { + + DELETE( Path ); + Ok = FALSE; + break; + + } + } + } + + DELETE( TmpName ); + DELETE( FullPath ); + DELETE( Directory ); + DELETE( Iterator ); + if ( NodeArray ) { + NodeArray->DeleteAllMembers(); + } + DELETE( NodeArray ); + DELETE( FullPath ); + } + + + } else { + + if (_PathArray->Put(PATH_ARGUMENT::_Path)) { + + _PathCount++; + + Ok = TRUE; + + } + } + + // + // We reset the _fValueSet flag, because we can + // always take another path. + // + ARGUMENT::_fValueSet = FALSE; + } + + return Ok; +} + + +#endif // _AUTOCHECK_ + + + +// +// Macro for handling case-sensitivity +// +#define CASESENS(c) ( CaseSensitive ? (c) : towupper((c)) ) + +STATIC +BOOLEAN +Match( + OUT PARGUMENT Argument, + OUT PARGUMENT_LEXEMIZER ArgumentLexemizer, + IN BOOLEAN CaseSensitive + ) +/*++ + +Routine Description: + + Tries to match a pattern, and if there is a match it + sets the value of the corresponding argument. + +Arguments: + + Argument - Supplies pointer to argument + ArgumentLexemizer - Supplies pointer to lexed string list + CaseSensitive - Supplies case sensitivity flag + +Return Value: + + TRUE - argument recognized and value set. + FALSE - argument not recognized and/or value not set. + +--*/ +{ + + BOOLEAN fFound; + CHNUM chnCurrent = 0; + CHNUM chnEnd = 0; + PWSTRING Lexeme; + PWSTRING Pattern; + CHNUM chn; + + + if (!(Lexeme = ArgumentLexemizer->GetLexemeAt( ArgumentLexemizer->QueryConsumedCount()))) { + return FALSE; + } + + Pattern = Argument->GetPattern(); + + fFound = FALSE; + + // + // If first character in the pattern is a switch, see if the + // first character in the Lexeme is also a switch. + // + if ( Pattern->QueryChCount() > 0 && + Lexeme->QueryChCount() > 0 && + ArgumentLexemizer->GetSwitches()->Strchr( Pattern->QueryChAt(0)) != INVALID_CHNUM ) { + + if ( ArgumentLexemizer->GetSwitches()->Strchr( Lexeme->QueryChAt(0)) != INVALID_CHNUM ) { + // + // Switch, advance pointer + // + chn = 1; + + } else { + // + // No switch, no match + // + return FALSE; + } + + } else { + // + // This is not a switch pattern, match from the beginning + // + chn = 0; + } + + for ( ; ; chn++ ) { + + switch( Pattern->QueryChAt( chn ) ) { + + case (WCHAR)'#': + + // + // Optional space between flag and argument + // + if ( Lexeme->QueryChAt( chn ) == INVALID_CHAR ) { + + // + // At the end of the Argument string. Must get the next. + // + ArgumentLexemizer->IncrementConsumedCount(); + Lexeme = ArgumentLexemizer->GetLexemeAt( ArgumentLexemizer->QueryConsumedCount() ); + + if (!Lexeme) { + goto FAIL; + } + + chn = 0; + + } + + chnCurrent = chn; + chnEnd = Lexeme->QueryChCount(); + fFound = TRUE; + break; + + + case (WCHAR)'*': + + // + // No space allowed between flag and argument + // + if ( !(Lexeme->QueryChAt( chn )) || + !(TailMatch( Pattern, Lexeme, chn, &chnEnd, CaseSensitive ))) { + + goto FAIL; + } + + chnCurrent = chn; + fFound = TRUE; + break; + + + case INVALID_CHAR: + + // + // Space required beteen flag and argument + // + if( Lexeme->QueryChAt( chn ) != INVALID_CHAR) { + goto FAIL; + + } + + Lexeme = ArgumentLexemizer->GetLexemeAt( ArgumentLexemizer->QueryConsumedCount() ); + ArgumentLexemizer->IncrementConsumedCount(); + fFound = TRUE; + chnEnd++; + break; + + + + default: + + if ( CASESENS(Lexeme->QueryChAt( chn )) != CASESENS(Pattern->QueryChAt( chn )) ) { + goto FAIL; + } + chnEnd++; + } + + if (fFound) { + break; + } + + } + + // + // The patterns matched, see if the argument is recognized. + // + if (Argument->SetValue( Lexeme, chnCurrent, chnEnd, ArgumentLexemizer ) == FALSE ) { + goto FAIL; + } + + //DELETE( Lexeme ); + + return TRUE; + +FAIL: + //DELETE( Lexeme ); + return FALSE; +} + + +STATIC +BOOLEAN +TailMatch( + IN PWSTRING Pattern, + IN PWSTRING String, + IN CHNUM chn, + OUT PCHNUM chnEnd, + IN BOOLEAN CaseSensitive + ) +/*++ + +Routine Description: + + Performs tailmatching of a pattern and a string + +Arguments: + + Pattern - Supplies pointer to pattern + String - Supplies pointer to string + chn - Supplies index of current char + chnEnd - Supplies pointer to index of first character to + match in tail; + CaseSensitive - Supplies case sensitivity flag + +Return Value: + + TRUE if match + FALSE otherwise + +--*/ +{ + CHNUM PatternIndex; + CHNUM StringIndex; + + PatternIndex = Pattern->QueryChCount() - 1; + StringIndex = String->QueryChCount() - 1; + + + if (chn == PatternIndex) { + + // + // wild card is the last thing in the format, it matches. + // + *chnEnd = StringIndex + 1 ; + return TRUE; + } + + // + // Check characters walking towards front + // + while( CASESENS(Pattern->QueryChAt(PatternIndex)) == CASESENS(String->QueryChAt(StringIndex)) ) { + + if ( chn == PatternIndex ) { + break; + } + + PatternIndex--; + StringIndex--; + + } + + // + // If we're back at the beginning of the Pattern and the string is + // either at the beginning or somewhere inside then we have a match. + // + *chnEnd = StringIndex + 1; + + return( (PatternIndex == chn ) && ( StringIndex != INVALID_CHNUM ) ); +} + + +#if !defined( _AUTOCHECK_ ) + + +DEFINE_EXPORTED_CONSTRUCTOR( REST_OF_LINE_ARGUMENT, ARGUMENT, ULIB_EXPORT ); + +ULIB_EXPORT +BOOLEAN +REST_OF_LINE_ARGUMENT::Initialize( + ) +{ + return ARGUMENT::Initialize("*"); +} + +BOOLEAN +REST_OF_LINE_ARGUMENT::SetIfMatch( + IN OUT PARGUMENT_LEXEMIZER ArgumentLexemizer, + IN BOOLEAN CaseSensitive + ) +/*++ + +Routine Description: + + This routine computes whether or not the current state of the argument lexemizer + lends itself to a MACRO argument as described by DOS 5's DOSKEY function. If the + current state of the argument lexemizer is indeed in such a state then this routine + will grab all of the remaining tokens on the line and copy the contents of the + command line from the current token to the end of the line in this class's argument. + +Arguments: + + ArgumentLexemizer - Supplies the argument lexemizer. + CaseSensitive - Supplies whether or not to distinguish letters based solely on case. + +Return Value: + + FALSE - argument not recognized and/or value not set. + TRUE - argument recognized and value set. + +--*/ +{ + CHNUM char_pos; + ULONG consumed_count; + + consumed_count = ArgumentLexemizer->QueryConsumedCount(); + char_pos = ArgumentLexemizer->QueryCharPos(consumed_count); + + if (!_RestOfLine.Initialize(ArgumentLexemizer->GetCmdLine(), char_pos)) { + _fValueSet = FALSE; + return FALSE; + } + + + // Consume all of the remaining tokens. + + ArgumentLexemizer->IncrementConsumedCount( + ArgumentLexemizer->QueryLexemeCount() - consumed_count); + + _fValueSet = TRUE; + + return TRUE; +} + + +#endif // _AUTOCHECK_ + diff --git a/private/utils/ulib/src/array.cxx b/private/utils/ulib/src/array.cxx new file mode 100644 index 000000000..ffec5c745 --- /dev/null +++ b/private/utils/ulib/src/array.cxx @@ -0,0 +1,760 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + array.cxx + +Abstract: + + This module contains the definition for the ARRAY class. ARRAY is a + concrete implementation of a SORTABLE_CONTAINER. It extends the interface + to allow for easy access uswing a simple ULONG as an index. It is + dynamically growable and supports bases other than zero. + +Author: + + David J. Gilman (davegi) 02-Nov-1990 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "array.hxx" +#include "arrayit.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR( ARRAY, SORTABLE_CONTAINER, ULIB_EXPORT ); + +DEFINE_CAST_MEMBER_FUNCTION( ARRAY ); + +VOID +ARRAY::Construct ( + ) + +/*++ + +Routine Description: + + Construct an ARRAY by setting the initial value of of the OBJECT array + pointer to NULL. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + _ObjectArray = NULL; +} + + + + + +ULIB_EXPORT +ARRAY::~ARRAY ( + ) + +/*++ + +Routine Description: + + Destroy an ARRAY by freeing it's internal storage. Note that this + deletes the array, not the objects themselves. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if ( _ObjectArray ) { + FREE( _ObjectArray ); + } +} + + + +ULIB_EXPORT +BOOLEAN +ARRAY::Initialize ( + IN ULONG Capacity, + IN ULONG CapacityIncrement + ) + +/*++ + +Routine Description: + + Initialize an ARRAY object by setting it's internal state to supplied + or default values. In addition allocate an initial chunk of memory for + the actual storage of POBJECTs. + +Arguments: + + Capacity - Supplies the total number of OBJECTs the ARRAY + can contain + CapacityIncrement - Supplies the number of OBJECTs to make room for + when growing the ARRAY + +Return Value: + + BOOLEAN - TRUE if the ARRAY is successfully initialized. + +--*/ + +{ + DebugAssert( Capacity != 0 ); + + // + // If re-initializing, se reuse the current array + // + if ( _ObjectArray ) { + _Capacity = SetArrayCapacity( Capacity ); + } else { + _ObjectArray = (PPOBJECT)CALLOC( (UINT)Capacity, + sizeof( POBJECT ) ); + _Capacity = Capacity; + } + + _CapacityIncrement = CapacityIncrement; + _PutIndex = 0; + +#if DBG==1 + _IteratorCount = 0; +#endif + + if ( _ObjectArray ) { + DebugCheckHeap(); + return TRUE; + } else { + return FALSE; + } +} + +ULIB_EXPORT +BOOLEAN +ARRAY::DeleteAllMembers ( + ) + +/*++ + +Routine Description: + + Deletes all the members of the array + +Arguments: + + None + +Return Value: + + BOOLEAN - TRUE if all members deleted + +--*/ + +{ + PPOBJECT PObject; + + if ( _PutIndex > 0 ) { + +#if 0 // Bogus assert due to compiler error. Put it back in when compiler fixed +#if DBG==1 + DebugAssert( _IteratorCount == 0 ); +#endif +#endif + + PObject = &_ObjectArray[ _PutIndex - 1 ]; + + while ( PObject >= _ObjectArray ) { + DELETE( *PObject ); + PObject--; + } + + _PutIndex = 0; + } + + return TRUE; +} + + + + +POBJECT +ARRAY::GetAt ( + IN ULONG Index + ) CONST + +/*++ + +Routine Description: + + Retrieves the OBJECT at the specified Index. + +Arguments: + + Index - Supplies the index of the OBJECT in question. + +Return Value: + + POBJECT - A constant pointer to the requested OBJECT. + +--*/ + +{ + DebugPtrAssert( _ObjectArray ); + + if ( (_PutIndex > 0) && (Index < _PutIndex) ) { + return _ObjectArray[ Index ]; + } else { + return NULL; + } +} + + + +ULONG +ARRAY::GetMemberIndex ( + IN POBJECT Object + ) CONST + +/*++ + +Routine Description: + + Returns the position (index) of an object in the array. + +Arguments: + + POBJECT - Pointer to the OBJECT in question. + +Return Value: + + ULONG - The position of the OBJECT in the array. If the OBJECT is not + in the array, returns INVALID_INDEX. + +--*/ + +{ + ULONG Index; + + DebugPtrAssert( _ObjectArray ); + DebugPtrAssert( Object ); + + if( Object == NULL ) { + return( INVALID_INDEX ); + } + + Index = 0; + while( ( Index < QueryMemberCount() ) && + ( _ObjectArray[ Index ] != Object ) ) { + Index++; + } + return( ( Index < QueryMemberCount() )? Index : INVALID_INDEX ); +} + + + +ULIB_EXPORT +BOOLEAN +ARRAY::Put ( + IN OUT POBJECT Member + ) + +/*++ + +Routine Description: + + Puts an OBJECT at the next available location in the array. + +Arguments: + + Member - Supplies the OBJECT to place in the array + +Return Value: + + BOOLEAN - TRUE if member put, FALSE otherwise + +--*/ + +{ + DebugPtrAssert( Member ); + DebugPtrAssert( _PutIndex <= _Capacity ); + + // + // Grow the array if necessary + // + if ( _PutIndex >= _Capacity ) { + if ( _PutIndex >= SetArrayCapacity( _Capacity + _CapacityIncrement ) ) { + // + // Could not grow the array + // + + return FALSE; + } + } + + _ObjectArray[ _PutIndex++ ] = Member; + + return TRUE; + +} + + + +BOOLEAN +ARRAY::PutAt ( + IN OUT POBJECT Member, + IN ULONG Index + ) + +/*++ + +Routine Description: + + Puts an OBJECT at a particular location in the ARRAY. + The new object has to replace an existing object, i.e. the + index has to be smaller than the member count. + +Arguments: + + Member - Supplies the OBJECT to place in the ARRAY + Index - Supplies the index where the member is to be put + +Return Value: + + BOOLEAN - TRUE if member put, FALSE otherwise + + +--*/ + +{ + DebugPtrAssert( Member ); + DebugPtrAssert( Index < _PutIndex ); + + if ( Index < _PutIndex ) { + _ObjectArray[ Index ] = Member; + return TRUE; + } + + return FALSE; +} + + +ULIB_EXPORT +PITERATOR +ARRAY::QueryIterator ( + ) CONST + +/*++ + +Routine Description: + + Create an ARRAY_ITERATOR object for this ARRAY. + +Arguments: + + None. + +Return Value: + + PITERATOR - Pointer to an ITERATOR object. + +--*/ + +{ + PARRAY_ITERATOR Iterator; + + // + // Create new iterator + // + if ( Iterator = NEW ARRAY_ITERATOR ) { + + // + // Initialize the iterator + // + if ( !Iterator->Initialize( (PARRAY)this ) ) { + DELETE( Iterator ); + } + } + + return Iterator; +} + + + +ULONG +ARRAY::QueryMemberCount ( + ) CONST + +/*++ + +Routine Description: + + Obtains the number of elements in the array + +Arguments: + + None + +Return Value: + + ULONG - The number of members in the array + + +--*/ + +{ + return _PutIndex; +} + + +ULIB_EXPORT +POBJECT +ARRAY::Remove ( + IN OUT PITERATOR Position + ) + +/*++ + +Routine Description: + + Removes a member from the array + +Arguments: + + Position - Supplies an iterator whose currency is to be removed + +Return Value: + + POBJECT - The object removed + + +--*/ + +{ + PARRAY_ITERATOR Iterator; + + DebugPtrAssert( Position ); + DebugPtrAssert( ARRAY_ITERATOR::Cast( Position )); + + Iterator = (PARRAY_ITERATOR)Position; + + return RemoveAt( Iterator->QueryCurrentIndex() ); +} + + +POBJECT +ARRAY::RemoveAt ( + IN ULONG Index + ) + +/*++ + +Routine Description: + + Removes a member from the array + +Arguments: + + Index - Supplies the index of the member to be removed + +Return Value: + + POBJECT - The object removed + + +--*/ + +{ + POBJECT Object = NULL; + + if ( Index < _PutIndex ) { + + // DebugAssert( _IteratorCount <= 1 ); + + // + // Get the object + // + Object = (POBJECT)_ObjectArray[ Index ]; + + // + // Shift the rest of the array + // + memmove ( &_ObjectArray[ Index ], + &_ObjectArray[ Index + 1 ], + (UINT)(_PutIndex - Index - 1) * sizeof( POBJECT ) ); + + // + // Update the _PutIndex + // + _PutIndex--; + + } + + return Object; +} + + + +ULONG +ARRAY::SetCapacity ( + IN ULONG Capacity + ) + +/*++ + +Routine Description: + + Sets the capacity of the array. Will not shrink the array if the + capacity indicated is less than the number of members in the array. + +Arguments: + + Capacity - New capacity of the array + +Return Value: + + ULONG - The new capacity of the array + + +--*/ + +{ + if ( Capacity >= _PutIndex ) { + + SetArrayCapacity( Capacity ); + + } + + return _Capacity; +} + + +BOOLEAN +ARRAY::Sort ( + IN BOOLEAN Ascending + ) + +/*++ + +Routine Description: + + Sorts the array + +Arguments: + + Ascending - Supplies ascending flag + +Return Value: + + BOOLEAN - TRUE if array sorted, FALSE otherwise + + +--*/ + +{ + int (_CRTAPI1 *CompareFunction)(const void *, const void*); + + CompareFunction = Ascending ? + &ARRAY::CompareAscending : + &ARRAY::CompareDescending; + + qsort( _ObjectArray, + (size_t)_PutIndex, + sizeof(POBJECT), + CompareFunction ); + + return TRUE; +} + + +BOOLEAN +ARRAY::Insert( + IN OUT POBJECT Member, + IN ULONG Index + ) +/*++ + +Routine Description: + + Inserts an element in the array at the specified position, shifting + elements to the right if necessary. + +Arguments: + + Member - Supplies pointer to object to be inserted in the array + + Index - Supplies the index where the element is to be put + +Return Value: + + BOOLEAN - TRUE if new element inserted, FALSE otherwise + + +--*/ + +{ + DebugPtrAssert( Member ); + DebugPtrAssert( Index <= _PutIndex ); + + // + // Make sure that there will be enough space in the array for the + // new element + // + if ( _PutIndex >= _Capacity ) { + + if ( _PutIndex >= SetArrayCapacity( _Capacity + _CapacityIncrement ) ) { + // + // Could not grow the array + // + return FALSE; + } + } + + // + // If required, shift the array to the right to make space for the + // new element. + // + if ( Index < _PutIndex ) { + + memmove ( &_ObjectArray[ Index + 1 ], + &_ObjectArray[ Index ], + (UINT)( _PutIndex - Index ) * sizeof( POBJECT ) ); + } + + // + // Insert the element + // + _ObjectArray[ Index ] = Member; + + // + // Increment the number of elements in the array + // + _PutIndex++; + + return TRUE; +} + + + +ULONG +ARRAY::SetArrayCapacity ( + IN ULONG NumberOfElements + ) + +/*++ + +Routine Description: + + Sets the capacity of the array. Allways reallocs the array. + +Arguments: + + NewSize - New capacity of the array + +Return Value: + + ULONG - The new capacity of the array + + +--*/ + +{ + PPOBJECT Tmp; + + Tmp = (PPOBJECT)REALLOC( _ObjectArray, + (UINT)NumberOfElements * sizeof(POBJECT) ); + + if ( Tmp ) { + _ObjectArray = Tmp; + _Capacity = NumberOfElements; + } + + return _Capacity; +} + + +int _CRTAPI1 +ARRAY::CompareAscending ( + IN const void * Object1, + IN const void * Object2 + ) + +/*++ + +Routine Description: + + Compares two objects. + +Arguments: + + Object1 - Supplies pointer to first object + Object2 - Supplies pointer to second object + +Return Value: + + Returns: + + <0 if Object1 is less that Object2 + 0 if Object1 is equal to Object2 + >0 if Object1 is greater than Object2 + + +--*/ + +{ + return (*(POBJECT *)Object1)->Compare( *(POBJECT *)Object2 ); +} + + + +int _CRTAPI1 +ARRAY::CompareDescending ( + IN const void * Object1, + IN const void * Object2 + ) + +/*++ + +Routine Description: + + Compares two objects + +Arguments: + + Object1 - Supplies pointer to first object + Object2 - Supplies pointer to second object + +Return Value: + + Returns: + + <0 if Object2 is less that Object1 + 0 if Object2 is equal to Object1 + >0 if Object2 is greater than Object1 + +--*/ + +{ + return (*(POBJECT *)Object2)->Compare( *(POBJECT *)Object1 ); +} diff --git a/private/utils/ulib/src/arrayit.cxx b/private/utils/ulib/src/arrayit.cxx new file mode 100644 index 000000000..dc51c73c9 --- /dev/null +++ b/private/utils/ulib/src/arrayit.cxx @@ -0,0 +1,261 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + arrayit.cxx + +Abstract: + + This file contains the definitions for the ARRAY_ITERATOR class. + ARRAY_ITERATOR is a concrete implementation of the abstract ITERATOR + class. + +Author: + + David J. Gilman (davegi) 03-Dec-1990 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "array.hxx" +#include "arrayit.hxx" + + +DEFINE_CAST_MEMBER_FUNCTION( ARRAY_ITERATOR ); + +DEFINE_CONSTRUCTOR( ARRAY_ITERATOR, ITERATOR ); + + +VOID +ARRAY_ITERATOR::Construct ( + ) + +/*++ + +Routine Description: + + Construct an ARRAY_ITERATOR by setting it's current index to 0 and it's + associated ARRAY to NULL. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + _Array = NULL; +} + + + +ARRAY_ITERATOR::~ARRAY_ITERATOR ( + ) +/*++ + +Routine Description: + + Destructor for the ARRAY_ITERATOR class + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ +#if DBG==1 + if ( _Array ) { + _Array->_IteratorCount--; + } +#endif +} + + + + +VOID +ARRAY_ITERATOR::Reset( + ) + +/*++ + +Routine Description: + + Resets the iterator + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + _CurrentIndex = INVALID_INDEX; +} + + + +POBJECT +ARRAY_ITERATOR::GetCurrent( + ) +/*++ + +Routine Description: + + Gets current member + +Arguments: + + None + +Return Value: + + POBJECT - Pointer to current member in the array + +--*/ + +{ + if ( _CurrentIndex == INVALID_INDEX ) { + return NULL; + } else { + return _Array->GetAt( _CurrentIndex ); + } +} + + + + +POBJECT +ARRAY_ITERATOR::GetNext( + ) +/*++ + +Routine Description: + + Gets next member in the array + +Arguments: + + None + +Return Value: + + POBJECT - Pointer to next member in the array + +--*/ + +{ + // + // Wrap if necessary. Note that this assumes that INVALID_INDEX + 1 == 0 + // + _CurrentIndex++; + + if ( _CurrentIndex >= _Array->QueryMemberCount() ) { + _CurrentIndex = INVALID_INDEX; + } + + // + // Get next + // + return _Array->GetAt( _CurrentIndex ); +} + + +POBJECT +ARRAY_ITERATOR::GetPrevious( + ) +/*++ + +Routine Description: + + Gets previous member in the array + +Arguments: + + None + +Return Value: + + POBJECT - Pointer to previous member in the array + +--*/ + +{ + // + // Wrap if necessary. Note that this assumes that 0 - 1 == INVALID_INDEX + // + + if ( _CurrentIndex == INVALID_INDEX ) { + _CurrentIndex = _Array->QueryMemberCount() - 1; + } else { + _CurrentIndex--; + } + + // + // Get next + // + return _Array->GetAt( _CurrentIndex ); +} + + + + +BOOLEAN +ARRAY_ITERATOR::Initialize ( + IN PARRAY Array + ) + +/*++ + +Routine Description: + + Associate an ARRAY with this ARRAY_ITERATOR and reset the current index + +Arguments: + + Array - Supplies pointer to the array object + +Return Value: + + BOOLEAN - Returns TRUE if the initialization was succesful. + +--*/ + +{ + DebugPtrAssert( Array ); + +#if DBG==1 + if ( _Array ) { + _Array->_IteratorCount--; + } + Array->_IteratorCount++; +#endif + _Array = Array; + _CurrentIndex = INVALID_INDEX; + + + return TRUE; +} diff --git a/private/utils/ulib/src/basesys.cxx b/private/utils/ulib/src/basesys.cxx new file mode 100644 index 000000000..e78b2b71f --- /dev/null +++ b/private/utils/ulib/src/basesys.cxx @@ -0,0 +1,249 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ +#include "ulib.hxx" +#include "basesys.hxx" + +extern "C" { + #include <stdio.h> +#if defined( _AUTOCHECK_ ) + +// +// This stuff is lifted from winuser.h, because with _AUTOCHECK_ we +// shouldn't include windows header files. +// + +#define MAKEINTRESOURCEW(i) (LPWSTR)((ULONG)((USHORT)(i))) +#define MAKEINTRESOURCE MAKEINTRESOURCEW +#define RT_MESSAGETABLE MAKEINTRESOURCE(11) + +#endif // _AUTOCHECK_ + +}; + +ULIB_EXPORT +BOOLEAN +BASE_SYSTEM::QueryResourceString( + OUT PWSTRING ResourceString, + IN MSGID MsgId, + IN PCSTR Format ... + ) +/*++ + +Routine Description: + + This routine computes the resource string identified by the resource + identifier 'MsgId'. In addition to the 'printf' format strings + supported, 'QueryResourceString' supports : + + 1. '%W' - Expects a pointer to a WSTRING. + +Arguments: + + ResourceString - Returns the resource string. + MsgId - Supplies the message id of the resource string. + Format - Supplies a 'printf' style format descriptor for the + arguments to the resource string. + ... - Supplies the arguments to the resource string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + va_list ap; + BOOLEAN r; + + va_start(ap, Format); + r = QueryResourceStringV(ResourceString, MsgId, Format, ap); + va_end(ap); + + return r; +} + +STATIC WSTR display_buffer[4096]; + + +ULIB_EXPORT +BOOLEAN +BASE_SYSTEM::QueryResourceStringV( + OUT PWSTRING ResourceString, + IN MSGID MsgId, + IN PCSTR Format, + IN va_list VarPointer + ) +/*++ + +Routine Description: + + This is a 'varargs' implementation of 'QueryResourceString'. + +Arguments: + + ResourceString - Returns the resource string. + MsgId - Supplies the message id of the resource string. + Format - Supplies a 'printf' style format descriptor for the + arguments to the resource string. + VarPointer - Supplies a varargs pointer to the arguments of the + resource string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + STATIC HANDLE lib_handle = 0; + PWSTR args[10]; + WSTR fmt[20]; + INT i, j; + PWSTR p; + PWSTRING gstring; + DSTRING UnicodeFormat; + +#if !defined( _AUTOCHECK_ ) + if (!lib_handle) { + lib_handle = GetModuleHandle((LPWSTR)L"ulib.dll"); + DebugAssert(lib_handle); + if (!lib_handle) { + return FALSE; + } + } + +#else + NTSTATUS Status; + PMESSAGE_RESOURCE_ENTRY MessageEntry; + PWSTR MessageFormat; + ULONG Result; + ANSI_STRING AnsiString; + UNICODE_STRING UnicodeString; + + if (!lib_handle) { + lib_handle = (PVOID)NtCurrentPeb()->ImageBaseAddress; + DebugAssert(lib_handle); + if (!lib_handle) { + return FALSE; + } + } +#endif + + for (i = 0; i < 10; i++) { + args[i] = NULL; + } + + if (!UnicodeFormat.Initialize(Format)) { + return FALSE; + } + + i = 0; + for (p = (PWSTR) UnicodeFormat.GetWSTR(); *p; p++) { + if (*p == '%') { + if (*(p + 1) == 'W') { + p++; + gstring = va_arg(VarPointer, PWSTRING); + gstring->QueryWSTR(0, TO_END, display_buffer, 4096); + } else { + j = 0; + fmt[j++] = *p++; + while (*p && *p != '%') { + if ((*p == 's' || *p == 'c') && *(p - 1) != 'w') { + fmt[j++] = 'h'; + } + fmt[j++] = *p++; + } + p--; + fmt[j] = 0; + swprintf(display_buffer, fmt, va_arg(VarPointer, PVOID)); + } + args[i] = (PWSTR)MALLOC(wcslen(display_buffer) * sizeof(WCHAR) + + sizeof(WCHAR)); + if (NULL == args[i]) { + return FALSE; + } + wcscpy( args[i++], display_buffer); + } + } + +#if !defined( _AUTOCHECK_ ) + FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | + FORMAT_MESSAGE_ARGUMENT_ARRAY, + (LPVOID)lib_handle, + (ULONG)MsgId, + 0L, + display_buffer, + 4096, + (va_list *)args); + + for (i = 0; i < 10; i++) { + FREE(args[i]); + } + + return ResourceString->Initialize(display_buffer); + +#else + Status = RtlFindMessage( lib_handle, + (ULONG)RT_MESSAGETABLE, + +#if defined JAPAN // v-junm - 08/03/93 +// The default TEB's value for NT-J is set to 0x411(JP) in the hives. Since +// we do not want Japanese messages to come out in the boot screen, we have to +// force autochk.exe to pick up the English text rather than the Japanese. +// +// NOTE: This has to be done because the current version of autochk.exe has +// bilingual messages. It's more efficient to make a US version rather +// than a bilingual version to save space. + 0x409, +#else + 0, +#endif + (ULONG)MsgId, + &MessageEntry + ); + + if (!NT_SUCCESS( Status )) { + return FALSE; + } + + if (!(MessageEntry->Flags & MESSAGE_RESOURCE_UNICODE)) { + RtlInitAnsiString( &AnsiString, (PCSZ)&MessageEntry->Text[ 0 ] ); + Status = RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, TRUE ); + if (!NT_SUCCESS( Status )) { + return FALSE; + } + + MessageFormat = UnicodeString.Buffer; + } else { + MessageFormat = (PWSTR)MessageEntry->Text; + UnicodeString.Buffer = NULL; + } + + Status = RtlFormatMessage( MessageFormat, + 0, + FALSE, + FALSE, + TRUE, + (va_list *)args, + (PWSTR)display_buffer, + sizeof( display_buffer ), + &Result + ); + + if (UnicodeString.Buffer != NULL) { + RtlFreeUnicodeString( &UnicodeString ); + } + + for (i = 0; i < 10; i++) { + FREE(args[i]); + } + + if (!NT_SUCCESS( Status )) { + return FALSE; + } + + return ResourceString->Initialize(display_buffer); + +#endif // _AUTOCHECK_ +} diff --git a/private/utils/ulib/src/bitvect.cxx b/private/utils/ulib/src/bitvect.cxx new file mode 100644 index 000000000..acda50365 --- /dev/null +++ b/private/utils/ulib/src/bitvect.cxx @@ -0,0 +1,595 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + bitvect.cxx + +Abstract: + + This module contains the definition for thje BITVECTOR class. + +Author: + + David J. Gilman (davegi) 01-Feb-1991 + Barry Gilhuly (w-barry) + Norbert P. Kusters (norbertk) + +Environment: + + ULIB, User Mode + +[Notes:] + + optional-notes + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "bitvect.hxx" +#include <limits.h> + +// +// Invalid bit count +// + +CONST PT InvalidBitCount = (PT)(-1); + +// +// Static member data. +// + +// +// Bits per byte value table e.g. 27->4 bits +// +// Algorithm: +// +// _BitsSetLookUp[0] = 0; +// +// For the ranges [1,1],[2,3],[4,7],[8,15],...,[128,255]. +// +// for (n = (( PT ) 1 ); n <= 8; n++) { +// +// +// Compute range for loop. +// +// r = (( PT ) 1 ) << (n - (( PT ) 1 )); +// +// +// [r, 2*r - 1 ] = [0, r - 1] + 1; +// +// for (i = 0; i < r; i++) { +// _BitsSetLookUp[i + r] = _BitsSetLookUp[i] + (( PT ) 1 ); +// } +// } +// } +// + +CONST BYTE BITVECTOR::_BitsSetLookUp[ 256 ] = { + + 0, 1, 1, 2, 1, 2, 2, 3, + 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, + 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, + 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, + 3, 4, 4, 5, 4, 5, 5, 6, + 1, 2, 2, 3, 2, 3, 3, 4, + 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, + 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, + 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, + 1, 2, 2, 3, 2, 3, 3, 4, + 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, + 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, + 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, + 2, 3, 3, 4, 3, 4, 4, 5, + 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, + 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, + 5, 6, 6, 7, 6, 7, 7, 8 +}; + + +DEFINE_EXPORTED_CONSTRUCTOR( BITVECTOR, OBJECT, ULIB_EXPORT ); + +DEFINE_CAST_MEMBER_FUNCTION( BITVECTOR ); + +VOID +BITVECTOR::Construct ( + ) + +/*++ + +Routine Description: + + Construct a BITVECTOR. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + REGISTER PT pt; + + // + // Find the number of bits per PTs + // + + _BitsPerPT = sizeof( PT ) * CHAR_BIT; + + // + // Set the smallest number of PTs needed + // + + _PTCount = (( PT ) 1 ); + + // + // Create the mask used to separate the array index from the bit index + // + + _BitPositionMask = _BitsPerPT - (( PT ) 1 ); + + // + // Count the number of bits required to make the shift count for + // accessing the Primitive Type. + // + + for( _IndexShiftCount = 0, pt = _BitPositionMask; pt; + pt >>= (( PT ) 1 ), _IndexShiftCount++ ); + + // + // Initialize BITVECTOR state. + // + + _BitVector = NULL; + _PTCount = 0; + _FreeBitVector = FALSE; +} + +ULIB_EXPORT +BOOLEAN +BITVECTOR::Initialize ( + IN PT Size, + IN BIT InitialValue, + IN PPT Memory + ) + +/*++ + +Routine Description: + + Construct a BITVECTOR with at least the size specified and + initialize all bits to SET or RESET. + +Arguments: + + Size - Supplies the number of bits in the vector + InitialValue - Supplies the initial value for the bits + Memory - Supplies a memory buffer to use for the vector + +Return Value: + + BOOLEAN - Returns TRUE if the BITVECTOR was succesfully initialized. + +Notes: + + Minimum and default BITVECTOR size is the number of bits in + one PT. Default initializer is RESET. The size of a BITVECTOR + is rounded up to the nearest whole multiple of (_BitsPerPT * CHAR_BIT). + + If the client supplies the buffer it is the client's responsibility + to ensure that Size and the size of the buffer are in sync. + Also SetSize will not change the size of a client supplied + buffer. + +--*/ + +{ + // + // Destroy the internals of a previous BITVECTOR. + // + + Destroy( ); + + // + // Find the number of PTs that will be required for this BITVECTOR + // (handles smallest size case (Size = 0) ). + // + + _PTCount = Size ? (( Size + _BitsPerPT - (( PT ) 1 )) / _BitsPerPT ) : (( PT ) 1 ); + + // + // If Memory was supplied use that for the vector else allocate + // the vector. + // + + if( Memory ) { + + _BitVector = Memory; + + } else { + _FreeBitVector = TRUE; + if( !( _BitVector = ( PT* ) MALLOC(( size_t ) ( _PTCount * sizeof( PT ))))) { + + return FALSE; + } + } + + // + // Set the bitvector to the supplied value ( SET | RESET ) + // + + ( InitialValue == SET ) ? SetAll( ) : ResetAll( ); + + return TRUE; +} + +ULIB_EXPORT +BITVECTOR::~BITVECTOR ( + ) + +/*++ + +Routine Description: + + Destroy a BITVECTOR by calling it's Destroy function. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + Destroy( ); +} + +VOID +BITVECTOR::Destroy ( + ) + +/*++ + +Routine Description: + + Destroy a BITVECTOR by possibly freeing it's internal storage. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + if( _FreeBitVector ) { + + DebugAssert( _BitVector != NULL ); + FREE( _BitVector ); + } +} + +ULIB_EXPORT +PT +BITVECTOR::SetSize ( + IN PT Size, + IN BIT InitialValue + ) + +/*++ + +Routine Description: + + Set the number of bits in the vector + +Arguments: + + Size - Supplies the number of bits to set the vector size to + InitialValue- Supplies the initial value for the bits + +Return Value: + + PT - Returns the new size of this BITVECTOR in bits. + +Notes: + + SetSize will merrily truncate the vector with no warning. + + Minimum and default BITVECTOR size is the number of bits in + one PT. Default initializer is RESET. The size of a BITVECTOR + is rounded up to the nearest whole multiple of (_BitsPerPT * CHAR_BIT). + + If the client supplied the buffer refuse to change it's size + +--*/ + +{ + REGISTER PT PTCountNew; + PT cbitsNew; + PT cbitsOld; + + // + // Check that the bitvector was created... + // + + DebugPtrAssert( _BitVector ); + if( _BitVector == NULL ) { + return( 0 ); + } + + // + // If the client supplied the buffer, refuse to change it's size. + // + + if( ! _FreeBitVector ) { + return( _PTCount * _BitsPerPT ); + } + + + // + // Compute the number of PTs and bits required for the new size + // + + PTCountNew = Size ? (( Size + _BitsPerPT - (( PT ) 1 ) ) / _BitsPerPT ) : (( PT ) 1 ); + cbitsNew = PTCountNew * _BitsPerPT; + + if( PTCountNew != _PTCount ) { + + // + // The new size requires a different number of PTs then the old + // + + if( !( _BitVector = ( PT* ) REALLOC(( VOID* ) _BitVector, + ( size_t ) ( PTCountNew * sizeof( PT ))))) { + + return( 0 ); + } + } + + // + // If the new size contains more bits, initialize them to the supplied + // value + // + + cbitsOld = _PTCount * _BitsPerPT; + _PTCount = PTCountNew; + + if( cbitsNew > cbitsOld ) { + if( InitialValue == SET ) { + SetBit( cbitsOld, cbitsNew - cbitsOld ); + } else { + ResetBit( cbitsOld, cbitsNew - cbitsOld ); + } + } + + return( _PTCount * _BitsPerPT ); +} + +ULIB_EXPORT +VOID +BITVECTOR::SetBit ( + IN PT Index, + IN PT Count + ) + +/*++ + +Routine Description: + + SET the supplied range of bits + +Arguments: + + Index - Supplies the index at which to start setting bits. + Count - Supplies the number of bits to set. + +Return Value: + + None. + +Notes: + + It may be faster to compute masks for setting sub-ranges. + +--*/ + +{ + REGISTER PT ptCurBit; + + DebugAssert( _BitVector != NULL ); + DebugAssert(( Index + Count ) <= ( _PTCount * _BitsPerPT )); + + // Set count to be the max instead. + Count += Index; + + for (ptCurBit = Index; (ptCurBit < Count) && + (ptCurBit & _BitPositionMask); ptCurBit++) { + _BitVector[ptCurBit >> _IndexShiftCount] |= + (1 << (ptCurBit & _BitPositionMask)); + } + + for (; ptCurBit + 8*sizeof(PT) <= Count; ptCurBit += 8*sizeof(PT)) { + _BitVector[ptCurBit >> _IndexShiftCount] = 0xffffffff; + } + + for (; ptCurBit < Count; ptCurBit++) { + _BitVector[ptCurBit >> _IndexShiftCount] |= + (1 << (ptCurBit & _BitPositionMask)); + } +} + +ULIB_EXPORT +VOID +BITVECTOR::ResetBit ( + IN PT Index, + IN PT Count + ) + +/*++ + +Routine Description: + + RESET the supplied range of bits + +Arguments: + + Index - Supplies the index at which to start resetting bits. + Count - Supplies the number of bits to reset. + +Return Value: + + None. + +Notes: + + It may be faster to compute masks for resetting sub-ranges. + +--*/ + +{ + REGISTER PT ptCurBit; + + DebugAssert( _BitVector != NULL ); + DebugAssert(( Index + Count ) <= ( _PTCount * _BitsPerPT )); + + // Set count to be the max instead. + Count += Index; + + for (ptCurBit = Index; (ptCurBit < Count) && + (ptCurBit & _BitPositionMask); ptCurBit++) { + _BitVector[ptCurBit >> _IndexShiftCount] &= + ~(1 << (ptCurBit & _BitPositionMask)); + } + + for (; ptCurBit + 8*sizeof(PT) <= Count; ptCurBit += 8*sizeof(PT)) { + _BitVector[ptCurBit >> _IndexShiftCount] = 0; + } + + for (; ptCurBit < Count; ptCurBit++) { + _BitVector[ptCurBit >> _IndexShiftCount] &= + ~(1 << (ptCurBit & _BitPositionMask)); + } +} + +VOID +BITVECTOR::ToggleBit ( + IN PT Index, + IN PT Count + ) + +/*++ + +Routine Description: + + Toggle the supplied range of bits. + +Arguments: + + Index - Supplies the index at which to start toggling bits. + Count - Supplies the number of bits to toggle. + +Return Value: + + None. + +--*/ + +{ + REGISTER PT ptCurBit; + + DebugAssert( _BitVector != NULL ); + DebugAssert( Index + Count <= _PTCount * _BitsPerPT); + + while( Count-- ) { + ptCurBit = Index + Count; + if( IsBitSet( ptCurBit )) { + ResetBit( ptCurBit ); + } else { + SetBit( ptCurBit ); + } + } +} + +ULIB_EXPORT +PT +BITVECTOR::ComputeCountSet( + ) CONST + +/*++ + +Routine Description: + + Compute the number of bits that are set in the bitvector using a table + look up. + +Arguments: + + None. + +Return Value: + + PT - Returns the number of set bits. + +--*/ + +{ + REGISTER PCBYTE pbBV; + REGISTER PT i; + REGISTER PT BitsSet; + + // + // Cast the bitvector into a string of bytes. + // + + pbBV = ( PCBYTE ) _BitVector; + + // + // Initialize the count to zero. + // + + BitsSet = 0; + + // + // For all of the bytes in the bitvector. + // + + for (i = 0; i < _PTCount * sizeof( PT ); i++) { + + // + // Add the number of bits set in this byte to the total. + // + + BitsSet += _BitsSetLookUp[pbBV[ i ]]; + } + + return( BitsSet ); +} diff --git a/private/utils/ulib/src/buffer.cxx b/private/utils/ulib/src/buffer.cxx new file mode 100644 index 000000000..51ecf5d9a --- /dev/null +++ b/private/utils/ulib/src/buffer.cxx @@ -0,0 +1,457 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + buffer.cxx + +Abstract: + + This contains all buffer class definition. + Buffers do not have implicit terminations. Sizes on construction + should include any termination bytes. + +Author: + + steve rowe stever 27-Nov-90 + +Environment: + + ULIB, User Mode + +Notes: + + + +Revision History: + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "buffer.hxx" + +#if defined( __BCPLUSPLUS__ ) + + #include <mem.h> +#else + + extern "C" { + #include <memory.h> + }; + +#endif // __BCPLUSPLUS__ + +// +// _ThresHold is the constant used by ReAllocate to determine when +// to actually call realloc to shrink the buffer. +// + +ULONG BUFFER::_ThresHold = 129; + +DEFINE_CONSTRUCTOR( BUFFER, OBJECT ); + +VOID +BUFFER::Construct ( + ) + +/*++ + +Routine Description: + + Construct a BUFFER by initializing it's internal state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + cb = 0; + _BufSize = 0; + pBuffer = NULL; +} + +BUFFER::~BUFFER ( + ) + +/*++ + +Routine Description: + + Destructor for general buffer class + +Arguments: + + None + +Return Value: + + None. + +--*/ + +{ + if( pBuffer ) { + FREE(pBuffer); + } +} + +BOOLEAN +BUFFER::BuffCat ( + IN PCBUFFER Buffer2 + ) + +/*++ + +Routine Description: + + Concatenates a buffer with this buffer. + +Arguments: + + Buffer2 - Buffer to add to current buffer. + +Return Value: + + TRUE - success + FALSE - failed to reallocate memory. + +--*/ + +{ + REGISTER ULONG cbT; + PCHAR pTmp; + + // Note W-Barry 11-JUN-91 Needed to add a variable to hold the + // current value of cb since the reallocate routine has been changed + // to update 'cb' when called... + // + ULONG CurrentCount; + + cbT = cb + Buffer2->QueryBytesInBuffer(); + CurrentCount = cb; + if ((pTmp = (char *)ReAllocate( cbT )) != NULL) { + memcpy( pTmp + CurrentCount, Buffer2->GetBufferPtr(), (size_t)(cbT - CurrentCount) ); + pBuffer = pTmp; + cb = cbT; + return( TRUE ); + } + return( FALSE ); +} + +BOOLEAN +BUFFER::BufferCopyAt ( + IN PCVOID BufferToCopy, + IN ULONG cbToCopy, + IN ULONG oStart + ) + +/*++ + +Routine Description: + + Copies a number of bytes from a buffer to a particular location. + Note that the total buffer size my increase, it will not decrease. + This way replaces can be done. StartingByte can be past end of + current buffer. What would lie between end of buffer and + startingbyte would be undefined. + + WARNING: BufferToCopy cannot point into this buffer. + +Arguments: + + BufferToCopy - Supplies the buffer to copy + SizeOfBuffer - Supplies the number of bytes to copy + +Return Value: + + ULONG - number of bytes copied. + 0 - if error. check error stack. + +--*/ + +{ + + + ULONG cbT; + PCHAR pBufferNew; + + // + // Enforce warning + // + +/*** Note davegi What does warning mean? + + DebugAssert(((( PCHAR ) pBuffer + cb ) <= BufferToCopy ) && + ( BufferToCopy < (PCHAR ) pBuffer )); + +***/ + /* + Copies to yourself are rare and will fall through the code so + no special action is taken. + + Copes of a null will fall through since realloc will free the + buffer for a size of 0. + + If the new buffer will fit in the old the size is not reduced to + the end of the new buffer. This is to support sub-string replacement. + The caller then must be aware of how the copy effects buffer size. + */ + + cbT = oStart + cbToCopy; + pBufferNew = (PCHAR) pBuffer; + // will it fit in current buffer + if (cb < cbT) { + if ((pBufferNew = (char *)ReAllocate( cbT )) != NULL) { + cb = cbT; + } else { + return( FALSE ); + } + } + + memcpy (pBufferNew + oStart, BufferToCopy, (size_t)cbToCopy); + pBuffer = pBufferNew; + return( TRUE ); +} + +BOOLEAN +BUFFER::DeleteAt( + IN ULONG cbToDelete, + IN ULONG oStartDelete + ) + +/*++ + +Routine Description: + + Deletes the specificied section of the current buffer + +Arguments: + + cbToDelete - Supplies the number of bytes to delete + oStartDelete - Supplies the offset for the delete + +Return Value: + + TRUE - insert success + FALSE - This can happen when cbToDelete is larger then + the size of the buffer, oStartDelete is past the + end of the buffer. +--*/ + + +{ + if (oStartDelete < cb) { + if (cbToDelete <= cb) { + cb = cb - cbToDelete; + pBuffer = ( PCCHAR )ReAllocate( cb ); + DebugPtrAssert( pBuffer ); + memmove(( PCCHAR )pBuffer + oStartDelete , + ( PCCHAR )pBuffer + (oStartDelete + cbToDelete), + (size_t)(cb - oStartDelete) ); + return( TRUE ); + } + } + return( FALSE ); +} + +BOOLEAN +BUFFER::InsertAt ( + IN PCVOID BufferToCopy, + IN ULONG cbToCopy, + IN ULONG oStartCopy + ) + +/*++ + +Routine Description: + + Inserts the specificied buffer of bytes at the specified + location. + +Arguments: + + BufferToCopy - Supplies the buffer to insert + cbToCopy - Supplies the number of bytes to insert + oStartCopy - Supplies the offset for the insertion + +Return Value: + + TRUE - insert success + FALSE - This can happen for memory allocation failure + or oStartCopy is past end of buffer. +--*/ + +{ + ULONG cbT; + + // Note W-Barry 11-JUN-91 Necessary to add since cb is currently + // being updated by ReAllocate(). + size_t CountToMove; + PCHAR pTmp; + + CountToMove = (size_t)( cb - oStartCopy ); + if (oStartCopy < cb ) { + cbT = cb + cbToCopy; + if ((pTmp = (char *)ReAllocate( cbT )) != NULL) { + memmove( pTmp + (oStartCopy + cbToCopy), + pTmp + oStartCopy, + CountToMove ); + memcpy( pTmp + oStartCopy, BufferToCopy, (size_t)cbToCopy ); + pBuffer = pTmp; + cb = cbT; + return( TRUE ); + } + } + return( FALSE ); +} + +BOOLEAN +BUFFER::PutBuffer ( + IN PCBUFFER BufferToCopy + ) + +/*++ + +Routine Description: + + Constructor for Buffer object. The buffer held in BufferToCopy + is not moved but copied to this object. If failed to init orginal + buffer state retained. + +Arguments: + + BufferToCopy - pointer to BUFFER object to copy + +Return Value: + + BOOLEAN - Returns TRUE if supplied buffer was succesfully copied + +--*/ + +{ + + ULONG cbNew; + PVOID pBufferNew; + + cbNew = BufferToCopy->QueryBytesInBuffer (); + + if (( pBufferNew = MALLOC( (size_t)cbNew )) != NULL) { + if( SetBuffer( pBufferNew, cbNew) ) { + // Note the buffer is not shortened on this? + pBuffer = BufferToCopy->GetBufferPtr(); + BufferCopyAt( pBuffer, cbNew ); + return( TRUE ); + } + } + + return( FALSE ); +} + +BOOLEAN +BUFFER::SetBuffer ( + IN PVOID InitialBuffer, + IN ULONG SizeOfBuffer + ) + +/*++ + +Routine Description: + + Constructor for Buffer object. The buffer passed in should not be + freed by the caller. BUFFER will free in upon deletion. + +Arguments: + + InitialBuffer - pointer to buffer + SizeOfBuffer - size of buffer in bytes. + +Return Value: + + None. + +--*/ + +{ + if (cb) { + FREE (pBuffer); + } + + pBuffer = InitialBuffer; + cb = SizeOfBuffer; + _BufSize = SizeOfBuffer; + + return( TRUE ); +} + +PVOID +BUFFER::ReAllocate ( + IN ULONG NewCount + ) + +/*++ + +Routine Description: + + Reallocates the private data member pBuffer if required. ReAllocate + supports the concept that BUFFER's internal buffer can be larger + than the number of bytes actually in use. + + +Arguments: + + NewCount - Supplies the new size of pBuffer in bytes. + + +Return Value: + + PVOID - Returns a pointer to the 'newly allocated' pBuffer. + +--*/ + +{ + REGISTER PVOID pv; + + // + // If the new buffer size is greater than what we currently have + // in reserve, or it is smaller than the threshold, realloc the + // buffer. + // + + if( ( NewCount > _BufSize ) || + ( ( _BufSize - NewCount ) >= _ThresHold ) + ) { + + // + // If the realloc of the buffer succeeds, record it's actual size. + // + + if(( pv = REALLOC( pBuffer, (size_t)NewCount )) != NULL ) { + + pBuffer = pv; + _BufSize = cb = NewCount; + + } + } else { + + // + // Enough storage is available in reserve, just return the + // existing pointer. + // + + _BufSize = cb = NewCount; + pv = pBuffer; + } + + return( pv ); +} diff --git a/private/utils/ulib/src/bufstrm.cxx b/private/utils/ulib/src/bufstrm.cxx new file mode 100644 index 000000000..5bd7eafab --- /dev/null +++ b/private/utils/ulib/src/bufstrm.cxx @@ -0,0 +1,1041 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + bufstrm.cxx + +Abstract: + + This module contains the definitions of the member functions + of BUFFER_STREAM class. + +Author: + + Jaime Sasson (jaimes) 14-Apr-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "bufstrm.hxx" +#include "mbstr.hxx" +#include "system.hxx" +#include "wstring.hxx" + +extern "C" { + #include <ctype.h> +} + +DEFINE_CONSTRUCTOR ( BUFFER_STREAM, STREAM ); + + + +BUFFER_STREAM::~BUFFER_STREAM ( + ) + +/*++ + +Routine Description: + + Destroy a BUFFER_STREAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + FREE( _Buffer ); +} + + + +VOID +BUFFER_STREAM::Construct ( + ) + +/*++ + +Routine Description: + + Constructs a BUFFER_STREAM object + +Arguments: + + None. + +Return Value: + + None. + + +--*/ + +{ + _Buffer = NULL; + _BufferSize = 0; + _CurrentByte = NULL; + _BytesInBuffer = 0; + _BufferStreamType = -1; +} + + +BOOLEAN +BUFFER_STREAM::Initialize ( + ULONG BufferSize + ) + +/*++ + +Routine Description: + + Initialize an object of type BUFFER_STREAM. + A BUFFER_STREAM object cannot be reinitialized. + +Arguments: + + BufferSize - Size of the buffer to be allocated. + The size of the buffer can be zero, but in this case no + memory will be allocated. This initialization should be used + only by FILE_STREAM when it is mapping a file in memory. In + this case, all methods that read from the buffer or test + the end of the file will be overloaded by methods defined + in FILE_STREAM. + +Return Value: + + BOOLEAN - Returns TRUE if the initialization succeed. + +--*/ + +{ + BOOLEAN Result; + + Result = FALSE; + if( BufferSize != 0 ) { + // + // The +2 is needed becase the buffer needs to be + // double NUL terminated + // + _Buffer = ( PBYTE ) MALLOC( ( size_t )( BufferSize + 2 ) ); + if( _Buffer != NULL ) { + *( _Buffer + BufferSize ) = 0; + *( _Buffer + BufferSize + 1 ) = 0; + _BufferSize = BufferSize; + _CurrentByte = NULL; + _BytesInBuffer = 0; + Result = TRUE; + } + } else { + _Buffer = NULL; + _BufferSize = 0; + _CurrentByte = NULL; + _BytesInBuffer = 0; + Result = TRUE; + } + return( ( STREAM::Initialize() ) && Result ); +} + + + +ULONG +BUFFER_STREAM::FlushBuffer ( + ) + +/*++ + +Routine Description: + + Empty the buffer. The contents of the buffer is lost, and the + buffer is reinitialized. + +Arguments: + + None. + +Return Value: + + ULONG - Returns the number of bytes lost in the buffer. + +--*/ + +{ + ULONG BytesLost; + + BytesLost = _BytesInBuffer; + _CurrentByte = NULL; + _BytesInBuffer = 0; + return( BytesLost ); +} + + + +BOOLEAN +BUFFER_STREAM::IsAtEnd( + ) CONST + +/*++ + +Routine Description: + + Informs the caller if all bytes were read (the buffer is empty and + end of file has occurred. + +Arguments: + + None. + +Return Value: + + BOOLEAN - TRUE indicates that there is no more byte to read. + + +--*/ + +{ + return( ( _BytesInBuffer == 0 ) && EndOfFile() ); +} + +VOID +BUFFER_STREAM::SetStreamTypeANSI() +{ + _BufferStreamType = 0; +} + +VOID +BUFFER_STREAM::DetermineStreamType( + IN OUT PBYTE *Buffer, + IN ULONG BufferSize + ) +/*++ +Routine Description: + Sets _BufferStreamType for memory mapped files, called from + file_stream. + +Arguments: + Pointer to data & byte count. + +Return Value: + True always. +--*/ +{ + if (_BufferStreamType < 0) { + if (IsTextUnicode((LPTSTR)*Buffer, (INT)BufferSize, NULL)) { + _BufferStreamType = 1; + if (*((LPWCH)*Buffer) == (WCHAR)0xfeff) + *Buffer+= 2 ; // eat the Byte Order Mark + } + else + _BufferStreamType = 0; + } +} + + +BOOLEAN +BUFFER_STREAM::Read( + OUT PBYTE Buffer, + IN ULONG BytesToRead, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Reads data from the buffer. + +Arguments: + + Buffer - Points to the buffer where the data will be put. + + BytesToRead - Indicates total number of bytes to read. + + BytesRead - Points to the variable that will contain the number of + bytes read. + + +Return Value: + + BOOLEAN - Returns TRUE if the read operation succeeded. If there was no + data to be read, the return value will be TRUE (to indicate + success), but BytesRead will be zero. + + +--*/ + +{ + ULONG BytesReadSoFar; + + DebugPtrAssert( Buffer ); + + if( BytesToRead <= _BytesInBuffer ) { + // + // If the buffer contains more bytes than requested, then + // just transfer bytes from one buffer to the other + // + memmove( Buffer, _CurrentByte, ( size_t )BytesToRead ); + _BytesInBuffer -= BytesToRead; + if( _BytesInBuffer != 0 ) { + _CurrentByte += BytesToRead; + } else { + _CurrentByte = NULL; + } + *BytesRead = BytesToRead; + return( TRUE ); + } + + // + // Buffer contains less bytes than the total number requested. + // Transfer all bytes in the buffer to the caller's buffer + // + memmove( Buffer, _CurrentByte, ( size_t )_BytesInBuffer ); + BytesReadSoFar = _BytesInBuffer; + _CurrentByte = _Buffer; + BytesToRead -= _BytesInBuffer; + _BytesInBuffer = 0; + // + // Refill the buffer and transfer bytes to the caller's buffer + // until all bytes are read or end of file occurs. + // + while( ( BytesToRead > 0 ) && !EndOfFile() ) { + if( !FillBuffer( _Buffer, _BufferSize, &_BytesInBuffer ) ) { + _BytesInBuffer = 0; + return( FALSE ); + } + if( BytesToRead >= _BytesInBuffer ) { + memmove( Buffer, _Buffer, ( size_t )_BytesInBuffer ); + Buffer += _BytesInBuffer; + BytesReadSoFar += _BytesInBuffer; + BytesToRead -= _BytesInBuffer; + _BytesInBuffer = 0; + } else { + memmove( Buffer, _Buffer, ( size_t )BytesToRead ); + BytesReadSoFar += BytesToRead; + _CurrentByte += BytesToRead; + _BytesInBuffer -= BytesToRead; + BytesToRead = 0; + } + } + *BytesRead = BytesReadSoFar; + return( TRUE ); +} + + +BOOLEAN +BUFFER_STREAM::AdvanceBufferPointer( + IN ULONG Offset + ) + +/*++ + +Routine Description: + + Adds an offset to the pointer to the current byte. + (It has the effect of removing the first 'offset' bytes from the + buffer.) + +Arguments: + + Offset - Number of bytes to remove from the buffer. + +Return Value: + + BOOLEAN - Returns TRUE if the pointer was advanced, or FALSE if the + offset was greater than the number of bytes in the buffer. + + +--*/ + +{ + BOOLEAN Result; + + if( Offset <= _BytesInBuffer ) { + _BytesInBuffer -= Offset; + _CurrentByte = ( _BytesInBuffer == 0 ) ? NULL : _CurrentByte + Offset; + Result = TRUE; + } else { + Result = FALSE; + } + return( Result ); +} + + + +PCBYTE +BUFFER_STREAM::GetBuffer( + PULONG BytesInBuffer + ) + +/*++ + +Routine Description: + + Returns to the caller the pointer to the buffer. If the buffer + is empty, then it fills the buffer. + +Arguments: + + BytesInBuffer - Points to the variable that will contain the number + of bytes added to the buffer. + + +Return Value: + + PCBYTE - Pointer to the buffer. + +--*/ + +{ + if( _BytesInBuffer == 0 ) { + if( !EndOfFile() ) { + FillBuffer( _Buffer, _BufferSize, &_BytesInBuffer ); + _CurrentByte = _Buffer; + } else { + _CurrentByte = NULL; + } + } + + if (_BufferStreamType < 0) { + if (IsTextUnicode((LPTSTR)_CurrentByte, (INT)_BufferSize, NULL) && + (_BufferSize > 1) ) { + + _BufferStreamType = 1; + if (*((LPWCH)_CurrentByte)==0xfeff) { + _CurrentByte+=2; // eat the Byte Order Mark + } + } else { + _BufferStreamType = 0; + } + } + *BytesInBuffer = _BytesInBuffer; + return( _CurrentByte ); +} + + +BOOLEAN +BUFFER_STREAM::ReadChar( + OUT PWCHAR Char, + IN BOOLEAN Unicode + ) + +/*++ + +Routine Description: + + Reads a character off the stream + +Arguments: + + Char - Supplies pointer to wide character. + +Return Value: + + TRUE if a character was read, + FALSE otherwise + +Notes: + + We always read the character from the stream as a multibyte character + and do the multibyte to wide character conversion. + +--*/ + +{ + + PBYTE Buffer; + ULONG BytesInBuffer; + USHORT BytesInChar; + + if (!Char || ((Buffer = (PBYTE)GetBuffer( &BytesInBuffer)) == NULL )) { + return FALSE; + } + // + // Buffer may be a pointer to a file mapped in memory. For this + // reason we have to be aware of exception while accessing it. + // + DebugAssert( _BufferStreamType >= 0 ); + if (_BufferStreamType == 0 && !Unicode) { + __try { + if( !( *Buffer ) ) { + // + // The first character in the buffer is a NULL. Return ZERO + // as the character read. + // + BytesInChar = 1; + Char = 0; + } else { + BytesInChar = (USHORT)mbtowc( (wchar_t *)Char, (char *)Buffer, (size_t)BytesInBuffer ); + } + } + __except( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ) { + return( FALSE ); + } + } else { + __try { + if( !( *((wchar_t *)Buffer) ) ) { + // + // The first character in the buffer is a NULL. Return ZERO + // as the character read. + // + BytesInChar = 2; + Char = 0; + } else { + BytesInChar = 2; + Char = (wchar_t *)Buffer; + } + } + __except( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ) { + return( FALSE ); + } + } + + if ( BytesInChar == 0 ) { + return FALSE; + } + + AdvanceBufferPointer( BytesInChar ); + + return TRUE; + +} + +//disable C4509 warning about nonstandard ext: SEH + destructor +#pragma warning(disable:4509) + + +BOOLEAN +BUFFER_STREAM::ReadString( + OUT PWSTRING String, + IN PWSTRING Delimiters, + IN BOOLEAN Unicode + ) + +/*++ + +Routine Description: + + Reads a string off the stream + +Arguments: + + String - Supplies pointer to string. The string must have been + previously initialized. + Delimiter - Supplies the set of characters that constitute a + string delimiter. + +Return Value: + + TRUE if a string was read, + FALSE otherwise + +--*/ + +{ + PCVOID pBuffer; + ULONG BytesInBuffer; + ULONG BytesConsumed; + BOOLEAN EndOfString; + PSTR delim; + PWSTR delim_U; + BOOLEAN r; + FSTRING fstring; + CHNUM old_string_length; + + DebugPtrAssert( String ); + + String->Truncate(); + + EndOfString = FALSE; + + // + // Since the buffer might not contain the entire string, we keep + // converting the buffer and concatenating to the string, until + // we reach a delimiter (or there is no more input). + // + while ( !EndOfString ) { + + // + // Get pointer into buffer + // + pBuffer = (PCVOID)GetBuffer( &BytesInBuffer ); + if ( BytesInBuffer == 0 ) { + // + // No more input + // + break; + } + + // + // Concatenate the buffer obtained to the one we have + // + // + // pBuffer may be a pointer to a file mapped in memory. For this + // reason we have to be aware of exception while accessing it. + // + DebugAssert( _BufferStreamType >= 0 ); + if ( _BufferStreamType == 0 && !Unicode) { + __try { + if (delim = Delimiters->QuerySTR()) { + // + // If pBuffer points to a file mapped in memory, and the + // end of the file is in a page boundary, and the last + // byte in the file is neither NUL nor one of the delimiters, + // we get an access violation. + // For this reason we call strcspn inside a try-except, and + // if an access violation occurs we consume all bytes in + // the buffer. + // The access violation will not occur if the end of the file + // is not in a page boundary. In this case, it is guaranteed that + // the remaining bytes on the last page will be 0s. + // + // The access violation will not occur if pBuffer points to the + // buffer defined in this class. In this case, it is guaranteed + // that the byte immediately after the end of the buffer is NUL + // (see the initialization of this object). + // + + __try { + BytesConsumed = strcspn((PCSTR) pBuffer, delim); + } + __except( GetExceptionCode() == STATUS_ACCESS_VIOLATION ) { + BytesConsumed = BytesInBuffer; + } + DELETE(delim); + old_string_length = String->QueryChCount(); + if (r = String->Resize(old_string_length + BytesConsumed)) { + fstring.Initialize((PWSTR) String->GetWSTR() + + old_string_length, BytesConsumed + 1); + r = fstring.WSTRING::Initialize((PCSTR) pBuffer, + BytesConsumed); + String->SyncLength(); + } + } else { + r = FALSE; + } + } + __except( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ) { + return( FALSE ); + } + + EndOfString = (BytesConsumed < BytesInBuffer); + + } else { + __try { + if (delim_U = Delimiters->QueryWSTR()) { + __try { + BytesConsumed = wcscspn((wchar_t *) pBuffer, delim_U)*sizeof(WCHAR); + } + __except( GetExceptionCode() == STATUS_ACCESS_VIOLATION ) { + BytesConsumed = BytesInBuffer; + } + if((BytesInBuffer & 0xfffe) != BytesInBuffer){ + BytesInBuffer++; + } + + DELETE(delim_U); + old_string_length = String->QueryChCount(); + if (r = String->Resize(old_string_length + BytesConsumed/sizeof(WCHAR))) { + fstring.Initialize((PWSTR)String->GetWSTR() + + old_string_length, BytesConsumed/sizeof(WCHAR) + 1); + r = fstring.WSTRING::Initialize((PCWSTR) pBuffer, + BytesConsumed/sizeof(WCHAR)); + String->SyncLength(); + } + } else { + r = FALSE; + } + } + __except( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ) { + return( FALSE ); + } + EndOfString = (BytesConsumed < BytesInBuffer); + } + + //EndOfString = (BytesConsumed < BytesInBuffer); + + DebugAssert( (BytesConsumed > 0) || EndOfString ); + + // + // Advance the buffer pointer the ammount consumed + // + if (r) { + if (!AdvanceBufferPointer( BytesConsumed )) { + break; + } + } + } + + return TRUE; + +} + + + + +BOOLEAN +BUFFER_STREAM::ReadMbString( + IN PSTR String, + IN DWORD BufferSize, + INOUT PDWORD StringSize, + IN PSTR Delimiters, + IN BOOLEAN ExpandTabs, + IN DWORD TabExp + ) + +/*++ + +Routine Description: + +Arguments: + + +Return Value: + +--*/ + +{ + + DWORD StrSize; + BOOLEAN EndOfString; + PCVOID pBuffer; + ULONG BytesInBuffer; + ULONG BytesConsumed; + BYTE Byte; + DWORD NumBytes; + DWORD ChunkSize; + DWORD Spaces; + PBYTE pBuf; + + DebugPtrAssert( String ); + DebugPtrAssert( BufferSize ); + DebugPtrAssert( Delimiters ); + + *String = '\0'; + StrSize = 0; + EndOfString = FALSE; + + // + // Since the buffer might not contain the entire string, we keep + // converting the buffer and concatenating to the string, until + // we reach a delimiter (or there is no more input). + // + while ( !EndOfString ) { + + // + // Get pointer into buffer + // + pBuffer = (PCVOID)GetBuffer( &BytesInBuffer ); + + if ( BytesInBuffer == 0 ) { + // + // No more input + // + break; + } + + // + // Concatenate the buffer obtained to the one we have + // + // + // pBuffer may be a pointer to a file mapped in memory. For this + // reason we have to be aware of exception while accessing it. + // + __try { + // + // If pBuffer points to a file mapped in memory, and the + // end of the file is in a page boundary, and the last + // byte in the file is neither NUL nor one of the delimiters, + // we get an access violation. + // For this reason we call strcspn inside a try-except, and + // if an access violation occurs we consume all bytes in + // the buffer. + // The access violation will not occur if the end of the file + // is not in a page boundary. In this case, it is guaranteed that + // the remaining bytes on the last page will be 0s. + // + // The access violation will not occur if pBuffer points to the + // buffer defined in this class. In this case, it is guaranteed + // that the byte immediately after the end of the buffer is NUL + // (see the initialization of this object). + // + __try { + BytesConsumed = MBSTR::Strcspn( (PSTR)pBuffer, Delimiters ); + } + __except( GetExceptionCode() == STATUS_ACCESS_VIOLATION ) { + BytesConsumed = BytesInBuffer; + } + + if ( BytesConsumed < BytesInBuffer ) { + EndOfString = TRUE; + } + + if ( ExpandTabs ) { + + // + // Expand tabs + // + ChunkSize = BytesConsumed; + NumBytes = BufferSize - StrSize - 1; + + pBuf = (PBYTE)pBuffer; + + while ( ChunkSize-- && NumBytes ) { + + Byte = *pBuf++; + + if ( Byte != '\t' ) { + + String[StrSize++] = Byte; + NumBytes--; + + } else { + + Spaces = min (TabExp - (StrSize % TabExp), NumBytes); + MBSTR::Memset( &String[StrSize], ' ', Spaces ); + StrSize += Spaces; + NumBytes -= Spaces; + } + } + ChunkSize++; + + if ( ChunkSize > 0 ) { + EndOfString = TRUE; + BytesConsumed -= ChunkSize; + } + + } else { + + // + // Just copy string + // + if ( BytesConsumed >= (BufferSize-StrSize) ) { + BytesConsumed = BufferSize - StrSize - 1; + EndOfString = TRUE; + } + + MBSTR::Memcpy( &String[StrSize], (PVOID) pBuffer, BytesConsumed ); + StrSize += BytesConsumed; + } + + } + __except( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ) { + return( FALSE ); + } + + DebugAssert( (BytesConsumed > 0) || EndOfString ); + + // + // Advance the buffer pointer the ammount consumed + // + if( BytesConsumed < BytesInBuffer ) { + // + // Get rid of the delimiter + // This is to improve the performance of FC, who calls + // STREAM::ReadMbLine several times + // + BytesConsumed++; + } + AdvanceBufferPointer( BytesConsumed ); + + } + + String[StrSize] = '\0'; + + *StringSize = StrSize; + + return TRUE; +} + + +BOOLEAN +BUFFER_STREAM::ReadWString( + IN PWSTR String, + IN DWORD BufferSize, // char count + INOUT PDWORD StringSize, // char count + IN PWSTR Delimiters, + IN BOOLEAN ExpandTabs, + IN DWORD TabExp + ) + +/*++ + +Routine Description: + +Arguments: + + +Return Value: + +--*/ + +{ + + DWORD StrSize; + BOOLEAN EndOfString; + PCVOID pBuffer; + ULONG BytesInBuffer; + ULONG BytesConsumed; + WCHAR Byte; + DWORD NumBytes; + DWORD ChunkSize; + DWORD Spaces; + PWCHAR pBuf; + + DebugPtrAssert( String ); + DebugPtrAssert( BufferSize ); + DebugPtrAssert( Delimiters ); + + *String = L'\0'; + StrSize = 0; + EndOfString = FALSE; + + // + // Since the buffer might not contain the entire string, we keep + // converting the buffer and concatenating to the string, until + // we reach a delimiter (or there is no more input). + // + while ( !EndOfString ) { + + // + // Get pointer into buffer + // + pBuffer = (PCVOID)GetBuffer( &BytesInBuffer ); + + if ( BytesInBuffer == 0 ) { + // + // No more input + // + break; + } + + // + // Concatenate the buffer obtained to the one we have + // + // + // pBuffer may be a pointer to a file mapped in memory. For this + // reason we have to be aware of exception while accessing it. + // + __try { + // + // If pBuffer points to a file mapped in memory, and the + // end of the file is in a page boundary, and the last + // byte in the file is neither NUL nor one of the delimiters, + // we get an access violation. + // For this reason we call strcspn inside a try-except, and + // if an access violation occurs we consume all bytes in + // the buffer. + // The access violation will not occur if the end of the file + // is not in a page boundary. In this case, it is guaranteed that + // the remaining bytes on the last page will be 0s. + // + // The access violation will not occur if pBuffer points to the + // buffer defined in this class. In this case, it is guaranteed + // that the byte immediately after the end of the buffer is NUL + // (see the initialization of this object). + // + __try { + BytesConsumed = wcscspn( (unsigned short *)pBuffer, Delimiters )*sizeof(WCHAR); + } + __except( GetExceptionCode() == STATUS_ACCESS_VIOLATION ) { + BytesConsumed = BytesInBuffer&0xFFFE; + } + + if ( BytesConsumed < BytesInBuffer ) { + EndOfString = TRUE; + } + + if ( ExpandTabs ) { + + // + // Expand tabs + // + ChunkSize = BytesConsumed/sizeof(WCHAR); + NumBytes = BufferSize - StrSize - 1; + + pBuf = (PWCHAR)pBuffer; + + while ( (ChunkSize--) && NumBytes ) { + + Byte = *pBuf++; + + if ( Byte != L'\t' ) { + + String[StrSize++] = Byte; + NumBytes--; + + } else { + + Spaces = min (TabExp - (StrSize % TabExp), NumBytes); + // wcsnset( (wchar_t *)&String[StrSize], L' ', Spaces ); + for (DWORD ii=0;ii<Spaces;ii++) { + String[StrSize+ii] = L' '; + } + StrSize += Spaces; + NumBytes -= Spaces; + } + } + ChunkSize++; + + if ( ChunkSize > 0 ) { + EndOfString = TRUE; + BytesConsumed = BytesConsumed - sizeof(WCHAR)*ChunkSize; + } + + } else { + + // + // Just copy string + // + if ( BytesConsumed >= (BufferSize-StrSize)*sizeof(WCHAR) ) { + BytesConsumed = (BufferSize - StrSize - 1)*sizeof(WCHAR); + EndOfString = TRUE; + } + + MBSTR::Memcpy( &String[StrSize], (PVOID) pBuffer, BytesConsumed ); + StrSize += BytesConsumed/sizeof(WCHAR); + } + + } + __except( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ) { + return( FALSE ); + } + + DebugAssert( (BytesConsumed > 0) || EndOfString ); + + // + // Advance the buffer pointer the ammount consumed + // + if( BytesConsumed < BytesInBuffer ) { + // + // Get rid of the delimiter + // This is to improve the performance of FC, who calls + // STREAM::ReadWLine several times + // + BytesConsumed+=2; + } + AdvanceBufferPointer( BytesConsumed ); + + } + + String[StrSize] = 0; + + *StringSize = StrSize; + + return TRUE; +} + diff --git a/private/utils/ulib/src/bytestrm.cxx b/private/utils/ulib/src/bytestrm.cxx new file mode 100644 index 000000000..3986f8031 --- /dev/null +++ b/private/utils/ulib/src/bytestrm.cxx @@ -0,0 +1,189 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + bytestrm.cxx + +Abstract: + + This module contains the definitions of the member functions + of BYTE_STREAM class. + +Author: + + Ramon J. San Andres (ramonsa) 28-Feb-1992 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "stream.hxx" +#include "bytestrm.hxx" + +DEFINE_EXPORTED_CONSTRUCTOR( BYTE_STREAM, OBJECT, ULIB_EXPORT ); + +VOID +BYTE_STREAM::Construct ( + ) + +/*++ + +Routine Description: + + Constructs a BYTE_STREAM object + +Arguments: + + None. + +Return Value: + + None. + + +--*/ + +{ + _Stream = NULL; + _Buffer = NULL; + _NextByte = NULL; + _BufferSize = 0; + _BytesInBuffer = 0; +} + + + +ULIB_EXPORT +BYTE_STREAM::~BYTE_STREAM ( + ) + +/*++ + +Routine Description: + + Destroy a BYTE_STREAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + FREE( _Buffer ); +} + + + + + + +ULIB_EXPORT +BOOLEAN +BYTE_STREAM::Initialize ( + IN PSTREAM Stream, + IN DWORD BufferSize + ) + +/*++ + +Routine Description: + + Initializes a BYTE_STREAM + +Arguments: + + Stream - Supplies the stream to be used + BufferSize - Supplies the size of the buffer to use + +Return Value: + + BOOLEAN - TRUE if successful. + +--*/ + +{ + STREAMACCESS Access; + + DebugPtrAssert( Stream ); + DebugAssert( BufferSize > 0 ); + + FREE( _Buffer ); + + Access = Stream->QueryAccess(); + + if ( (Access == READ_ACCESS) || (Access == READ_AND_WRITE_ACCESS)) { + + if ( _Buffer = (PBYTE)MALLOC( BufferSize ) ) { + + _Stream = Stream; + _NextByte = _Buffer; + _BufferSize = BufferSize; + _BytesInBuffer = 0; + + return TRUE; + + } + } + + return FALSE; +} + + + +ULIB_EXPORT +BOOLEAN +BYTE_STREAM::FillAndReadByte( + IN PBYTE Byte + ) +/*++ + + +Routine Description: + + Fills the buffer and reads next byte + +Arguments: + + Byte - Supplies pointer to where to put the byte + +Return Value: + + BOOLEAN - TRUE if byte read. + +--*/ + +{ + ULONG BytesRead; + + DebugAssert( _BytesInBuffer == 0 ); + + if ( _Stream->Read( _Buffer, _BufferSize, &BytesRead ) && + (BytesRead > 0) ) { + + _NextByte = _Buffer; + _BytesInBuffer = (DWORD)BytesRead; + + *Byte = *_NextByte++; + _BytesInBuffer--; + + return TRUE; + + } + + return FALSE; +} diff --git a/private/utils/ulib/src/clasdesc.cxx b/private/utils/ulib/src/clasdesc.cxx new file mode 100644 index 000000000..983c91acf --- /dev/null +++ b/private/utils/ulib/src/clasdesc.cxx @@ -0,0 +1,124 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + clasdesc.cxx + +Abstract: + + This module contains the definition for the CLASS_DESCRIPTOR class. + CLASS_DESCRIPTOR classes are special concrete classes derived from + OBJECT. They are special in that a single staic object of this class + exists for every other concrete class in the Ulib hierarchy. + CLASS_DESCRIPTORs allocate and maintain information that can be used + at run-time to determine the actual type of an object. + +Author: + + David J. Gilman (davegi) 30-Oct-1990 + +Environment: + + ULIB, User Mode + +Notes: + + The definitions for all concrete class' CLASS_DESCRIPTORs can be found + in the file ulib.cxx. + + See the Cast member function in ulibdef.hxx to see how dynamic casting + and CLASS_DESCRIPTORs work. + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" + + +ULIB_EXPORT +CLASS_DESCRIPTOR::CLASS_DESCRIPTOR ( + ) +{ +} + +#if DBG==1 + +// +// For debugging purposes CLASS_DESCRIPTORs maintain the name of the class +// that they describe. +// + +#include <string.h> + +ULIB_EXPORT +BOOLEAN +CLASS_DESCRIPTOR::Initialize ( + IN PCCLASS_NAME ClassName + ) + +/*++ + +Routine Description: + + Initialize a CLASS_DESCRIPTOR object by initializing the classname + and class ids. + +Arguments: + + ClassName - Supplies the name of the class being described. + +Return Value: + + None. + +--*/ + +{ + DebugPtrAssert( ClassName ); + strncpy(( PCCHAR ) _ClassName, + ( PCCCHAR ) ClassName, + ( INT ) _MaxClassNameLength ); + + // + // Note that this guarantees that the CLASS_ID is unique for all classes + // at the expense of not being able to recognize a class based on it's + // CLASS_ID. The benefit is that IDs are guaranteed to be unique and + // do not have to be cleared or registered. + // + + _ClassID = ( ULONG ) &_ClassID; + return( TRUE ); +} + +#else // DBG==0 + +ULIB_EXPORT +BOOLEAN +CLASS_DESCRIPTOR::Initialize ( + ) + +/*++ + +Routine Description: + + Initialize a CLASS_DESCRIPTOR object by initializing the class id. + +Arguments: + +Return Value: + + None. + +--*/ + +{ + _ClassID = ( ULONG ) &_ClassID; + return( TRUE ); +} + +#endif // DBG diff --git a/private/utils/ulib/src/cmem.cxx b/private/utils/ulib/src/cmem.cxx new file mode 100644 index 000000000..bf13aefc7 --- /dev/null +++ b/private/utils/ulib/src/cmem.cxx @@ -0,0 +1,107 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ +#include "ulib.hxx" +#include "cmem.hxx" +#include "error.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR( CONT_MEM, MEM, ULIB_EXPORT ); + +VOID +CONT_MEM::Construct ( + ) +/*++ + +Routine Description: + + Constructor for CONT_MEM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _buf = NULL; + _size = 0; +} + + +ULIB_EXPORT +BOOLEAN +CONT_MEM::Initialize( + IN PVOID Buffer, + IN ULONG Size + ) +/*++ + +Routine Description: + + This routine supplies the object with a store of memory from which to + work with. + +Arguments: + + Buffer - Supplies a pointer to memory. + Size - Supplies the number of bytes of memory addressable through + the pointer. + +Return Value: + + None. + +--*/ +{ + _buf = Buffer; + _size = Size; + + return TRUE; +} + + +ULIB_EXPORT +PVOID +CONT_MEM::Acquire( + IN ULONG Size, + IN ULONG AlignmentMask + ) +/*++ + +Routine Description: + + This routine takes size bytes of memory from the current memory + pool and returns it to the user. If size bytes of memory are not + available then this routine return NULL. After a call to this routine + the local pool of memory is decreased by Size bytes. Successive requests + will be granted as long as there is sufficient memory to grant them. + + This method will fail if the memory is not at the alignment requested. + +Arguments: + + Size - Supplies the number of bytes of memory requested. + Alignment - Supplies the necessary alignment for the memory. + +Return Value: + + A pointer to size bytes of memory or NULL. + +--*/ +{ + PVOID rv; + + if (Size > _size || + ((ULONG) _buf)&AlignmentMask) { + return NULL; + } + + _size -= Size; + rv = _buf; + _buf = (PCHAR) _buf + Size; + return rv; +} diff --git a/private/utils/ulib/src/comm.cxx b/private/utils/ulib/src/comm.cxx new file mode 100644 index 000000000..f951d6754 --- /dev/null +++ b/private/utils/ulib/src/comm.cxx @@ -0,0 +1,700 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + COMM_DEVICE + +Abstract: + + This module contains the implementation for the COMM_DEVICE class. + +Author: + + Ramon J. San Andres (ramonsa) 08-Jul-1991 + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "comm.hxx" +#include "file.hxx" + + +// +// Default timeout is one minute +// +#define DEFAULT_TIMEOUT 60000 + + + +DEFINE_EXPORTED_CONSTRUCTOR( COMM_DEVICE, OBJECT, ULIB_EXPORT ); + +DEFINE_CAST_MEMBER_FUNCTION( COMM_DEVICE ); + +ULIB_EXPORT +COMM_DEVICE::~COMM_DEVICE( + ) +{ + Destroy(); +} + +VOID +COMM_DEVICE::Construct ( + ) + +/*++ + +Routine Description: + + Constructs a COMM_DEVICE object + +Arguments: + + None. + +Return Value: + + None. + + +--*/ + +{ + _Handle = NULL; + +#if DBG==1 + + _Initialized = FALSE; + +#endif + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::Initialize ( + IN PCPATH PortName, + OUT PBOOLEAN OpenError + ) + +/*++ + +Routine Description: + + Phase 2 of construction for a COMM_DEVICE. + +Arguments: + + Port - Supplies pointer to the FSN_FILE object of the port. + OpenError - Supplies pointer to flag which if TRUE means that + the port could not be openend. + +Return Value: + + BOOLEAN - TRUE if the serial port was successfully initialized, + FALSE otherwise. + +--*/ + +{ + DSTRING QualifiedName; + BOOLEAN InitOk; + + DebugPtrAssert( PortName ); + + Destroy(); + + if( !QualifiedName.Initialize( L"\\\\.\\" ) || + !QualifiedName.Strcat( PortName->GetPathString() ) ) { + + if( OpenError ) { + *OpenError = FALSE; + } + return FALSE; + } + + // + // Open the Port and get a handle to it. + // + _Handle = CreateFile( QualifiedName.GetWSTR(), + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL ); + + + if ( _Handle != INVALID_HANDLE_VALUE ) { + + if ( OpenError ) { + *OpenError = FALSE; + } + + // + // Get the current port state + // + InitOk = GetCommState( _Handle, &_Dcb ); + +#if DBG==1 + GetLastError(); +#endif + +#if DBG==1 + + _Initialized = InitOk; + +#endif + + } else if ( OpenError ) { + *OpenError = TRUE; + } + + return InitOk; +} + +VOID +COMM_DEVICE::Destroy ( + ) + +/*++ + +Routine Description: + + Brings the object to a point at which it can be initialized. + +Arguments: + + none + +Return Value: + + none + +--*/ + +{ + + if ( _Handle != INVALID_HANDLE_VALUE ) { + + CloseHandle( _Handle ); + + _Handle = INVALID_HANDLE_VALUE; + + } + +#if DBG==1 + + _Initialized = FALSE; + +#endif + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::CommitState ( + ) + +/*++ + +Routine Description: + + Sets the port state. + +Arguments: + + none + +Return Value: + + BOOLEAN - TRUE if state set + FALSE otherwise. + +--*/ + +{ + + DebugAssert( _Initialized ); + + return SetCommState( _Handle, &_Dcb ); + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::QueryTimeOut ( + ) CONST + +/*++ + +Routine Description: + + Queries whether infinite timeouts are enabled or not. + +Arguments: + + none + +Return Value: + + BOOLEAN - TRUE if infinite timeouts are enabled + FALSE otherwise. + +--*/ + +{ + COMMTIMEOUTS TimeOut; + + DebugAssert( _Initialized ); + + GetCommTimeouts( _Handle, &TimeOut ); + + return ( (TimeOut.ReadTotalTimeoutConstant == 0) && + (TimeOut.WriteTotalTimeoutConstant == 0) ); + +} + +BOOLEAN +COMM_DEVICE::ReadState ( + ) + +/*++ + +Routine Description: + + Gets the current port state. + +Arguments: + + none + +Return Value: + + BOOLEAN - TRUE if state read + FALSE otherwise. + +--*/ + +{ + + DebugAssert( _Initialized ); + + return GetCommState( _Handle, &_Dcb ); + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetBaudRate ( + IN ULONG BaudRate + ) + +/*++ + +Routine Description: + + Sets the baud rate. Note that all changes take effect only after the + CommitState() method is called. + +Arguments: + + BaudRate - Supplies the baud rate + +Return Value: + + BOOLEAN - TRUE if valid baud rate + FALSE otherwise + +--*/ + +{ + + DebugAssert( _Initialized ); + + _Dcb.BaudRate = BaudRate; + + return TRUE; + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetDataBits ( + IN ULONG DataBits + ) + +/*++ + +Routine Description: + + Sets the number of data bits. Note that all changes take effect only + after the CommitState() method is called. + +Arguments: + + DataBits - Supplies the number of data bits + +Return Value: + + BOOLEAN - TRUE if valid number of data bits + FALSE otherwise + +--*/ + +{ + + DebugAssert( _Initialized ); + + _Dcb.ByteSize = (BYTE)DataBits; + + return TRUE; + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetDtrControl ( + IN DTR_CONTROL DtrControl + ) + +/*++ + +Routine Description: + + Sets the DTR control. Note that all changes take effect only + after the CommitState() method is called. + +Arguments: + + DtrControl - Supplies the DTR control value + +Return Value: + + BOOLEAN - TRUE if valid DTR control + FALSE otherwise + +--*/ + +{ + + DebugAssert( _Initialized ); + + if ( (DtrControl == DTR_ENABLE) || + (DtrControl == DTR_DISABLE) || + (DtrControl == DTR_HANDSHAKE) ) { + + _Dcb.fDtrControl = (DWORD)DtrControl; + return TRUE; + } + + return FALSE; +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetIdsr ( + IN BOOLEAN Idsr + ) + +/*++ + +Routine Description: + + Enables/disables DSR sensitivity + +Arguments: + + Odsr - Supplies a flag which if TRUE, enables DSR sensitivity + if FALSE, it disables it. + +Return Value: + + BOOLEAN - TRUE if DSR sensitivity enabled/disabled, FALSE otherwise. + +--*/ + +{ + DebugAssert( _Initialized ); + + if ( Idsr ) { + _Dcb.fDsrSensitivity = TRUE; + } else { + _Dcb.fDsrSensitivity = FALSE; + } + + return TRUE; +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetOcts ( + IN BOOLEAN Octs + ) + +/*++ + +Routine Description: + + Sets/resets CTS handshaking + +Arguments: + + Octs - Supplies a flag which if TRUE, enables CTS handshaking, + if FALSE, it disables it. + +Return Value: + + BOOLEAN - TRUE if handshaking enabled/disabled, FALSE otherwise. + +--*/ + +{ + DebugAssert( _Initialized ); + + if ( Octs ) { + _Dcb.fOutxCtsFlow = TRUE; + } else { + _Dcb.fOutxCtsFlow = FALSE; + } + + return TRUE; +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetOdsr ( + IN BOOLEAN Odsr + ) + +/*++ + +Routine Description: + + Sets/resets DSR handshaking + +Arguments: + + Odsr - Supplies a flag which if TRUE, enables DSR handshaking, + if FALSE, it disables it. + +Return Value: + + BOOLEAN - TRUE if handshaking enabled/disabled, FALSE otherwise. + +--*/ + +{ + DebugAssert( _Initialized ); + + if ( Odsr ) { + _Dcb.fOutxDsrFlow = TRUE; + } else { + _Dcb.fOutxDsrFlow = FALSE; + } + + return TRUE; +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetParity ( + IN PARITY Parity + ) + +/*++ + +Routine Description: + + Sets the parity. Note that all changes take effect only after the + CommitState() method is called. + +Arguments: + + Parity - Supplies the parity value + +Return Value: + + BOOLEAN - TRUE if valid parity + FALSE otherwise + +--*/ + +{ + + + DebugAssert( _Initialized ); + + DebugAssert( (Parity == COMM_PARITY_NONE) || (Parity == COMM_PARITY_ODD) || + (Parity == COMM_PARITY_EVEN) || (Parity == COMM_PARITY_MARK) || + (Parity == COMM_PARITY_SPACE)); + + _Dcb.Parity = (BYTE)Parity; + + return TRUE; + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetRtsControl ( + IN RTS_CONTROL RtsControl + ) + +/*++ + +Routine Description: + + Sets the RTS control. Note that all changes take effect only + after the CommitState() method is called. + +Arguments: + + RtsControl - Supplies the RTS control value + +Return Value: + + BOOLEAN - TRUE if valid RTS control + FALSE otherwise + +--*/ + +{ + + DebugAssert( _Initialized ); + + if ( (RtsControl == RTS_ENABLE) || + (RtsControl == RTS_DISABLE) || + (RtsControl == RTS_HANDSHAKE) || + (RtsControl == RTS_TOGGLE ) + ) { + + _Dcb.fRtsControl = (DWORD)RtsControl; + return TRUE; + } + + return FALSE; +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetStopBits ( + IN STOPBITS StopBits + ) + +/*++ + +Routine Description: + + Sets the number of stop bits. Note that all changes take effect + only after the CommitState() method is called. + +Arguments: + + StopBits - Supplies the number of stop bits + +Return Value: + + BOOLEAN - TRUE if valid number of stop bits + FALSE otherwise + +--*/ + +{ + + DebugAssert( _Initialized ); + + DebugAssert( (StopBits == COMM_STOPBITS_1) || (StopBits == COMM_STOPBITS_15) || + (StopBits == COMM_STOPBITS_2) ); + + _Dcb.StopBits = (BYTE)StopBits; + + return TRUE; + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetTimeOut ( + IN BOOLEAN TimeOut + ) + +/*++ + +Routine Description: + + Sets/resets infinite timeouts. + +Arguments: + + TimeOut - Supplies a flag which if TRUE means that infinite timeout + is to be set. if FALSE, a 1-minute timeout is set for + both reading and writting. + +Return Value: + + BOOLEAN = TRUE if timeout set, FALSE otherwise + +--*/ + +{ + COMMTIMEOUTS Time; + + DebugAssert( _Initialized ); + + GetCommTimeouts( _Handle, &Time ); + + if ( TimeOut ) { + Time.ReadTotalTimeoutConstant = 0; + Time.WriteTotalTimeoutConstant = 0; + } else { + Time.ReadTotalTimeoutConstant = DEFAULT_TIMEOUT; + Time.WriteTotalTimeoutConstant = DEFAULT_TIMEOUT; + } + + return SetCommTimeouts( _Handle, &Time ); + +} + +ULIB_EXPORT +BOOLEAN +COMM_DEVICE::SetXon ( + IN BOOLEAN Xon + ) + +/*++ + +Routine Description: + + Sets/resets XON/XOFF data-flow protocol. + +Arguments: + + Xon - Supplies flag which if TRUE, enables XON/XOFF protocol, + if FALSE, disables it. + +Return Value: + + BOOLEAN = TRUE if protocol set/reset, FALSE otherwise + +--*/ + +{ + DebugAssert( _Initialized ); + + if ( Xon ) { + _Dcb.fInX = TRUE; + _Dcb.fOutX = TRUE; + } else { + _Dcb.fInX = FALSE; + _Dcb.fOutX = FALSE; + } + + return TRUE; +} diff --git a/private/utils/ulib/src/contain.cxx b/private/utils/ulib/src/contain.cxx new file mode 100644 index 000000000..4ca6b8e8f --- /dev/null +++ b/private/utils/ulib/src/contain.cxx @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + contain.cxx + +Abstract: + + This module contains the definition for the CONTAINER class, the most + primitive, abstract class in the container sub-hierarchy. Given it's + abstract, prmitive nature there is minimal implementation at this point + in the hierarchy. + +Author: + + David J. Gilman (davegi) 02-Nov-1990 + +Environment: + + ULIB, User Mode + +--*/ +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "contain.hxx" + + +DEFINE_CONSTRUCTOR( CONTAINER, OBJECT ); + +CONTAINER::~CONTAINER( + ) +{ +} diff --git a/private/utils/ulib/src/dir.cxx b/private/utils/ulib/src/dir.cxx new file mode 100644 index 000000000..308848b9a --- /dev/null +++ b/private/utils/ulib/src/dir.cxx @@ -0,0 +1,939 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + dir.cxx + +Abstract: + + This module contains the defintion for the FSN_DIRECTORY class. + +Author: + + David J. Gilman (davegi) 09-Jan-1991 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "array.hxx" +#include "arrayit.hxx" +#include "dir.hxx" +#include "filter.hxx" +#include "wstring.hxx" +#include "path.hxx" +#include "system.hxx" + +BOOLEAN +IsDot ( + IN WCHAR *p + ); + +INLINE +BOOLEAN +IsDot ( + IN WCHAR *p + ) +/*++ + +Routine Description: + + Determines if a name is a '.' or '..' entry in a directory. + + It is only intended to be used when processing a WIN32_FIND_DATA + structure. + +Arguments: + + p - Supplies pointer to char array + +Return Value: + + BOOLEAN - Returns TRUE if the name is a '.' or '..' entry. + +--*/ +{ + + + return ( (p[0] == '.' && p[1] == '\0') || + (p[0] == '.' && p[1] == '.' && p[2] == '\0' ) ); +} + + + + +DEFINE_CONSTRUCTOR( FSN_DIRECTORY, FSNODE ); + +DEFINE_CAST_MEMBER_FUNCTION( FSN_DIRECTORY ); + +BOOLEAN +FSN_DIRECTORY::Copy ( + IN PFSN_FILTER FsnFilter, + IN PCFSN_DIRECTORY DestinationDir, + IN BOOLEAN Recurse, + IN BOOLEAN OverWrite + ) CONST + +/*++ + +Routine Description: + + Copies a set of FSNODEs to a destination directory. + +Arguments: + + FsnFilter - Supplies a pointer top a constant FSN_FILTER, which + describes the set of FSNODEs to be copied. + + DestinationDir - Supplies a pointer to a constant FSN_DIRECTORY which is + the destination of the copy. + + Recurse - Supplies a flag which if TRUE causes Copy to perform + a recursive copy if it encounters a FSN_DIRECTORY. + + OverWrite - Supplies a flag which if TRUE, allows Copy to over + write an existing destination file. + +Return Value: + + BOOLEAN - Returns TRUE if the entire Copy operation was succesful. + +--*/ + + +{ + + ULONG Files = 0; + DWORD ErrorStatus = 0; + PARRAY SrcFiles; + PARRAY_ITERATOR Iterator; + PPATH SourcePath = NULL; + LPWSTR SourcePathString = NULL; + ULONG SourceBufferSize = 0; + PPATH DestinationPath = NULL; + LPWSTR DestinationPathString = NULL; + ULONG DestinationBufferSize = 0; + ULONG BufferSize; + PFSNODE FsNode; + PWSTRING Name; + BOOLEAN ReturnValue = TRUE; + PFSN_DIRECTORY SourceDirectory = NULL; + PFSN_DIRECTORY DestinationDirectory = NULL; + + DebugPtrAssert( FsnFilter ); + DebugPtrAssert( DestinationDir ); + if ( // + // Verify arguments + // + ( FsnFilter != NULL ) && + ( DestinationDir != NULL ) && + // + // Get array of nodes for files in the directory + // + (( SrcFiles = QueryFsnodeArray( FsnFilter )) != NULL ) && + // + // Get an iterator for processing the nodes + // + (( Iterator = ( PARRAY_ITERATOR ) SrcFiles->QueryIterator( )) != NULL ) && + // + // Get paths + // + ((SourcePath = NEW PATH) != NULL) && + ((DestinationPath = DestinationDir->GetPath( )->QueryFullPath( )) != NULL) ) { + + // + // For each FSNODE in the ARRAY either: + // + // - set up and call Copy on the sub directory (based on Recurse) + // - or copy the file + // + while (( FsNode = (PFSNODE)Iterator->GetNext( )) != NULL ) { + + // + // Append the name portion of the source to the + // destination path. + // + if ( ((Name = FsNode->QueryName()) == NULL) || + !DestinationPath->AppendBase( Name ) ) { + break; + } + + + // + // Get paths and strings + // + SourcePath->Initialize( FsNode->GetPath() ); + + BufferSize = (SourcePath->GetPathString()->QueryChCount() + 1) * 2; + if ( BufferSize > SourceBufferSize ) { + if (SourceBufferSize == 0) { + SourcePathString = (LPWSTR)MALLOC((size_t)BufferSize); + } else { + SourcePathString = (LPWSTR)REALLOC( SourcePathString, (size_t)BufferSize); + } + SourceBufferSize = BufferSize; + } + + BufferSize = (DestinationPath->GetPathString()->QueryChCount() + 1) * 2; + if ( BufferSize > DestinationBufferSize ) { + if (DestinationBufferSize == 0) { + DestinationPathString = (LPWSTR)MALLOC((size_t)BufferSize); + } else { + DestinationPathString = (LPWSTR)REALLOC( DestinationPathString, (size_t)BufferSize); + } + DestinationBufferSize = BufferSize; + } + + if ( (SourcePathString == NULL) || (DestinationPathString == NULL)) { + break; + } + + SourcePath->GetPathString()->QueryWSTR(0, TO_END, SourcePathString, SourceBufferSize); + DestinationPath->GetPathString()->QueryWSTR(0, TO_END, DestinationPathString, DestinationBufferSize ); + + + if ( FsNode->IsDirectory() ) { + + // + // Copy directory + // + + CreateDirectoryEx( SourcePathString, DestinationPathString, NULL ); + + if ( Recurse ) { + + if ( ((SourceDirectory = SYSTEM::QueryDirectory( SourcePath )) != NULL) && + ((DestinationDirectory = SYSTEM::QueryDirectory( DestinationPath )) != NULL)) { + + if ( SourceDirectory->Copy( FsnFilter, + DestinationDirectory, + Recurse, + OverWrite )) { + + DELETE( SourceDirectory ); + DELETE( DestinationDirectory ); + + SourceDirectory = NULL; + DestinationDirectory = NULL; + + } else { + + break; + + } + + } else { + + break; + + } + + } + + } else { + + // + // Copy file + // + if (!CopyFile( SourcePathString, DestinationPathString, !OverWrite)) { + + ReturnValue = FALSE; + break; + } + + } + + DELETE( Name ); + + DestinationPath->TruncateBase(); + + } + + + if (SourcePathString != NULL) { + FREE( SourcePathString ); + } + + if (DestinationPathString != NULL) { + FREE( DestinationPathString ); + } + + if (SourceDirectory != NULL ) { + DELETE( SourceDirectory ); + } + + if (DestinationDirectory != NULL) { + DELETE( DestinationDirectory ); + } + + DELETE( DestinationPath ); + DELETE( SourcePath ); + DELETE( Iterator ); + DELETE( SrcFiles ); + + } + + return ReturnValue; + +} + +ULIB_EXPORT +PFSN_DIRECTORY +FSN_DIRECTORY::CreateDirectoryPath ( + IN PCPATH Path + ) CONST + +/*++ + +Routine Description: + + Creates all the directories along a path and returns the directory + of the deepest one. + +Arguments: + + Path - Supplies pointer to the path + +Return Value: + + PFSN_DIRECTORY - Returns pointer to the directory object of the + deepest directory created. + +--*/ + +{ + + PARRAY DesiredComponentArray; + PARRAY ExistingComponentArray; + PITERATOR IteratorDesired; + PITERATOR IteratorExisting; + PPATH PathToCreate; + PWSTRING DesiredComponent; + PWSTRING ExistingComponent; + BOOLEAN OkSoFar = TRUE; + PFSN_DIRECTORY Directory = NULL; + LPWSTR Buffer = NULL; + ULONG BufferSize = 0; + ULONG Size; + + + DebugPtrAssert( Path ); + + // + // Split both paths in their component parts + // + DesiredComponentArray = Path->QueryComponentArray(); + ExistingComponentArray = GetPath()->QueryComponentArray(); + + DebugPtrAssert( DesiredComponentArray ); + DebugPtrAssert( ExistingComponentArray ); + + if ( DesiredComponentArray && ExistingComponentArray ) { + + IteratorDesired = DesiredComponentArray->QueryIterator(); + IteratorExisting = ExistingComponentArray->QueryIterator(); + + DebugPtrAssert( IteratorDesired ); + DebugPtrAssert( IteratorExisting ); + + if ( IteratorDesired && IteratorExisting ) { + + // + // Make sure that the existing components are a subset of the + // desired components. + // + while (TRUE) { + + if (!(ExistingComponent = (PWSTRING)(IteratorExisting->GetNext()))) { + break; + } + + DesiredComponent = (PWSTRING)(IteratorDesired->GetNext()); + + DebugPtrAssert( DesiredComponent ); + + if ( !DesiredComponent || ( *DesiredComponent != *ExistingComponent )) { + + DebugAssert( FALSE ); + OkSoFar = FALSE; + break; + + } + } + + if ( OkSoFar ) { + + // + // Now we can start creating directories + // + // PathToCreate = GetPath()->QueryFullPath(); + PathToCreate = GetPath()->QueryPath(); + + while ( DesiredComponent = (PWSTRING)(IteratorDesired->GetNext()) ) { + + // + // One directory to create + // + PathToCreate->AppendBase( DesiredComponent, TRUE ); + + Size = (PathToCreate->GetPathString()->QueryChCount() + 1) * 2; + if ( Size > BufferSize ) { + if ( Buffer ) { + Buffer = (LPWSTR)REALLOC( Buffer, (unsigned int)Size ); + } else { + Buffer = (LPWSTR)MALLOC( (unsigned int)Size ); + } + DebugPtrAssert( Buffer ); + BufferSize = Size; + } + PathToCreate->GetPathString()->QueryWSTR( 0, TO_END, (LPWSTR)Buffer, BufferSize ); + + OkSoFar = CreateDirectory( (LPWSTR)Buffer, NULL ); + + // DebugAssert( OkSoFar ); + + } + + if ( OkSoFar ) { + + // + // Create directory object + // + Directory = SYSTEM::QueryDirectory( Path ); + DebugPtrAssert( Directory ); + } + + DELETE( PathToCreate ); + } + } + + DELETE( IteratorDesired ); + DELETE( IteratorExisting ); + + } + + DesiredComponentArray->DeleteAllMembers(); + ExistingComponentArray->DeleteAllMembers(); + + DELETE( DesiredComponentArray ); + DELETE( ExistingComponentArray ); + + return Directory; + +} + +ULIB_EXPORT +BOOLEAN +FSN_DIRECTORY::DeleteDirectory ( + ) + +/*++ + +Routine Description: + + Deltes this directory and everything underneath it. + + Note that after this, the directory object must be deleted! + +Arguments: + + none + +Return Value: + + BOOLEAN - Return TRUE if everything was deleted + +--*/ + +{ + + FSN_FILTER Filter; + PARRAY Array; + ULONG Size; + LPWSTR Buffer = NULL; + ULONG BufferSize = 0; + BOOLEAN Ok = TRUE; + PITERATOR Iterator; + PFSNODE FsNode; + + Filter.Initialize(); + Filter.SetFileName( "*.*" ); + + Array = QueryFsnodeArray( &Filter ); + + if ( Array ) { + + Iterator = ( PARRAY_ITERATOR ) Array->QueryIterator( ); + DebugPtrAssert( Iterator ); + + // + // Delete everything underneath us. + // + while ( Ok && (( FsNode = (PFSNODE)Iterator->GetNext( )) != NULL )) { + + if ( FsNode->IsDirectory() ) { + + // + // Directory, just recurse. + // + Ok = ((PFSN_DIRECTORY)FsNode)->DeleteDirectory(); + + } else { + + // + // File, delete it. + // + Size = (FsNode->GetPath()->GetPathString()->QueryChCount() + 1) * 2; + if (Size > BufferSize) { + if (Buffer == NULL) { + Buffer = (LPWSTR)MALLOC((unsigned int)Size ); + } else { + Buffer = (LPWSTR)REALLOC(Buffer, (unsigned int)Size ); + } + DebugPtrAssert(Buffer); + BufferSize = Size; + } + + FsNode->GetPath()->GetPathString()->QueryWSTR( 0, TO_END, Buffer, BufferSize ); + + Ok = DeleteFile( (LPWSTR)Buffer ); + + } + } + + DELETE( Array ); + + } + + if ( Ok ) { + // + // Commit suicide + // + Size = (GetPath()->GetPathString()->QueryChCount() + 1) * 2; + if (Size > BufferSize) { + if (Buffer == NULL) { + Buffer = (LPWSTR)MALLOC( (unsigned int)Size ); + } else { + Buffer = (LPWSTR)REALLOC(Buffer, (unsigned int)Size ); + } + DebugPtrAssert(Buffer); + BufferSize = Size; + } + + GetPath()->GetPathString()->QueryWSTR( 0, TO_END, Buffer, BufferSize ); + + Ok = RemoveDirectory( (LPWSTR)Buffer ); + + FREE( Buffer ); + + } + + return Ok; + +} + +ULIB_EXPORT +BOOLEAN +FSN_DIRECTORY::IsEmpty ( + ) CONST + +/*++ + +Routine Description: + + Determines if a directory is empty (A directory is empty if has + no entries other than "." and ".." + +Arguments: + + none + +Return Value: + + BOOLEAN - TRUE if directory is empty + FALSE otherwise + +--*/ + +{ + + + PATH Path; + FSTRING Base; + WIN32_FIND_DATA FindData; + HANDLE Handle; + BOOLEAN IsEmpty; + PFSN_DIRECTORY SubDirectory; + PATH SubPath; + DSTRING SubBase; + BOOLEAN SubEmpty; + + + IsEmpty = FALSE; + + if ( Path.Initialize( GetPath() ) && + Base.Initialize((PWSTR) L"*.*") && + Path.AppendBase( &Base ) ) { + + // + // Get the first entry + // + Handle = FindFirstFile( &Path, &FindData ); + + if ( Handle == INVALID_HANDLE_VALUE ) { + + // + // If we fail we assume that the directory + // is empty. + // + IsEmpty = TRUE; + + } else { + + if ( IsDot(FindData.cFileName) ) { + + while ( TRUE ) { + + if ( !FindNextFile( Handle, &FindData ) ) { + IsEmpty = TRUE; + break; + } + + if ( !IsDot( FindData.cFileName ) ) { + + // If this file is a sub-directory check to + // see whether or not it is empty. If it is + // empty then we still do not know whether or + // not this directory is empty. + + if (FindData.dwFileAttributes & + FILE_ATTRIBUTE_DIRECTORY) { + + if (!SubPath.Initialize(GetPath()) || + !SubBase.Initialize(FindData.cFileName) || + !SubPath.AppendBase(&SubBase) || + !(SubDirectory = + SYSTEM::QueryDirectory(&SubPath))) { + + break; + } + + SubEmpty = SubDirectory->IsEmpty(); + DELETE(SubDirectory); + + if (!SubEmpty) { + break; + } + } else { + break; + } + } + } + } + + FindClose( Handle ); + } + } else { + + DebugAssert( FALSE ); + + } + + return IsEmpty; + +} + + +ULIB_EXPORT +PARRAY +FSN_DIRECTORY::QueryFsnodeArray ( + IN PFSN_FILTER FsnFilter + ) CONST + +/*++ + +Routine Description: + + Construct and fill an ARRAY object with FSNODE object that meet the + criteria maintained by the supplied FSN_FILTER. + +Arguments: + + FsnFilter - Supplies a constant pointer to an FS_FILTER which will be + used to determine if a found 'file' should be constructed and + included in the ARRAY. + +Return Value: + + PARRAY - Returns a pointer to an ARRAY of FSNODEs. If no 'file' meets + the FSN_FILTER criteria returns a pointer to an empy array. + Returns NULL if the array couldn't be constructed or initialized. + +--*/ + +{ + REGISTER PARRAY parr; + REGISTER PFSNODE pfsn; + WIN32_FIND_DATA ffd; + PATH Path; + HANDLE hndl; + PFSN_FILTER Filter; + BOOLEAN DeleteFilter; + + + // + // If a filter was not provided, we use a default match-all + // filter. + // + if ( FsnFilter ) { + + Filter = FsnFilter; + DeleteFilter = FALSE; + + } else { + + Filter = NEW FSN_FILTER; + DebugPtrAssert( Filter ); + if (!Filter) { + return NULL; + } + Filter->Initialize(); + DeleteFilter = TRUE; + } + + // + // Initialize the ARRAY pointer + // + + parr = NULL; + + // + // Append the filter name to this DIRECTORY's name + // + + Path.Initialize( (PCPATH)&_Path, TRUE); + Path.AppendBase( Filter->GetFileName() ); + + // + // If there are found files and the ARRAY is succesfully + // constructed and initialized... + // + + if((( parr = NEW ARRAY ) != NULL ) && + ( parr->Initialize( ))) { + + if( ( hndl = FindFirstFile( &Path, &ffd )) != INVALID_HANDLE_VALUE ) { + // + // if there is at least one file that meetes the filter + // criteria, put the fsnodes in the array. Otherwise, leave + // the array empty + // + do { + + // + // If the found 'file' meets the filter criteria, put the + // returned FSNODE in the ARRAY + // + + if(( pfsn = Filter->QueryFilteredFsnode( this, &ffd )) != NULL ) { + + // + // If the FSNODE can not be put in the ARRAY + // delete it and exit the loop. + // + + if( ! ( parr->Put( pfsn ))) { + DELETE( pfsn ); + break; + } + } + + // + // Loop while there are still more files to find. + // + + } while( FindNextFile( hndl, &ffd )); + + // + // Close the search. + // + + FindClose( hndl ); + + } + // + // There is no file that meets the filter criteria. + // Return pointer to an empty array + // + + } else { + + // + // There were no found files or the construction or + // initialization of the ARRAY failed, delete the ARRAY in case + // it was constructed and setup to return a NULL pointer i.e. no ARRAY + // + + if( parr != NULL ) { + DELETE( parr ); + } + parr = NULL; + } + + // + // Return the pointer to the ARRAY (which may be NULL) + // + + if ( DeleteFilter ) { + DELETE( Filter ); + } + + return( parr ); +} + + + +ULIB_EXPORT +BOOLEAN +FSN_DIRECTORY::Traverse ( + IN PVOID Object, + IN PFSN_FILTER FsnFilter, + IN OUT PPATH DestinationPath, + IN CALLBACK_FUNCTION CallBackFunction + ) CONST + +/*++ + +Routine Description: + + Traverses a directory, calling the callback function for each node + (directory of file) visited. The traversal may be finished + prematurely when the callback function returnes FALSE. + + The destination path is modified to reflect the directory structure + being traversed. + +Arguments: + + Object - Supplies pointer to the object + + FsnFilter - Supplies a pointer to the filter that determines the + nodes to be visited. + + DestinationPath - Supplies pointer to path to be used with the callback + function. + + CallBackFunction- Supplies pointer to the function to be called back + with the node to be visited. + +Return Value: + + BOOLEAN - Returns TRUE if the entire traversal was successful. + +--*/ + + +{ + + PARRAY SrcFiles; + PARRAY_ITERATOR Iterator; + PFSNODE FsNode; + PPATH SubDirectoryPath = NULL; + PFSN_DIRECTORY SubDirectory = NULL; + BOOLEAN StatusOk = TRUE; + PWSTRING Name; + + + DebugPtrAssert( FsnFilter ); + DebugPtrAssert( CallBackFunction ); + + // + // Get array of nodes for files in the directory + // + SrcFiles = QueryFsnodeArray( FsnFilter ); + DebugPtrAssert( SrcFiles ); + + // + // Get an iterator for processing the nodes + // + Iterator = ( PARRAY_ITERATOR ) SrcFiles->QueryIterator( ); + DebugPtrAssert( Iterator ); + + // + // Get path + // + SubDirectoryPath = NEW PATH; + DebugPtrAssert( SubDirectoryPath ); + + + // + // Visit all the nodes in the array. We recurse if the node is + // a directory. + // + while ( StatusOk && (( FsNode = (PFSNODE)Iterator->GetNext( )) != NULL )) { + + + if ( DestinationPath ) { + + // + // Append the name portion of the node to the destination path. + // + Name = FsNode->QueryName(); + DebugPtrAssert( Name ); + + StatusOk = DestinationPath->AppendBase( Name ); + DebugAssert( StatusOk ); + + DELETE( Name ); + } + + // + // Visit the node + // + if ( StatusOk = CallBackFunction( Object, FsNode, DestinationPath )) { + + if ( FsNode->IsDirectory() ) { + + // + // Recurse + // + SubDirectoryPath->Initialize( FsNode->GetPath() ); + + SubDirectory = SYSTEM::QueryDirectory( SubDirectoryPath ); + + DebugPtrAssert( SubDirectory ); + + StatusOk = SubDirectory->Traverse( Object, + FsnFilter, + DestinationPath, + CallBackFunction ); + DELETE( SubDirectory ); + + } + + } + + if ( DestinationPath ) { + + // + // Restore the destination path + // + DestinationPath->TruncateBase(); + } + } + + DELETE( SrcFiles ); + DELETE( Iterator ); + DELETE( SubDirectoryPath ); + + return StatusOk; +} diff --git a/private/utils/ulib/src/error.cxx b/private/utils/ulib/src/error.cxx new file mode 100644 index 000000000..65e3c3e11 --- /dev/null +++ b/private/utils/ulib/src/error.cxx @@ -0,0 +1,510 @@ +#include <pch.cxx> + +#define _NTAPI_ULIB_ +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "error.hxx" + +DEFINE_CONSTRUCTOR( ERRSTACK, OBJECT ); + + + + + + + + +#if 0 // Note davegi Fix.... + + +#include "ulib.hxx" +#include "error.hxx" +#include "bitvect.hxx" +// #include "string.hxx" +// #include "path.hxx" +// #include "message.hxx" + + +/**************************************************************************\ + +MEMBER: ERROR + +SYNOPSIS: constructor for ERROR object using no parameters + +ALGORITHM: + +ARGUMENTS: + +RETURNS: pointer to ERROR objects + +NOTES: Constructs an empty error object with no initialized error code + or Class Id. + +HISTORY: 3-7-90 + +KEYWORDS: ERROR + +SEEALSO: +\**************************************************************************/ + +ERROR::ERROR ( + ) : OBJECT(ID_ERROR) { + + err = 0; + id = 0; +} + + + +/**************************************************************************\ + +MEMBER: ERROR + +SYNOPSIS: constructor for ERROR object + +ALGORITHM: + +ARGUMENTS: errIn - error code + idIn - class id + pmsgIn - pointer to message (optional) + +RETURNS: pointer to ERROR objects + +NOTES: Class id is usually the class id where the error occured. In cases + where there is no class id then a special class id below ID_BASE + should be defined. There is currently a generic id called + ID_NOT_AN_OBJECT that can be used if no more information is needed. + +HISTORY: 3-6-90 + +KEYWORDS: ERROR + +SEEALSO: +\**************************************************************************/ + +/****************************** +ERROR::ERROR ( + ERRCODE errIn, + CLASS_ID idIn, + const MESSAGE * pmsgIn + ) : OBJECT(ID_ERROR) { + + err = errIn; + id = idIn; + pmsg = NULL; + if (pmsgIn) { + pmsg = NEW MESSAGE(*pmsgIn); + } + +} +*****************************/ + +/**************************************************************************\ + +MEMBER: ~ERROR + +SYNOPSIS: destructor for the error + +ALGORITHM: delete the message pointed to in ERROR + +ARGUMENTS: + +RETURNS: + +NOTES: + +HISTORY: 3-6-90 + +KEYWORDS: ERRROR ERRSTK + +SEEALSO: +\**************************************************************************/ +ERROR::~ERROR ( + ) { + +// if (pmsg) { +// delete pmsg; +// } +} + + +/**************************************************************************\ + +MEMBER: operator= + +SYNOPSIS: assignment operator for assigning one error to another. + +ALGORITHM: + +ARGUMENTS: error - reference to error to assign from. + +RETURNS: reference to ERROR object assigned to. + +NOTES: This is used in ERRSTK to copy the ERROR object locally. + +HISTORY: 3-7-90 + +KEYWORDS: ERROR + +SEEALSO: +\**************************************************************************/ + +ERROR & +ERROR::operator= ( + ERROR & error + ) { + + err = error.QueryErr(); + id = error.QueryClassId(); +// pmsg = NEW MESSAGE(*error.GetMsg()); + return(*this); + +} + +/**************************************************************************\ + +MEMBER: ERRSTK + +SYNOPSIS: constructor for error stack. + +ALGORITHM: + +ARGUMENTS: cpoIn - size of stack to alloc. (# of entries) + +RETURNS: + +NOTES: The actual amount alloc'd is cpoIn + 1. One slot is reserved + for a stack overflow error. A QueryCount should be done to + determine if stack could be allocated. + + Pointers to ERROR objects are put in this stack. The scope + of these pointers is assumed to be global. + +HISTORY: 3-6-90 + +KEYWORDS: ERRSTK + +SEEALSO: ERROR +\**************************************************************************/ + +ERRSTACK::ERRSTACK ( + ULONG cpoInitIn, + ULONG cpoIncIn + ) : OBJECT (ID_ERRSTACK) { + + ipoCur = cpoMax = 0; + cpoInit = cpoInitIn; + if (cpoIncIn) { + cpoInc = cpoIncIn; + } else { + cpoInc = cpoInitIn; + } + // save 1 slot for stack overflow + if (papo = (ERROR **)malloc((size_t)(++cpoInit) * (sizeof (ERROR *)))) { + cpoMax = cpoInit; + } + +} + +/**************************************************************************\ + +MEMBER: ~ERRSTK + +SYNOPSIS: destructor for the error stack + +ALGORITHM: delete each error in the stack then free space used for stack + +ARGUMENTS: + +RETURNS: + +NOTES: + +HISTORY: 3-6-90 + +KEYWORDS: ERRSTK + +SEEALSO: ERROR +\**************************************************************************/ + +ERRSTACK::~ERRSTACK ( + ) { + + for (ULONG i = ipoCur; i > 0; i--) { + delete papo[i]; + } + if (papo) { + free((void *)papo); + } +} + +/**************************************************************************\ + +MEMBER: ClearStack + +SYNOPSIS: deletes error in stack but does not free stack. + +ALGORITHM: + +ARGUMENTS: + +RETURNS: number of free entries in stack. + +NOTES: + +HISTORY: 5-6-90 + +KEYWORDS: ERRSTK ClearStack + +SEEALSO: ERROR +\**************************************************************************/ +ULONG +ERRSTACK::ClearStack ( + ) { + + for (ULONG i = ipoCur; i > 0; i--) { + /* delete papo[i]; */ + papo[i] = (ERROR *)NULL; + } + papo = (ERROR **)realloc(papo, (size_t)cpoInit * (sizeof (ERROR *))); // can't fail. realloc down + + ipoCur = 0; + cpoMax = cpoInit; + return(cpoMax); +} + +/**************************************************************************\ + +MEMBER: AllocError + +SYNOPSIS: Alocates an ERROR object and pushes it on the stack. + +ALGORITHM: + +ARGUMENTS: + +RETURNS: pointer to ERROR object on the top of the stack if a + push occurred. If the ERROR object could not be alloc'd + then NULL is returned. + +NOTES: This is used internally by push with error code argument. + It creates an uninitiallized ERROR object and pushes it on the + stack. If there is no room it grows the stack. If it can't + grow the stack it pushes a stack overflow error on the stack. + Space is always available for the stack overflow error. + +HISTORY: 3-14-90 + +KEYWORDS: ERRSTK AllocError + +SEEALSO: ERROR +\**************************************************************************/ +ERROR * +ERRSTACK::AllocError( + ) { + + ERROR ** papoT; + + // Note: optimize by precompute cpoMax - 1 + if (ipoCur == (cpoMax - 1)) { // stack full + return((ERROR *)NULL); + } + + if ((papo[++ipoCur] = NEW ERROR ()) == NULL) { + ipoCur--; // don't leave a null pointer to stack + return((ERROR *)NULL); // can't push create an error on stack + } + + if (ipoCur == (cpoMax - 1)) { + if ((papoT = (ERROR **)realloc(papo, (size_t)((sizeof (ERROR *)) * (cpoMax = (cpoMax + cpoInc))))) == NULL) { +// (papo[ipoCur])->PutIdErrMsg(this->QueryClassId(), ERR_ERRSTK_STACK_OVERFLOW); + } else { + papo = papoT; + } + } + + return(papo[ipoCur]); + +} + +/**************************************************************************\ + +MEMBER: push + +SYNOPSIS: pushes a pointer to an ERROR object onto the stack + +ALGORITHM: + +ARGUMENTS: perr - pointer to ERROR object + +RETURNS: pointer to ERROR object pushed. This is not be the same + as the perr argument. perr is copied to the stack. + +NOTES: The ERROR objected is copied so it's scope should + match that of the ERRSTK. + +HISTORY: 3-6-90 + +KEYWORDS: push ERRSTK + +SEEALSO: ERROR +\**************************************************************************/ + +ERROR * +ERRSTACK::push ( + const ERROR *perr + ) { + + if (AllocError()) { + return(&(*(papo[ipoCur]) = *( ERROR *)perr)); + } else { + return((ERROR *)NULL); + } +} + +/**************************************************************************\ + +MEMBER: push + +SYNOPSIS: The form of push takes direct error arguments, creates an ERROR + object and pushes it on the stack. + +ALGORITHM: + +ARGUMENTS: errcoIn - error code + idIn - class id + pmsgIn - pointer to message object. (optional) + +RETURNS: pointer to ERROR object pushed. This is not be the same + as the perr argument. perr is copied to the stack. + +NOTES: The ERROR objected is copied so it's scope should + match that of the ERRSTK. + +HISTORY: 3-6-90 + +KEYWORDS: push ERRSTK + +SEEALSO: ERROR +\**************************************************************************/ +ERROR * +ERRSTACK::push ( + ERRCODE errcoIn, + CLASS_ID idIn + ) { + + ERROR *perrT; + + if ((perrT = AllocError()) != NULL) { + if (perrT->QueryErr() != ERR_ERRSTK_STACK_OVERFLOW) { +// return(perrT->PutIdErrMsg(idIn, errcoInIn)); + } + } + return(perrT); +} + +/**************************************************************************\ + +MEMBER: pop + +SYNOPSIS: pop's a pointer to an ERROR object of the stack + +ALGORITHM: + +ARGUMENTS: + +RETURNS: pointer to a ERROR object. If the stack is empty NULL is returned. + +NOTES: + +HISTORY: 3-6-90 + +KEYWORDS: pop ERRSTK + +SEEALSO: ERROR +\**************************************************************************/ + +ERROR * +ERRSTACK::pop( + ) { + + if (!ipoCur) { // stack empty + return((ERROR *)NULL); + } + return(papo[ipoCur--]); + +} + +#ifdef DEBUG + +/**************************************************************************\ + +MEMBER: print + +SYNOPSIS: prints each error on the stack to standard out + +ALGORITHM: + +ARGUMENTS: + +RETURNS: # of errors printed. + +NOTES: + +HISTORY: 3-6-90 + +KEYWORDS: print ERRSTK + +SEEALSO: ERROR +\**************************************************************************/ + +ULONG +ERRSTACK::print( + ) { + + printf("Error Stack: entries = %ld, Top of Stack = %ld, Size of Stack = %ld\n", QueryCount(), QueryTop(), QuerySize()); + if (!ipoCur) { + printf("\tError: stack empty\n"); + return(0); + } + + for (ULONG i = ipoCur; i > 0 ; i--) { // 0 not used. + printf("\t"); + (papo[i])->print(); + } + return(QueryCount()); +} + +/**************************************************************************\ + +MEMBER: print + +SYNOPSIS: print a error to standard out + +ALGORITHM: + +ARGUMENTS: + +RETURNS: + +NOTES: + +HISTORY: + +KEYWORDS: + +SEEALSO: +\**************************************************************************/ + +BOOL +ERROR::print( + ) { + + printf("Error: id:%x, error:%X\n", id, err); + return(TRUE); +} + +#endif + +#endif // 0 Note davegi Fix.... diff --git a/private/utils/ulib/src/file.cxx b/private/utils/ulib/src/file.cxx new file mode 100644 index 000000000..eeb5e460a --- /dev/null +++ b/private/utils/ulib/src/file.cxx @@ -0,0 +1,251 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + file.cxx + +Abstract: + + This module contains the definition for the FSN_FILE class. + +Author: + + David J. Gilman (davegi) 09-Jan-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "system.hxx" +#include "file.hxx" +#include "timeinfo.hxx" + +DEFINE_CONSTRUCTOR( FSN_FILE, FSNODE ); + +DEFINE_CAST_MEMBER_FUNCTION( FSN_FILE ); + + + +ULIB_EXPORT +BOOLEAN +FSN_FILE::Copy ( + IN OUT PPATH NewFile, + OUT PCOPY_ERROR CopyError, + IN BOOLEAN OverwriteReadOnly, + IN BOOLEAN ResetReadOnly, + IN BOOLEAN Restartable, + IN LPPROGRESS_ROUTINE CallBack, + IN VOID * Data, + IN PBOOL Cancel + ) CONST + +/*++ + +Routine Description: + + Copies this file to another path. If appropriate the NewFile + will be altered to its "short" (FAT) form before the copy. + +Arguments: + + NewFile - Supplies path of new file. All the subdirectories must + exist. + + CopyError - Supplies pointer to variable that receives the + error code. + + OverwriteReadOnly - Supplies flag which if TRUE means that read-only files + should be overwritten. + + ResetReadOnly - Supplies flag which if TRUE causes the readonly flag + in the target to be reset. + + Restartable - Copy is restartable. + + Callback - Pointer to callback routine passed to CopyFileEx. + + Data - Pointer to opaque data passed to CopyFileEx. + + Cancel - Pointer to cancel flag passed to CopyFileEx. + +Return Value: + + BOOLEAN - TRUE if the file was successfully copied, + FALSE otherwise. + +--*/ + +{ + + PCWSTR Source; + PCWSTR Destination; + BOOLEAN CopiedOk = FALSE; + FSN_FILE File; + DWORD Attr; + WIN32_FIND_DATA FindData; + FSTRING AlternateFileName; + + + Source = GetPath()->GetPathString()->GetWSTR(); + DebugPtrAssert( Source ); + + if ( Source ) { + + Destination = NewFile->GetPathString()->GetWSTR(); + DebugPtrAssert( Destination ); + + if ( Destination ) { + + CopiedOk = TRUE; + + // + // If we must overwrite read-only files, we must + // get the file attributes and change to writeable. + // + // What we should do here is do + // a SYSTEM::QueryFile of the destination file and + // use the FILE methods for resetting the read-only + // attribute. However this is faster! + // + if ( OverwriteReadOnly ) { + + Attr = GetFileAttributes( (LPWSTR) Destination ); + + if (Attr != -1 && + (Attr & (FILE_ATTRIBUTE_READONLY | + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM))) { + + Attr &= ~( FILE_ATTRIBUTE_READONLY | + FILE_ATTRIBUTE_HIDDEN | + FILE_ATTRIBUTE_SYSTEM ); + + if ( !SetFileAttributes( (LPWSTR) Destination, Attr ) ) { + CopiedOk = FALSE; + } + } + } + + // + // Copy the file + // + if ( CopiedOk ) { + CopiedOk = CopyFileEx( (LPWSTR) Source, + (LPWSTR) Destination, + CallBack, + Data, + (LPBOOL) Cancel, + Restartable ? COPY_FILE_RESTARTABLE : 0); + } + + if ( CopiedOk && ResetReadOnly ) { + + FindData = _FileData; + NewFile->GetPathString()->QueryWSTR( 0, + TO_END, + FindData.cFileName, + MAX_PATH ); + FindData.cAlternateFileName[ 0 ] = ( WCHAR )'\0'; + + + if( File.Initialize( NewFile->GetPathString(), + &FindData ) ) { + + File.ResetReadOnlyAttribute(); + + } else { + + // + // The file is no longer there, we fail the copy + // + CopiedOk = FALSE; + *CopyError = (COPY_ERROR) ERROR_FILE_NOT_FOUND; + } + + + + } else if ( !CopiedOk && CopyError ) { + + *CopyError = (COPY_ERROR)GetLastError(); + + } + } + } + + return CopiedOk; + +} + + + +BOOLEAN +FSN_FILE::DeleteFromDisk( + IN BOOLEAN Force + ) +{ + PCWSTR FileName; + + UNREFERENCED_PARAMETER( Force ); + + if ( FileName = _Path.QueryFullPathString()->GetWSTR() ) { + + if ( FileName[0] != (WCHAR)'\0' ) { + return DeleteFile( (LPWSTR) FileName ); + } + } + + return FALSE; +} + + + + +ULIB_EXPORT +PFILE_STREAM +FSN_FILE::QueryStream ( + STREAMACCESS Access + ) + +/*++ + +Routine Description: + + Creates a FILE_STREAM object associated with the file described + by FSN_FILE, and returns the pointer to the FILE_STREAM. + + +Arguments: + + Access - Desired access to the stream + +Return Value: + + PFILE_STREAM - Returns a pointer to a FILE_STREAM, or NULL + if the FILE_STREAM couldn't be created. + +--*/ + +{ + PFILE_STREAM FileStream; + + if( IsReadOnly() && ( Access != READ_ACCESS ) ) { + return( NULL ); + } + FileStream = NEW( FILE_STREAM ); + DebugPtrAssert( FileStream ); + if( !FileStream->Initialize( this, Access ) ) { + DELETE( FileStream ); + return( NULL ); + } + return( FileStream ); +} diff --git a/private/utils/ulib/src/filestrm.cxx b/private/utils/ulib/src/filestrm.cxx new file mode 100644 index 000000000..6516b9186 --- /dev/null +++ b/private/utils/ulib/src/filestrm.cxx @@ -0,0 +1,937 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + filestrm.cxx + +Abstract: + + This module contains the definitions of the member functions + of FILE_STREAM class. + +Author: + + Jaime Sasson (jaimes) 24-Mar-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define BUFFER_SIZE 256 +#define BIG_BUFFER_SIZE (64 * 1024) + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "file.hxx" +#include "wstring.hxx" +#include "stream.hxx" +#include "bufstrm.hxx" +#include "filestrm.hxx" + + +DEFINE_CONSTRUCTOR ( FILE_STREAM, BUFFER_STREAM ); + +DEFINE_EXPORTED_CAST_MEMBER_FUNCTION( FILE_STREAM , ULIB_EXPORT ); + + +FILE_STREAM::~FILE_STREAM ( + ) + +/*++ + +Routine Description: + + Destroy a FILE_STREAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if( ( _MemoryMappedFile ) && !_EmptyFile ) { + if( _FileBaseAddress != 0 ) { + UnmapViewOfFile( _FileBaseAddress ); + } + if( _FileMappingHandle != NULL ) { + CloseHandle( _FileMappingHandle ); + _FileMappingHandle = NULL; + } + } + if( _ShouldCloseHandle ) { + if( _FileHandle != NULL ) { + CloseHandle( _FileHandle ); + _FileHandle = NULL; + } + } +} + + + +VOID +FILE_STREAM::Construct ( + ) + +/*++ + +Routine Description: + + Constructs a FILE_STREAM object + +Arguments: + + None. + +Return Value: + + None. + + +--*/ + +{ + _FileHandle = NULL; + _FileMappingHandle = NULL; + _EndOfFile = FALSE; + _ShouldCloseHandle = FALSE; + _FileBaseAddress = 0; + _MemoryMappedFile = FALSE; + _EmptyFile = FALSE; +} + + + + + + + +BOOLEAN +FILE_STREAM::Initialize( + IN PCFSN_FILE File, + IN STREAMACCESS Access + ) + +/*++ + +Routine Description: + + Initializes an object of type FILE_STREAM. + +Arguments: + + PCFSN_FILE - Pointer to a FSN_FILE object (will provide the filename). + + STREAMACCESS - Access allowed in the stream. + + +Return Value: + + None. + + +--*/ + + +{ + ULONG DesiredAccess; + ULONG CreationDisposition; + ULONG ShareMode; + PCPATH Path; + PCWSTRING String; +// PCWC_STRING String; + PCWSTR FileName; + BOOLEAN MappingFailed = FALSE; + + DebugPtrAssert( File ); + + _Access = Access; + _EndOfFile = FALSE; + _ShouldCloseHandle = TRUE; + _EmptyFile = FALSE; + if (_Access == READ_ACCESS) { + _MemoryMappedFile = TRUE; + } else { + _MemoryMappedFile = FALSE; + } + + Path = File->GetPath(); + String = Path->GetPathString(); + FileName = String->GetWSTR(); + + if( Access == READ_ACCESS ) { + DesiredAccess = GENERIC_READ; + CreationDisposition = OPEN_EXISTING; + ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + } else if( Access == WRITE_ACCESS ) { + DesiredAccess = GENERIC_WRITE; + CreationDisposition = OPEN_ALWAYS; + ShareMode = FILE_SHARE_READ; + } else { + DesiredAccess = GENERIC_READ | GENERIC_WRITE; + CreationDisposition = OPEN_EXISTING; + ShareMode = FILE_SHARE_READ; + } + + _FileHandle = CreateFile( (LPWSTR) FileName, + DesiredAccess, + ShareMode, + NULL, // Security attributes + CreationDisposition, + FILE_ATTRIBUTE_NORMAL, + NULL ); + if( _FileHandle == INVALID_HANDLE_VALUE ) { + return( FALSE ); + } + + // + // If stream is to be created with READ_ACCESS, then map file + // in memory + // + + if( _MemoryMappedFile ) { + if( ( _FileSize = File->QuerySize() ) == 0 ) { + // + // Empty file that is also read-only, cannot be mapped in + // memory, but we pretend we do it + // + _FileBaseAddress = NULL; + _EmptyFile = TRUE; + _EndOfFile = TRUE; + } else { + _FileMappingHandle = CreateFileMapping( _FileHandle, + NULL, + PAGE_READONLY, + 0, + 0,NULL ); + if( _FileMappingHandle == NULL ) { + CloseHandle( _FileHandle ); + _FileHandle = NULL; + DebugPrintf( "GetLastError() = %x \n", GetLastError() ); + DebugAbort( "CreateFileMapping() failed" ); + return( FALSE ); + } + _FileBaseAddress = ( PBYTE )MapViewOfFile( _FileMappingHandle, + FILE_MAP_READ, + 0, + 0, + 0 ); + + if( _FileBaseAddress == NULL ) { + DebugPrintf("map view of file failed with %d\n", GetLastError()); + CloseHandle( _FileMappingHandle ); + _FileMappingHandle = NULL; + _MemoryMappedFile = FALSE; + MappingFailed = TRUE; + } + } + + if (_MemoryMappedFile) { + _CurrentByte = _FileBaseAddress; + // + // If the file is maped in memory then we don't need + // a buffer. For this reason BUFFER_STREAM is initialized + // with zero + // + return( BUFFER_STREAM::Initialize( 0 ) ); + } + } + + if (!_MemoryMappedFile) { + + // + // If the stream is to be created with WRITE or READ_AND_WRITE + // access, then allocate a buffer. If we attempted to map + // the file and failed, it must be very large--use a big + // buffer. + // + return( BUFFER_STREAM::Initialize( MappingFailed ? + BIG_BUFFER_SIZE : + BUFFER_SIZE ) ); + } + + return FALSE; // Keep compiler happy. +} + + + + +BOOLEAN +FILE_STREAM::Initialize( + IN HANDLE FileHandle, + IN STREAMACCESS Access + ) + +/*++ + +Routine Description: + + Initializes an object of type FILE_STREAM. + +Arguments: + + FileHandle - File handle. + + Access - Access allowed in the stream. + + +Return Value: + + BOOLEAN - Returns TRUE if the initialization succeeded. + + +--*/ + + +{ + BOOLEAN MappingFailed = FALSE; + + _Access = Access; + _EndOfFile = FALSE; + _ShouldCloseHandle = FALSE; + _FileHandle = FileHandle; + + if (_Access == READ_ACCESS) { + _MemoryMappedFile = TRUE; + } else { + _MemoryMappedFile = FALSE; + } + + // + // If stream is to be creadted with READ access, then map file in + // memory + // + if( _MemoryMappedFile ) { + _FileSize = SetFilePointer( _FileHandle, 0, NULL, FILE_END ); + if( _FileSize == -1 ) { + return( FALSE ); + } + if( _FileSize == 0 ) { + // + // Empty file that is also read only cannot be mapped in + // memory, but we pretend we do it. + // + _FileBaseAddress = NULL; + _EmptyFile = TRUE; + _EndOfFile = TRUE; + } else { + _FileMappingHandle = CreateFileMapping( _FileHandle, + NULL, + PAGE_READONLY, + 0, + 0,NULL ); + if( _FileMappingHandle == NULL ) { + return( FALSE ); + } + _FileBaseAddress = ( PBYTE )MapViewOfFile( _FileMappingHandle, + FILE_MAP_READ, + 0, + 0, + 0 ); + + if( _FileBaseAddress == NULL ) { + CloseHandle( _FileMappingHandle ); + _FileMappingHandle = NULL; + MappingFailed = TRUE; + _MemoryMappedFile = FALSE; + } + } + + if (_MemoryMappedFile) { + _CurrentByte = _FileBaseAddress; + return( BUFFER_STREAM::Initialize( 0 ) ); + } + } + // + // If stream is to be created with WRITE and READ_AND_WRITE access, + // then allocate a buffer. Or the file was so big that it couldn't + // be mapped into memory. If the mapping failed, use a big buffer. + + return( BUFFER_STREAM::Initialize( MappingFailed ? + BIG_BUFFER_SIZE : + BUFFER_SIZE ) ); +} + + + +BOOLEAN +FILE_STREAM::AdvanceBufferPointer( + IN ULONG Offset + ) + +/*++ + +Routine Description: + + Advance the buffer pointer by an offset. (Removes bytes from + the buffer) + +Arguments: + + Offset - Number of bytes to remove from the buffer. + +Return Value: + + BOOLEAN - Returns TRUE if the pointer was advanced, or FALSE if the + offset was greater than the number of bytes in the buffer. + + +--*/ + +{ + if( _MemoryMappedFile ) { + return( MovePointerPosition( (LONG)Offset, STREAM_CURRENT )); + } else { + return( BUFFER_STREAM::AdvanceBufferPointer( Offset ) ); + } +} + + + +BOOLEAN +FILE_STREAM::FillBuffer( + IN PBYTE Buffer, + IN ULONG BufferSize, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Fills a buffer with bytes read from a file. + This function will fill the buffer only if the stream has + READ_AND_WRITE access. + It won't do anything if the stream has READ access. (In this case + the file was mapped in memory and the buffer was not defined). + + +Arguments: + + Buffer - Buffer where the bytes are to be stored. + + BufferSize - Size of the buffer. + + BytesRead - Pointer to the variable that will contain the number of bytes + put in the buffer. + + +Return Value: + + BOOLEAN - Returns TRUE if the buffer was filled. FALSE otherwise. + + +--*/ + +{ + BOOLEAN Result; + + DebugPtrAssert( Buffer ); + DebugPtrAssert( BytesRead ); + + Result = FALSE; + if( _Access != WRITE_ACCESS ) { + Result = ReadFile( _FileHandle, + Buffer, + BufferSize, + BytesRead, + NULL ); + if( Result && ( *BytesRead == 0 ) ) { + _EndOfFile = TRUE; + } + } + return( Result ); +} + + + +PCBYTE +FILE_STREAM::GetBuffer( + PULONG BytesInBuffer + ) + +/*++ + +Routine Description: + + Returns the pointer to the buffer, and the number of bytes in + the buffer. + +Arguments: + + BytesInBuffer - Points to the variable that will contain the number + of bytes in the buffer being returned. + + +Return Value: + + PCBYTE - Pointer to the buffer. + +--*/ + + +{ + if( _MemoryMappedFile ) { + *BytesInBuffer = _FileSize - ( _CurrentByte - _FileBaseAddress ); + BUFFER_STREAM::DetermineStreamType(&_CurrentByte,*BytesInBuffer); + return( _CurrentByte ); + } else { + return( BUFFER_STREAM::GetBuffer( BytesInBuffer )); + } +} + + +BOOLEAN +FILE_STREAM::MovePointerPosition( + IN LONG Position, + IN SEEKORIGIN Origin + ) + +/*++ + +Routine Description: + + Sets the file pointer to a particular position. + +Arguments: + + Position - Indicates the displacement in relation to the Origin + where the file pointer is to be moved. + + Origin - Defines the origin of the stream. + + +Return Value: + + BOOLEAN - Indicates if the seek operation succeeded. + + +--*/ + + +{ + ULONG NewPosition; + ULONG MoveMethod; + PBYTE Pointer; + + if( _MemoryMappedFile ) { + // + // The file IS mapped on memory + // + if( Origin == STREAM_BEGINNING ) { + Pointer = _FileBaseAddress; + } else if( Origin == STREAM_CURRENT ) { + Pointer = _CurrentByte; + } else { + Pointer = _FileBaseAddress + _FileSize - 1; + } + Pointer += Position; + if( ( Pointer < _FileBaseAddress ) || + ( Pointer > _FileBaseAddress + _FileSize ) ) { + _CurrentByte = Pointer; + _EndOfFile = ( BOOLEAN )( Pointer >= _FileBaseAddress + _FileSize ); + return( FALSE ); + } + _CurrentByte = Pointer; + _EndOfFile = ( BOOLEAN )( Pointer == _FileBaseAddress + _FileSize ); + + } else { + // + // The file IS NOT mapped in memory, so access to the file + // must be through APIs. + // + if( Origin == STREAM_BEGINNING ) { + MoveMethod = FILE_BEGIN; + } else if( Origin == STREAM_CURRENT ) { + MoveMethod = FILE_CURRENT; + } else { + MoveMethod = FILE_END; + } + NewPosition = SetFilePointer( _FileHandle, + Position, + 0, + MoveMethod ); + if( NewPosition == ( ULONG )-1 ) { + return( FALSE ); + } + // + // Since the file is buffered, we have to flush the buffer. + // The return value of FlushBuffer can be ignored because + // the file pointer was already moved to the right position. + // + BUFFER_STREAM::FlushBuffer(); + _EndOfFile = FALSE; + } + return( TRUE ); +} + + + +BOOLEAN +FILE_STREAM::QueryPointerPosition( + OUT PULONG Position + ) + +/*++ + +Routine Description: + + Returns the position of the file pointer in relation to the beginning of + the stream. + +Arguments: + + Position - Address of the variable that will contain the position of the + file pointer. + + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + ULONG BytesInBuffer; + + if( _MemoryMappedFile ) { + *Position = ( _CurrentByte - _FileBaseAddress ); + } else { + *Position = SetFilePointer( _FileHandle, + 0, + 0, + FILE_CURRENT ); + if( *Position == ( ULONG )-1 ) { + return( FALSE ); + } + // + // Needs to subtract the number of bytes in the buffer + // to obtain the position where the client thinks that + // the pointer is. + // + BUFFER_STREAM::GetBuffer( &BytesInBuffer ); + *Position -= BytesInBuffer; + } + return( TRUE ); +} + + + +BOOLEAN +FILE_STREAM::Read( + OUT PBYTE Buffer, + IN ULONG BytesToRead, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Reads data from the file. + +Arguments: + + Buffer - Points to the buffer where the data will be put. + + BytesToRead - Indicates total number of bytes to read from the stream. + + BytesRead - Points to the variable that will contain the number of + bytes read. + +Return Value: + + BOOLEAN - Indicates if the read operation succeeded. If there was no + data to be read (end of stream), the return value will be + TRUE (to indicate success), but NumberOfBytesRead will be + zero. + + +--*/ + +{ + if( _MemoryMappedFile ) { + if( ( _CurrentByte + BytesToRead ) > _FileBaseAddress + _FileSize ) { + BytesToRead = _FileBaseAddress + _FileSize - _CurrentByte; + } + __try { + memcpy( Buffer, _CurrentByte, ( size_t )BytesToRead ); + } + __except( GetExceptionCode() == EXCEPTION_IN_PAGE_ERROR ) { + return( FALSE ); + } + *BytesRead = BytesToRead; + _CurrentByte += BytesToRead; + if( _CurrentByte >= _FileBaseAddress + _FileSize ) { + _EndOfFile = TRUE; + } + return( TRUE ); + } else { + return( BUFFER_STREAM::Read( Buffer, BytesToRead, BytesRead ) ); + } +} + + + +ULIB_EXPORT +BOOLEAN +FILE_STREAM::ReadAt( + OUT PBYTE Buffer, + IN ULONG BytesToRead, + IN LONG Position, + IN SEEKORIGIN Origin, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Reads data from the file stream at a specified position. + +Arguments: + + Buffer - Points to the buffer where the data will be put. + + BytesToRead - Indicates total number of bytes to read from the stream. + + Position - Position in the stream where data is to be read from, + relative to the origin of the stream. + + Origin - Indicates what position in the stream should be used + as origin. + + BytesRead - Points to the variable that will contain the number of + bytes read. + + +Return Value: + + BOOLEAN - Indicates if the read operation succeeded. If there was no + data to be read (end of stream), the return value will be + TRUE (to indicate success), but BytesRead will be zero. + + +--*/ + +{ + BOOLEAN Result; + ULONG SavedPosition; + + DebugPtrAssert( Buffer ); + DebugPtrAssert( BytesRead ); + + Result = FALSE; + if( QueryPointerPosition( &SavedPosition ) && + MovePointerPosition( Position, Origin ) && + Read( Buffer, BytesToRead, BytesRead ) ) { + Result = MovePointerPosition( SavedPosition, STREAM_BEGINNING ); + } + return( Result ); +} + + + +BOOLEAN +FILE_STREAM::Write( + IN PCBYTE Buffer, + IN ULONG BytesToWrite, + OUT PULONG BytesWritten + ) + +/*++ + +Routine Description: + + Writes data a file stream with WRITE_ACCESS or READ_AND_WRITE_ACCESS. + +Arguments: + + Buffer - Points to the buffer that contains the data to be written. + + BytesToWrite - Indicates total number of bytes to write to the stream. + + BytesWritten - Points to the variable that will contain the number of + bytes written. + +Return Value: + + BOOLEAN - Indicates if the write operation succeeded. + + +--*/ + +{ + LONG Offset; + + DebugPtrAssert( Buffer ); + DebugPtrAssert( BytesWritten ); + + // + // If the stream have READ_AND_WRITE_ACCESS, we have to flush the + // buffer before we write to the file, and move the file pointer + // to the right place. + // + if( _Access == READ_AND_WRITE_ACCESS ) { + Offset = FlushBuffer(); + if( !MovePointerPosition( -Offset, STREAM_CURRENT ) ) { + return( FALSE ); + } + } + return( STREAM::Write( Buffer, BytesToWrite, BytesWritten ) ); +} + + + +BOOLEAN +FILE_STREAM::WriteAt( + IN PBYTE Buffer, + IN ULONG BytesToWrite, + IN LONG Position, + IN SEEKORIGIN Origin, + OUT PULONG BytesWritten + ) + +/*++ + +Routine Description: + + Writes data to the stream at a specified position. + +Arguments: + + Buffer - Points to the buffer that contains the data to be written. + + BytesToWrite - Indicates total number of bytes to write to the stream. + + Position - Position in the stream where data is to be written to, + relative to the origin of the stream. + + Origin - Indicates what position in the stream should be used + as origin. + + BytesWritten - Points to the variable that will contain the number of + bytes written. + +Return Value: + + BOOLEAN - Returns TRUE to indicate that the operation succeeded. + Returns FALSE otherwise. + + +--*/ + +{ + BOOLEAN Result; + ULONG SavedPosition; + + DebugPtrAssert( Buffer ); + DebugPtrAssert( BytesWritten ); + + Result = FALSE; + if( QueryPointerPosition( &SavedPosition ) && + MovePointerPosition( Position, Origin ) && + Write( Buffer, BytesToWrite, BytesWritten ) ) { + Result = MovePointerPosition( SavedPosition, STREAM_BEGINNING ); + } + return( Result ); +} + + +BOOLEAN +FILE_STREAM::EndOfFile( + ) CONST + +/*++ + +Routine Description: + + Informs the caller if end of file has occurred. End of file happens + when all bytes from the file were read, and there is no more bytes + to read (the API returns zero bytes read). + +Arguments: + + None. + +Return Value: + + A boolean value that indicates if end of file was detected. + + +--*/ + + +{ + return( _EndOfFile ); +} + + + +STREAMACCESS +FILE_STREAM::QueryAccess( + ) CONST + +/*++ + +Routine Description: + + Returns the type of access of the file stream + +Arguments: + + None. + +Return Value: + + The stream access. + + +--*/ + + +{ + return( _Access ); +} + + + +HANDLE +FILE_STREAM::QueryHandle( + ) CONST + +/*++ + +Routine Description: + + Returns the file handle + +Arguments: + + None. + +Return Value: + + The file handle. + + +--*/ + + +{ + return( _FileHandle ); +} diff --git a/private/utils/ulib/src/filter.cxx b/private/utils/ulib/src/filter.cxx new file mode 100644 index 000000000..60d141596 --- /dev/null +++ b/private/utils/ulib/src/filter.cxx @@ -0,0 +1,719 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + filter.cxx + +Abstract: + + This module contains the definition for the FSN_FILTER class. + FSN_FILTER essentially maintains the state information needed to + establish the criteria by which other 'file' or FSNODE objects are + compared against. + +Author: + + David J. Gilman (davegi) 09-Jan-1991 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "dir.hxx" +#include "file.hxx" +#include "filter.hxx" +#include "wstring.hxx" + +extern "C" { + #include <string.h> + #include <ctype.h> +} + + + + +// +// Pattern that matches all files +// +#define MATCH_ALL_FILES "*.*" + + + +DEFINE_EXPORTED_CONSTRUCTOR( FSN_FILTER, OBJECT, ULIB_EXPORT ); + +DEFINE_CAST_MEMBER_FUNCTION( FSN_FILTER ); + + + + +ULIB_EXPORT +FSN_FILTER::~FSN_FILTER ( + ) +/*++ + +Routine Description: + + Destructs an FSN_FILTER objtect + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +} + + + +VOID +FSN_FILTER::Construct ( + ) + +/*++ + +Routine Description: + + Construct a FSN_FILTER by setting it's internal data to a known state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + _AttributesSet = FALSE; + _FileNameSet = FALSE; + + // + // Note that even though _FileNameSet is false, we initialize + // the _FileName criteria with a match-all pattern. having the + // _FileNameSet flag set to FALSE saves us time because we don't + // have to do pattern-matching, since we know that everything will + // match anyway. + // + _FileName.Initialize( MATCH_ALL_FILES ); + _TimeInfoSet[FSN_TIME_MODIFIED] = FALSE; + _TimeInfoSet[FSN_TIME_CREATED] = FALSE; + _TimeInfoSet[FSN_TIME_ACCESSED] = FALSE; + +} + +ULIB_EXPORT +BOOLEAN +FSN_FILTER::Initialize ( + ) + +/*++ + +Routine Description: + + Initializes the FSN_FILTER + +Arguments: + + none + +Return Value: + + TRUE if the filter was succesfully initialized. + +--*/ + +{ + + return _TimeInfo[FSN_TIME_MODIFIED].Initialize() && + _TimeInfo[FSN_TIME_CREATED].Initialize() && + _TimeInfo[FSN_TIME_ACCESSED].Initialize(); + +} + +ULIB_EXPORT +BOOLEAN +FSN_FILTER::DoesNodeMatch ( + IN PFSNODE FsNode + ) +/*++ + +Routine Description: + + Determine if the supplied node matches the criteria established + in this FSN_FILTER. + +Arguments: + + Node - Node to match + +Return Value: + + TRUE if match, FALSE otherwise + +--*/ + +{ + FSTRING FileName; + + if (!FsNode) { + return FALSE; + } + + if (FilterFileName(FileName.Initialize(FsNode->_FileData.cFileName)) || + (FsNode->_FileData.cAlternateFileName[0] && + FilterFileName(FileName.Initialize(FsNode->_FileData.cAlternateFileName)))) { + + if (FilterAttributes(FsNode->QueryAttributes()) && + FilterTimeInfo( FsNode->GetCreationTime(), + FsNode->GetLastAccessTime(), + FsNode->GetLastWriteTime())) { + + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +FSN_FILTER::FilterAttributes ( + IN FSN_ATTRIBUTE Attributes + ) + +/*++ + +Routine Description: + + Determines if the supplied data matches the attribute criteria. + +Arguments: + + FindData - Supplies the system data which represents a found file. + +Return Value: + + TRUE if data matches attribute criteria. + FALSE otherwise + +--*/ + +{ + if ( _AttributesSet ) { + return ( ((Attributes & _AttributesAll) == _AttributesAll) && + ((_AttributesAny == 0) || (Attributes & _AttributesAny)) && + !(Attributes & _AttributesNone) ); + } + + return TRUE; + +} + +BOOLEAN +FSN_FILTER::FilterFileName ( + IN PCWSTRING FileName + ) + +/*++ + +Routine Description: + + Determines if the supplied data matches the path criteria. We never + return "." or ".." entries. + +Arguments: + + FindData - Supplies the system data which represents a found file. + +Return Value: + + TRUE if data matches the path criteria. + FALSE otherwise + +--*/ + +{ + CHNUM ChCount; + WCHAR c; + + ChCount = FileName->QueryChCount(); + + // + // We never return the "." or ".." entries + // + if ( ( FileName->QueryChAt(0) == (WCHAR)'.') && + ( (ChCount == 1) || + ((FileName->QueryChAt(1) == (WCHAR)'.') && (ChCount == 2))) ) { + + return FALSE; + } + + + if ( _FileNameSet ) { + // + // We only match the base portion of the name + // + ChCount = FileName->QueryChCount()-1; + while (ChCount < ~0 ) { + c = FileName->QueryChAt( ChCount ); + + if ( c == (WCHAR)':' || c == (WCHAR)'\\' ) { + break; + } + ChCount--; + } + ChCount++; + + return PatternMatch( &_FileName, 0, FileName, ChCount ); + } + + return TRUE; + +} + +BOOLEAN +FSN_FILTER::FilterTimeInfo ( + IN PFILETIME CreationTime, + IN PFILETIME LastAccessTime, + IN PFILETIME LastWriteTime + ) + +/*++ + +Routine Description: + + Determines if the supplied data matches the TimeInfo criteria. + +Arguments: + + FindData - Supplies the system data which represents a found file. + +Return Value: + + TRUE if data matches TimeInfo criteria. + FALSE otherwise + +--*/ + +{ + + BOOLEAN Match = TRUE; + + if ( _TimeInfoSet[FSN_TIME_MODIFIED] ) { + Match = TimeInfoMatch( &_TimeInfo[FSN_TIME_MODIFIED], + LastWriteTime, + _TimeInfoMatch[FSN_TIME_MODIFIED] ); + } + + if ( Match && _TimeInfoSet[FSN_TIME_CREATED] ) { + Match = TimeInfoMatch( &_TimeInfo[FSN_TIME_CREATED], + CreationTime, + _TimeInfoMatch[FSN_TIME_CREATED] ); + } + + if ( Match && _TimeInfoSet[FSN_TIME_ACCESSED] ) { + Match = TimeInfoMatch( &_TimeInfo[FSN_TIME_ACCESSED], + LastAccessTime, + _TimeInfoMatch[FSN_TIME_ACCESSED] ); + } + + return Match; + +} + +BOOLEAN +IsThereADot( + IN PCWSTRING String + ) +{ + PATH path; + PWSTRING p; + BOOLEAN r; + + if (!path.Initialize(String) || + !(p = path.QueryName())) { + + return FALSE; + } + + r = (p->Strchr('.') != INVALID_CHNUM); + + DELETE(p); + + return r; +} + + +BOOLEAN +FSN_FILTER::PatternMatch ( + IN PCWSTRING Pattern, + IN CHNUM PatternPosition, + IN PCWSTRING FileName, + IN CHNUM FileNamePosition + ) + +/*++ + +Routine Description: + + Determines if a file name matches a pattern. + +Arguments: + + Pattern - Supplies the pattern to compare against. + PatternPosition - Supplies first position within pattern. + FileName - Supplies the name to match. Cannot contain + wildcards. + FileNamePosition - Supplies first position within FileName. + + +Return Value: + + TRUE if name matches + +--*/ + +{ + if ( PatternPosition == Pattern->QueryChCount() ) { + + return (FileNamePosition == FileName->QueryChCount()); + + } + + switch( Pattern->QueryChAt( PatternPosition )) { + + case (WCHAR)'?': + if ((FileNamePosition == FileName->QueryChCount()) || + (FileName->QueryChAt( FileNamePosition ) == (WCHAR)'.' )) { + return PatternMatch( Pattern, PatternPosition + 1, + FileName, FileNamePosition ); + } else { + return PatternMatch( Pattern, PatternPosition + 1, + FileName, FileNamePosition + 1 ); + } + + case (WCHAR) '*': + do { + if (PatternMatch( Pattern, PatternPosition+1, + FileName, FileNamePosition )) { + return TRUE; + } + FileNamePosition++; + } while (FileNamePosition <= FileName->QueryChCount()); + + return FALSE; + + case (WCHAR)'.': + if (FileNamePosition == FileName->QueryChCount() && + !IsThereADot(FileName) && + Pattern->Strchr('.') == PatternPosition) { + + return PatternMatch( Pattern, PatternPosition+1, + FileName, FileNamePosition ); + } + + default: + return ( (WCHAR)CharUpper((LPTSTR)Pattern->QueryChAt( PatternPosition )) == + (WCHAR)CharUpper((LPTSTR)FileName->QueryChAt( FileNamePosition ))) && + PatternMatch( Pattern, PatternPosition + 1, + FileName, FileNamePosition + 1 ); + + } +} + +PFSNODE +FSN_FILTER::QueryFilteredFsnode ( + IN PCFSN_DIRECTORY ParentDirectory, + IN PWIN32_FIND_DATA FindData + ) + +/*++ + +Routine Description: + + Determine if the supplied system data matches the criteria established + in this FSN_FILTER. If it is create the appropriate FSNODE (i.e. FSN_FILE + or FSN_DIRECTORY) and return it to the caller. + +Arguments: + + ParentDirectory - Supplies pointer to the parent directory object + FindData - Supplies the system data which represents a found file. + +Return Value: + + Pointer to an FSNODE if the criteria was met. NULL otherwise. + +--*/ + +{ + PFSNODE FsNode = NULL; + FSTRING FileName; + + + if ( (FindData != NULL) && + ((FileName.Initialize( FindData->cFileName ) && + FilterFileName( &FileName )) || + (FindData->cAlternateFileName[0] && + FileName.Initialize( FindData->cAlternateFileName ) && + FilterFileName( &FileName ))) && + FilterAttributes( (FSN_ATTRIBUTE)FindData->dwFileAttributes ) && + FilterTimeInfo( &FindData->ftCreationTime, + &FindData->ftLastAccessTime, + &FindData->ftLastWriteTime ) + ) { + + // + // The data matches the filter criteria. + // + if ( FindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { + + // + // We have to create a directory object + // + FsNode = NEW FSN_DIRECTORY; + + } else { + + // + // We have to create a file object + // + FsNode = NEW FSN_FILE; + } + + if ( FsNode ) { + + if ( !(FsNode->Initialize( (LPWSTR)FindData->cFileName, ParentDirectory, FindData )) ) { + + DELETE( FsNode ); + + } + } + } + + return FsNode; +} + +ULIB_EXPORT +BOOLEAN +FSN_FILTER::SetAttributes ( + IN FSN_ATTRIBUTE All, + IN FSN_ATTRIBUTE Any, + IN FSN_ATTRIBUTE None + ) + +/*++ + +Routine Description: + + Sets the attributes criteria + +Arguments: + + All - Supplies the mask for the ALL attributes + Any - Supplies the mask for the ANY attributes + None - Supplies the mask for the NONE attributes + +Return Value: + + TRUE if the Attributes criteria was set. + +--*/ + +{ + + // + // Verify that no attribute is set in more than one mask + // + if ((All | Any | None) != ( All ^ Any ^ None )) { + return FALSE; + } + + _AttributesAll = All; + _AttributesAny = Any; + _AttributesNone = None; + + return (_AttributesSet = TRUE); + +} + +ULIB_EXPORT +BOOLEAN +FSN_FILTER::SetFileName ( + IN PCSTR FileName + ) + +/*++ + +Routine Description: + + Sets the FileName criteria + +Arguments: + + FileName - Supplies the filename to match against + +Return Value: + + TRUE if the filename criteria was set. + +--*/ + +{ + + if ( _FileName.Initialize( FileName ) ) { + + return ( _FileNameSet = TRUE ); + + } + + return FALSE; + +} + +ULIB_EXPORT +BOOLEAN +FSN_FILTER::SetFileName ( + IN PCWSTRING FileName + ) + +/*++ + +Routine Description: + + Sets the FileName criteria + +Arguments: + + FileName - Supplies the filename to match against + +Return Value: + + TRUE if the filename criteria was set. + +--*/ + +{ + + if ( _FileName.Initialize( FileName ) ) { + + return ( _FileNameSet = TRUE ); + + } + + return FALSE; + +} + +ULIB_EXPORT +BOOLEAN +FSN_FILTER::SetTimeInfo ( + IN PCTIMEINFO TimeInfo, + IN FSN_TIME TimeInfoType, + IN USHORT TimeInfoMatch + ) + +/*++ + +Routine Description: + + Sets a TimeInfo criteria + +Arguments: + + TimeInfo - Supplies the timeinfo + TimeinfoType - Supplies the type of timeinfo to set + TimeInfoMatch - Supplies the match criteria + +Return Value: + + TRUE if the timeinfo criteria was set. + +--*/ + +{ + + // + // Verify the parameters + // + if ((TimeInfoType < FSN_TIME_MODIFIED) || + (TimeInfoType > FSN_TIME_ACCESSED) || + (TimeInfoMatch == 0) || + (TimeInfoMatch & ~(TIME_BEFORE | TIME_AT | TIME_AFTER)) || + ((TimeInfoMatch & TIME_BEFORE) && (TimeInfoMatch & TIME_AFTER)) + ) { + + return FALSE; + } + + _TimeInfo[TimeInfoType].Initialize( (TIMEINFO *)TimeInfo ); + + _TimeInfoMatch[TimeInfoType] = TimeInfoMatch; + + return (_TimeInfoSet[TimeInfoType] = TRUE); + +} + +BOOLEAN +FSN_FILTER::TimeInfoMatch ( + IN PTIMEINFO TimeInfo, + IN PFILETIME FileTime, + IN USHORT Criteria + ) + +/*++ + +Routine Description: + + Determines if the supplied file time matches the criteria for a certain + time + +Arguments: + + TimeInfo - Supplies pointer to Timeinfo object to match against + FileTime - Supplies the file time to match + Criteria - Supplies the match criteria + +Return Value: + + TRUE if criteria met + FALSE otherwise + +--*/ + +{ + + USHORT Compare; + + UNREFERENCED_PARAMETER( (void)this ); + + // + // Compare and set in range 0 - 2 + // + Compare = (USHORT)(TimeInfo->CompareTimeInfo( FileTime ) + 1); + + // + // Our crietria is a bit mask, so we transform the result of the + // comparison to something that we can compare our mask against. + // + // i.e. {0,1,2} to {1,2,4} + // + Compare = (USHORT)((Compare * 2) + ( (Compare == 0) ? 1 : 0)); + + return BOOLEAN( (USHORT)Compare & ~Criteria ); + +} diff --git a/private/utils/ulib/src/fsnode.cxx b/private/utils/ulib/src/fsnode.cxx new file mode 100644 index 000000000..e5b2b5993 --- /dev/null +++ b/private/utils/ulib/src/fsnode.cxx @@ -0,0 +1,459 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + fsnode.cxx + +Abstract: + + This module contains the definition for the FSNODE class, the most + primitive, abstract class in the file system sub-hierarchy. Given it's + abstract, prmitive nature it contains very minimal implementation. It's + primary intent is to support a polymorphic base class for file system + objects. + +Author: + + David J. Gilman (davegi) 02-Jan-1991 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "array.hxx" +#include "dir.hxx" +#include "fsnode.hxx" +#include "wstring.hxx" +#include "path.hxx" +#include "timeinfo.hxx" +#include "system.hxx" + +DEFINE_CONSTRUCTOR( FSNODE, OBJECT ); + +FSNODE::~FSNODE ( + ) + +/*++ + +Routine Description: + + Destroy an FSNODE. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ +} + +BOOLEAN +FSNODE::Initialize ( + IN PCWSTR PathName, + IN PCFSN_DIRECTORY ParentDirectory, + IN PWIN32_FIND_DATA FileData + ) + +/*++ + +Routine Description: + + Initialize an FSNODE by constructing and initializing it's contained + PATH object. + +Arguments: + + PathName - Supplies a name used to initialize the contained PATH + + FileData - Points to the structure that contains all file information. + +Return Value: + + BOOLEAN - TRUE if the contained PATH was succesfully constructed and + initialized. + +--*/ + +{ + + FSTRING wcs; + + DebugPtrAssert( PathName ); + DebugPtrAssert( ParentDirectory ); + if( ( PathName != NULL ) && + ( ParentDirectory != NULL ) && + _Path.Initialize((( PFSN_DIRECTORY ) + ParentDirectory )->GetPath( ), FALSE) && + wcs.Initialize( (PWSTR) PathName ) && + _Path.AppendBase( &wcs ) ) { + memcpy( &_FileData, FileData, sizeof( WIN32_FIND_DATA ) ); + _Path.GetPathString( )->QueryWSTR( 0, TO_END, + ( LPWSTR )_FileData.cFileName, + sizeof( _FileData.cFileName)); + return( TRUE ); + + } else { + + DebugAbort( "Could not construct/initialize PATH" ); + return( FALSE ); + + } +} + +BOOLEAN +FSNODE::Initialize ( + IN PCWSTRING PathName, + IN PWIN32_FIND_DATA FileData + ) + +/*++ + +Routine Description: + + Initialize an FSNODE by constructing and initializing it's contained + PATH object. + +Arguments: + + PathName - Supplies a name used to initialize the contained PATH + + FileData - Points to the structure that contains all file information. + +Return Value: + + BOOLEAN - TRUE if the contained PATH was succesfully constructed and + initialized. + +--*/ + +{ + + DebugPtrAssert( PathName ); + if( ( PathName != NULL ) && + _Path.Initialize( PathName, FALSE ) ) { + memcpy( &_FileData, FileData, sizeof( WIN32_FIND_DATA ) ); + PathName->QueryWSTR( 0, TO_END, + ( LPWSTR )_FileData.cFileName, + sizeof( _FileData.cFileName )); + return( TRUE ); + + } else { + + DebugAbort( "Could not construct/initialize PATH" ); + return( FALSE ); + + } +} + +PFSN_DIRECTORY +FSNODE::QueryParentDirectory ( + ) CONST + +/*++ + +Routine Description: + + Construct and return the FSN_DIRECTORY object which represents this + FSNODE's parent. + +Arguments: + + None. + +Return Value: + + PFSN_DIRECTORY - Returns a pointer the the parent FSN_DIRECTORY. + +--*/ + +{ + REGISTER PFSN_DIRECTORY pfsnDir; + PATH path; + + if( path.Initialize( ((PFSNODE) this)->_Path.QueryPrefix( )) && + (( pfsnDir = SYSTEM::QueryDirectory( &path )) != NULL )) { + + return( pfsnDir ); + } else { + + DebugAbort( "Can't construct parent directory" ); + return( NULL ); + } +} + +PTIMEINFO +FSNODE::QueryTimeInfo ( + IN FSN_TIME FsnTime + ) CONST + +/*++ + +Routine Description: + + Query the time imformation pertaining to this FSNODE. + +Arguments: + + None. + +Return Value: + + PTIMEINFO - Returns a pointer to the TIMEINFO object. + +--*/ + +{ + PTIMEINFO TimeInfo; + PFILETIME DesiredFileTime; + + TimeInfo = NULL; + + TimeInfo = NEW( TIMEINFO ); + DebugPtrAssert( TimeInfo ); + + switch( FsnTime ) { + + case FSN_TIME_MODIFIED: + DesiredFileTime = &( ((PFSNODE) this)->_FileData.ftLastWriteTime ); + break; + + case FSN_TIME_CREATED: + DesiredFileTime = &( ((PFSNODE) this)->_FileData.ftCreationTime ); + break; + + case FSN_TIME_ACCESSED: + DesiredFileTime = &( ((PFSNODE) this)->_FileData.ftLastAccessTime ); + break; + + default: + DebugAbort( "Invalid value of FsnTime \n" ); + return( NULL ); + } + + if( !TimeInfo->Initialize( DesiredFileTime ) ) { + DebugAbort( "TimeInfo->Initialize() failed \n" ); + return( NULL ); + } + return( TimeInfo ); +} + +BOOLEAN +FSNODE::SetTimeInfo ( + IN PCTIMEINFO TimeInfo, + IN FSN_TIME TimeInfoType + ) + +/*++ + +Routine Description: + + Change the time information of an FSNODE. + +Arguments: + + TimeInfo - Pointer to a TIMEINFO object that contains the new time. + + TimeInfoType - Indicates the time to be modified (creation time, + last access time, or last modified time ) + + +Return Value: + + BOOLEAN - Returns TRUE if the operation succeeds. FALSE otherwise. + + +--*/ + +{ + PFILETIME DesiredFileTime; + HANDLE FileHandle; + BOOLEAN TimeSet; + + DebugPtrAssert( TimeInfo ); + + switch( TimeInfoType ) { + + case FSN_TIME_MODIFIED: + DesiredFileTime = &( _FileData.ftLastWriteTime ); + break; + + case FSN_TIME_CREATED: + DesiredFileTime = &( _FileData.ftCreationTime ); + break; + + case FSN_TIME_ACCESSED: + DesiredFileTime = &( _FileData.ftLastAccessTime ); + break; + + default: + DebugAbort( "Invalid value of FsnTime \n" ); + return( NULL ); + } + + *DesiredFileTime = *( TimeInfo->GetFileTime() ); + if( DesiredFileTime == NULL ) { + return( FALSE ); + } + + FileHandle = CreateFile( &_FileData.cFileName[0], + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL ); + if( FileHandle == INVALID_HANDLE_VALUE ) { + return( FALSE ); + } + + TimeSet = SetFileTime( FileHandle, + &( _FileData.ftCreationTime ), + &( _FileData.ftLastAccessTime ), + &( _FileData.ftLastWriteTime ) ); + + CloseHandle( FileHandle ); + return( TimeSet ); +} + + + +BOOLEAN +FSNODE::Rename( + IN PCPATH NewName + ) +/*++ + +Routine Description: + + Renames a file and updates its FSNODE + +Arguments: + + NewName - New name for the file. + +Return Value: + + BOOLEAN - Returns TRUE if the operation succeeds. FALSE otherwise. + +--*/ + +{ + + PCWSTRING NewNameWstring; + PCWSTR NewNameString; + + + DebugPtrAssert( NewName ); + NewNameWstring = NewName->GetPathString(); + if( NewNameWstring == NULL ) { + return( FALSE ); + } + NewNameString = NewNameWstring->GetWSTR(); + if( NewNameString == NULL ) { + return( FALSE ); + } + if( !MoveFile( _FileData.cFileName, + (LPWSTR) NewNameString ) ) { + return( FALSE ); + } + memmove( _FileData.cFileName, + NewNameString, + (NewNameWstring->QueryChCount() + 1) * sizeof( WCHAR ) ); + if( !_Path.Initialize( NewName ) ) { + return( FALSE ); + } + return( TRUE ); +} + + +BOOLEAN +FSNODE::DeleteFromDisk( + IN BOOLEAN Force + ) +{ + UNREFERENCED_PARAMETER( Force ); + return( FALSE ); +} + + + +BOOLEAN +FSNODE::UpdateFsNode ( + ) + +/*++ + +Routine Description: + + Update the file attributes in this FSNODE object. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Returns TRUE if the attributes were updated. + +--*/ + +{ + HANDLE Handle; + WIN32_FIND_DATA Data; + + if( ( Handle = FindFirstFile( &_Path, &Data ) ) == INVALID_HANDLE_VALUE ) { + DebugPrint( "FindFirstFile() failed \n" ); + return( FALSE ); + } + _FileData = Data; + FindClose( Handle ); + return( TRUE ); +} + + +ULIB_EXPORT +BOOLEAN +FSNODE::UseAlternateName( + ) +/*++ + +Routine Description: + + This routine set the last component of the path for this object to + the alternate name if it is available. + +Arguments: + + None. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + FSTRING f; + + // If there is no alternate then we are already DOS compatible. + + if (!_FileData.cAlternateFileName[0]) { + return TRUE; + } + + return _Path.SetName(f.Initialize(_FileData.cAlternateFileName)); +} diff --git a/private/utils/ulib/src/hmem.cxx b/private/utils/ulib/src/hmem.cxx new file mode 100644 index 000000000..e5ce2394f --- /dev/null +++ b/private/utils/ulib/src/hmem.cxx @@ -0,0 +1,247 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ +#include "ulib.hxx" +#include "error.hxx" +#include "hmem.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR( HMEM, MEM, ULIB_EXPORT ); + +VOID +HMEM::Construct ( + ) +/*++ + +Routine Description: + + The is the contructor of HMEM. It initializes the private data + to reasonable default values. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _size = 0; + _real_buf = NULL; + _buf = NULL; +} + + +ULIB_EXPORT +HMEM::~HMEM( + ) +/*++ + +Routine Description: + + Destructor for HMEM. Frees up any memory used. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + Destroy(); +} + + +ULIB_EXPORT +BOOLEAN +HMEM::Initialize( + ) +/*++ + +Routine Description: + + This routine initializes HMEM to an initial state. All pointers or + information previously aquired from this object will become invalid. + +Arguments: + + None. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + Destroy(); + + return TRUE; +} + + +ULIB_EXPORT +PVOID +HMEM::Acquire( + IN ULONG Size, + IN ULONG AlignmentMask + ) +/*++ + +Routine Description: + + This routine acquires the memory resources of this object for + the client to use. 'Size' bytes of data are guaranteed by + this routine or this routine will return NULL. After one call + of 'Acquire' has succeeded, all subsequent calls will return the + same memory, provided that the Size requested is within bounds + specified in the first successful call. The first successful call + will dictate the size and location of the memory which will be + available by calls to 'QuerySize' and 'GetBuf' respectively. + + A call to Initialize will invalidate all memory previously granted + by this object and enable the next call to Acquire to specify + any size. + +Arguments: + + Size - The number of bytes of memory expected. + AlignmentMask - Supplies the alignment required on the memory. + +Return Value: + + A valid pointer to 'Size' bytes of memory or NULL. + +--*/ +{ + if (_buf) { + if (Size <= _size && !(((ULONG) _buf)&AlignmentMask)) { + return _buf; + } else { + return NULL; + } + } + + _size = Size; + + if (!(_real_buf = MALLOC((UINT) (_size + AlignmentMask)))) { + return NULL; + } + + _buf = (PVOID) ((ULONG) ((PCHAR) _real_buf + AlignmentMask) & + (~AlignmentMask)); + + return _buf; +} + + +ULIB_EXPORT +BOOLEAN +HMEM::Resize( + IN ULONG NewSize, + IN ULONG AlignmentMask + ) +/*++ + +Routine Description: + + This method reallocates the object's buffer to a larger + chunk of memory. + +Arguments: + + NewSize -- supplies the new size of the buffer. + AlignmentMask -- supplies the alignment requirements on the memory. + +Return Value: + + TRUE upon successful completion. + +Notes: + + This method allocates a new buffer, copies the appropriate + amount of data to it, and then frees the old buffer. Clients + who use Resize must avoid caching pointers to the memory, but + must use GetBuf to find out where the memory is. + + If NewSize is smaller than the current buffer size, we keep + the current buffer. + + If this method fails, the object is left unchanged. + +--*/ +{ + PVOID NewBuffer; + PVOID NewRealBuffer; + + // First, check to see if our current buffer is big enough + // and has the correct alignment + // to satisfy the client. + + if( _buf && + NewSize <= _size && + !(((ULONG) _buf)&AlignmentMask)) { + + return TRUE; + } + + // We need to allocate a new chunk of memory. + + if( (NewRealBuffer = MALLOC((UINT) (NewSize + AlignmentMask))) == NULL ) { + + return FALSE; + } + + NewBuffer = (PVOID) ((ULONG) ((PCHAR) NewRealBuffer + AlignmentMask) & + (~AlignmentMask)); + + // Copy data from the old buffer to the new. Since we know + // that NewSize is greater than _size, we copy _size bytes. + + memset( NewBuffer, 0, (UINT) NewSize ); + memcpy( NewBuffer, _buf, (UINT) min(_size, NewSize) ); + + // Free the old buffer and set the object's private variables. + + FREE( _real_buf ); + _real_buf = NewRealBuffer; + _buf = NewBuffer; + _size = NewSize; + + return TRUE; +} + + +VOID +HMEM::Destroy( + ) +/*++ + +Routine Description: + + This routine frees the memory of a previous call to Acquire thus + invalidating all pointers to that memory and enabling future + Acquires to succeed. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _size = 0; + if (_real_buf) { + FREE(_real_buf); + _real_buf = NULL; + } + _buf = NULL; +} diff --git a/private/utils/ulib/src/i386/dosttr.c b/private/utils/ulib/src/i386/dosttr.c new file mode 100644 index 000000000..e6fc847c6 --- /dev/null +++ b/private/utils/ulib/src/i386/dosttr.c @@ -0,0 +1,76 @@ +#include <windows.h> + +#define MaxCallStack 20 + +VOID +DoStackTrace( DWORD callstack[] ) + +/*++ + +Routine Description: + + Backtrace a stack recording all the return addresses in the supplied + structure. The mips version of this code does nothing. + +Arguments: + + DWORD Callstack[] - The array in which the addresses are stored. + +Return Value: + + None. + +--*/ + +{ + +#pragma message( "Including the stack trace!" ) + + int i; + DWORD bytes; + HANDLE hProcess; + DWORD dwEbp; + + hProcess = GetCurrentProcess(); + + // + // Get the current contents of the control registers... + // + _asm { + + mov dwEbp, ebp + + } + + // + // Ignore the entry on the stack for this procedure... + // + if( !ReadProcessMemory( hProcess, + (LPVOID)dwEbp, + (LPVOID)&dwEbp, + sizeof( DWORD ), + NULL ) ) { + return; + } + + for( i = 0; ( i < MaxCallStack ) && dwEbp; i++ ) { + + if( !ReadProcessMemory( hProcess, + (LPVOID)( (PDWORD)dwEbp + 1 ), + (LPVOID)( &callstack[ i ] ), + sizeof( DWORD ), + NULL ) ) { + break; + } + if( !ReadProcessMemory( hProcess, + (LPVOID)dwEbp, + (LPVOID)&dwEbp, + sizeof( DWORD ), + NULL ) ) { + break; + } + + } + + return; +} diff --git a/private/utils/ulib/src/iterator.cxx b/private/utils/ulib/src/iterator.cxx new file mode 100644 index 000000000..5c344449a --- /dev/null +++ b/private/utils/ulib/src/iterator.cxx @@ -0,0 +1,63 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + iterator.cxx + +Abstract: + + This contains the definitions for the non-inline member functions + for the abstract ITERATOR class. The only interesting aspect of this + implementation is that the destructor decrements the iterator count in + it's associated CONTAINER. This count, increment by the CONTAINER when + the ITERATOR is constructed, allows the associated CONTAINER to watch + for outstanding ITERATORs when it is destroyed - a situation which is + dangerous and surely a bug. + +Author: + + David J. Gilman (davegi) 03-Dec-1990 + +Environment: + + ULIB, User Mode + +[Notes:] + + optional-notes + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "iterator.hxx" + + +DEFINE_CONSTRUCTOR( ITERATOR, OBJECT ); + +ITERATOR::~ITERATOR( + ) +{ +} + + +POBJECT +ITERATOR::FindNext( + IN PCOBJECT Key + ) +{ + POBJECT p; + + for (p = GetNext(); p; p = GetNext()) { + if (!Key->Compare(p)) { + break; + } + } + + return p; +} diff --git a/private/utils/ulib/src/keyboard.cxx b/private/utils/ulib/src/keyboard.cxx new file mode 100644 index 000000000..fca87c2e9 --- /dev/null +++ b/private/utils/ulib/src/keyboard.cxx @@ -0,0 +1,920 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + keyboard.cxx + +Abstract: + + This module contains the definitions of the member functions + of KEYBOARD class. + +Author: + + Jaime Sasson (jaimes) 24-Mar-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "stream.hxx" +#include "bufstrm.hxx" +#include "keyboard.hxx" + + +BOOL KEYBOARD::_FlagBreak; + + +#define CTRL_Z 0x1a + +DEFINE_EXPORTED_CONSTRUCTOR ( KEYBOARD, BUFFER_STREAM, ULIB_EXPORT ); + + +DEFINE_EXPORTED_CAST_MEMBER_FUNCTION( KEYBOARD, ULIB_EXPORT ); + + +KEYBOARD::~KEYBOARD ( + ) + +/*++ + +Routine Description: + + Destroy a KEYBOARD (close a keyboard handle). + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + SetConsoleMode( _KeyboardHandle, _PreviousMode ); + CloseHandle( _KeyboardHandle ); +} + + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::Initialize( + BOOLEAN LineMode, + BOOLEAN EchoMode + ) + +/*++ + +Routine Description: + + Initializes a KEYBOARD class. + +Arguments: + + LineMode - Indicates if the keyboard is to be set in line mode. + + EchoMode - Indicates if the keyboard is to be set in the echo mode + (characters are echoed to the current active screen) + +Return Value: + + BOOLEAN - Indicates if the initialization succeeded. + +--*/ + +{ + ULONG KeyboardMode; + + _KeyboardHandle = CreateFile( (LPWSTR)L"CONIN$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL ); + if( _KeyboardHandle ==INVALID_HANDLE_VALUE ) { + return( FALSE ); + } + if( !GetConsoleMode( _KeyboardHandle, &_PreviousMode ) ) { + return( FALSE ); + } + KeyboardMode = _PreviousMode; + if( LineMode ) { + KeyboardMode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT; + } else { + KeyboardMode &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT); + } + if( EchoMode ) { + KeyboardMode |= ENABLE_ECHO_INPUT; + } else { + KeyboardMode &= ~ENABLE_ECHO_INPUT; + } + if( !SetConsoleMode( _KeyboardHandle, KeyboardMode ) ) { + return( FALSE ); + } + _FlagCtrlZ = FALSE; + return( BUFFER_STREAM::Initialize( 256 ) ); +} + + +BOOL +KEYBOARD::BreakHandler ( + IN ULONG CtrlType + ) + +/*++ + +Routine Description: + + Handles Break events. Sets up the static data so that it can be + queried later on. + +Arguments: + + CtrlType - Supplies the type of Ctrl + +Return Value: + + none + +--*/ + +{ + UNREFERENCED_PARAMETER( CtrlType ); + + _FlagBreak = TRUE; + return TRUE; +} + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::GotABreak ( + ) + +/*++ + +Routine Description: + + Determines if a Break event (e.g Ctrl-C) was caught and handled. + + The static data that contains the Break information is set to a + "FALSE" state. Note that this means that if there is no Break + between two consecutive calls to this method, then the second + one will always return FALSE. + +Arguments: + + None. + +Return Value: + + BOOLEAN - TRUE if a Break event happened, FALSE otherwise. + +--*/ + +{ + BOOLEAN GotBreak = _FlagBreak; + + _FlagBreak = FALSE; + + return GotBreak; + +} + +ULIB_EXPORT +BOOLEAN +KEYBOARD::EnableBreakHandling( + ) + +/*++ + +Routine Description: + + Enables Break events handling (E.g. Ctrl-C). + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + _FlagBreak = FALSE; + + return SetConsoleCtrlHandler( KEYBOARD::BreakHandler, TRUE ); + +} + +ULIB_EXPORT +BOOLEAN +KEYBOARD::EnableLineMode( + ) + +/*++ + +Routine Description: + + Set the keyboard in line mode. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + ULONG Mode; + + if( !GetConsoleMode( _KeyboardHandle, &Mode ) ) { + return( FALSE ); + } + + Mode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT; + return( SetConsoleMode( _KeyboardHandle, Mode ) ); +} + + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::DisableBreakHandling( + ) + +/*++ + +Routine Description: + + Disables Break event handling (E.g. Ctrl-C). + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + _FlagBreak = FALSE; + + return SetConsoleCtrlHandler( KEYBOARD::BreakHandler, FALSE ); + +} + +ULIB_EXPORT +BOOLEAN +KEYBOARD::DisableLineMode( + ) + +/*++ + +Routine Description: + + Set the keyboard in character mode. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + ULONG Mode; + + // unreferenced parameters + (void)(this); + + if( !GetConsoleMode( _KeyboardHandle, &Mode ) ) { + return( FALSE ); + } + Mode &= ~(ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT); + return( SetConsoleMode( _KeyboardHandle, Mode ) ); +} + + + + +BOOLEAN +KEYBOARD::IsLineModeEnabled( + ) CONST + +/*++ + +Routine Description: + + Finds out if the keyboard is in line mode. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the keyboard is in line mode + +--*/ + +{ + ULONG Mode; + + // unreferenced parameters + (void)(this); + + GetConsoleMode( _KeyboardHandle, &Mode ); + return( ( Mode & ENABLE_LINE_INPUT ) != 0 ); +} + + + +BOOLEAN +KEYBOARD::EnableEchoMode( + ) + +/*++ + +Routine Description: + + Set the keyboard in echo mode. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + ULONG Mode; + + if( !GetConsoleMode( _KeyboardHandle, &Mode ) ) { + return( FALSE ); + } + Mode |= ENABLE_ECHO_INPUT; + return( SetConsoleMode( _KeyboardHandle, Mode ) ); +} + + + +BOOLEAN +KEYBOARD::DisableEchoMode( + ) + +/*++ + +Routine Description: + + Does not echo characters read from keyboard. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + +--*/ + +{ + ULONG Mode; + + if( !GetConsoleMode( _KeyboardHandle, &Mode ) ) { + return( FALSE ); + } + Mode &= ~ENABLE_ECHO_INPUT; + return( SetConsoleMode( _KeyboardHandle, Mode ) ); +} + + + +BOOLEAN +KEYBOARD::IsEchoModeEnabled( + ) CONST + +/*++ + +Routine Description: + + Finds out if characters read from keyboard echoed to the screen. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the keyboard is in echo mode + +--*/ + +{ + ULONG Mode; + + GetConsoleMode( _KeyboardHandle, &Mode ); + return( ( Mode | ENABLE_ECHO_INPUT ) != 0 ); +} + + + +BOOLEAN +KEYBOARD::CheckForAsciiKey( + IN PINPUT_RECORD InputRecord, + IN ULONG NumberOfInputRecords + ) CONST + +/*++ + +Routine Description: + + Examines an array of input records in order to find out if at least + one ascii key was pressed. + +Arguments: + + InputRecord - Pointer to an array of INPUT_RECORDS. + + NumberOfInputRecords - Number of elements in the array + + +Return Value: + + BOOLEAN - Indicates if the input buffer contains at least one + ASCII key. + + +--*/ + +{ + BOOLEAN Result; + + // unreferenced parameters + (void)(this); + + Result = FALSE; + while( !Result && NumberOfInputRecords ) { + if( ( InputRecord->EventType == KEY_EVENT ) && + ( InputRecord->Event ).KeyEvent.bKeyDown && + +#if defined DBCS +// MSKK KazuM Sep,24,1993 + ( ( InputRecord->Event ).KeyEvent.uChar.UnicodeChar > 0 ) && + ( ( InputRecord->Event >.KeyEvent.uChar.UnicodeChar <= 0x7e ) ) { +#else + ( ( InputRecord->Event ).KeyEvent.uChar.AsciiChar > 0 ) && + ( ( InputRecord->Event ).KeyEvent.uChar.AsciiChar <= 0x7e ) ) { +#endif + + Result = TRUE; + } else { + NumberOfInputRecords--; + InputRecord++; + } + } + return( Result ); +} + + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::IsKeyAvailable( + OUT PBOOLEAN Available + ) CONST + +/*++ + +Routine Description: + + Determines if there is at least one key to be read. + +Arguments: + + Available - Pointer to the variable that will contain the result of + the query (if there is a key in the keyboard buffer). + +Return Value: + + BOOLEAN - A boolean value that indicates if the operation succeeded + If this value is FALSE, the contets of 'Available' has no + meaning (the calls to the APIs failed). + + +--*/ + + +{ + BOOLEAN Result; + ULONG NumberOfInputEvents; + PINPUT_RECORD Event; + ULONG NumberOfEventsRead; + + // + // Keys read, but not yet consumed, are kept are in a buffer. + // So, we have to check first if there is at least one key + // in this buffer. + // + if( BUFFER_STREAM::QueryBytesInBuffer() != 0 ) { + *Available = TRUE; + return( TRUE ); + } + // + // If there was no key previously read, we have to check the + // keyboard buffer for key events. + // + Result = FALSE; + if ( GetNumberOfConsoleInputEvents( _KeyboardHandle, + &NumberOfInputEvents ) ) { + + if( NumberOfInputEvents == 0 ) { + *Available = FALSE; + Result = TRUE; + } else { + Event = ( PINPUT_RECORD ) MALLOC( ( size_t )( sizeof( INPUT_RECORD ) * NumberOfInputEvents ) ); + if( PeekConsoleInput( _KeyboardHandle, + Event, + NumberOfInputEvents, + &NumberOfEventsRead ) && + NumberOfEventsRead != 0 ) { + + *Available = CheckForAsciiKey( Event, NumberOfInputEvents ); + Result = TRUE; + } + FREE( Event ); + } + + } + return( Result ); +} + + + + +BOOLEAN +KEYBOARD::FillBuffer( + OUT PBYTE Buffer, + IN ULONG BufferSize, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Fills a buffer with data read from the keyboard. + +Arguments: + + Buffer - Points to the buffer where the data will be put. + + BufferSize - Indicates total number of bytes to read from the stream. + + BytesRead - Points to the variable that will contain the number of + bytes read. + +Return Value: + + BOOLEAN - Indicates if the read operation succeeded. + + +--*/ + + +{ + BOOLEAN Result; + ULONG Count; + + + Result = ReadFile( _KeyboardHandle, + Buffer, + BufferSize, + BytesRead, + NULL ); + if( !Result ) { + return( Result ); + } + if (*BytesRead == 0) { + _FlagCtrlZ = TRUE; + } else if ( IsLineModeEnabled() ) { + Count = *BytesRead; + while( Count > 0 ) { + if( *Buffer != CTRL_Z ) { + Count--; + Buffer++; + } else { + *Buffer = 0; + *BytesRead -= Count; + _FlagCtrlZ = TRUE; + Count = 0; // To get out of while() loop + } + } + } + BUFFER_STREAM::SetStreamTypeANSI(); + return( Result ); +} + + +ULIB_EXPORT +BOOLEAN +KEYBOARD::Flush( + ) + +/*++ + +Routine Description: + + Discards all keys in the buffer in BUFFER_STREAM, and flushes the + console input buffer. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + BUFFER_STREAM::FlushBuffer(); + return( FlushConsoleInputBuffer( _KeyboardHandle ) ); +} + + + +BOOLEAN +KEYBOARD::EndOfFile( + ) CONST + +/*++ + +Routine Description: + + Indicates if end-of-file has occurred when the keyboard was read. + End-of-file for a keyboard means that the keyboard was in line + mode and a Ctrl-Z was read from the keyboard. + +Arguments: + + None. + +Return Value: + + BOOLEAN - returns TRUE if the keyboard is in the line mode and a + CTRL-Z was read. Returns FALSE otherwise. + +--*/ + +{ + BOOLEAN CtrlZ; + BOOLEAN MoreKeys; + PBOOLEAN Pointer; + + CtrlZ = _FlagCtrlZ; + if( CtrlZ ) { + if( IsKeyAvailable( &MoreKeys ) ) { + // + // Enables client to read again from the keyboard + // + // This method is CONST and shouldn't modify + // _FlagCtrlZ, but here is the place to do it. + // I cannot define the method as non-const because it was + // defined as CONST in the base class + // + Pointer = &(((PKEYBOARD) this)->_FlagCtrlZ); + *Pointer = !MoreKeys; + } + } + return( CtrlZ ); +} + +STREAMACCESS +KEYBOARD::QueryAccess( + ) CONST + +/*++ + +Routine Description: + + Informs the caller about the access to the keyboard. + +Arguments: + + None. + +Return Value: + + STREAMACCESS - Returns READ_ACCESS always. + +--*/ + +{ + // unreferenced parameters + (void)(this); + + return( READ_ACCESS ); +} + + + + +ULONG +KEYBOARD::QueryDelay( + ) CONST + +/*++ + +Routine Description: + + Obtains the delay value of the keyboard. + +Arguments: + + None. + +Return Value: + + ULONG - The delay value. + +--*/ + +{ + INT Delay; + + SystemParametersInfo( SPI_GETKEYBOARDDELAY, 0, &Delay, 0 ); + + return Delay; +} + +HANDLE +KEYBOARD::QueryHandle( + ) CONST + +/*++ + +Routine Description: + + Returns to the caller the keyboard handle. + +Arguments: + + None. + +Return Value: + + HANDLE - Returns the keyboard handle. + +--*/ + +{ + return( _KeyboardHandle ); +} + + +ULONG +KEYBOARD::QuerySpeed( + ) CONST + +/*++ + +Routine Description: + + Obtains the speed rate of the keyboard. + +Arguments: + + None. + +Return Value: + + ULONG - The speed value. + +--*/ + +{ + WORD Speed; + + SystemParametersInfo( SPI_GETKEYBOARDSPEED, 0, &Speed, 0 ); + + return Speed; + +} + + +BOOLEAN +KEYBOARD::SetDelay( + IN ULONG Delay + ) CONST + +/*++ + +Routine Description: + + Sets the delay value of the keyboard. + +Arguments: + + Delay - Supplies the delay value + +Return Value: + + BOOLEAN - TRUE if delay set, FALSE otherwise + +--*/ + +{ + + // return SystemParametersInfo( SPI_SETKEYBOARDDELAY, (UINT)Delay, NULL, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE ); + return TRUE; + +} + + +BOOLEAN +KEYBOARD::SetSpeed ( + IN ULONG Speed + ) CONST + +/*++ + +Routine Description: + + Sets the speed rate of the keyboard. + +Arguments: + + Speed - Supplies the speed value + +Return Value: + + BOOLEAN - TRUE if speed set, FALSE otherwise + +--*/ + +{ + + // return SystemParametersInfo( SPI_SETKEYBOARDSPEED, (UINT)Speed, NULL, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE ); + return TRUE; + +} + +ULIB_EXPORT +CONST +PBOOL +KEYBOARD::GetPFlagBreak ( + VOID + ) CONST + +/*++ + +Routine Description: + + Returns pointer to _FlagBreak. Used by xcopy to pass pointer to _FlagBreak + as the lpCancel flag to CopyFileEx. When the user hits a Ctrl-C, this flag + becomes TRUE and CopyFileEx will stop copying the current file. + +Arguments: + + none + +Return Value: + + Pointer to _Flagbreak +--*/ + +{ + return (&_FlagBreak); +} diff --git a/private/utils/ulib/src/list.cxx b/private/utils/ulib/src/list.cxx new file mode 100644 index 000000000..85f6afc2c --- /dev/null +++ b/private/utils/ulib/src/list.cxx @@ -0,0 +1,336 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ +#include "ulib.hxx" +#include "list.hxx" +#include "listit.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR( LIST, SEQUENTIAL_CONTAINER, ULIB_EXPORT ); + +VOID +LIST::Construct( + ) +/*++ + +Routine Description: + + This routine initializes the object to a default state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _head = NULL; + _tail = NULL; + _count = 0; +} + + +VOID +LIST::Destroy( + ) +/*++ + +Routine Description: + + This routine returns the object to a default state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _head = NULL; + _tail = NULL; + _count = 0; +} + + +ULIB_EXPORT +LIST::~LIST( + ) +/*++ + +Routine Description: + + Destructor for LIST. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + Destroy(); +} + + +ULIB_EXPORT +BOOLEAN +LIST::Initialize( + ) +/*++ + +Routine Description: + + This routine initializes the object to a valid initial state. + +Arguments: + + None. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + Destroy(); + + if (!_mem_block_mgr.Initialize(sizeof(OBJECT_LIST_NODE))) { + Destroy(); + return FALSE; + } + + return TRUE; +} + + +ULONG +LIST::QueryMemberCount( + ) CONST +/*++ + +Routine Description: + + This routine computes the number of members in the list. + +Arguments: + + None. + +Return Value: + + The number of members in the list. + +--*/ +{ + return _count; +} + + +ULIB_EXPORT +BOOLEAN +LIST::Put( + IN POBJECT Member + ) +/*++ + +Routine Description: + + This routine adds a new member to the end of the list. + +Arguments: + + Member - Supplies the element to add to the list. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + if (!_tail) { + + if (!(_head = _tail = (POBJECT_LIST_NODE) _mem_block_mgr.Alloc())) { + return FALSE; + } + + _head->next = _head->prev = NULL; + _head->data = Member; + + _count++; + return TRUE; + } + + if (!(_tail->next = (POBJECT_LIST_NODE) _mem_block_mgr.Alloc())) { + return FALSE; + } + + _tail->next->prev = _tail; + _tail = _tail->next; + + _tail->next = NULL; + _tail->data = Member; + + _count++; + return TRUE; +} + + +POBJECT +LIST::Remove( + IN OUT PITERATOR Position + ) +/*++ + +Routine Description: + + This routine removes the element at the specified position from the + list. The iterator is left pointing at the following element in + the list. + +Arguments: + + Position - Supplies a pointer to the element to remove. + +Return Value: + + A pointer to the element removed. + +--*/ +{ + POBJECT_LIST_NODE p; + PLIST_ITERATOR piter; + POBJECT pobj; + + DebugAssert(LIST_ITERATOR::Cast(Position)); + + if (!(piter = (PLIST_ITERATOR) Position) || !(p = piter->_current)) { + return NULL; + } + + if (p->next) { + p->next->prev = p->prev; + } + + if (p->prev) { + p->prev->next = p->next; + } + + if (_head == p) { + _head = p->next; + } + + if (_tail == p) { + _tail = p->prev; + } + + piter->_current = p->next; + + pobj = p->data; + + _mem_block_mgr.Free(p); + + _count--; + + return pobj; +} + + +ULIB_EXPORT +PITERATOR +LIST::QueryIterator( + ) CONST +/*++ + +Routine Description: + + This routine returns an iterator for this list. + +Arguments: + + None. + +Return Value: + + A valid iterator. + +--*/ +{ + PLIST_ITERATOR p; + + if (!(p = NEW LIST_ITERATOR)) { + return NULL; + } + + p->Initialize(this); + + return p; +} + + +ULIB_EXPORT +BOOLEAN +LIST::Insert( + IN OUT POBJECT Member, + IN OUT PITERATOR Position + ) +/*++ + +Routine Description: + + This routine inserts a new element before the specified position. + The 'Position' continues to point to the same element. + +Arguments: + + Member - Supplies the element to insert. + Position - Supplies the point at which to insert this member. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + POBJECT_LIST_NODE p, current; + + DebugAssert(LIST_ITERATOR::Cast(Position)); + + current = ((PLIST_ITERATOR) Position)->_current; + + if (!current) { + return Put(Member); + } + + if (!(p = (POBJECT_LIST_NODE) _mem_block_mgr.Alloc())) { + return FALSE; + } + + _count++; + p->data = Member; + + if (current == _head) { + _head = p; + } + + p->next = current; + p->prev = current->prev; + current->prev = p; + + if (p->prev) { + p->prev->next = p; + } + + return TRUE; +} diff --git a/private/utils/ulib/src/listit.cxx b/private/utils/ulib/src/listit.cxx new file mode 100644 index 000000000..f10f1832e --- /dev/null +++ b/private/utils/ulib/src/listit.cxx @@ -0,0 +1,45 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ +#include "ulib.hxx" +#include "listit.hxx" + + +DEFINE_CONSTRUCTOR( LIST_ITERATOR, ITERATOR ); + + +DEFINE_CAST_MEMBER_FUNCTION( LIST_ITERATOR ); + + +VOID +LIST_ITERATOR::Reset( + ) +{ + _current = NULL; +} + + +POBJECT +LIST_ITERATOR::GetCurrent( + ) +{ + return _current ? _current->data : NULL; +} + + +POBJECT +LIST_ITERATOR::GetNext( + ) +{ + _current = _current ? _current->next : _list->_head; + return _current ? _current->data : NULL; +} + + +POBJECT +LIST_ITERATOR::GetPrevious( + ) +{ + _current = _current ? _current->prev : _list->_tail; + return _current ? _current->data : NULL; +} diff --git a/private/utils/ulib/src/machine.cxx b/private/utils/ulib/src/machine.cxx new file mode 100644 index 000000000..ad548e2dd --- /dev/null +++ b/private/utils/ulib/src/machine.cxx @@ -0,0 +1,312 @@ + +#include <pch.cxx> + +#define _NTAPI_ULIB_ + +#if defined(_AUTOCHECK_) +extern "C" { + #include "nt.h" + #include "ntrtl.h" + #include "nturtl.h" +} +#endif // defined(_AUTOCHECK_) + +#include "ulib.hxx" +#include "machine.hxx" + +extern "C" { + #include "windows.h" +} + +BOOLEAN bInitialized = FALSE; + +#if defined(JAPAN) && defined(_X86_) + +extern "C" { +#include "..\..\..\machine\machinep.h" +} + +#if defined( _AUTOCHECK_ ) + +DWORD _dwMachineId = MACHINEID_MICROSOFT; + +// +// Local Support routine +// + +#define KEY_WORK_AREA ((sizeof(KEY_VALUE_FULL_INFORMATION) + \ + sizeof(ULONG)) + 64) + + +InitializeMachineId( + VOID +) +/*++ + +Routine Description: + + Given a unicode value name this routine will go into the registry + location for the machine identifier information and get the + value. + +Return Value: + +--*/ + +{ + HANDLE Handle; + NTSTATUS Status; + ULONG RequestLength; + ULONG ResultLength; + UCHAR Buffer[KEY_WORK_AREA]; + UNICODE_STRING ValueName; + UNICODE_STRING KeyName; + OBJECT_ATTRIBUTES ObjectAttributes; + PKEY_VALUE_FULL_INFORMATION KeyValueInformation; + + if( bInitialized ) { + return TRUE; + } else { + bInitialized = TRUE; + } + + // + // Read the registry to determine of machine type. + // + + ValueName.Buffer = REGISTRY_MACHINE_IDENTIFIER; + ValueName.Length = sizeof(REGISTRY_MACHINE_IDENTIFIER) - sizeof(WCHAR); + ValueName.MaximumLength = sizeof(REGISTRY_MACHINE_IDENTIFIER); + + KeyName.Buffer = REGISTRY_HARDWARE_DESCRIPTION; + KeyName.Length = sizeof(REGISTRY_HARDWARE_DESCRIPTION) - sizeof(WCHAR); + KeyName.MaximumLength = sizeof(REGISTRY_HARDWARE_DESCRIPTION); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + Status = NtOpenKey(&Handle, + KEY_READ, + &ObjectAttributes); + + if (!NT_SUCCESS(Status)) { + + return FALSE; + } + + RequestLength = KEY_WORK_AREA; + + KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer; + + Status = NtQueryValueKey(Handle, + &ValueName, + KeyValueFullInformation, + KeyValueInformation, + RequestLength, + &ResultLength); + + ASSERT( Status != STATUS_BUFFER_OVERFLOW ); + + if (Status == STATUS_BUFFER_OVERFLOW) { + + return FALSE; + + } + + NtClose(Handle); + + if (NT_SUCCESS(Status)) { + + if (KeyValueInformation->DataLength != 0) { + + PWCHAR DataPtr; + UNICODE_STRING DetectedString, TargetString1, TargetString2; + + // + // Return contents to the caller. + // + + DataPtr = (PWCHAR) + ((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset); + + // + // Initialize strings. + // + + RtlInitUnicodeString( &DetectedString, DataPtr ); + RtlInitUnicodeString( &TargetString1, FUJITSU_FMR_NAME_W ); + RtlInitUnicodeString( &TargetString2, NEC_PC98_NAME_W ); + + // + // Check the hardware platform + // + + if (RtlPrefixUnicodeString( &TargetString1 , &DetectedString , TRUE)) { + + // + // Fujitsu FMR Series. + // + + _dwMachineId = MACHINEID_FUJITSU_FMR; + + } else if (RtlPrefixUnicodeString( &TargetString2 , &DetectedString , TRUE)) { + + // + // NEC PC-9800 Seriss + // + + _dwMachineId = MACHINEID_NEC_PC98; + + } else { + + // + // Standard PC/AT comapatibles + // + + _dwMachineId = MACHINEID_MS_PCAT; + + } + + return TRUE; + + } else { + + // + // Treat as if no value was found + // + + return FALSE; + + } + } + + return FALSE; +} + +#else // _AUTOCHECK_ + +DEFINE_EXPORTED_CONSTRUCTOR( MACHINE, OBJECT, ULIB_EXPORT ); + +DWORD MACHINE::_dwMachineId = MACHINEID_MICROSOFT; + +ULIB_EXPORT MACHINE MachinePlatform; + +NONVIRTUAL +ULIB_EXPORT +BOOLEAN +MACHINE::Initialize( + VOID + ) +{ + HKEY hkeyMap; + int ret; + DWORD cb; + WCHAR szBuff[80]; + UNICODE_STRING DetectedString, + TargetString1, + TargetString2; + + if( bInitialized ) { + return TRUE; + } else { + bInitialized = TRUE; + } + + if ( RegOpenKeyExW(HKEY_LOCAL_MACHINE, + REGISTRY_HARDWARE_SYSTEM, + 0, + KEY_READ, + &hkeyMap) != ERROR_SUCCESS ) { + return( FALSE ); + } + + // + // Reg functions deal with bytes, not chars + // + + cb = sizeof(szBuff); + + ret = RegQueryValueExW(hkeyMap, + REGISTRY_MACHINE_IDENTIFIER, + NULL, NULL, (LPBYTE)szBuff, &cb); + + RegCloseKey(hkeyMap); + + if (ret != ERROR_SUCCESS) return( FALSE ); + + // + // Initialize strings. + // + + RtlInitUnicodeString( &DetectedString, szBuff ); + RtlInitUnicodeString( &TargetString1, FUJITSU_FMR_NAME_W ); + RtlInitUnicodeString( &TargetString2, NEC_PC98_NAME_W ); + + // + // Check the hardware platform + // + + if (RtlPrefixUnicodeString( &TargetString1 , &DetectedString , TRUE)) { + + // + // Fujitsu FMR Series. + // + + _dwMachineId = MACHINEID_FUJITSU_FMR; + + } else if (RtlPrefixUnicodeString( &TargetString2 , &DetectedString , TRUE)) { + + // + // NEC PC-9800 Seriss + // + + _dwMachineId = MACHINEID_NEC_PC98; + + } else { + + // + // Standard PC/AT comapatibles + // + + _dwMachineId = MACHINEID_MS_PCAT; + + } + + return( TRUE ); +} + +NONVIRTUAL +ULIB_EXPORT +BOOLEAN +MACHINE::IsFMR( + VOID +) +{ + return( ISFUJITSUFMR( _dwMachineId ) ); +} + +NONVIRTUAL +ULIB_EXPORT +BOOLEAN +MACHINE::IsPC98( + VOID +) +{ + return( ISNECPC98( _dwMachineId ) ); +} + +NONVIRTUAL +ULIB_EXPORT +BOOLEAN +MACHINE::IsPCAT( + VOID +) +{ + return( ISMICROSOFT( _dwMachineId ) ); +} + +#endif // defined( _AUTOCHECK_ ) +#endif // defined(JAPAN) && defined(_X86_) diff --git a/private/utils/ulib/src/makefile b/private/utils/ulib/src/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/utils/ulib/src/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/utils/ulib/src/makefile.inc b/private/utils/ulib/src/makefile.inc new file mode 100644 index 000000000..6cf902f60 --- /dev/null +++ b/private/utils/ulib/src/makefile.inc @@ -0,0 +1,4 @@ +..\inc\rtmsg.h msg00001.bin rtmsg.rc: rtmsg.mc ulib.rc + mc -v -h ..\inc\ rtmsg.mc + copy rtmsg.rc + ulib.rc rtmsg.rc + diff --git a/private/utils/ulib/src/mbstr.cxx b/private/utils/ulib/src/mbstr.cxx new file mode 100644 index 000000000..421d98301 --- /dev/null +++ b/private/utils/ulib/src/mbstr.cxx @@ -0,0 +1,597 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + mbstr.cxx + +Abstract: + + This module contains the implementation of the MBSTR class. The MBSTR + class is a module that provides static methods for operating on + multibyte strings. + + +Author: + + Ramon J. San Andres (ramonsa) 21-Feb-1992 + +Environment: + + ULIB, User Mode + +Notes: + + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "mbstr.hxx" + +extern "C" { + #include <string.h> + #include <ctype.h> +} + +#ifdef DBCS +#define DB_SP_HI 0x81 +#define DB_SP_LO 0x40 +#endif + +PSTR* +MBSTR::MakeLineArray ( + INOUT PSTR* Buffer, + INOUT PDWORD BufferSize, + INOUT PDWORD NumberOfLines + ) +/*++ + +Routine Description: + + Constructs an array of strings into a buffer, one string per line. + Adds nulls in the buffer. + +Arguments: + + Buffer - Supplies the buffer. + Receives pointer remaining buffer + + BufferSize - Supplies the size of the buffer. + Receives the size of the remaining buffer + + NumberOfLines - Supplies number of lines wanted. + Receives number of lines obtained. If BufferSize is + 0 on output, the last line is partial (i.e. equal + to Buffer). + +Return Value: + + Pointer to array of string pointers. + + +--*/ +{ + +#if 0 + PSTR *Array = NULL; + DWORD NextElement; + DWORD ArraySize; + DWORD ArrayLeft; + DWORD Lines = 0; + DWORD LinesLeft; + DWORD Size, Size1; + PSTR Buf, Buf1; + PSTR p; + DWORD Idx; + + if ( Buffer && BufferSize && NumberOfLines ) { + + Buf = *Buffer; + Size = *BufferSize; + Linesleft = *NumberOfLines; + + if ( Buf && (Array = (PSTR *)MALLOC( CHUNK_SIZE * sizeof( PSTR *)) ) ) { + + ArrayLeft = CHUNK_SIZE; + ArraySize = CHUNK_SIZE; + + // + // Linearize the buffer and get pointers to all the lines + // + while ( Size && LinesLeft ) { + + // + // If Array is full, reallocate it. + // + if ( ArrayLeft == 0 ) { + + if ( !(Array = (PSTR *)REALLOC( Array, (ArraySize+CHUNK_SIZE) * sizeof( PSTR * ) ) )) { + + Buf = *Buffer; + Size = *BufferSize; + Lines = 0; + break; + } + + ArraySize += CHUNK_SIZE; + ArrayLeft += CHUNK_SIZE; + + } + + + // + // Get one line and add it to the array + // + Buf1 = Buf; + Size1 = Size; + + while ( TRUE ) { + + // + // Look for end of line + // + Idx = Strcspn( Buf1, "\r\n" ); + + + // + // If end of line not found, we add the last chunk to the list and + // increment the line count, but to not update the size. + // + if ( Idx > Size1 ) { + // + // End of line not found, we add the last chunk + // to the list and stop looking for strings, but + // we do not update the size. + // + LinesLeft = 0; + Size1 = Size; + Buf1 = Buf; + break; + + } else { + // + // If this is really the end of a line we stop. + // + Buf1 += Idx; + Size1 -= Idx; + + // + // If '\r', see if this is really the end of a line. + // + if ( *Buf1 == '\r' ) { + + if ( Size1 == 0 ) { + + // + // Cannot determine if end of line because + // ran out of buffer + // + LinesLeft = 0; + Size1 = Size; + Buf1 = Buf; + break; + + } else if ( *(Buf+1) == '\n' ) { + + // + // End of line is \r\n + // + *Buf1++ = '\0'; + *Buf1++ = '\0'; + Size1--; + break; + + } else { + + // + // Not end of line + // + Buf1++; + Size1--; + + } + + } else { + + // + // End of line is \n + // + Buf1++; + Size1--; + break; + } + + } + } + + // + // Add line to array + // + Array[Lines++] = Buf; + + Buf = Buf1; + Size = Size1; + + } + } + + *Buffer = Buf; + *BufferSize = Size; + *NumberOfLines = Lines; + } + + return Array; +#endif + + UNREFERENCED_PARAMETER( Buffer ); + UNREFERENCED_PARAMETER( BufferSize ); + UNREFERENCED_PARAMETER( NumberOfLines ); + + return NULL; +} + + + +DWORD +MBSTR::Hash( + IN PSTR String, + IN DWORD Buckets, + IN DWORD BytesToSum + ) +{ + + DWORD HashValue = 0; + DWORD Bytes; + + if ( !String ) { + + HashValue = (DWORD)-1; + + } else { + + if ( (Bytes = (DWORD)Strlen( String )) > BytesToSum ) { + Bytes = BytesToSum; + } + + while ( Bytes > 0 ) { + HashValue += *(String + --Bytes); + } + + HashValue = HashValue % Buckets; + } + + return HashValue; +} + + + +PSTR +MBSTR::SkipWhite( + IN PSTR p + ) +{ + +#ifdef DBCS + + while (*p) { + + if (*p == DB_SP_HI && *(p+1) == DB_SP_LO) { + *p++ = ' '; + *p++ = ' '; + } else if (!IsDBCSLeadByte(*p) && issspace(*p)) { + p++; + } else { + break; + } + } + +#else + while (isspace(*p)) { + p++; + } +#endif + + return p; + +} + + + +/**************************************************************************/ +/* Compare two strings, ignoring white space, case is significant, return */ +/* 0 if identical, <>0 otherwise. Leading and trailing white space is */ +/* ignored, internal white space is treated as single characters. */ +/**************************************************************************/ +ULIB_EXPORT +INT +MBSTR::Strcmps ( + IN PSTR p1, + IN PSTR p2 + ) +{ + char *q; + + p1 = MBSTR::SkipWhite(p1); /* skip any leading white space */ + p2 = MBSTR::SkipWhite(p2); + + while (TRUE) + { + if (*p1 == *p2) + { + if (*p1++ == 0) /* quit if at the end */ + return (0); + else + p2++; + +#ifdef DBCS + if (CheckSpace(p1)) +#else + if (isspace(*p1)) /* compress multiple spaces */ +#endif + { + q = MBSTR::SkipWhite(p1); + p1 = (*q == 0) ? q : q - 1; + } + +#ifdef DBCS + if (CheckSpace(p2)) +#else + if (isspace(*p2)) +#endif + { + q = MBSTR::SkipWhite(p2); + p2 = (*q == 0) ? q : q - 1; + } + } + else + return *p1-*p2; + } +} + + + + + +/**************************************************************************/ +/* Compare two strings, ignoring white space, case is not significant, */ +/* return 0 if identical, <>0 otherwise. Leading and trailing white */ +/* space is ignored, internal white space is treated as single characters.*/ +/**************************************************************************/ +ULIB_EXPORT +INT +MBSTR::Strcmpis ( + IN PSTR p1, + IN PSTR p2 + ) +{ +#ifndef DBCS + char *q; + + p1 = MBSTR::SkipWhite(p1); /* skip any leading white space */ + p2 = MBSTR::SkipWhite(p2); + + while (TRUE) + { + if (toupper(*p1) == toupper(*p2)) + { + if (*p1++ == 0) /* quit if at the end */ + return (0); + else + p2++; + + if (isspace(*p1)) /* compress multiple spaces */ + { + q = SkipWhite(p1); + p1 = (*q == 0) ? q : q - 1; + } + + if (isspace(*p2)) + { + q = MBSTR::SkipWhite(p2); + p2 = (*q == 0) ? q : q - 1; + } + } + else + return *p1-*p2; + } +#else // DBCS +// MSKK KazuM Jan.28.1993 +// Unicode DBCS support + PSTR q; + + p1 = MBSTR::SkipWhite(p1); /* skip any leading white space */ + p2 = MBSTR::SkipWhite(p2); + + while (TRUE) + { + if (toupper(*p1) == toupper(*p2)) + { + if (*p1++ == 0) /* quit if at the end */ + return (0); + else + p2++; + + if (CheckSpace(p1)) + { + q = SkipWhite(p1); + p1 = (*q == 0) ? q : q - 1; + } + + if (CheckSpace(p2)) + { + q = MBSTR::SkipWhite(p2); + p2 = (*q == 0) ? q : q - 1; + } + } + else + return *p1-*p2; + } +#endif // DBCS +} + + + +#ifdef DBCS + +/**************************************************************************/ +/* Routine: CheckSpace */ +/* Arguments: an arbitrary string */ +/* Function: Determine whether there is a space in the string. */ +/* Side effects: none */ +/**************************************************************************/ +INT +MBSTR::CheckSpace( + IN PSTR s + ) +{ + if (isspace(*s) || (*s == DB_SP_HI && *(s+1) == DB_SP_LO)) + return (TRUE); + else + return (FALSE); +} + +#endif + + + + + +#if 0 +/**************************************************************************/ +/* strcmpi will compare two string lexically and return one of */ +/* the following: */ +/* - 0 if the strings are equal */ +/* - 1 if first > the second */ +/* - (-1) if first < the second */ +/* */ +/* This was written to replace the run time library version of */ +/* strcmpi which does not correctly compare the european character set. */ +/* This version relies on a version of toupper which uses IToupper. */ +/**************************************************************************/ + +int FC::_strcmpi(unsigned char *str1, unsigned char *str2) +{ + unsigned char c1, c2; + +#ifdef DBCS + while (TRUE) + { + c1 = *str1++; + c2 = *str2++; + if (c1 == '\0' || c2 == '\0') + break; + if (IsDBCSLeadBYTE(c1) && IsDBCSLeadBYTE(c2)) + { + if (c1 == c2) + { + c1 = *str1++; + c2 = *str2++; + if (c1 != c2) + break; + } + else + break; + } + else if (IsDBCSLeadBYTE(c1) || IsDBCSLeadBYTE(c2)) + return (IsDBCSLeadBYTE(c1) ? 1 : -1); + else + if ((c1 = toupper(c1)) != (c2 = toupper(c2))) + break; + } + return (c1 == c2 ? 0 : (c1 > c2 ? 1 : -1)); +#else + while ((c1 = toupper(*str1++)) == (c2 = toupper(*str2++))) + { + if (c1 == '\0') + return (0); + } + + if (c1 > c2) + return (1); + else + return (-1); +#endif // DBCS +} +#endif // if 0 + +#ifdef DBCS +//fix kksuzuka: #930 +//Enabling strcmpi disregarding the case of DBCS letters. + +ULIB_EXPORT +INT +MBSTR::Stricmp ( + IN PSTR p1, + IN PSTR p2 + ) +{ + char c1,c2; + + while (TRUE) + { + c1 = *p1++; + c2 = *p2++; + + if (c1=='\0' || c2 == '\0') + break; + + if (IsDBCSLeadByte(c1) && IsDBCSLeadByte(c2) && c1 == c2) + { + if (c1==c2) + { + c1 = *p1++; + c2 = *p2++; + if (c1 != c2) + break; + } + else + break; + } + + else if (IsDBCSLeadByte(c1) || IsDBCSLeadByte(c2)) + return (IsDBCSLeadByte(c1) ? 1: -1); + + else + if ((c1 = toupper(c1)) != (c2 = toupper(c2))) + break; + + } + return (c1 == c2 ? 0 : (c1 >c2 ? 1: -1)); +} + +//fix kksuzuka: #926 +//Enabling strstr disregarding the case of DBCS letters. +ULIB_EXPORT +PSTR +MBSTR::Strstr ( + IN PSTR p1, + IN PSTR p2 + ) +{ + DWORD dLen; + PSTR pEnd; + + dLen = Strlen(p2); + pEnd = p1+ Strlen(p1); + + while ((p1+dLen)<=pEnd) { + if ( !memcmp(p1,p2,dLen) ) { + return(p1); + } + if ( IsDBCSLeadByte(*p1) ) { + p1 += 2; + } else { + p1++; + } + } + + return( NULL ); +} + +#endif diff --git a/private/utils/ulib/src/mem.cxx b/private/utils/ulib/src/mem.cxx new file mode 100644 index 000000000..89df14071 --- /dev/null +++ b/private/utils/ulib/src/mem.cxx @@ -0,0 +1,8 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ +#include "ulib.hxx" +#include "mem.hxx" + + +DEFINE_CONSTRUCTOR( MEM, OBJECT ); diff --git a/private/utils/ulib/src/membmgr.cxx b/private/utils/ulib/src/membmgr.cxx new file mode 100644 index 000000000..3f0bd4494 --- /dev/null +++ b/private/utils/ulib/src/membmgr.cxx @@ -0,0 +1,415 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + membmgr.cxx + +Author: + + Norbert P. Kusters (norbertk) 29-May-92 + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "membmgr.hxx" +#include "iterator.hxx" + + +DEFINE_CONSTRUCTOR( STATIC_MEM_BLOCK_MGR, OBJECT ); + + +STATIC_MEM_BLOCK_MGR::~STATIC_MEM_BLOCK_MGR( + ) +/*++ + +Routine Description: + + Destructor for STATIC_MEM_BLOCK_MGR. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + Destroy(); +} + + +VOID +STATIC_MEM_BLOCK_MGR::Construct( + ) +/*++ + +Routine Description: + + This routine initializes the object to a default initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _heap = NULL; + _num_blocks = 0; + _block_size = 0; + _num_allocated = 0; + _next_alloc = 0; +} + + +VOID +STATIC_MEM_BLOCK_MGR::Destroy( + ) +/*++ + +Routine Description: + + This routine returns the object to a default initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + FREE(_heap); + _num_blocks = 0; + _block_size = 0; + _num_allocated = 0; + _next_alloc = 0; +} + + +BOOLEAN +STATIC_MEM_BLOCK_MGR::Initialize( + IN ULONG MemBlockSize, + IN ULONG NumBlocks + ) +/*++ + +Routine Description: + + This routine initializes this object to a usable initial state. + +Arguments: + + MemBlockSize - Supplies the number of bytes per mem block. + NumBlocks - Supplies the number of mem blocks to be + contained by this object. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + Destroy(); + + DebugAssert(MemBlockSize); + + if (!(_heap = (PCHAR) MALLOC(NumBlocks*MemBlockSize)) || + !_bitvector.Initialize(NumBlocks)) { + + Destroy(); + return FALSE; + } + + _num_blocks = NumBlocks; + _block_size = MemBlockSize; + + return TRUE; +} + + +PVOID +STATIC_MEM_BLOCK_MGR::Alloc( + ) +/*++ + +Routine Description: + + This routine allocates a single memory block and returns its + pointer. + +Arguments: + + None. + +Return Value: + + A pointer to a mem block. + +--*/ +{ + if (_num_allocated == _num_blocks) { + return NULL; + } + + for (;;) { + + if (!_bitvector.IsBitSet(_next_alloc)) { + + _bitvector.SetBit(_next_alloc); + _num_allocated++; + return &_heap[_next_alloc*_block_size]; + } + + _next_alloc = (_next_alloc + 1) % _num_blocks; + } +} + + +BOOLEAN +STATIC_MEM_BLOCK_MGR::Free( + OUT PVOID MemBlock + ) +/*++ + +Routine Description: + + This routine frees the given mem block for use by other clients. + +Arguments: + + MemBlock - Supplies a pointer to the mem block to free. + +Return Value: + + FALSE - The mem block was not freed. + TRUE - Success. + +--*/ +{ + ULONG i; + + if (!MemBlock) { + return TRUE; + } + + i = ((PCHAR) MemBlock - _heap)/_block_size; + if (i >= _num_blocks) { + return FALSE; + } + + DebugAssert(((PCHAR) MemBlock - _heap)%_block_size == 0); + + _bitvector.ResetBit(i); + _num_allocated--; + _next_alloc = i; + return TRUE; +} + + +DEFINE_EXPORTED_CONSTRUCTOR( MEM_BLOCK_MGR, OBJECT, ULIB_EXPORT ); + + +VOID +MEM_BLOCK_MGR::Construct( + ) +/*++ + +Routine Description: + + This routine initializes the object to a default initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + memset(_static_mem_list, 0, 32*sizeof(PVOID)); +} + + +VOID +MEM_BLOCK_MGR::Destroy( + ) +/*++ + +Routine Description: + + This routine returns the object to a default initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + ULONG i; + + for (i = 0; _static_mem_list[i]; i++) { + DELETE(_static_mem_list[i]); + } +} + + +ULIB_EXPORT +MEM_BLOCK_MGR::~MEM_BLOCK_MGR( + ) +/*++ + +Routine Description: + + Destructor for MEM_BLOCK_MGR. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + Destroy(); +} + + +ULIB_EXPORT +BOOLEAN +MEM_BLOCK_MGR::Initialize( + IN ULONG MemBlockSize, + IN ULONG InitialNumBlocks + ) +/*++ + +Routine Description: + + This routine initializes the class to a valid initial state. + +Arguments: + + MemBlockSize - Specifies the size of the memory blocks to + be allocated from this object. + InitialNumBlocks - Specifies the initial number of blocks + to be allocated by this object. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + Destroy(); + + if (!(_static_mem_list[0] = NEW STATIC_MEM_BLOCK_MGR) || + !_static_mem_list[0]->Initialize(MemBlockSize, InitialNumBlocks)) { + + Destroy(); + return FALSE; + } + + return TRUE; +} + + +ULIB_EXPORT +PVOID +MEM_BLOCK_MGR::Alloc( + ) +/*++ + +Routine Description: + + This routine allocates a mem blocks and returns its pointer. + +Arguments: + + None. + +Return Value: + + A pointer to a mem block. + +--*/ +{ + ULONG i; + PVOID r; + + for (i = 0; _static_mem_list[i]; i++) { + if (r = _static_mem_list[i]->Alloc()) { + return r; + } + } + + // At this point all of the current buffers are full so + // start another one. + + if (!(_static_mem_list[i] = NEW STATIC_MEM_BLOCK_MGR) || + !_static_mem_list[i]->Initialize( + _static_mem_list[i - 1]->QueryBlockSize(), + 2*_static_mem_list[i - 1]->QueryNumBlocks())) { + + DELETE(_static_mem_list[i]); + return NULL; + } + + return _static_mem_list[i]->Alloc(); +} + + +ULIB_EXPORT +BOOLEAN +MEM_BLOCK_MGR::Free( + IN OUT PVOID MemPtr + ) +/*++ + +Routine Description: + + This routine frees the given memory block. + +Arguments: + + MemPtr - Supplies a pointer to the buffer to free. + +Return Value: + + This function returns TRUE if the memory was successfully + freed. + +--*/ +{ + ULONG i; + + for (i = 0; _static_mem_list[i]; i++) { + if (_static_mem_list[i]->Free(MemPtr)) { + return TRUE; + } + } + + return FALSE; +} diff --git a/private/utils/ulib/src/message.cxx b/private/utils/ulib/src/message.cxx new file mode 100644 index 000000000..141b501c8 --- /dev/null +++ b/private/utils/ulib/src/message.cxx @@ -0,0 +1,400 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ +#include "ulib.hxx" +#include "message.hxx" +#include "hmem.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR(MESSAGE, OBJECT, ULIB_EXPORT); + + +ULIB_EXPORT +MESSAGE::~MESSAGE( + ) +/*++ + +Routine Description: + + Destructor for MESSAGE. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +} + +BOOLEAN +MESSAGE::Set( + IN MSGID MsgId, + IN MESSAGE_TYPE MessageType, + IN ULONG MessageVisual + ) +/*++ + +Routine Description: + + This routine sets up the MESSAGE class to display the message with the + 'MsgId' resource identifier. + +Arguments: + + MsgId - Supplies the resource id of the message. + MessageType - Suppies the type of the message to be displayed. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + // unreferenced parameters + (void)(this); + (void)(MsgId); + (void)(MessageType); + (void)(MessageVisual); + + return TRUE; +} + + +ULIB_EXPORT +BOOLEAN +MESSAGE::Display( + IN PCSTR Format ... + ) +/*++ + +Routine Description: + + This routine displays the message with the specified parameters. + +Arguments: + + Format ... - Supplies a printf style list of arguments. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + va_list ap; + BOOLEAN r; + + // unreferenced parameters + (void)(this); + + va_start(ap, Format); + r = DisplayV(Format, ap); + va_end(ap); + + return r; +} + + +BOOLEAN +MESSAGE::DisplayV( + IN PCSTR Format, + IN va_list VarPointer + ) +/*++ + +Routine Description: + + This routine displays the message with the specified parameters. + +Arguments: + + Format - Supplies a printf style list of arguments. + VarPointer - Supplies a varargs pointer to the arguments. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + // unreferenced parameters + (void)(this); + (void)(Format); + (void)(VarPointer); + + return TRUE; +} + + +PMESSAGE +MESSAGE::Dup( + ) +/*++ + +Routine Description: + + This routine returns a new MESSAGE of the same type. + +Arguments: + + None. + +Return Value: + + A pointer to a new MESSAGE object. + +--*/ +{ + // unreferenced parameters + (void)(this); + + return NEW MESSAGE; +} + + +ULIB_EXPORT +BOOLEAN +MESSAGE::IsYesResponse( + IN BOOLEAN Default + ) +/*++ + +Routine Description: + + This routine queries to see if the response to a message is either + yes or no. + +Arguments: + + Default - Supplies a default answer to the question. + +Return Value: + + FALSE - A "no" response. + TRUE - A "yes" response. + +--*/ +{ + // unreferenced parameters + (void)(this); + + return Default; +} + + +ULIB_EXPORT +BOOLEAN +MESSAGE::QueryStringInput( + OUT PWSTRING String + ) +/*++ + +Routine Description: + + This routine queries a string from the user. + +Arguments: + + String - Supplies a buffer to return the string into. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + // unreferenced parameters + (void)(this); + + return String->Initialize(""); +} + + + +ULIB_EXPORT +MSGID +MESSAGE::SelectResponse( + IN ULONG NumberOfSelections ... + ) +/*++ + +Routine Descriptions: + + This routine queries a response from the user. It returns the + message id of the response inputted. + +Arguments: + + NumberOfSelections - Supplies the number of possible message + responses. + + ... - Supplies 'NumberOfSelections' message identifiers. + +Return Value: + + The first message id on the list. + +--*/ +{ + va_list ap; + MSGID msg; + + // unreferenced parameters + (void)(this); + + va_start(ap, NumberOfSelections); + msg = va_arg(ap, MSGID); + va_end(ap); + return msg; +} + + + +ULIB_EXPORT +BOOLEAN +MESSAGE::WaitForUserSignal( + ) +/*++ + +Routine Description: + + This routine waits for a signal from the user. + +Arguments: + + None. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + // unreferenced parameters + (void)(this); + + return TRUE; +} + +ULIB_EXPORT +BOOLEAN +MESSAGE::SetDotsOnly( + IN BOOLEAN DotsState + ) +{ + // unreferenced parameters + (void)this; + (void)DotsState; + + return FALSE; +} + +ULIB_EXPORT +BOOLEAN +MESSAGE::IsLoggingEnabled( + ) +{ + return FALSE; +} + +ULIB_EXPORT +VOID +MESSAGE::SetLoggingEnabled( + IN BOOLEAN Enable + ) +{ + (void)this; + (void)Enable; +} + + +ULIB_EXPORT +VOID +MESSAGE::ResetLoggingIterator( + ) +{ +} + + +ULIB_EXPORT +BOOLEAN +MESSAGE::QueryNextLoggedMessage( + OUT PFSTRING MessageText + ) +{ + return FALSE; +} + + +ULIB_EXPORT +BOOLEAN +MESSAGE::QueryPackedLog( + IN OUT PHMEM Mem, + OUT PULONG PackedDataLength + ) +/*++ + +Routine Description: + +Arguments: + + Mem -- Supplies a container for the packed log. + PackedDataLength -- Receives the number of bytes written to Mem. + +Return Value: + + TRUE upon successful completion. + +--*/ +{ + FSTRING CurrentString; + PWCHAR Buffer; + ULONG NewBufferSize, CurrentOffset; + + if( !IsLoggingEnabled() ) { + + // BUGBUG billmc -- this should really return FALSE! + // + FSTRING Hello; + + Hello.Initialize( L"Hello World!\n" ); + + *PackedDataLength = Hello.QueryChCount() * sizeof(WCHAR); + + return( Mem->Resize( Hello.QueryChCount() * sizeof(WCHAR) ) && + Hello.QueryWSTR( 0, TO_END, + (PWCHAR)Mem->GetBuf(), Mem->QuerySize() ) ); + } + + ResetLoggingIterator(); + CurrentOffset = 0; + + while( QueryNextLoggedMessage( &CurrentString ) ) { + + NewBufferSize = (CurrentOffset + CurrentString.QueryChCount()) * sizeof(WCHAR); + if( NewBufferSize > Mem->QuerySize() && + !Mem->Resize( (NewBufferSize + 1023)/1024 * 1024, 0x1 ) ) { + + return FALSE; + } + + Buffer = (PWCHAR)Mem->GetBuf(); + memcpy( Buffer + CurrentOffset, + CurrentString.GetWSTR(), + CurrentString.QueryChCount() * sizeof(WCHAR) ); + + CurrentOffset += CurrentString.QueryChCount(); + } + + *PackedDataLength = CurrentOffset * sizeof(WCHAR); + return TRUE; +} diff --git a/private/utils/ulib/src/newdel.cxx b/private/utils/ulib/src/newdel.cxx new file mode 100644 index 000000000..1cf15b52d --- /dev/null +++ b/private/utils/ulib/src/newdel.cxx @@ -0,0 +1,260 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + newdel.cxx + +Abstract: + + This module implements the C++ new and delete operators for + the Setup-Loader environment. In other environments, the utilities + use the standard C++ new and delete. + +Author: + + David J. Gilman (davegi) 07-Dec-1990 + +Environment: + + ULIB, User Mode + +--*/ +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" + + + +extern "C" +int _cdecl +_purecall( ); + +int _cdecl +_purecall( ) +{ + + DebugAbort( "Pure virtual function called.\n" ); + + return 0; +} + + + + + +#if defined( _SETUP_LOADER_ ) || defined( _AUTOCHECK_ ) + +// When the utilities are running the Setup Loader +// or Autocheck environments, they can't use the C-Run- +// Time new and delete; instead, these functions are +// provided. +// +PVOID _cdecl +operator new ( + IN size_t bytes + ) +/*++ + +Routine Description: + + This routine allocates 'bytes' bytes of memory. + +Arguments: + + bytes - Supplies the number of bytes requested. + +Return Value: + + A pointer to 'bytes' bytes or NULL. + +--*/ +{ + #if defined( _AUTOCHECK_ ) + + return RtlAllocateHeap(RtlProcessHeap(), 0, bytes); + + #elif defined( _SETUP_LOADER_ ) + + return SpMalloc( bytes ); + + #else // _AUTOCHECK_ and _SETUP_LOADER_ not defined + + return (PVOID) LocalAlloc(0, bytes); + + #endif // _AUTOCHECK_ +} + + +VOID _cdecl +operator delete ( + IN PVOID pointer + ) +/*++ + +Routine Description: + + This routine frees the memory pointed to by 'pointer'. + +Arguments: + + pointer - Supplies a pointer to the memoery to be freed. + +Return Value: + + None. + +--*/ +{ + if (pointer) { + + #if defined( _AUTOCHECK_ ) + + RtlFreeHeap(RtlProcessHeap(), 0, pointer); + + #elif defined( _SETUP_LOADER_ ) + + SpFree( pointer ); + + #else // _AUTOCHECK_ and _SETUP_LOADER_ not defined + + LocalFree( pointer ); + + #endif // _AUTOCHECK_ + + } +} + + +typedef void (*PF)(PVOID); +typedef void (*PFI)(PVOID, int); +PVOID +__vec_new( + IN OUT PVOID op, + IN int number, + IN int size, + IN PVOID f) +/* + allocate a vector of "number" elements of size "size" + and initialize each by a call of "f" +*/ +{ + if (op == 0) { + + #if defined( _AUTOCHECK_ ) + + op = RtlAllocateHeap(RtlProcessHeap(), 0, number*size); + + #elif defined( _SETUP_LOADER_ ) + + op = SpMalloc( number*size ); + + #else // _AUTOCHECK_ and _SETUP_LOADER_ not defined + + op = (PVOID) LocalAlloc(0, number*size); + + #endif // _AUTOCHECK_ + + } + + if (op && f) { + + register char* p = (char*) op; + register char* lim = p + number*size; + register PF fp = PF(f); + while (p < lim) { + (*fp) (PVOID(p)); + p += size; + } + } + + return op; +} + + +void +__vec_delete( + PVOID op, + int n, + int sz, + PVOID f, + int del, + int x) + +/* + destroy a vector of "n" elements of size "sz" +*/ +{ + // unreferenced parameters + // I wonder what it does--billmc + (void)(x); + + if (op) { + if (f) { + register char* cp = (char*) op; + register char* p = cp; + register PFI fp = PFI(f); + p += n*sz; + while (p > cp) { + p -= sz; + (*fp)(PVOID(p), 2); // destroy VBC, don't delete + } + } + if (del) { + + #if defined( _AUTOCHECK_ ) + + RtlFreeHeap(RtlProcessHeap(), 0, op); + + #elif defined( _SETUP_LOADER_ ) + + SpFree( op ); + + #else // _AUTOCHECK_ not defined + + LocalFree(op); + + #endif // _AUTOCHECK_ + + } + } +} + +#endif // _SETUP_LOADER_ + +ULIB_EXPORT +PVOID +UlibRealloc( + PVOID x, + ULONG size + ) +{ +#if defined( _SETUP_LOADER_ ) + + return SpRealloc(x, size); + +#else // _SETUP_LOADER_ + + PVOID p; + ULONG l; + + + if (size <= (l = RtlSizeHeap(RtlProcessHeap(), 0, x))) { + return x; + } + + if (!(p = MALLOC(size))) { + return NULL; + } + + memcpy(p, x, (UINT) l); + + FREE(x); + + return p; + +#endif // _SETUP_LOADER_ +} diff --git a/private/utils/ulib/src/object.cxx b/private/utils/ulib/src/object.cxx new file mode 100644 index 000000000..c89eb4a70 --- /dev/null +++ b/private/utils/ulib/src/object.cxx @@ -0,0 +1,94 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + object.cxx + +Abstract: + + This module contains the definitions for the non-inline member functions + for the class OBJECT, the root of the Ulib hierarchy. OBJECT's + constructor merely initializes it's internal CLASS_DESCRIPTOR to point + to the static descriptor for the class at the beginning of this + construction chain. + +Author: + + David J. Gilman (davegi) 30-Oct-1990 + +Environment: + + ULIB, User Mode + +[Notes:] + + optional-notes + +--*/ +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" + +ULIB_EXPORT +OBJECT::OBJECT( + ) +{ +} + +ULIB_EXPORT +OBJECT::~OBJECT( + ) +{ +} + + +ULIB_EXPORT +LONG +OBJECT::Compare ( + IN PCOBJECT Object + ) CONST + +/*++ + +Routine Description: + + Compare two objects based on their CLASS_ID's + +Arguments: + + Object - Supplies the object to compare with. + +Return Value: + + LONG < 0 - supplied OBJECT has a higher CLASS_ID + == 0 - supplied object has same CLASS_ID + > 0 - supplied OBJECT has a lower CLASS_ID + +Notes: + + It is expected that derived classes will overload this method and supply + an implementation that is more meaningful (i.e. class specific). This + implementation is ofeered as a default but is fairly meaningless as + CLASS_IDs are allocated randomly (but uniquely) at run-time by + CLASS_DESCRIPTORs. Therefore comparing two CLASS_IDs is not very + interesting (e.g. it will help if an ORDERED_CONTAINER of homogenous + objects is sorted). + +--*/ + +{ + LONG r; + + DebugPtrAssert( Object ); + + r = QueryClassId() - Object->QueryClassId(); + + return r ? r : (this - Object); +} + + +DEFINE_OBJECT_DBG_FUNCTIONS; diff --git a/private/utils/ulib/src/path.cxx b/private/utils/ulib/src/path.cxx new file mode 100644 index 000000000..c502c6828 --- /dev/null +++ b/private/utils/ulib/src/path.cxx @@ -0,0 +1,1449 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + path.cxx + +Abstract: + + This contains the implementation for all methods handling file + path names. These are needed for use with an file i/o or the + FILE and DIR objects. + +Author: + + bruce wilson w-wilson 21-Mar-90 + steve rowe stever 27-Dec-90 + +Environment: + + ULIB, user mode + +Revision History: + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +extern "C" { + #include <string.h> +} +#include "ulib.hxx" +#include "wstring.hxx" +#include "path.hxx" +#include "system.hxx" + +#if DBG==1 + #define PATH_SIGNATURE 0xADDBEEAD +#endif + + +typedef enum _SPECIAL_DEVICES { + LPT, + COM, + CON, + PRN, + AUX, + LAST_SPECIAL_DEVICE +} SPECIAL_DEVICES; + + +// +// Static member data. +// +PWSTRING _SlashString; +BOOLEAN _fInit = FALSE; +PWSTRING _SpecialDevices[ LAST_SPECIAL_DEVICE ]; + +#define DELIMITER_STRING "\\" +#define DELIMITER_CHAR ((WCHAR)'\\') + + + +BOOLEAN +PATH::Initialize ( + ) + +/*++ + +Routine Description: + + Perform global initialization of the PATH class. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Returns TRUE if global initialization was succesful + +Notes: + + Global initialization should be interpreted as class (rather than object) + initialization. This routine should be called by ALL other + PATH::Initialize member functions. + + Current this routine: + + - constructs and initializes _SlashString, a WSTRING that + contains a '\' + +--*/ + +{ + // unreferenced parameters + (void)(this); + + if (!_fInit) { + + if ( (( _SlashString = NEW DSTRING) != NULL) && + ((_SpecialDevices[LPT] = NEW DSTRING) != NULL) && + ((_SpecialDevices[COM] = NEW DSTRING) != NULL) && + ((_SpecialDevices[CON] = NEW DSTRING) != NULL) && + ((_SpecialDevices[PRN] = NEW DSTRING) != NULL) && + ((_SpecialDevices[AUX] = NEW DSTRING) != NULL) && + _SlashString->Initialize( DELIMITER_STRING ) && + _SpecialDevices[LPT]->Initialize( "LPT" ) && + _SpecialDevices[COM]->Initialize( "COM" ) && + _SpecialDevices[CON]->Initialize( "CON" ) && + _SpecialDevices[PRN]->Initialize( "PRN" ) && + _SpecialDevices[AUX]->Initialize( "AUX" ) + ) { + + return _fInit = TRUE; + + } + } + + return FALSE; +} + +ULIB_EXPORT +BOOLEAN +PATH::EndsWithDelimiter ( + ) CONST + +/*++ + +Routine Description: + + Returns TRUE if the path ends with slash + +Arguments: + + None. + +Return Value: + + BOOLEAN - Returns TRUE if the path ends with a slash + +--*/ +{ + + return ( _PathString.QueryChAt( _PathString.QueryChCount() - 1 ) == DELIMITER_CHAR ); + +} + +ULIB_EXPORT +PARRAY +PATH::QueryComponentArray ( + OUT PARRAY Array + ) CONST + +/*++ + +Routine Description: + + Obtain an array of strings containing all the components in the path. + Each string will have an element in the path delimited by '\\' + +Arguments: + + Array - Supplies an optional pointer to the array to fill. + +Return Value: + + Pointer to the array + +--*/ + +{ + + CHNUM Index; + CHNUM DelimiterPosition; + CHNUM StringSize; + PWSTRING Component; + + if (!Array) { + Array = NEW ARRAY; + } + + DebugPtrAssert( Array ); + DebugAssert( _Initialized == TRUE ); + + Array->Initialize(); + + Index = 0; + StringSize = _PathString.QueryChCount(); + + while ( ( Index < StringSize) && + ( _PathString.QueryChAt( Index ) == DELIMITER_CHAR ) ) { + Index++; + } + + while ( Index < StringSize ) { + + DelimiterPosition = _PathString.Strchr( DELIMITER_CHAR, Index ); + + Component = _PathString.QueryString( Index, + (DelimiterPosition == INVALID_CHNUM) ? TO_END : DelimiterPosition - Index ); + + DebugPtrAssert( Component ); + + if ( !Component ) { + break; + } + + Array->Put( Component ); + + if ( DelimiterPosition == INVALID_CHNUM ) { + Index = StringSize; + } else { + Index = DelimiterPosition + 1; + } + } + + return Array; +} + +CHNUM +PATH::QueryDeviceLen( + IN PWSTRING pString + ) CONST + +/*++ + +Routine Description: + + Find length in character of drive section + +Arguments: + + pString - Supplies the string to determine drive size. + +Return Value: + + CHNUM - Number of characters making up drive section. If no + drive section then the length is 0. + +--*/ +{ + CHNUM Position = 0; + CHNUM Position1; + SPECIAL_DEVICES Index; + ULONG tmp; + INT Pos; + LONG Number; + + + UNREFERENCED_PARAMETER( (void)this ); + + DebugPtrAssert( pString ); + + if ( pString->QueryChCount() > 0) { + + // + // Check for special device + // + Pos = (INT)pString->QueryChCount() - 1; + + while ( (Pos >= 0) && (pString->QueryChAt( (CHNUM)Pos ) != DELIMITER_CHAR) ) { + Pos --; + } + + Pos++; + + for (Index = LPT; Index < LAST_SPECIAL_DEVICE; + (tmp = (ULONG) Index, tmp++, Index = (SPECIAL_DEVICES) tmp) ) { + + if ( !pString->Stricmp( _SpecialDevices[Index], + (CHNUM)Pos ) ) { + + Position = (CHNUM)Pos + _SpecialDevices[Index]->QueryChCount(); + + // + // LPT && COM must be followed by a number; + // + if ( (Index == LPT) || (Index == COM) ) { + if ( Position >= pString->QueryChCount()) { + continue; + } + while ( (Position < pString->QueryChCount()) && + pString->QueryNumber( &Number, Position, 1 ) ) { + + Position++; + } + } + + if (Position >= pString->QueryChCount()) { + return Position; + } else if (pString->QueryChAt( Position ) == (WCHAR)':') { + return Position+1; + } + } + } + // + // Look for ':' + // + if ((Position = pString->Strchr((WCHAR)':')) != INVALID_CHNUM) { + return Position + 1; + } + + // + // check for leading "\\" + // + if ( pString->QueryChCount() > 1 && + pString->QueryChAt(0) == DELIMITER_CHAR && + pString->QueryChAt(1) == DELIMITER_CHAR) { + + // + // the device is a machine name - find the second backslash + // (start search after first double backsl). Note that this + // means that the device names if formed by the machine name + // and the sharepoint. + // + if ( ((Position = pString->Strchr( DELIMITER_CHAR, 2 )) != INVALID_CHNUM )) { + + Position1 = pString->Strchr( DELIMITER_CHAR, Position+1 ); + if ( Position1 == INVALID_CHNUM ) { + return pString->QueryChCount(); + } + return Position1; + + } + + // + // No backslash found, this is an invalid device + // + DebugAbort( "Invalid Device name" ); + + } + + + } + + return 0; +} + +VOID +PATH::SetPathState( + ) + +/*++ + +Routine Description: + + Sets the state information for the Path + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + + CHNUM chnLastSlash; + CHNUM chnLastDot; + CHNUM chnAcum; + CHNUM FirstSeparator; + + // + // Find the number of characters in the device name + // + chnAcum = _PathState.DeviceLen = QueryDeviceLen( &_PathString ); + + // + // Find the number of characters in the dirs portion of the path + // by searching for the last '\' + // + if ( _PathString.QueryChAt( chnAcum ) == DELIMITER_CHAR ) { + // + // Skip over the slash after the device name + // + FirstSeparator = 1; + chnAcum++; + + } else { + + FirstSeparator = 0; + } + + if ( chnAcum < _PathString.QueryChCount() ) { + + if (( chnLastSlash = _PathString.Strrchr( DELIMITER_CHAR, chnAcum )) != INVALID_CHNUM ) { + + // + // The dirs length is that character position less the length + // of the device + // + _PathState.DirsLen = chnLastSlash - _PathState.DeviceLen; + _PathState.SeparatorLen = 1; + + chnAcum += _PathState.DirsLen; + if ( FirstSeparator == 0 ) { + chnAcum++; + } + } else { + // + // There is no dirs portion of this path, but there is a name. + // + _PathState.DirsLen = FirstSeparator; + _PathState.SeparatorLen = 0; + + } + } else { + + // + // There is no name portion in this path, and the dirs portion + // might be empty (or consist solely of the delimiter ). + // + _PathState.DirsLen = FirstSeparator; + _PathState.SeparatorLen = 0; + } + + if ( chnAcum < _PathString.QueryChCount() ) { + + // + // Find the number of characters in the name portion of the path + // by searching for the last '.' + // + if (( chnLastDot = _PathString.Strrchr( ( WCHAR )'.', + chnAcum )) != INVALID_CHNUM ) { + + _PathState.BaseLen = chnLastDot - chnAcum; + + chnAcum += _PathState.BaseLen + 1; + + _PathState.ExtLen = _PathString.QueryChCount() - chnAcum; + + _PathState.NameLen = _PathState.BaseLen + _PathState.ExtLen + 1; + + + } else { + + // + // There is no last '.' so the name length is the length of the + // component from the last '\' to the end of the path (adjusted + // for zero base) and there is no extension. + // + + _PathState.NameLen = _PathString.QueryChCount() - chnAcum; + _PathState.BaseLen = _PathState.NameLen; + _PathState.ExtLen = 0; + + } + } else { + + // + // There is no name part + // + _PathState.NameLen = 0; + _PathState.BaseLen = 0; + _PathState.ExtLen = 0; + + } + + + // + // The prefix length is the sum of the device and dirs + // + _PathState.PrefixLen = _PathState.DeviceLen + _PathState.DirsLen; + + // + // If The device refers to a drive, uppercase it. (Done for + // compatibility with some DOS apps ). + // + if ( _PathState.DeviceLen == 2 ) { + _PathString.Strupr( 0, 1 ); + } + +} + +DEFINE_EXPORTED_CONSTRUCTOR( PATH, OBJECT, ULIB_EXPORT ); + +DEFINE_CAST_MEMBER_FUNCTION( PATH ); + +VOID +PATH::Construct ( + ) + +{ + _PathState.BaseLen = 0; + _PathState.DeviceLen= 0; + _PathState.DirsLen = 0; + _PathState.ExtLen = 0; + _PathState.NameLen = 0; + _PathState.PrefixLen= 0; + + _PathBuffer[0] = 0; + _PathString.Initialize(_PathBuffer, MAX_PATH); + +#if DBG==1 + _Signature = PATH_SIGNATURE; +#endif + +} + +ULIB_EXPORT +BOOLEAN +PATH::Initialize( + IN PCWSTR InitialPath, + IN BOOLEAN Canonicalize + ) + +/*++ + +Routine Description: + + Initialize a PATH object with the supplied string. No validation + on the given path is performed unless 'Canonicalize' is set to TRUE. + +Arguments: + + InitialPath - Supplies a zero terminated string + Canonicalize- Supplies a flag, which if TRUE indicates that the PATH + should be canoicalized at initialization time (i.e. now) + +Return Value: + + BOOLEAN - Returns TRUE if the PATH was succesfully initialized. + +--*/ + +{ + PWSTR filepart; + DWORD CharsInPath; + + + DebugPtrAssert( InitialPath ); + + // + // Perform global (class) initialization + // + if ( !_fInit ) { + if (!Initialize()) { + DebugAbort( "Class initialization failed" ); + return FALSE; + } + } + + // Avoid copies during Strcat by making this a reasonable size. + if (!_PathString.NewBuf(MAX_PATH - 1)) { + return FALSE; + } + + if ( Canonicalize ) { + + if (!_PathString.NewBuf(MAX_PATH - 1) || + !(CharsInPath = GetFullPathName((LPWSTR) InitialPath, + MAX_PATH, + (LPWSTR) _PathString.GetWSTR(), + &filepart)) || + CharsInPath > MAX_PATH) { + + return FALSE; + } + + _PathString.SyncLength(); + + SetPathState( ); +#if DBG==1 + _Initialized = TRUE; +#endif + return TRUE; + + } else if( ((PWSTRING) &_PathString)->Initialize( InitialPath )) { + + SetPathState( ); +#if DBG==1 + _Initialized = TRUE; +#endif + return TRUE; + } + + return FALSE; +} + +ULIB_EXPORT +BOOLEAN +PATH::Initialize( + IN PCWSTRING InitialPath, + IN BOOLEAN Canonicalize + + ) +{ + DebugPtrAssert( InitialPath ); + + return Initialize( InitialPath->GetWSTR(), Canonicalize ); +} + +ULIB_EXPORT +BOOLEAN +PATH::Initialize ( + IN PCPATH InitialPath, + IN BOOLEAN Canonicalize + ) + +{ + DebugPtrAssert( InitialPath ); + + return Initialize( InitialPath->GetPathString()->GetWSTR(), Canonicalize ); +} + +ULIB_EXPORT +PATH::~PATH ( + ) + +{ +} + +ULIB_EXPORT +BOOLEAN +PATH::AppendBase ( + IN PCWSTRING Base, + IN BOOLEAN Absolute + ) + +/*++ + +Routine Description: + + Append the supplied name to the end of this PATH. + +Arguments: + + Base - Supplies the string to be appended. + Absolute - Supplies a flag which if TRUE means that the path must + be absolute. + +Return Value: + + BOOLEAN - Returns TRUE if the '\' and the supplied string was succesfully + appended. + +--*/ + +{ + BOOLEAN AppendedSlash = FALSE; + + DebugPtrAssert( Base ); + DebugAssert( _Initialized ); + + // + // If the path does not consist of only a drive letter followed by a + // colon, we might need to add a '\' + // + if ( _PathString.QueryChCount() > 0 ) { + if ( !(( _PathState.DeviceLen == _PathString.QueryChCount()) && + ( _PathString.QueryChAt( _PathState.DeviceLen - 1) == (WCHAR)':')) || + Absolute ) { + + + if ( _PathString.QueryChAt( _PathString.QueryChCount() - 1 ) != (WCHAR)'\\' ) { + + if ( !_PathString.Strcat( _SlashString )) { + return FALSE; + } + + AppendedSlash = TRUE; + } + } + } + + // + // Append the base + // + if ( _PathString.Strcat( Base )) { + SetPathState(); + return TRUE; + } + + // + // Could not append base, remove the slash if we appended it + // + if ( AppendedSlash ) { + TruncateBase(); + } + + return FALSE; +} + +ULIB_EXPORT +BOOLEAN +PATH::HasWildCard ( + ) CONST + +/*++ + +Routine Description: + + Determines if the name portion of the path contains wild cards + +Arguments: + + None. + +Return Value: + + TRUE if the name portion of the path has wild cards + FALSE otherwise + +--*/ + +{ + + FSTRING WildCards; + + DebugAssert( _Initialized ); + + if ( _PathString.QueryChCount() > 0 ) { + + WildCards.Initialize( (PWSTR) L"*?" ); + + if (_PathString.Strcspn( &WildCards, _PathState.PrefixLen ) != INVALID_CHNUM ) { + return TRUE; + } + } + + return FALSE; + +} + +ULIB_EXPORT +BOOLEAN +PATH::IsDrive( + ) CONST + +/*++ + +Routine Description: + + Returns TRUE if the path refers to a device name + +Arguments: + + None. + +Return Value: + + BOOLEAN - TRUE if the path is a device name. + FALSE otherwise. + +--*/ + +{ + DebugAssert( _Initialized ); + + return ( _PathState.DeviceLen > 0 ) && + ( (_PathString.QueryChCount() == _PathState.DeviceLen) ); + +} + +BOOLEAN +PATH::IsRoot( + ) CONST + +/*++ + +Routine Description: + + Returns TRUE if the path refers to a root directory + +Arguments: + + None. + +Return Value: + + BOOLEAN - TRUE if the path is a root directory. + FALSE otherwise. + +--*/ + +{ + DebugAssert( _Initialized ); + + return( ( (_PathString.QueryChCount() == 1 ) && + (_PathString.QueryChAt( 0 ) == DELIMITER_CHAR ) ) || + ( ( _PathState.DeviceLen > 0 ) && + ( _PathString.QueryChCount() == _PathState.DeviceLen + 1 ) && + ( _PathString.QueryChAt( _PathState.DeviceLen ) == DELIMITER_CHAR ) ) + ); +} + +ULIB_EXPORT +PPATH +PATH::QueryFullPath( + ) CONST + +/*++ + +Routine Description: + +Arguments: + + None. + +Return Value: + + PPATH + +--*/ + +{ + + + REGISTER PPATH pFullPath; + REGISTER PWSTRING pFullPathString; + + DebugAssert( _Initialized ); + + // + // If the full path name string for this PATH can not be queried + // or a new PATH, representing the full path, can not be constructed + // return NULL. + // + + if ((( pFullPathString = QueryFullPathString( )) == NULL ) || + (( pFullPath = NEW PATH ) == NULL )) { + + return NULL; + } + + // + // If the new, full path, can not be initialized, delete it. + // + + if( ! ( pFullPath->Initialize( pFullPathString ))) { + + DELETE( pFullPath ); + } + + // + // Delete the full path string and return a pointer to the new, full path + // (note that the pointer may be NULL). + // + + DELETE( pFullPathString ); + + return pFullPath ; +} + +ULIB_EXPORT +PWSTRING +PATH::QueryFullPathString ( + ) CONST +{ + + LPWSTR pszName; + + PWSTRING pwcFullPathString; + WSTR szBufferSrc[ MAX_PATH ]; + WSTR szBufferTrg[ MAX_PATH ]; + + DebugAssert( _Initialized ); + + if( (pwcFullPathString = NEW DSTRING ()) != NULL ) { + + if ( _PathString.QueryWSTR( 0, TO_END, szBufferSrc, MAX_PATH ) ) { + + if (GetFullPathName( szBufferSrc,MAX_PATH,szBufferTrg,&pszName)) { + + if (pwcFullPathString->Initialize(szBufferTrg)) { + + return pwcFullPathString; + + } + } + } + } + + DELETE( pwcFullPathString ); + + return NULL; + +} + +ULIB_EXPORT +BOOLEAN +PATH::SetDevice ( + IN PCWSTRING NewDevice + ) +{ + DebugAssert( _Initialized ); + DebugPtrAssert( NewDevice ); + + if (_PathState.DeviceLen) { + if (!_PathString.Replace(QueryDeviceStart(), _PathState.DeviceLen, + NewDevice)) { + + return FALSE; + } + } else { + if (!_PathString.Strcat(NewDevice)) { + return FALSE; + } + } + + SetPathState(); + + return TRUE; +} + +BOOLEAN +PATH::SetPrefix ( + IN PCWSTRING NewPrefix + ) +{ + DebugAssert( _Initialized ); + DebugPtrAssert( NewPrefix ); + + if (_PathState.PrefixLen) { + + if (!_PathString.Replace(QueryPrefixStart(), _PathState.PrefixLen, + NewPrefix)) { + + return FALSE; + } + + } else { + + if (!_PathString.Strcat(NewPrefix)) { + return FALSE; + } + } + + SetPathState(); + + return TRUE; +} + +ULIB_EXPORT +BOOLEAN +PATH::SetName ( + IN PCWSTRING NewName + ) +{ + DebugAssert( _Initialized ); + DebugPtrAssert( NewName ); + + if (_PathState.NameLen) { + + if (!_PathString.Replace(QueryNameStart(), _PathState.NameLen, + NewName)) { + + return FALSE; + } + + } else { + + if (!_PathString.Strcat(NewName)) { + return FALSE; + } + } + + SetPathState(); + + return TRUE; +} + +BOOLEAN +PATH::SetBase ( + IN PCWSTRING NewBase + ) +{ + DebugAssert( _Initialized ); + DebugPtrAssert( NewBase ); + + if (_PathState.BaseLen) { + + if (!_PathString.Replace(QueryBaseStart(), _PathState.BaseLen, + NewBase)) { + + return FALSE; + } + + } else { + + if (!_PathString.Strcat(NewBase)) { + return FALSE; + } + } + + SetPathState(); + + return TRUE; +} + +BOOLEAN +PATH::SetExt ( + IN PCWSTRING NewExt + ) +{ + DebugAssert( _Initialized ); + DebugPtrAssert( NewExt ); + + if (_PathState.ExtLen) { + + if (!_PathString.Replace(QueryExtStart(), _PathState.ExtLen, + NewExt)) { + + return FALSE; + } + + } else { + + if (!_PathString.Strcat(NewExt)) { + return FALSE; + } + } + + SetPathState(); + + return TRUE; +} + +ULIB_EXPORT +BOOLEAN +PATH::TruncateBase ( + ) + +/*++ + +Routine Description: + + This routine truncates the path after the prefix portion. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Returns TRUE if the base existed and was succesfully removed. + +--*/ + +{ + DebugAssert( _Initialized ); + + // If this is the root then the prefix len will include the \. + // If not, then it won't. Either way. Truncate this string to + // the prefix length. + + _PathString.Truncate( _PathState.PrefixLen ); + + SetPathState(); + + return TRUE; +} + + + +ULIB_EXPORT +PPATH +PATH::QueryPath( + ) CONST + +/*++ + +Routine Description: + +Arguments: + + None. + +Return Value: + + PPATH + +--*/ + +{ + + + REGISTER PPATH pPath; + + DebugAssert( _Initialized ); + + if (( pPath = NEW PATH ) == NULL ) { + return NULL; + } + + // + // If the new path can not be initialized, delete it. + // + if( ! ( pPath->Initialize( GetPathString()->GetWSTR(), FALSE ))) { + + DELETE( pPath ); + } + + return pPath ; +} + +ULIB_EXPORT +PPATH +PATH::QueryWCExpansion( + IN PPATH BasePath + ) +/*++ + +Routine Description: + + Expands any wildcards in path to match the equivalent characters in + the base path. + +Arguments: + + PCPATH BasePath - The base path from which the equivalent characters are + retrieved. + +Return Value: + + Pointer to the generated path. + + +--*/ +{ + PPATH pGeneratedPath; + PWSTRING pBasePathStr; + PWSTRING pGeneratedPathStr; + PWSTRING pTmp; + FSTRING fstring; + DSTRING new_string; + + // + // Initialize the path to be generated with the current path (this) + // + pGeneratedPath = NEW PATH; + if( pGeneratedPath == NULL ) { + DebugAbort( "Failed to create a new path.\n" ); + return( NULL ); + } + + // Does the Base have '*' while the ext is not there? If so then + // make the extension '*'. + + if (_PathState.ExtLen == 0 && + _PathString.Strchr('*', _PathState.PrefixLen) != INVALID_CHNUM && + _PathString.QueryChAt(_PathString.QueryChCount() - 1) != '.') { + + if (!new_string.Initialize(GetPathString()) || + !new_string.Strcat(fstring.Initialize((PWSTR) L".*")) || + !pGeneratedPath->Initialize(&new_string)) { + + return NULL; + } + } else { + if (!pGeneratedPath->Initialize(GetPathString())) { + return NULL; + } + } + + if( ( pTmp = pGeneratedPath->QueryBase() ) != NULL ) { + pGeneratedPathStr = pTmp->QueryString(); + DebugPtrAssert( pGeneratedPathStr ); + DELETE( pTmp ); + + // + // If the base path doesn't have a findable base, return an error... + // (filenames must have a base - in Dos anyways...) + // + if( ( pTmp = BasePath->QueryBase() ) == NULL ) { + DELETE( pGeneratedPathStr ); + DELETE( pGeneratedPath ); + return( NULL ); + } + pBasePathStr = pTmp->QueryString(); + DebugPtrAssert( pBasePathStr ); + DELETE( pTmp ); + + if( !ExpandWildCards( pBasePathStr, pGeneratedPathStr ) ) { + DELETE( pBasePathStr ); + DELETE( pGeneratedPathStr ); + DELETE( pGeneratedPath ); + return( NULL ); + } + pGeneratedPath->SetBase( pGeneratedPathStr ); + DELETE( pBasePathStr ); + DELETE( pGeneratedPathStr ); + } + + if( ( pTmp = pGeneratedPath->QueryExt() ) != NULL ) { + pGeneratedPathStr = pTmp->QueryString(); + DebugPtrAssert( pGeneratedPathStr ); + + DELETE( pTmp ); + + // + // If no extension is found, create an empty string to pass to + // the wildcard expansion routine - this is to allow 'tmp.*' to + // match 'tmp.'... + // + if( ( pTmp = BasePath->QueryExt() ) == NULL ) { + pBasePathStr = NEW DSTRING; + pBasePathStr->Initialize(); + } else { + pBasePathStr = pTmp->QueryString(); + DebugPtrAssert( pBasePathStr ); + DELETE( pTmp ); + } + + if( !ExpandWildCards( pBasePathStr, pGeneratedPathStr ) ) { + DELETE( pBasePathStr ); + DELETE( pGeneratedPathStr ); + DELETE( pGeneratedPath ); + return( NULL ); + } + pGeneratedPath->SetExt( pGeneratedPathStr ); + DELETE( pBasePathStr ); + DELETE( pGeneratedPathStr ); + } + return( pGeneratedPath ); +} + +BOOLEAN +PATH::ExpandWildCards( + IN OUT PWSTRING pStr1, + IN OUT PWSTRING pStr2 + ) +/*++ + +Routine Description: + + Expands any wildcards in string 2 to match the equivalent characters in + string 1. Used by QueryWildCardExpansion(). + +Arguments: + + Str1 - A pointer to the 'base' string + Str2 - A pointer to the string to be expanded + +Return Value: + + TRUE if expansion was successful. + +--*/ +{ + CHNUM idx; + + + UNREFERENCED_PARAMETER( (void)this); + + // Deal with the * wild card first... + // + // Note: This method will ignore, even remove, any characters after the + // '*' in string 2. This is to comform with the behavior of Dos... + // + if( ( idx = pStr2->Strchr( '*' ) ) != INVALID_CHNUM ) { + if( idx > pStr1->QueryChCount() ) { + return( FALSE ); + } + if( idx == pStr1->QueryChCount() ) { + pStr2->Truncate( idx ); + } else { + pStr2->Replace( idx, TO_END, pStr1, idx, TO_END ); + } + } + + // Now convert any '?' in the base + while( ( idx = pStr2->Strchr( '?' ) ) != INVALID_CHNUM ) { + // Make sure that the wild card is within the limits of the + // base string... + if( idx >= pStr1->QueryChCount() ) { + return( FALSE ); + } + pStr2->SetChAt( pStr1->QueryChAt( idx ), idx ); + } + return( TRUE ); +} + +ULIB_EXPORT +BOOLEAN +PATH::ModifyName ( + IN PCWSTRING Pattern + ) + +/*++ + +Routine Description: + + Modifies the file name of the path according to a pattern. The pattern + may contain wildcards. + +Arguments: + + Pattern - Supplies pointer to string with the pattern + +Return Value: + + none + +--*/ + +{ + PATH PatternPath; + PPATH TargetPath; + PWSTRING NewName; + + + // If the pattern is trivial then just bail out since there's + // nothing to change. + + if (Pattern->QueryChCount() == 1 && + Pattern->QueryChAt(0) == '*') { + + return TRUE; + } + + if (Pattern->QueryChCount() == 3 && + Pattern->QueryChAt(0) == '*' && + Pattern->QueryChAt(1) == '.' && + Pattern->QueryChAt(2) == '*') { + + return TRUE; + } + + if (!PatternPath.Initialize(Pattern)) { + return FALSE; + } + + TargetPath = PatternPath.QueryWCExpansion(this); + if (!TargetPath) { + return FALSE; + } + + NewName = TargetPath->QueryName(); + + DELETE(TargetPath); + + if (!NewName) { + return FALSE; + } + + TruncateBase(); + AppendBase( NewName ); + + DELETE( NewName ); + + return TRUE; +} + +ULIB_EXPORT +VOID +PATH::TruncateNameAtColon ( + ) + +/*++ + +Routine Description: + + This is an awful hack to keep XCopy compatibility. + + If the last segment of the path contains a colon, we truncate the + path at that point. + +Arguments: + + none + +Return Value: + + none + +--*/ + +{ + + CHNUM IndexColon; + CHNUM IndexDelimiter; + + + IndexColon = _PathString.Strrchr( (WCHAR)':', 0 ); + + if ( IndexColon != INVALID_CHNUM ) { + + IndexDelimiter = _PathString.Strrchr( DELIMITER_CHAR, 0 ); + + if ( ( IndexDelimiter == INVALID_CHNUM ) || + ( IndexColon > IndexDelimiter ) ) { + + if (IndexColon > 1) { + + // + // Truncate the path + // + _PathString.Truncate( IndexColon ); + SetPathState(); + } + } + } +} + + + + +ULIB_EXPORT +PWSTRING +PATH::QueryRoot ( + ) + +/*++ + +Routine Description: + + Returns a string that contains the canonicalized name of the root + directory (device name followed by "\"). + + QueryRoot returns NULL if there is no device component part of + this path. In other words it may be necessary to canonicalize + the path before having access to the Root. + +Arguments: + + none + +Return Value: + + Pointer to a WSTRING that contains the root directory in its + canonicalized form. + +--*/ + +{ + PWSTRING Root; + + if( _PathState.DeviceLen == 0 ) { + return( NULL ); + } + Root = NEW( DSTRING ); + DebugPtrAssert( Root ); + + if( !Root->Initialize( &_PathString, 0, _PathState.DeviceLen ) ) { + DELETE( Root ); + return( NULL ); + } + + Root->Strcat( _SlashString ); + return( Root ); +} diff --git a/private/utils/ulib/src/pch.cxx b/private/utils/ulib/src/pch.cxx new file mode 100644 index 000000000..056a4201d --- /dev/null +++ b/private/utils/ulib/src/pch.cxx @@ -0,0 +1,75 @@ +/*++ + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + pch.cxx + +Abstract: + + This module implements pre-compiled headers for ulib. + +Author: + + Matthew Bradburn (mattbr) 26-Apr-1994 + +--*/ + +#define _ULIB_MEMBER_ + +// +// Include all ulib headers, except a couple of troublemakers. +// + +#include "ulib.hxx" +#include "smsg.hxx" +#include "array.hxx" +#include "basesys.hxx" +#include "bitvect.hxx" +#include "buffer.hxx" +#include "bufstrm.hxx" +#include "bytestrm.hxx" +#include "contain.hxx" +#include "wstring.hxx" +#include "system.hxx" +#include "achkmsg.hxx" +#include "arg.hxx" +#include "arrayit.hxx" +#include "comm.hxx" +#include "dir.hxx" +#include "error.hxx" +#include "file.hxx" +#include "filestrm.hxx" +#include "filter.hxx" +#include "fsnode.hxx" +#include "ifsentry.hxx" +#include "ifsserv.hxx" +#include "iterator.hxx" +#include "keyboard.hxx" +#include "list.hxx" +#include "listit.hxx" +#include "mbstr.hxx" +#include "membmgr.hxx" +#include "message.hxx" +#include "newdelp.hxx" +#include "path.hxx" +#include "pipe.hxx" +#include "pipestrm.hxx" +#include "program.hxx" +#include "prtstrm.hxx" +#include "rtmsg.h" +#include "screen.hxx" +#include "seqcnt.hxx" +#include "sortcnt.hxx" +#include "sortlist.hxx" +#include "sortlit.hxx" +#include "stream.hxx" +#include "string.hxx" +#include "stringar.hxx" +#include "substrng.hxx" +#include "ulibcl.hxx" +#include "timeinfo.hxx" +#include "object.hxx" +#include "clasdesc.hxx" + diff --git a/private/utils/ulib/src/pipe.cxx b/private/utils/ulib/src/pipe.cxx new file mode 100644 index 000000000..b5e06ca3c --- /dev/null +++ b/private/utils/ulib/src/pipe.cxx @@ -0,0 +1,165 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + pipe.cxx + +Abstract: + + This module contains the implementation of the PIPE class. + +Author: + + Barry J. Gilhuly (W-Barry) June 27, 1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "pipestrm.hxx" +#include "pipe.hxx" +#include "wstring.hxx" + + +DEFINE_CONSTRUCTOR( PIPE, OBJECT ); + +DEFINE_CAST_MEMBER_FUNCTION( PIPE ); + + +VOID +PIPE::Destroy( + ) +/*++ + +Routine Description: + + Close the handles which were opened by the initialize method. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + if( !_fInitialized ) { + return; + } + + // + // Close the pipe... + // + CloseHandle( _hReadPipe ); + CloseHandle( _hWritePipe ); + _fInitialized = FALSE; + + return; +} + +BOOLEAN +PIPE::Initialize( + IN LPSECURITY_ATTRIBUTES PipeAttributes, + IN ULONG PipeSize, + IN PWSTRING PipeName + ) +/*++ + +Routine Description: + + Create a PIPE by making a call to the system API. If the PIPE object + has been previously initialized, destroy it first. + +Arguments: + + PipeAttributes - A pointer to a structure which defines the attributes + of the pipe to be created. + + PipeSize - A suggested buffer size for the pipe. + + PipeName - The name of the pipe. Currently, this option is + unimplemented, it should ALWAYS be NULL. + +Return Value: + + TRUE if the PIPE was created successfully. + +--*/ +{ + BOOLEAN PipeStatus = FALSE; + + Destroy(); + + if( PipeName == NULL ) { + // + // Create an anonomous pipe... + // + if( !( PipeStatus = CreatePipe( &_hReadPipe, + &_hWritePipe, + PipeAttributes, + PipeSize ) ) ) { + DebugPrint( "Unable to create the pipe - returning failure!\n" ); + _fInitialized = FALSE; + } else { + _fInitialized = TRUE; + } + } else { + DebugPrint( "Named Pipes are not currently implemented!\n" ); + } + return( PipeStatus ); +} + +PPIPE_STREAM +PIPE::QueryPipeStream( + IN HANDLE hPipe, + IN STREAMACCESS Access + ) +/*++ + +Routine Description: + + Create and initialize a stream to the PIPE object. + +Arguments: + + hPipe - A handle to use in the initialization of the stream. + + Access - The desired access on this stream. + +Return Value: + + Returns a pointer to the created PIPE STREAM if successful. Otherwise, + it returns NULL. + +--*/ +{ + PPIPE_STREAM NewStream; + + if( !_fInitialized ) { + DebugPrint( "Pipe object is uninitialized!\n" ); + NewStream = NULL; + } else { + if( ( NewStream = NEW PIPE_STREAM ) == NULL ) { + DebugPrint( "Unable to create a new copy of the Read Stream!\n" ); + } else { + if( !NewStream->Initialize( hPipe, Access ) ) { + DebugPrint( "Unable to initialize the new stream!\n" ); + DELETE( NewStream ); + NewStream = NULL; + } + } + } + return( NewStream ); +} diff --git a/private/utils/ulib/src/pipestrm.cxx b/private/utils/ulib/src/pipestrm.cxx new file mode 100644 index 000000000..a989bd926 --- /dev/null +++ b/private/utils/ulib/src/pipestrm.cxx @@ -0,0 +1,356 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + pipestrm.cxx + +Abstract: + + This module contains the definitions of the member functions + of PIPE_STREAM class. + +Author: + + Jaime Sasson (jaimes) 24-Mar-1991 + +Environment: + + ULIB, User Mode + + +--*/ +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "stream.hxx" +#include "bufstrm.hxx" +#include "pipestrm.hxx" + +#define BUFFER_SIZE 4*1024 + + +DEFINE_CONSTRUCTOR ( PIPE_STREAM, BUFFER_STREAM ); + + +DEFINE_CAST_MEMBER_FUNCTION( PIPE_STREAM ); + + +PIPE_STREAM::~PIPE_STREAM ( + ) + +/*++ + +Routine Description: + + Destroy a PIPE_STREAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ +} + + +BOOLEAN +PIPE_STREAM::Initialize( + IN HANDLE Handle, + IN STREAMACCESS Access + ) + +/*++ + +Routine Description: + + Initializes a PIPE_STREAM object. + +Arguments: + + Handle - Handle to the anonymous pipe. + + Access - Access allowed to the stream. + + +Return Value: + + BOOLEAN - Indicates if the initialization succeeded. + + +--*/ + + +{ + if( ( Access == READ_ACCESS ) || ( Access == WRITE_ACCESS ) ) { + _PipeHandle = Handle; + _Access = Access; + _EndOfFile = FALSE; + return( BUFFER_STREAM::Initialize( BUFFER_SIZE ) ); + } else { + return( FALSE ); + } +} + + +BOOLEAN +PIPE_STREAM::EndOfFile( + ) CONST + +/*++ + +Routine Description: + + Informs the caller if end of file has occurred. End of file happens + when all bytes were read from the pipe (in the case of anonymous + pipe, "end of file" happens when ReadFile returns STATUS_END_OF_FILE). + +Arguments: + + None. + +Return Value: + + A boolean value that indicates if end of file was detected. + + +--*/ + + +{ + return( _EndOfFile ); +} + +#ifdef DBCS // v-junm - 10/15/93 + +BOOLEAN +PIPE_STREAM::CheckIfLeadByte( + IN PUCHAR text, + IN ULONG offset + ) + +/*++ + +Routine Description: + + Checks to see if the character at an given offset in a MBCS string is a + leadbyte of a DBCS character. + +Arguments: + + text - MBCS string. + +Return Value: + + TRUE - if char is leadbyte. + FALSE - otherwise. + +--*/ + +{ + ULONG i = offset; + + for ( ; i; i-- ) + if ( !IsDBCSLeadByte ( text[i] ) ) + break; + + return( ( offset - i ) % 2 ); +} + +#endif + + + +BOOLEAN +PIPE_STREAM::FillBuffer( + IN PBYTE Buffer, + IN ULONG BufferSize, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Fills a buffer with bytes read from the pipe, if the pipe has + READ_ACCESS. + Returns FALSE if the pipe has WRITE_ACCESS. + +Arguments: + + Buffer - Buffer where the bytes are to be stored. + + BufferSize - Size of the buffer. + + BytesRead - Pointer to the variable that will contain the number of bytes + put in the buffer. + + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + +{ + BOOLEAN Result; + PBYTE p; + +#ifdef DBCS // v-junm - 10/15/93 + + // + // This define keeps the remaining leadbyte that was read from the + // pipe stream and concatanates it to the next set of strings read. + // The remaining byte means that if there is a leadbyte at the end + // of a string without a cooresponding tail byte. + // + // NOTE: The following code assumes that the pipe stream is always + // constant and is continuously reading from the same pipe for the + // same caller. + // + + static BYTE LeadByte = 0; + + + // + // If there was a leadbyte, put it in buffer and decrement buffer size. + // + + if ( LeadByte != 0 ) { + *Buffer++ = LeadByte; + BufferSize--; + } + +#endif + + Result = FALSE; + if( _Access == READ_ACCESS ) { + Result = ReadFile( _PipeHandle, + Buffer, + BufferSize, + BytesRead, + NULL ); + +#ifdef DBCS // v-junm - 10/15/93 + + // + // If there was a leadbyte placed earlier, + // re-adjust buffer and buffercount. + // + + if ( LeadByte != 0 ) { + *BytesRead = *BytesRead + 1; + Buffer--; + } + + // + // If bytes were read, check if string ends with a leadbyte. + // If so, save it for next time. + // + + if ( (*BytesRead != 0) && CheckIfLeadByte( Buffer, *BytesRead-1 ) ) { + + // + // Check if buffer contains only the leadbyte that was placed + // from the previous call to this function. + // + + if ( (LeadByte != 0) && (*BytesRead == 1) ) + LeadByte = 0; + else { + + // + // Leadbyte is at end of string. save it for next time + // and adjust buffer size so a null will be replaced + // for the leadbyte. + // + + LeadByte = *(Buffer + *BytesRead - 1); + *BytesRead = *BytesRead - 1; + } + + } + else + LeadByte = 0; + +#endif + + // + // no bytes read means end of file (according to markl) + // + if( *BytesRead == 0 ) { + _EndOfFile = TRUE; + } else { + p = (PBYTE)Buffer + *BytesRead; + *p++ = '\0'; + *p = '\0'; + } + } + return( Result ); +} + + + +STREAMACCESS +PIPE_STREAM::QueryAccess( + ) CONST + +/*++ + +Routine Description: + + Returns the type of access of the pipe stream + +Arguments: + + None. + +Return Value: + + The stream access. + + +--*/ + + +{ + return( _Access ); +} + + + +HANDLE +PIPE_STREAM::QueryHandle( + ) CONST + +/*++ + +Routine Description: + + Returns the file handle + +Arguments: + + None. + +Return Value: + + The file handle. + + +--*/ + + +{ + return( _PipeHandle ); +} + diff --git a/private/utils/ulib/src/prnthack.cxx b/private/utils/ulib/src/prnthack.cxx new file mode 100644 index 000000000..d7fdb5dab --- /dev/null +++ b/private/utils/ulib/src/prnthack.cxx @@ -0,0 +1,16 @@ +// Because the name of the function to be used is +// DbgPrint, we can't include "ulib.hxx" + +void +DbgPrint ( + char* String + ); + + +void +AutoCheckDisplayString ( + char* String + ) +{ + DbgPrint(String); +} diff --git a/private/utils/ulib/src/program.cxx b/private/utils/ulib/src/program.cxx new file mode 100644 index 000000000..7d00baef3 --- /dev/null +++ b/private/utils/ulib/src/program.cxx @@ -0,0 +1,453 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + program.cxx + +Abstract: + +Author: + + David J. Gilman (davegi) 02-Mar-1991 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "path.hxx" +#include "program.hxx" +#include "system.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR( PROGRAM, OBJECT, ULIB_EXPORT ); + +ULIB_EXPORT +PROGRAM::~PROGRAM ( + ) +{ + +} + +ULIB_EXPORT +BOOLEAN +PROGRAM::Initialize ( + IN MSGID UsageMsg, + IN MSGID FatalMsg, + IN ULONG FatalLevel + ) + +/*++ + +Routine Description: + + Initializes a PROGRAM object. + +Arguments: + + UsageMsg - Supplies usage (help) message id. + FatalMsg - Supplies default fatal message id. + FatalLevel - Supplies default fatal exit level. + +Return Value: + + BOOLEAN - Returns TRUE if object initialized, + FALSE otherwise. + + +--*/ + +{ + + // + // Get standard streams. + // + _Standard_Input = Standard_Input_Stream; + _Standard_Output = Standard_Output_Stream; + _Standard_Error = Standard_Error_Stream; + + // + // Initialize the message object + // + if ( _Standard_Output && + _Standard_Input && + _Message.Initialize( _Standard_Output, _Standard_Input, _Standard_Error ) ) { + + // + // Initialize message ids and error levels + + _UsageMsg = UsageMsg; + _FatalMsg = FatalMsg; + _FatalLevel = FatalLevel; + + return TRUE; + + } + + _Standard_Input = NULL; + _Standard_Output = NULL; + _Standard_Error = NULL; + return FALSE; +} + +ULIB_EXPORT +BOOLEAN +PROGRAM::DisplayMessage ( + IN MSGID Message, + IN MESSAGE_TYPE Type + ) CONST + +/*++ + +Routine Description: + + Displays a message + +Arguments: + + Message - Supplies the message id of the message to display + Type - Supplies the type of message + +Return Value: + + BOOLEAN - Returns TRUE if message displayed, + FALSE otherwise. + + +--*/ + +{ + return DisplayMessage( Message, Type, NULL ); +} + +ULIB_EXPORT +BOOLEAN +PROGRAM::DisplayMessage ( + IN MSGID Message, + IN MESSAGE_TYPE Type, + IN PSTR Format, + IN ... + ) CONST + +/*++ + +Routine Description: + + Displays a message with arguments + + +Arguments: + + Message - Supplies the message id of the message to display + Type - Supplies the message type + Format - Supplies a format string + ... - Supplies list of arguments + +Return Value: + + BOOLEAN - Returns TRUE if message displayed, + FALSE otherwise. + +--*/ + +{ + + va_list Arguments; + BOOLEAN Status; + + if ( ((PPROGRAM) this)->_Message.Set( Message, Type ) ) { + + if ( !Format ) { + + return ((PPROGRAM) this)->_Message.Display( "" ); + + } else { + + va_start( Arguments, Format ); + Status = ((PPROGRAM) this)->_Message.DisplayV( Format, Arguments ); + va_end( Arguments ); + return Status; + } + } + + return FALSE; + +} + +ULIB_EXPORT +VOID +PROGRAM::ExitProgram ( + ULONG Level + ) +{ + ExitProcess( Level ); +} + +ULIB_EXPORT +PSTREAM +PROGRAM::GetStandardInput ( + ) + +/*++ + +Routine Description + + Obtains the standard input stream + +Arguments: + + None + +Return Value: + + PSTREAM - Returns the standard input stream + +--*/ + +{ + + return _Standard_Input; + +} + +ULIB_EXPORT +PSTREAM +PROGRAM::GetStandardOutput ( + ) + +/*++ + +Routine Description + + Obtains the standard output stream + +Arguments: + + None + +Return Value: + + PSTREAM - Returns the standard output stream + +--*/ + +{ + + return _Standard_Output; + +} + + +ULIB_EXPORT +PSTREAM +PROGRAM::GetStandardError ( + ) + +/*++ + +Routine Description + + Obtains the standard error stream + +Arguments: + + None + +Return Value: + + PSTREAM - Returns the standard error stream + +--*/ + +{ + + return _Standard_Error; + +} + + +ULIB_EXPORT +VOID +PROGRAM::Fatal ( + ) CONST + +/*++ + +Routine Description + + Displays the default fatal message and exits with the default + fatal error level. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + + Fatal( _FatalLevel, _FatalMsg, NULL ); + +} + +ULIB_EXPORT +VOID +PROGRAM::Fatal ( + IN ULONG ErrorLevel, + IN MSGID Message, + IN PSTR Format, + IN ... + ) CONST + +/*++ + +Routine Description: + + Displays a message (with arguments) and exits with the specified + error level. + +Arguments: + + ErrorLevel - Supplies the error level to exit with. + Message - Supplies the id of the message to display + Format - Supplies the format string + ... - Supply pointers to the arguments + +Return Value: + + None + +--*/ + +{ + va_list Arguments; + + if ( ((PPROGRAM) this)->_Message.Set( Message, ERROR_MESSAGE ) ) { + + if ( !Format ) { + + ((PPROGRAM) this)->_Message.Display( "" ); + + } else { + + va_start( Arguments, Format ); + ((PPROGRAM) this)->_Message.DisplayV( Format, Arguments ); + + } + } + + ExitProcess( ErrorLevel ); +} + +ULIB_EXPORT +VOID +PROGRAM::Usage ( + ) CONST + +/*++ + +Routine Description: + + Displays the usage (help) message and exits with an error level of + zero. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + ((PPROGRAM) this)->_Message.Set( _UsageMsg, NORMAL_MESSAGE ); + ((PPROGRAM) this)->_Message.Display(); + + ExitProcess( 0 ); +} + +PPATH +PROGRAM::QueryImagePath ( + ) + +/*++ + +Routine Description: + + Queries the path to the program image (executable file) + +Arguments: + + None + +Return Value: + + PPATH - Returns a canonicalized path to the program image. + +--*/ + +{ + WSTR PathName[ MAX_PATH ]; + PPATH Path; + + if (( GetModuleFileName( NULL, PathName, MAX_PATH ) != 0 ) && + (( Path = NEW PATH ) != NULL ) && + Path->Initialize( PathName, TRUE )) { + + return Path; + + } + + return NULL; +} + + +ULIB_EXPORT +VOID +PROGRAM::ValidateVersion ( + IN MSGID InvalidVersionMsg, + IN ULONG ErrorLevel + ) CONST + +/*++ + +Routine Description: + + Validates the version, and if the version is invalid, exits the + program. + +Arguments: + + InvalidVersionMsg - Supplies id of message to display if the + version number is incorrect. + + ErrorLevel - Supplies the error level with which to exit + if the version number is incorrect. + +Return Value: + + None (Only returns if is correct version). + + +--*/ + +{ + if ( !SYSTEM::IsCorrectVersion() ) { + + Fatal( ErrorLevel, InvalidVersionMsg, "" ); + } +} diff --git a/private/utils/ulib/src/prtstrm.cxx b/private/utils/ulib/src/prtstrm.cxx new file mode 100644 index 000000000..fa53906da --- /dev/null +++ b/private/utils/ulib/src/prtstrm.cxx @@ -0,0 +1,392 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + prtstrm.cxx + +Abstract: + + This module contains the definitions of the member functions + of PRINT_STREAM class. + +Author: + + Jaime Sasson (jaimes) 12-Jun-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "wstring.hxx" +#include "path.hxx" +#include "stream.hxx" +#include "prtstrm.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR ( PRINT_STREAM, STREAM, ULIB_EXPORT ); + +DEFINE_CAST_MEMBER_FUNCTION( PRINT_STREAM ); + + +VOID +PRINT_STREAM::Construct( + ) +{ + _Handle = INVALID_HANDLE_VALUE; +} + + +ULIB_EXPORT +PRINT_STREAM::~PRINT_STREAM ( + ) + +/*++ + +Routine Description: + + Destroy a PRINT_STREAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + if (INVALID_HANDLE_VALUE != _Handle) { + + CloseHandle( _Handle ); + } +} + + + +ULIB_EXPORT +BOOLEAN +PRINT_STREAM::Initialize( + IN PCPATH DeviceName + ) + +/*++ + +Routine Description: + + Initializes an object of type PRINT_STREAM. + +Arguments: + + DevicName - A path to the device associated with the printer. + + +Return Value: + + BOOLEAN - TRUE if the initialization succeeded. FALSE otherwise. + + +--*/ + + +{ + ULONG FileType; + PCWSTRING String; + + String = DeviceName->GetPathString(); + + + _Handle = CreateFile( String->GetWSTR(), + GENERIC_WRITE, + FILE_SHARE_READ, + NULL, // Security attributes + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL ); + if( _Handle == INVALID_HANDLE_VALUE ) { + return( FALSE ); + } + return( STREAM::Initialize() ); +} + + +BOOLEAN +PRINT_STREAM::IsAtEnd( + ) CONST + +/*++ + +Routine Description: + + Informs the caller if end of file has occurred. The concept of + end of file for a PRINT_STREAM does not have any meaning, so this + method will always return FALSE. + +Arguments: + + None. + +Return Value: + + Returns FALSE. + + +--*/ + + +{ + (void)(this); + return( FALSE ); +} + + +STREAMACCESS +PRINT_STREAM::QueryAccess( + ) CONST + +/*++ + +Routine Description: + + Returns the type of access of the print stream + +Arguments: + + None. + +Return Value: + + Returns always WRITE_ACCESS. + + +--*/ + + +{ + (void)(this); + return( WRITE_ACCESS ); +} + + + +HANDLE +PRINT_STREAM::QueryHandle( + ) CONST + +/*++ + +Routine Description: + + Returns the handle to the stream. + +Arguments: + + None. + +Return Value: + + Returns a handle. + + +--*/ + + +{ + return( _Handle ); +} + + +BOOLEAN +PRINT_STREAM::Read( + OUT PBYTE Buffer, + IN ULONG BytesToRead, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Reads bytes from the print stream. + +Arguments: + + PBYTE - Points that will receive the bytes read. + + ULONG - Number of bytes to read (buffer size) + + PULONG - Points to the variable that will contain the total + number of bytes read. + +Return Value: + + Returns always FALSE since no data can be read from a print stream. + + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(Buffer); + (void)(BytesToRead); + (void)(BytesRead); + + return( FALSE ); +} + + + +BOOLEAN +PRINT_STREAM::ReadChar( + OUT PWCHAR Char, + IN BOOLEAN Unicode + ) + +/*++ + +Routine Description: + + Reads a character from the print stream. + +Arguments: + + Char - Supplies poinbter to wide character + +Return Value: + + Returns always FALSE since no data can be read from a print stream. + + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(Char); + (void)(Unicode); + + return( FALSE ); +} + + + +BOOLEAN +PRINT_STREAM::ReadString( + OUT PWSTRING String, + IN PWSTRING Delimiter, + IN BOOLEAN Unicode + ) + +/*++ + +Routine Description: + + Reads a STRING from the print stream. + +Arguments: + + Pointer to the variable that will contain the pointer to the STRING + object. + +Return Value: + + Returns always FALSE since no data can be read from a print stream. + + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(String); + (void)(Delimiter); + (void)(Unicode); + + return( FALSE ); +} + + + +BOOLEAN +PRINT_STREAM::ReadMbString( + IN PSTR String, + IN DWORD BufferSize, + INOUT PDWORD StringSize, + IN PSTR Delimiters, + IN BOOLEAN ExpandTabs, + IN DWORD TabExp + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(String); + (void)(BufferSize); + (void)(StringSize); + (void)(Delimiters); + (void)(ExpandTabs); + (void)(TabExp); + + return( FALSE ); +} + + +BOOLEAN +PRINT_STREAM::ReadWString( + IN PWSTR String, + IN DWORD BufferSize, + INOUT PDWORD StringSize, + IN PWSTR Delimiters, + IN BOOLEAN ExpandTabs, + IN DWORD TabExp + ) + +/*++ + +Routine Description: + +Arguments: + +Return Value: + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(String); + (void)(BufferSize); + (void)(StringSize); + (void)(Delimiters); + (void)(ExpandTabs); + (void)(TabExp); + + return( FALSE ); +} diff --git a/private/utils/ulib/src/rtmsg.dbl b/private/utils/ulib/src/rtmsg.dbl new file mode 100644 index 000000000..3d8cd0be3 --- /dev/null +++ b/private/utils/ulib/src/rtmsg.dbl @@ -0,0 +1,387 @@ +MessageId=30100 SymbolicName=MSG_CONV_USAGE +Language=English +Converts FAT or HPFS volumes to NTFS. + +CONVERT drive: /FS:NTFS [/V] +CONVERT /UNCOMPRESS[:sss] drive: /FS:NTFS [/V] [/C] + + drive Specifies the drive to convert to NTFS. Note that + you cannot convert the current drive. + /FS:NTFS Specifies to convert the volume to NTFS. + /UNCOMPRESS Causes files to be extracted from a DoubleSpace volume. + sss Specifies the sequence number of a compressed volume file. + /C The resulting filesystem is compressed. +. + + +MessageId=30115 SymbolicName=MSG_CONV_SLASH_C_INVALID +Language=English +The /C option is only valid with the /UNCOMPRESS option. +. + +;//---------------------- +;// +;// Dblspace-specific Convert messages (cudbfs) +;// +;//---------------------- + +MessageId=30190 SymbolicName=MSG_DBLCONV_CANT_CREATE +Language=English +Cannot create the file %1 +. + +MessageId=30191 SymbolicName=MSG_DBLCONV_CVF_CORRUPT +Language=English +The Compressed Volume File is corrupt -- run SCANDISK +. + +MessageId=30192 SymbolicName=MSG_DBLCONV_CREATE_FILE +Language=English +Creating %1 +. + +MessageId=30193 SymbolicName=MSG_DBLCONV_FILE_CONFLICT +Language=English +A file in the Compressed Volume File would conflict with %1 +. + +MessageId=30194 SymbolicName=MSG_DBLCONV_NOT_ENOUGH_SPACE +Language=English +Not enough free space on host; need %1 clusters, have %2 +. + +MessageId=30195 SymbolicName=MSG_DBLCONV_AGAIN +Language=English +After the machine is rebooted, run CONVERT /UNCOMPRESS again. +. + +MessageId=30196 SymbolicName=MSG_DBLCONV_SPACE_EXHAUSTED +Language=English +All disk space on the host volume has been exhausted. Please delete +files from the host volume and run CONVERT /UNCOMPRESS again. +. + + +;//----------------------- +;// +;// DOUBLE SPACE messages +;// +;//----------------------- + +MessageId=30600 SymbolicName=MSG_DBLSPACE_USAGE +Language=English +Creates or configures DoubleSpace compressed drives. + +DBLSPACE /AUTOMOUNT=0|1 +DBLSPACE /LIST +DBLSPACE /MOUNT[=sss] [drive:] [/NEWDRIVE=drive2:] +DBLSPACE /UNCOMPRESS[=sss] drive: [/V] +DBLSPACE /UNMOUNT [drive:] + +. + +MessageId=30601 SymbolicName=MSG_DBLSPACE_CREATE_DISK_ERROR +Language=English +A disk error occurred; the Double Space volume cannot +be created. Run CHKDSK /R on the host volume to map out +bad sectors. +. + +MessageId=30602 SymbolicName=MSG_DBLSPACE_NO_CVF_NAME +Language=English +No name is available for the Double Space volume; the +volume could not be created. +. + +MessageId=30603 SymbolicName=MSG_DBLSPACE_CVF_NAME_EXISTS +Language=English +A file already exists with the specified Compressed Volume File +extension; the specified file cannot be created. Use FORMAT to +reformat existing Double Space volumes. +. + +MessageId=30604 SymbolicName=MSG_DBLSPACE_HOST_NOT_FAT +Language=English +The specified host volume is not FAT; Double Space volumes +can only be created on FAT host volumes. +. + +MessageId=30605 SymbolicName=MSG_DBLSPACE_NO_SPACE_ON_HOST +Language=English +There is not enough free space on the host drive. +. + +MessageId=30606 SymbolicName=MSG_DBLSPACE_CVF_CREATE_ERROR +Language=English +The Double Space volume could not be created. +. + +MessageId=30607 SymbolicName=MSG_DBLSPACE_PARSE_NO_DRIVE +Language=English +No drive specified. +. + +MessageId=30608 SymbolicName=MSG_DBLSPACE_INVALID_PARAMETERS +Language=English +Invalid parameters. +. + +MessageId=30609 SymbolicName=MSG_DBLSPACE_INVALID_DRIVE +Language=English +Invalid drive. +. + +MessageId=30610 SymbolicName=MSG_DBLSPACE_UNSUPPORTED_OPERATION +Language=English +This operation is not supported on Windows NT. +. + +MessageId=30611 SymbolicName=MSG_DBLSPACE_VOLUME_CREATED +Language=English +%1\%2 created. +. + +MessageId=30612 SymbolicName=MSG_DBLSPACE_VOLUME_NOT_CREATED +Language=English +The compressed volume was not created. +. + +MessageId=30613 SymbolicName=MSG_DBLSPACE_INVALID_PARAMETER +Language=English +Invalid parameter - %1 +. + +MessageId=30614 SymbolicName=MSG_DBLSPACE_INSUFFICIENT_SPACE_TO_CREATE +Language=English +There is not enough free space on drive %1 to create the +specified Double Space volume. +. + +MessageId=30615 SymbolicName=MSG_CANT_READ_FAT_EXTENS +Language=English +Error reading FAT extensions. +. + +MessageId=30616 SymbolicName=MSG_CANT_WRITE_FAT_EXTENS +Language=English +Error writing FAT extensions. +. + +MessageId=30617 SymbolicName=MSG_DBLSPACE_CANT_MOUNT +Language=English +Can't mount %1 +. + +MessageId=30618 SymbolicName=MSG_DBLSPACE_MOUNTED +Language=English +%1 mounted as drive %2 +. + +MessageId=30619 SymbolicName=MSG_DBLSPACE_DRIVE_LETTER_IN_USE +Language=English +Drive %1 is already in use. +. + +MessageId=30620 SymbolicName=MSG_DBLSPACE_CANT_ASSIGN_DRIVE_LETTER +Language=English +Cannot assign drive letter %1 to volume. +. + +MessageId=30621 SymbolicName=MSG_DBLSPACE_UNMOUNTED +Language=English +Drive %1 unmounted. +. + +MessageId=30622 SymbolicName=MSG_DBLSPACE_NO_DRIVE_LETTER +Language=English +No drive letter is available to mount the volume. +. + +MessageId=30623 SymbolicName=MSG_DBLSPACE_CANT_GET_CVF_NAME +Language=English +Cannot determine the name of the Compressed Volume File. +. + +MessageId=30624 SymbolicName=MSG_DBLSPACE_REQUIRED_PARAMETER +Language=English +Required parameter missing. +. + +MessageId=30625 SymbolicName=MSG_DBLSPACE_NOT_COMPRESSED +Language=English +Drive %1 is not a compressed drive. +. + +MessageId=30626 SymbolicName=MSG_DBLSPACE_NOT_COMPRESSED_NO_NAME +Language=English +The specified drive is not compressed. +. + +MessageId=30627 SymbolicName=MSG_DBLSPACE_FMT_NOT_COMPRESSED +Language=English +Drive %1 is not a compressed drive. To format it, use the FORMAT command. +. + +MessageId=30628 SymbolicName=MSG_DBLSPACE_CHK_NOT_COMPRESSED +Language=English +Drive %1 is not a compressed drive. To check it, use the CHKDSK command. +. + +MessageId=30629 SymbolicName=MSG_DBLSPACE_CONFIRM_DELETE +Language=English. +Deleting drive %1 will permanently erase it and all the files +it contains. Are you sure you want to delete drive %1 (Y/N)? %0 +. + +MessageId=30630 SymbolicName=MSG_DBLSPACE_DELETING +Language=English +DoubleSpace is deleting drive %1. +. + +MessageId=30631 SymbolicName=MSG_DBLSPACE_DELETED +Language=English +DoubleSpace has deleted drive %1. +. + + +MessageId=30632 SymbolicName=MSG_DBLSPACE_DISMOUNTED +Language=English +Drive %1 has been dismounted. +. + +MessageId=30634 SymbolicName=MSG_DBLSPACE_DISMOUNTED_NO_NAME +Language=English +The volume has been dismounted. +. + +MessageId=30635 SymbolicName=MSG_DBLSPACE_CANT_DELETE_CVF +Language=English +Unable to delete Compressed Volume File. +. + +MessageId=30636 SymbolicName=MSG_DBLSPACE_LIST_HEADER +Language=English +Drive Type MB Free MB Size CVF Filename +----- -------------------------- ---------- ---------- --------------- +. + +MessageId=30637 SymbolicName=MSG_DBLSPACE_LIST_REMOVABLE +Language=English + %1 Removable-media drive %0 +. + +MessageId=30638 SymbolicName=MSG_DBLSPACE_LIST_FLOPPY +Language=English + %1 Floppy disk %0 +. + +MessageId=30639 SymbolicName=MSG_DBLSPACE_LIST_FIXED +Language=English + %1 Local hard drive %0 +. + +MessageId=30640 SymbolicName=MSG_DBLSPACE_LIST_COMPRESSED_REMOVABLE +Language=English + %1 Compressed removable disk %0 +. + +MessageId=30641 SymbolicName=MSG_DBLSPACE_LIST_COMPRESSED_FLOPPY +Language=English + %1 Compressed floppy disk %0 +. + +MessageId=30642 SymbolicName=MSG_DBLSPACE_LIST_COMPRESSED_FIXED +Language=English + %1 Compressed hard drive %0 +. + +MessageId=30643 SymbolicName=MSG_DBLSPACE_LIST_NOT_PRESENT_REMOVABLE +Language=English +No disk in drive. +. + +MessageId=30644 SymbolicName=MSG_DBLSPACE_LIST_NOT_PRESENT_FIXED +Language=English +Information not available. +. + +MessageId=30645 SymbolicName=MSG_DBLSPACE_LIST_DETAIL +Language=English + %1.%2 %3.%4 %5 +. + +MessageId=30646 SymbolicName=MSG_DBLSPACE_CANT_REMOVE_DRIVE_LETTER +Language=English +Cannot remove definition of drive letter %1. +. + +MessageId=30647 SymbolicName=MSG_DBLSPACE_AUTOMOUNT_STATE_ON +Language=English +Automounting is enabled for removable drives. +. + +MessageId=30648 SymbolicName=MSG_DBLSPACE_AUTOMOUNT_STATE_OFF +Language=English +Automounting is not enabled for removable drives. +. + +MessageId=30649 SymbolicName=MSG_DBLSPACE_AUTOMOUNT_ENABLED +Language=English +Automounting has been enabled for removable drives. +. + +MessageId=30650 SymbolicName=MSG_DBLSPACE_AUTOMOUNT_DISABLED +Language=English +Automounting has been disabled for removable drives. +. + +MessageId=30651 SymbolicName=MSG_DBLSPACE_AUTOMOUNT_ENABLE_FAILED +Language=English +DBLSPACE could not enable automounting. +. + +MessageId=30652 SymbolicName=MSG_DBLSPACE_AUTOMOUNT_DISABLE_FAILED +Language=English +DBLSPACE could not disable automounting. +. + +MessageId=30653 SymbolicName=MSG_DBLSPACE_REBOOT +Language=English +For this change to take effect, you must restart your computer. +. + +MessageId=30515 SymbolicName=MSG_DBLSPACE_SECTOR_DUP_ALLOC +Language=English +Sector allocated by multiple clusters. +. + +MessageId=30516 SymbolicName=MSG_DBLSPACE_FAT_EXTENS_MISMATCH +Language=English +FAT extensions don't match FAT, cluster %1. +. + +MessageId=30517 SymbolicName=MSG_DBLSPACE_FAT_EXTENS_INVALID +Language=English +FAT extensions invalid, cluster %1. +. + +MessageId=30518 SymbolicName=MSG_DBLSPACE_SECTOR_RANGE +Language=English +FAT extensions contain invalid sector number. +. + +MessageId=30519 SymbolicName=MSG_DBLSPACE_UNCOMPRESSING +Language=English +Uncompressing files +. + +MessageId=30520 SymbolicName=MSG_DBLSPACE_NO_SUCH_FILE +Language=English +The file %1 does not exist. +. + +MessageId=30521 SymbolicName=MSG_DBLSPACE_CANT_UNMOUNT_CURRENT_DRIVE +Language=English +DBLSPACE cannot unmount the current drive. +. + diff --git a/private/utils/ulib/src/rtmsg.mc b/private/utils/ulib/src/rtmsg.mc new file mode 100644 index 000000000..8720bb674 --- /dev/null +++ b/private/utils/ulib/src/rtmsg.mc @@ -0,0 +1,4851 @@ +;/*++ BUILD Version: 0001 // Increment this if a change has global effects +; +;Copyright (c) 1990 Microsoft Corporation +; +;Module Name: +; +; rtmsg.h +; +;Abstract: +; +; This file contains the message definitions for the Win32 utilities +; library. +; +;Author: +; +; Norbert P. Kusters (norbertk) 2-Apr-1991 +; +;Revision History: +; +;--*/ + +;//---------------------- +;// +;// DOS 5 chkdsk message. +;// +;//---------------------- + +MessageId=1000 SymbolicName=MSG_CONVERT_LOST_CHAINS +Language=English +Convert lost chains to files (Y/N)? %0 +. + +MessageId=1001 SymbolicName=MSG_CHK_ERROR_IN_DIR +Language=English +Unrecoverable error in directory %1 +. + +MessageId=1002 SymbolicName=MSG_CHK_CONVERT_DIR_TO_FILE +Language=English +Convert directory to file (Y/N)? %0 +. + +MessageId=1003 SymbolicName=MSG_TOTAL_DISK_SPACE +Language=English + +%1 bytes total disk space. +. + +MessageId=1004 SymbolicName=MSG_BAD_SECTORS +Language=English +%1 bytes in bad sectors. +. + +MessageId=1005 SymbolicName=MSG_HIDDEN_FILES +Language=English +%1 bytes in %2 hidden files. +. + +MessageId=1006 SymbolicName=MSG_DIRECTORIES +Language=English +%1 bytes in %2 directories. +. + +MessageId=1007 SymbolicName=MSG_USER_FILES +Language=English +%1 bytes in %2 user files. +. + +MessageId=1008 SymbolicName=MSG_RECOVERED_FILES +Language=English +%1 bytes in %2 recovered files. +. + +MessageId=1009 SymbolicName=MSG_WOULD_BE_RECOVERED_FILES +Language=English +%1 bytes would be in %2 recovered files. +. + +MessageId=1010 SymbolicName=MSG_AVAILABLE_DISK_SPACE +Language=English +%1 bytes available on disk. +. + +MessageId=1011 SymbolicName=MSG_TOTAL_MEMORY +Language=English +%1 total bytes memory. +. + +MessageId=1012 SymbolicName=MSG_AVAILABLE_MEMORY +Language=English +%1 bytes free. +. + +MessageId=1013 SymbolicName=MSG_CHK_CANT_NETWORK +Language=English +Cannot CHKDSK a network drive. +. + +MessageId=1014 SymbolicName=MSG_1014 +Language=English +Cannot CHKDSK a SUBSTed or ASSIGNed drive. +. + +MessageId=1015 SymbolicName=MSG_PROBABLE_NON_DOS_DISK +Language=English +Probable non-Windows NT disk +Continue (Y/N)? %0 +. + +MessageId=1016 SymbolicName=MSG_DISK_ERROR_READING_FAT +Language=English +Disk error reading FAT %1 +. + +MessageId=1017 SymbolicName=MSG_DIRECTORY +Language=English +Directory %1. +. + +MessageId=1018 SymbolicName=MSG_CONTIGUITY_REPORT +Language=English +%1 Contains %2 non-contiguous blocks. +. + +MessageId=1019 SymbolicName=MSG_ALL_FILES_CONTIGUOUS +Language=English +All specified file(s) are contiguous. +. + +MessageId=1020 SymbolicName=MSG_CORRECTIONS_WILL_NOT_BE_WRITTEN +Language=English +Errors found, F parameter not specified. +Corrections will not be written to disk. +. + +MessageId=1021 SymbolicName=MSG_BAD_FAT_DRIVE +Language=English + File allocation table (FAT) is bad on drive %1. +. + +MessageId=1022 SymbolicName=MSG_BAD_FIRST_UNIT +Language=English +%1 First allocation unit is invalid, entry truncated. +. + +MessageId=1023 SymbolicName=MSG_CHK_DONE_CHECKING +Language=English +File and directory verification completed. +. + +MessageId=1024 SymbolicName=MSG_DISK_TOO_LARGE_TO_CONVERT +Language=English +The volume is too large to convert. +. + +MessageId=1025 SymbolicName=MSG_CONV_NTFS_CHKDSK +Language=English +The volume is dirty -- run chkdsk. +. + +MessageId=1028 SymbolicName=MSG_1028 +Language=English + Allocation error, size adjusted. +. + +MessageId=1029 SymbolicName=MSG_1029 +Language=English + Cannot recover .. entry, processing continued. +. + +MessageId=1030 SymbolicName=MSG_1030 +Language=English + Directory is totally empty, no . or .. +. + +MessageId=1031 SymbolicName=MSG_1031 +Language=English + Directory is joined. +. + +MessageId=1032 SymbolicName=MSG_1032 +Language=English + Cannot recover .. entry. +. + +MessageId=1033 SymbolicName=MSG_BAD_LINK +Language=English +%1 Entry has a bad link. +. + +MessageId=1034 SymbolicName=MSG_BAD_ATTRIBUTE +Language=English + Entry has a bad attribute. +. + +MessageId=1035 SymbolicName=MSG_BAD_FILE_SIZE +Language=English +%1 Entry has a bad size. +. + +MessageId=1036 SymbolicName=MSG_CROSS_LINK +Language=English +%1 Is cross linked on allocation unit %2 +. + +MessageId=1037 SymbolicName=MSG_1037 +Language=English + Cannot CHDIR to %1, +tree past this point not processed. +. + +MessageId=1038 SymbolicName=MSG_1038 +Language=English + tree past this point not processed. +. + +MessageId=1039 SymbolicName=MSG_BYTES_FREED +Language=English +%1 bytes disk space freed. +. + +MessageId=1040 SymbolicName=MSG_BYTES_WOULD_BE_FREED +Language=English +%1 bytes disk space would be freed. +. + +MessageId=1041 SymbolicName=MSG_VOLUME_LABEL_AND_DATE +Language=English +Volume %1 created %2 %3 +. + +MessageId=1042 SymbolicName=MSG_TOTAL_ALLOCATION_UNITS +Language=English +%1 total allocation units on disk. +. + +MessageId=1043 SymbolicName=MSG_BYTES_PER_ALLOCATION_UNIT +Language=English +%1 bytes in each allocation unit. +. + +MessageId=1044 SymbolicName=MSG_1044 +Language=English +CHKDSK not available on drive %1. +. + +MessageId=1045 SymbolicName=MSG_1045 +Language=English +Invalid parameter. +. + +MessageId=1046 SymbolicName=MSG_PATH_NOT_FOUND +Language=English +Path not found. +. + +MessageId=1047 SymbolicName=MSG_FILE_NOT_FOUND +Language=English +%1 : File not found. +. + +MessageId=1048 SymbolicName=MSG_LOST_CHAINS +Language=English + %1 lost allocation units found in %2 chains. +. + +MessageId=1049 SymbolicName=MSG_BLANK_LINE +Language=English + +. + +MessageId=1050 SymbolicName=MSG_1050 +Language=English + Cannot CHDIR to root +. + +MessageId=1051 SymbolicName=MSG_BAD_FAT_WRITE +Language=English + Disk error writing FAT +. + +MessageId=1052 SymbolicName=MSG_ONE_STRING +Language=English +%1. +. + +MessageId=1054 SymbolicName=MSG_ONE_STRING_NEWLINE +Language=English +%1 +. + +MessageId=1055 SymbolicName=MSG_NO_ROOM_IN_ROOT +Language=English + Insufficient room in root directory + Move files from root directory and repeat CHKDSK. +. + +MessageId=1056 SymbolicName=MSG_1056 +Language=English +%1 %2 %3. +. + +MessageId=1057 SymbolicName=MSG_1057 +Language=English +%1 %2, %3. +. + +MessageId=1058 SymbolicName=MSG_1058 +Language=English +%1%2%3%4%5. +. + +MessageId=1059 SymbolicName=MSG_1059 +Language=English +%1%2%3%4. +. + +MessageId=1060 SymbolicName=MSG_UNITS_ON_DISK +Language=English +%1 available allocation units on disk. +. + +MessageId=1061 SymbolicName=MSG_1061 +Language=English +CHKDSK /F cannot be done in a Windows/DosShell Command Prompt +. + +MessageId=1062 SymbolicName=MSG_CHK_NO_MEMORY +Language=English + - Insufficient Memory. +. + +MessageId=1063 SymbolicName=MSG_HIDDEN_STATUS +Language=English +This never gets printed. +. + + +MessageId=1064 SymbolicName=MSG_CHK_USAGE_HEADER +Language=English +Checks a disk and displays a status report. + +. + +MessageId=1065 SymbolicName=MSG_CHK_COMMAND_LINE +Language=English +CHKDSK [drive:][[path]filename] [/F] [/V] [/R] [/L[:size]] + +. + +MessageId=1066 SymbolicName=MSG_CHK_DRIVE +Language=English + [drive:] Specifies the drive to check. +. + +MessageId=1067 SymbolicName=MSG_CHK_USG_FILENAME +Language=English + filename Specifies the file(s) to check for fragmentation (FAT only). +. + +MessageId=1068 SymbolicName=MSG_CHK_F_SWITCH +Language=English + /F Fixes errors on the disk. +. + +MessageId=1069 SymbolicName=MSG_CHK_V_SWITCH +Language=English + /V Displays the full path and name of every file on the disk. + /R Locates bad sectors and recovers readable information. + /L:size NTFS only: changes the log file size to the specified number + of kilobytes. If size is not specified, displays current size. +. + +MessageId=1070 SymbolicName=MSG_WITHOUT_PARAMETERS +Language=English +Type CHKDSK without parameters to check the current disk. +. + + +MessageId=1071 SymbolicName=MSG_CHK_CANT_CDROM +Language=English +CHKDSK does not run on CD-ROM drives. +. + +MessageId=1072 SymbolicName=MSG_CHK_RUNNING +Language=English +Checking file system on %1 +. + +MessageId=1073 SymbolicName=MSG_CHK_VOLUME_CLEAN +Language=English +The volume is clean. +. + +MessageId=1074 SymbolicName=MSG_CHK_TRAILING_DIRENTS +Language=English +Removing trailing directory entries from %1 +. + +MessageId=1075 SymbolicName=MSG_CHK_BAD_CLUSTERS_IN_FILE_SUCCESS +Language=English +CHKDSK replaced bad clusters in file %1. +. + +MessageId=1076 SymbolicName=MSG_CHK_BAD_CLUSTERS_IN_FILE_FAILURE +Language=English +Insufficient disk space to replace bad clusters +detected in file %1. +. + +MessageId=1077 SymbolicName=MSG_CHK_RECOVERING_FREE_SPACE +Language=English +CHKDSK is verifying free space... +. + +MessageId=1078 SymbolicName=MSG_CHK_DONE_RECOVERING_FREE_SPACE +Language=English +Free space verification completed. +. + +MessageId=1079 SymbolicName=MSG_CHK_CHECKING_FILES +Language=English +CHKDSK is verifying files and directories... +. + +;//----------------------- +;// +;// Windows NT Chkdsk messages. +;// +;//----------------------- + + +MessageId=1080 SymbolicName=MSG_CHK_ON_REBOOT +Language=English +Do you want AUTOCHK to be run the next time that +the system restarts? [Y] %0 +. + +MessageId=1081 SymbolicName=MSG_CHK_VOLUME_SET_DIRTY +Language=English +AUTOCHK will run the next time that the system restarts. +. + +MessageId=1082 SymbolicName=MSG_CHK_BOOT_PARTITION_REBOOT +Language=English + +CHKDSK has finished checking your boot partition. +Please wait while the system restarts. +. + +MessageId=1083 SymbolicName=MSG_CHK_BAD_LONG_NAME +Language=English +Removing invalid long directory entry from %1 +. + +MessageId=1084 SymbolicName=MSG_CHK_CHECKING_VOLUME +Language=English +Checking %1 +. + +MessageId=1085 SymbolicName=MSG_CHK_BAD_LONG_NAME_IS +Language=English +Removing orphan long directory entry: %1 +. + +MessageId=1086 SymbolicName=MSG_CHK_WONT_ZERO_LOGFILE +Language=English +The logfile size must be greater than zero. +. + +MessageId=1087 SymbolicName=MSG_CHK_LOGFILE_NOT_NTFS +Language=English +CHKDSK cannot set the logfile size on non-NTFS volumes. +. + +MessageId=1088 SymbolicName=MSG_CHK_LOGFILE_SIZE +Language=English +The current logfile size is %1 kilobytes. +The default logfile size for this volume is %2 kilobytes. +. + +MessageId=1089 SymbolicName=MSG_CHK_BAD_LOGFILE_SIZE +Language=English +The size specified for the logfile is too small. +. + +MessageId=1090 SymbolicName=MSG_CHK_BAD_DRIVE_PATH_FILENAME +Language=English +Invalid drive, path, or filename +. + +;//----------------------- +;// +;// DOS 5 Format messages. +;// +;//----------------------- + + +MessageId=2000 SymbolicName=MSG_PERCENT_COMPLETE +Language=English +%1 percent completed. %r%0 +. + +MessageId=2001 SymbolicName=MSG_FORMAT_COMPLETE +Language=English +Format complete. %b +. + +MessageId=2002 SymbolicName=MSG_INSERT_DISK +Language=English +Insert new disk for drive %1: +. + +MessageId=2003 SymbolicName=MSG_REINSERT_DISKETTE +Language=English +Reinsert disk for drive %1: +. + +MessageId=2006 SymbolicName=MSG_BAD_IOCTL +Language=English +Error in IOCTL call. +. + +MessageId=2007 SymbolicName=MSG_CANT_DASD +Language=English +Cannot open volume for direct access. +. + +MessageId=2008 SymbolicName=MSG_CANT_WRITE_FAT +Language=English +Error writing File Allocation Table (FAT). +. + +MessageId=2009 SymbolicName=MSG_CANT_WRITE_ROOT_DIR +Language=English +Error writing directory. +. + +MessageId=2012 SymbolicName=MSG_FORMAT_NO_NETWORK +Language=English +Cannot format a network drive. +. + +MessageId=2013 SymbolicName=MSG_UNSUPPORTED_PARAMETER +Language=English +Parameters not supported. +. + +MessageId=2016 SymbolicName=MSG_UNUSABLE_DISK +Language=English +Invalid media or Track 0 bad - disk unusable. +. + +MessageId=2018 SymbolicName=MSG_BAD_DIR_READ +Language=English +Error reading directory. +. + +MessageId=2019 SymbolicName=MSG_PRESS_ENTER_WHEN_READY +Language=English +and press ENTER when ready... %0 +. + +MessageId=2021 SymbolicName=MSG_ENTER_CURRENT_LABEL +Language=English +Enter current volume label for drive %1: %0 +. + +MessageId=2022 SymbolicName=MSG_INCOMPATIBLE_PARAMETERS_FOR_FIXED +Language=English +Parameters incompatible with fixed disk. +. + +MessageId=2023 SymbolicName=MSG_READ_PARTITION_TABLE +Language=English +Error reading partition table. +. + +MessageId=2028 SymbolicName=MSG_NOT_SUPPORTED_BY_DRIVE +Language=English +Parameters not supported by drive. +. + +MessageId=2029 SymbolicName=MSG_2029 +Language=English + +. + +MessageId=2030 SymbolicName=MSG_2030 +Language=English + + +. + +MessageId=2031 SymbolicName=MSG_INSERT_DOS_DISK +Language=English +Insert Windows NT disk in drive %1: +. + +MessageId=2032 SymbolicName=MSG_WARNING_FORMAT +Language=English + +WARNING, ALL DATA ON NON-REMOVABLE DISK +DRIVE %1: WILL BE LOST! +Proceed with Format (Y/N)? %0 +. + +MessageId=2033 SymbolicName=MSG_FORMAT_ANOTHER +Language=English + +Format another (Y/N)? %0 +. + +MessageId=2035 SymbolicName=MSG_WRITE_PARTITION_TABLE +Language=English +Error writing partition table. +. + +MessageId=2036 SymbolicName=MSG_INCOMPATIBLE_PARAMETERS +Language=English +Parameters not compatible. +. + +MessageId=2037 SymbolicName=MSG_AVAILABLE_ALLOCATION_UNITS +Language=English +%1 allocation units available on disk. +. + +MessageId=2038 SymbolicName=MSG_ALLOCATION_UNIT_SIZE +Language=English + +%1 bytes in each allocation unit. +. + +MessageId=2040 SymbolicName=MSG_PARAMETER_TWICE +Language=English +Same parameter entered twice. +. + +MessageId=2041 SymbolicName=MSG_NEED_BOTH_T_AND_N +Language=English +Must enter both /t and /n parameters. +. + +MessageId=2042 SymbolicName=MSG_2042 +Language=English +Trying to recover allocation unit %1. %0 +. + +MessageId=2047 SymbolicName=MSG_NO_LABEL_WITH_8 +Language=English +Volume label is not supported with /8 parameter. +. + +MessageId=2049 SymbolicName=MSG_FMT_NO_MEMORY +Language=English +Insufficient memory. +. + +MessageId=2050 SymbolicName=MSG_QUICKFMT_ANOTHER +Language=English + +QuickFormat another (Y/N)? %0 +. + +MessageId=2052 SymbolicName=MSG_CANT_QUICKFMT +Language=English +Invalid existing format. +This disk cannot be QuickFormatted. +Proceed with unconditional format (Y/N)? %0 +. + +MessageId=2053 SymbolicName=MSG_FORMATTING_KB +Language=English +Formatting %1K +. + +MessageId=2054 SymbolicName=MSG_FORMATTING_MB +Language=English +Formatting %1M +. + +MessageId=2055 SymbolicName=MSG_FORMATTING_DOT_MB +Language=English +Formatting %1.%2M +. + +MessageId=2057 SymbolicName=MSG_VERIFYING_KB +Language=English +Verifying %1K +. + +MessageId=2058 SymbolicName=MSG_VERIFYING_MB +Language=English +Verifying %1M +. + +MessageId=2059 SymbolicName=MSG_VERIFYING_DOT_MB +Language=English +Verifying %1.%2M +. + +MessageId=2060 SymbolicName=MSG_2060 +Language=English +Saving UNFORMAT information. +. + +MessageId=2061 SymbolicName=MSG_2061 +Language=English +Checking existing disk format. +. + +MessageId=2062 SymbolicName=MSG_QUICKFORMATTING_KB +Language=English +QuickFormatting %1K +. + +MessageId=2063 SymbolicName=MSG_QUICKFORMATTING_MB +Language=English +QuickFormatting %1M +. + +MessageId=2064 SymbolicName=MSG_QUICKFORMATTING_DOT_MB +Language=English +QuickFormatting %1.%2M +. + +MessageId=2065 SymbolicName=MSG_FORMAT_INFO +Language=English +Formats a disk for use with Windows NT. + +. + +MessageId=2066 SymbolicName=MSG_FORMAT_COMMAND_LINE_1 +Language=English +FORMAT drive: [/FS:file-system] [/V:label] [/Q] [/A:size] [/C] +FORMAT drive: [/V:label] [/Q] [/F:size] +. + +MessageId=2067 SymbolicName=MSG_FORMAT_COMMAND_LINE_2 +Language=English +FORMAT drive: [/V:label] [/Q] [/T:tracks /N:sectors] +. + +MessageId=2068 SymbolicName=MSG_FORMAT_COMMAND_LINE_3 +Language=English +FORMAT drive: [/V:label] [/Q] [/1] [/4] +. + +MessageId=2069 SymbolicName=MSG_FORMAT_COMMAND_LINE_4 +Language=English +FORMAT drive: [/Q] [/1] [/4] [/8] + + /FS:file-system Specifies the type of the file system (FAT or NTFS). +. + +MessageId=2070 SymbolicName=MSG_FORMAT_SLASH_V +Language=English + /V:label Specifies the volume label. +. + +MessageId=2071 SymbolicName=MSG_FORMAT_SLASH_Q +Language=English + /Q Performs a quick format. +. + +MessageId=2072 SymbolicName=MSG_FORMAT_SLASH_C +Language=English + /C Files created on the new volume will be compressed by + default. +. + +MessageId=2073 SymbolicName=MSG_FORMAT_SLASH_F +Language=English + /A:size Overrides the default allocation unit size. Default settings + are strongly recommended for general use. + NTFS supports 512, 1024, 2048, 4096, 8192, 16K, 32K, 64K. + FAT supports 8192, 16K, 32K, 64K, 128K, 256K. + NTFS compression is not supported for allocation unit sizes + above 4096. + /F:size Specifies the size of the floppy disk to format (160, +. + +MessageId=2074 SymbolicName=MSG_FORMAT_SUPPORTED_SIZES +Language=English + 180, 320, 360, 720, 1.2, 1.44, 2.88, or 20.8). +. + +MessageId=2075 SymbolicName=MSG_WRONG_CURRENT_LABEL +Language=English +An incorrect volume label was entered for this drive. +. + +MessageId=2077 SymbolicName=MSG_FORMAT_SLASH_T +Language=English + /T:tracks Specifies the number of tracks per disk side. +. + +MessageId=2078 SymbolicName=MSG_FORMAT_SLASH_N +Language=English + /N:sectors Specifies the number of sectors per track. +. + +MessageId=2079 SymbolicName=MSG_FORMAT_SLASH_1 +Language=English + /1 Formats a single side of a floppy disk. +. + +MessageId=2080 SymbolicName=MSG_FORMAT_SLASH_4 +Language=English + /4 Formats a 5.25-inch 360K floppy disk in a + high-density drive. +. + +MessageId=2081 SymbolicName=MSG_FORMAT_SLASH_8 +Language=English + /8 Formats eight sectors per track. +. + +MessageId=2083 SymbolicName=MSG_FORMAT_NO_CDROM +Language=English +Cannot format a CD-ROM drive. +. + +MessageId=2084 SymbolicName=MSG_FORMAT_NO_RAMDISK +Language=English +Cannot format a RAM DISK drive. +. + +MessageId=2086 SymbolicName=MSG_FORMAT_PLEASE_USE_FS_SWITCH +Language=English +Please use the /FS switch to specify the file system +you wish to use on this volume. +. + +MessageId=2087 SymbolicName=MSG_NTFS_FORMAT_FAILED +Language=English +Format failed. +. + +MessageId=2088 SymbolicName=MSG_FMT_WRITE_PROTECTED_MEDIA +Language=English +Cannot format. This media is write protected. +. + +MessageId=2089 SymbolicName=MSG_FMT_INSTALL_FILE_SYSTEM +Language=English + +WARNING! The %1 file system is not enabled. +Would you like to enable it (Y/N)? %0 +. + +MessageId=2090 SymbolicName=MSG_FMT_FILE_SYSTEM_INSTALLED +Language=English + +The file system will be enabled when you restart the system. +. + +MessageId=2091 SymbolicName=MSG_FMT_CANT_INSTALL_FILE_SYSTEM +Language=English + +FORMAT is unable to enable the file system. +. + +MessageId=2092 SymbolicName=MSG_FMT_VOLUME_TOO_SMALL +Language=English +The volume is too small for the specified file system. +. + +MessageId=2093 SymbolicName=MSG_FMT_CREATING_FILE_SYSTEM +Language=English +Creating file system structures. +. + +MessageId=2094 SymbolicName=MSG_FMT_VARIABLE_CLUSTERS_NOT_SUPPORTED +Language=English +%1 FORMAT does not support user selected allocation unit sizes. +. + +MessageId=2096 SymbolicName=MSG_DEVICE_BUSY +Language=English +The device is busy. +. + +MessageId=2097 SymbolicName=MSG_FMT_DMF_NOT_SUPPORTED_ON_288_DRIVES +Language=English +The specified format cannot be mastered on 2.88MB drives. +. + +MessageId=2098 SymbolicName=MSG_HPFS_NO_FORMAT +Language=English +FORMAT does not support the HPFS file system type. +. + +MessageId=2099 SymbolicName=MSG_FMT_ALLOCATION_SIZE_CHANGED +Language=English +Allocation unit size changed to %1 bytes. +. + +MessageId=2203 SymbolicName=MSG_CONV_PAUSE_BEFORE_REBOOT +Language=English + +Preinstallation completed successfully. Press any key to +shut down/reboot. +. + +MessageId=2204 SymbolicName=MSG_CONV_WILL_REBOOT +Language=English + +Convert will take some time to process the files on the volume. +When this phase of conversion is complete, the system will be +rebooted. + +. + +;//---------------------- +;// +;// Common ulib messages. +;// +;//---------------------- + +MessageId=3000 SymbolicName=MSG_CANT_LOCK_THE_DRIVE +Language=English +Cannot lock the drive. The volume is still in use. +. + +MessageId=3002 SymbolicName=MSG_CANT_READ_BOOT_SECTOR +Language=English +Cannot read boot sector. +. + +MessageId=3003 SymbolicName=MSG_VOLUME_SERIAL_NUMBER +Language=English +Volume Serial Number is %1-%2 +. + +MessageId=3004 SymbolicName=MSG_VOLUME_LABEL_PROMPT +Language=English +Volume label (11 characters, ENTER for none)? %0 +. + +MessageId=3005 SymbolicName=MSG_INVALID_LABEL_CHARACTERS +Language=English +Invalid characters in volume label +. + +MessageId=3006 SymbolicName=MSG_CANT_READ_ANY_FAT +Language=English +There are no readable file allocation tables (FAT). +. + +MessageId=3007 SymbolicName=MSG_SOME_FATS_UNREADABLE +Language=English +Some file allocation tables (FAT) are unreadable. +. + +MessageId=3008 SymbolicName=MSG_CANT_WRITE_BOOT_SECTOR +Language=English +Cannot write boot sector. +. + +MessageId=3009 SymbolicName=MSG_SOME_FATS_UNWRITABLE +Language=English +Some file allocation tables (FAT) are unwritable. +. + +MessageId=3010 SymbolicName=MSG_INSUFFICIENT_DISK_SPACE +Language=English +Insufficient disk space. +. + +MessageId=3011 SymbolicName=MSG_TOTAL_KILOBYTES +Language=English +%1 kilobytes total disk space. +. + +MessageId=3012 SymbolicName=MSG_AVAILABLE_KILOBYTES +Language=English +%1 kilobytes are available. +. + +MessageId=3013 SymbolicName=MSG_NOT_FAT +Language=English +Disk not formatted or not FAT. +. + +MessageId=3014 SymbolicName=MSG_REQUIRED_PARAMETER +Language=English +Required parameter missing - +. + +MessageId=3015 SymbolicName=MSG_FILE_SYSTEM_TYPE +Language=English +The type of the file system is %1. +. + +MessageId=3016 SymbolicName=MSG_NEW_FILE_SYSTEM_TYPE +Language=English +The new file system is %1. +. + +MessageId=3017 SymbolicName=MSG_FMT_AN_ERROR_OCCURRED +Language=English +An error occurred while running Format. +. + +MessageId=3018 SymbolicName=MSG_FS_NOT_SUPPORTED +Language=English +%1 is not available for %2 drives. +. + +MessageId=3019 SymbolicName=MSG_FS_NOT_DETERMINED +Language=English +Cannot determine file system of drive %1. +. + +MessageId=3020 SymbolicName=MSG_CANT_DISMOUNT +Language=English +Cannot dismount the drive. +. + +MessageId=3021 SymbolicName=MSG_NOT_FULL_PATH_NAME +Language=English +%1 is not a complete name. +. + +MessageId=3022 SymbolicName=MSG_YES +Language=English +Yes +. + +MessageId=3023 SymbolicName=MSG_NO +Language=English +No +. + +MessageId=3024 SymbolicName=MSG_DISK_NOT_FORMATTED +Language=English +Disk is not formatted. +. + +MessageId=3025 SymbolicName=MSG_NONEXISTENT_DRIVE +Language=English +Specified drive does not exist. +. + +MessageId=3026 SymbolicName=MSG_INVALID_PARAMETER +Language=English +Invalid parameter - %1 +. + +MessageId=3027 SymbolicName=MSG_INSUFFICIENT_MEMORY +Language=English +Out of memory. +. + +MessageId=3028 SymbolicName=MSG_ACCESS_DENIED +Language=English +Access denied - %1 +. + +MessageId=3029 SymbolicName=MSG_DASD_ACCESS_DENIED +Language=English +Access denied. +. + +MessageId=3030 SymbolicName=MSG_CANT_LOCK_CURRENT_DRIVE +Language=English +Cannot lock current drive. +. + +MessageId=3031 SymbolicName=MSG_INVALID_LABEL +Language=English +Invalid volume label +. + +MessageId=3032 SymbolicName=MSG_DISK_TOO_LARGE_TO_FORMAT +Language=English +The disk is too large to format for the specified file system. +. + +MessageId=3033 SymbolicName=MSG_VOLUME_LABEL_NO_MAX +Language=English +Volume label (ENTER for none)? %0 +. + +MessageId=3034 SymbolicName=MSG_CHKDSK_ON_REBOOT_PROMPT +Language=English +Chkdsk cannot run because the volume is in use by another +process. Would you like to schedule this volume to be +checked the next time the system restarts? (Y/N) %0 +. + +MessageId=3035 SymbolicName=MSG_CHKDSK_CANNOT_SCHEDULE +Language=English + +Chkdsk could not schedule this volume to be checked +the next time the system boots. +. + +MessageId=3036 SymbolicName=MSG_CHKDSK_SCHEDULED +Language=English + +This volume will be checked the next time the system restarts. +. + +MessageId=3037 SymbolicName=MSG_COMPRESSION_NOT_AVAILABLE +Language=English +Compression is not available for %1. +. + +MessageId=3038 SymbolicName=MSG_CANNOT_ENABLE_COMPRESSION +Language=English +Cannot enable compression for the volume. +. + +MessageId=3039 SymbolicName=MSG_CANNOT_COMPRESS_HUGE_CLUSTERS +Language=English +Compression is not supported on volumes with clusters larger than +4096 bytes. +. + +MessageId=3040 SymbolicName=MSG_CANT_UNLOCK_THE_DRIVE +Language=English +Cannot unlock the drive. +. + +MessageId=4004 SymbolicName=MSG_HPFS_CHKDSK_ERRORS_DETECTED +Language=English +CHKDSK detected minor inconsistencies on the drive. +. + +MessageId=4005 SymbolicName=MSG_HPFS_CHKDSK_ERRORS_FIXED +Language=English +CHKDSK detected and fixed minor inconsistencies on the drive. +. + +;//--------------------- +;// +;// FAT ChkDsk Messages. +;// +;//--------------------- + +MessageId=5000 SymbolicName=MSG_CHK_ERRORS_IN_FAT +Language=English +Errors in file allocation table (FAT) corrected. +. + +MessageId=5001 SymbolicName=MSG_CHK_EAFILE_HAS_HANDLE +Language=English +Extended attribute file has handle. Handle removed. +. + +MessageId=5002 SymbolicName=MSG_CHK_EMPTY_EA_FILE +Language=English +Extended attribute file contains no extended attributes. File deleted. +. + +MessageId=5003 SymbolicName=MSG_CHK_ERASING_INVALID_LABEL +Language=English +Erasing invalid label. +. + +MessageId=5004 SymbolicName=MSG_CHK_EA_SIZE +Language=English +%1 bytes in extended attributes. +. + +MessageId=5005 SymbolicName=MSG_CHK_CANT_CHECK_EA_LOG +Language=English +Unreadable extended attribute header. +Cannot check extended attribute log. +. + +MessageId=5006 SymbolicName=MSG_CHK_BAD_LOG +Language=English +Extended attribute log is unintelligible. +Ignore log and Continue? (Y/N) %0 +. + +MessageId=5007 SymbolicName=MSG_CHK_UNUSED_EA_PORTION +Language=English +Unused, unreadable, or unwritable portion of extended attribute file removed. +. + +MessageId=5008 SymbolicName=MSG_CHK_EASET_SIZE +Language=English +Total size entry for extended attribute set at cluster %1 corrected. +. + +MessageId=5009 SymbolicName=MSG_CHK_EASET_NEED_COUNT +Language=English +Need count entry for extended attribute set at cluster %1 corrected. +. + +MessageId=5010 SymbolicName=MSG_CHK_UNORDERED_EA_SETS +Language=English +Extended attribute file is unsorted. +Sorting extended attribute file. +. + +MessageId=5011 SymbolicName=MSG_CHK_NEED_MORE_HEADER_SPACE +Language=English +Insufficient space in extended attribute file for its header. +Attempting to allocate more disk space. +. + +MessageId=5012 SymbolicName=MSG_CHK_INSUFFICIENT_DISK_SPACE +Language=English +Insufficient disk space to correct disk error. +Please free up some disk space and run CHKDSK again. +. + +MessageId=5013 SymbolicName=MSG_CHK_RELOCATED_EA_HEADER +Language=English +Bad clusters in extended attribute file header relocated. +. + +MessageId=5014 SymbolicName=MSG_CHK_ERROR_IN_EA_HEADER +Language=English +Errors in extended attribute file header corrected. +. + +MessageId=5015 SymbolicName=MSG_CHK_MORE_THAN_ONE_DOT +Language=English +More than one dot entry in directory %1. Entry removed. +. + +MessageId=5016 SymbolicName=MSG_CHK_DOT_IN_ROOT +Language=English +Dot entry found in root directory. Entry removed. +. + +MessageId=5017 SymbolicName=MSG_CHK_DOTDOT_IN_ROOT +Language=English +Dot-dot entry found in root directory. Entry removed. +. + +MessageId=5018 SymbolicName=MSG_CHK_ERR_IN_DOT +Language=English +Dot entry in directory %1 has incorrect link. Link corrected. +. + +MessageId=5019 SymbolicName=MSG_CHK_ERR_IN_DOTDOT +Language=English +Dot-dot entry in directory %1 has incorrect link. Link corrected. +. + +MessageId=5020 SymbolicName=MSG_CHK_REPEATED_ENTRY +Language=English +More than one %1 entry in directory %2. Entry removed. +. + +MessageId=5021 SymbolicName=MSG_CHK_CYCLE_IN_TREE +Language=English +Directory %1 causes cycle in directory tree. +Directory entry removed. +. + +MessageId=5022 SymbolicName=MSG_CHK_BAD_CLUSTERS_IN_DIR +Language=English +Directory %1 has bad clusters. +Bad clusters removed from directory. +. + +MessageId=5023 SymbolicName=MSG_CHK_BAD_DIR +Language=English +Directory %1 is entirely unreadable. +Directory entry removed. +. + +MessageId=5024 SymbolicName=MSG_CHK_FILENAME +Language=English +%1 +. + +MessageId=5025 SymbolicName=MSG_CHK_DIR_TRUNC +Language=English +Directory truncated. +. + +MessageId=5026 SymbolicName=MSG_CHK_CROSS_LINK_COPY +Language=English +Cross link resolved by copying. +. + +MessageId=5027 SymbolicName=MSG_CHK_CROSS_LINK_TRUNC +Language=English +Insufficient disk space to copy cross-linked portion. +File being truncated. +. + +MessageId=5028 SymbolicName=MSG_CHK_INVALID_NAME +Language=English +%1 Invalid name. Directory entry removed. +. + +MessageId=5029 SymbolicName=MSG_CHK_INVALID_TIME_STAMP +Language=English +%1 Invalid time stamp. +. + +MessageId=5030 SymbolicName=MSG_CHK_DIR_HAS_FILESIZE +Language=English +%1 Directory has non-zero file size. +. + +MessageId=5031 SymbolicName=MSG_CHK_UNRECOG_EA_HANDLE +Language=English +%1 Unrecognized extended attribute handle. +. + +MessageId=5032 SymbolicName=MSG_CHK_SHARED_EA +Language=English +%1 Has handle extended attribute set belonging to another file. + Handle removed. +. + +MessageId=5033 SymbolicName=MSG_CHK_UNUSED_EA_SET +Language=English +Unused extended attribute set with handle %1 deleted from +extended attribute file. +. + +MessageId=5034 SymbolicName=MSG_CHK_NEW_OWNER_NAME +Language=English +Extended attribute set with handle %1 owner changed +from %2 to %3. +. + +MessageId=5035 SymbolicName=MSG_CHK_BAD_LINKS_IN_ORPHANS +Language=English +Bad links in lost-chain at cluster %1 corrected. +. + +MessageId=5036 SymbolicName=MSG_CHK_CROSS_LINKED_ORPHAN +Language=English +Lost-chain cross-linked at cluster %1. Orphan truncated. +. + +MessageId=5037 SymbolicName=MSG_ORPHAN_DISK_SPACE +Language=English +Insufficient disk space to recover lost data. +. + +MessageId=5038 SymbolicName=MSG_TOO_MANY_ORPHANS +Language=English +Insufficient disk space to recover lost data. +. + +MessageId=5039 SymbolicName=MSG_CHK_ERROR_IN_LOG +Language=English +Error in extended attribute log. +. + +MessageId=5040 SymbolicName=MSG_CHK_ERRORS_IN_DIR_CORR +Language=English +%1 Errors in directory corrected. +. + + +;//-------------------- +;// +;// Messages for label. +;// +;//-------------------- + + +MessageId=6000 SymbolicName=MSG_LBL_INFO +Language=English +Creates, changes, or deletes the volume label of a disk. + +. + +MessageId=6001 SymbolicName=MSG_LBL_USAGE +Language=English +LABEL [drive:][label] + +. + +MessageId=6002 SymbolicName=MSG_LBL_NO_LABEL +Language=English +Volume in drive %1 has no label +. + +MessageId=6003 SymbolicName=MSG_LBL_THE_LABEL +Language=English +Volume in drive %1 is %2 +. + +MessageId=6005 SymbolicName=MSG_LBL_DELETE_LABEL +Language=English + +Delete current volume label (Y/N)? %0 +. + +MessageId=6006 SymbolicName=MSG_LBL_NOT_SUPPORTED +Language=English +The network request is not supported. +. + + +;//--------------------- +;// +;// Messages for attrib. +;// +;//--------------------- + + +MessageId=7000 SymbolicName=MSG_ATTRIB_ARCHIVE +Language=English +A +. + +MessageId=7001 SymbolicName=MSG_ATTRIB_HIDDEN +Language=English +H +. + +MessageId=7002 SymbolicName=MSG_ATTRIB_READ_ONLY +Language=English +R +. + +MessageId=7003 SymbolicName=MSG_ATTRIB_SYSTEM +Language=English +R +. + +MessageId=7004 SymbolicName=MSG_ATTRIB_FILE_NOT_FOUND +Language=English +File not found - %1 +. + +MessageId=7005 SymbolicName=MSG_ATTRIB_PATH_NOT_FOUND +Language=English +Path not found - %1 +. + +MessageId=7006 SymbolicName=MSG_ATTRIB_PARAMETER_NOT_CORRECT +Language=English +Parameter format not correct - +. + +MessageId=7007 SymbolicName=MSG_ATTRIB_NOT_RESETTING_SYS_FILE +Language=English +Not resetting system file - %1 +. + +MessageId=7008 SymbolicName=MSG_ATTRIB_NOT_RESETTING_HIDDEN_FILE +Language=English +Not resetting hidden file - %1 +. + +MessageId=7009 SymbolicName=MSG_ATTRIB_DISPLAY_ATTRIBUTE +Language=English +%1 %2%3%4 %5 +. + +MessageId=7010 SymbolicName=MSG_ATTRIB_HELP_MESSAGE +Language=English +Displays or changes file attributes. + +ATTRIB [+R | -R] [+A | -A ] [+S | -S] [+H | -H] [[drive:] [path] filename] [/S] + + + Sets an attribute. + - Clears an attribute. + R Read-only file attribute. + A Archive file attribute. + S System file attribute. + H Hidden file attribute. + /S Processes matching files in the current directory + and all subdirectories. + +. + +MessageId=7012 SymbolicName=MSG_ATTRIB_INVALID_SWITCH +Language=English +Invalid switch - %1 +. + +MessageId=7013 SymbolicName=MSG_ATTRIB_ACCESS_DENIED +Language=English +Access denied - %1 +. + +MessageId=7014 SymbolicName=MSG_ATTRIB_UNABLE_TO_CHANGE_ATTRIBUTE +Language=English +Unable to change attribute - %1 +. + +;//-------------------- +;// +;// Messages for sort +;// +;//-------------------- + + +MessageId=8000 SymbolicName=MSG_SORT_VALUE_NOT_IN_RANGE +Language=English +SORT: Parameter value not in allowed range +. + +MessageId=8001 SymbolicName=MSG_SORT_INVALID_SWITCH +Language=English +SORT: Invalid switch +. + +MessageId=8002 SymbolicName=MSG_SORT_TOO_MANY_PARAMETERS +Language=English +SORT: Too many parameters +. + +MessageId=8003 SymbolicName=MSG_SORT_HELP_MESSAGE +Language=English +Sorts input and writes results to the screen, a file, or another device. + +SORT [/R] [/+n] < [drive1:][path1]filename1 [> [drive2:][path2]filename2] +[command |] SORT [/R] [/+n] [> [drive2:][path2]filename2] + + /R Reverses the sort order; that is, sorts Z to A, + then 9 to 0. + /+n Sorts the file according to characters in + column n. + [drive1:][path1]filename1 Specifies a file to be sorted. + [drive2:][path2]filename2 Specifies a file where the sorted input is to be + stored. + command Specifies a command whose output is to be sorted. + + +. + +;//------------------- +;// +;// Diskcopy messages. +;// +;//------------------- + + +MessageId=9000 SymbolicName=MSG_9000 +Language=English + +. + +MessageId=9001 SymbolicName=MSG_9001 +Language=English +Do not specify filename(s) +Command Format: DISKCOPY [drive1: [drive2:]] [/1] [/V] +. + +MessageId=9002 SymbolicName=MSG_DCOPY_INVALID_DRIVE +Language=English + +Invalid drive specification +Specified drive does not exist +or is non-removable +. + +MessageId=9003 SymbolicName=MSG_9003 +Language=English + +Cannot DISKCOPY to or from +a network drive +. + +MessageId=9004 SymbolicName=MSG_DCOPY_FORMATTING_WHILE_COPYING +Language=English + +Formatting while copying +. + +MessageId=9005 SymbolicName=MSG_DCOPY_INSERT_SOURCE +Language=English + +Insert SOURCE disk in drive %1 +. + +MessageId=9006 SymbolicName=MSG_DCOPY_INSERT_TARGET +Language=English + +Insert TARGET disk in drive %1 +. + +MessageId=9007 SymbolicName=MSG_9007 +Language=English +Make sure a disk is inserted into +the drive and the door is closed +. + +MessageId=9008 SymbolicName=MSG_9008 +Language=English + +Target disk may be unusable +. + +MessageId=9009 SymbolicName=MSG_DCOPY_BAD_TARGET +Language=English + +Target disk unusable +. + +MessageId=9010 SymbolicName=MSG_DCOPY_ANOTHER +Language=English + +Copy another disk (Y/N)? %0 +. + +MessageId=9011 SymbolicName=MSG_DCOPY_COPYING +Language=English + +Copying %1 tracks +%2 sectors per track, %3 side(s) +. + +MessageId=9012 SymbolicName=MSG_DCOPY_NON_COMPAT_DISKS +Language=English + +Drive types or disk types +not compatible +. + +MessageId=9013 SymbolicName=MSG_DCOPY_READ_ERROR +Language=English + +Unrecoverable read error on drive %1 +side %2, track %3 +. + +MessageId=9014 SymbolicName=MSG_DCOPY_WRITE_ERROR +Language=English + +Unrecoverable write error on drive %1 +side %2, track %3 +. + +MessageId=9015 SymbolicName=MSG_DCOPY_ENDED +Language=English + +Copy process ended +. + +MessageId=9016 SymbolicName=MSG_DCOPY_BAD_SOURCE +Language=English + +SOURCE disk bad or incompatible. +. + +MessageId=9017 SymbolicName=MSG_DCOPY_BAD_DEST +Language=English + +TARGET disk bad or incompatible. +. + +MessageId=9020 SymbolicName=MSG_DCOPY_INFO +Language=English +Copies the contents of one floppy disk to another. + +. + +MessageId=9021 SymbolicName=MSG_DCOPY_USAGE +Language=English +DISKCOPY [drive1: [drive2:]] [/V] + +. + +MessageId=9023 SymbolicName=MSG_DCOPY_SLASH_V +Language=English + /V Verifies that the information is copied correctly. + +. + +MessageId=9024 SymbolicName=MSG_DCOPY_INFO_2 +Language=English +The two floppy disks must be the same type. +You may specify the same drive for drive1 and drive2. +. + +MessageId=9025 SymbolicName=MSG_DCOPY_INSERT_SOURCE_AND_TARGET +Language=English + +Insert SOURCE disk in drive %1 + +Insert TARGET disk in drive %2 +. + +MessageId=9026 SymbolicName=MSG_DCOPY_UNRECOGNIZED_FORMAT +Language=English +Unrecognized format. +. + +MessageId=9027 SymbolicName=MSG_DCOPY_NOT_ADMINISTRATOR +Language=English +You need to be an administrator to copy this disk. +. + +MessageId=9028 SymbolicName=MSG_DCOPY_DISK_TOO_LARGE +Language=English +Cannot copy disk larger than %1 Megabytes. +. + +;// this message will never appear as text message. +;// this is a placeholder for the GUI version of the message. +MessageId=9029 SymbolicName=MSG_DCOPY_UNRECOGNIZED_MEDIA +Language=English +Unrecognized media. Please insert the correct media into drive %1. +. + +;// this message will never appear as text message. +;// this is a placeholder for the GUI version of the message. +MessageId=9030 SymbolicName=MSG_DCOPY_NO_MEDIA_IN_DEVICE +Language=English +There is no disk in the drive. Please insert a disk into drive %1. +. + +;// this message will never appear as text message. +;// this is a placeholder for the GUI version of the message. +MessageId=9031 SymbolicName=MSG_DCOPY_MEDIA_WRITE_PROTECTED +Language=English +The disk in drive %1 is write protected. Please use a writable disk. +. + +;//------------------- +;// +;// Diskcomp messages. +;// +;//------------------- + +MessageId=10000 SymbolicName=MSG_10000 +Language=English +Do not specify filename(s) +Command format: DISKCOMP [drive1: [drive2:]] [/1] [/8] +. + +MessageId=10001 SymbolicName=MSG_10001 +Language=English + +Invalid drive specification +Specified drive does not exist +or is non-removable. +. + +MessageId=10003 SymbolicName=MSG_DCOMP_INSERT_FIRST +Language=English + +Insert FIRST disk in drive %1 +. + +MessageId=10004 SymbolicName=MSG_DCOMP_INSERT_SECOND +Language=English + +Insert SECOND disk in drive %1 +. + +MessageId=10005 SymbolicName=MSG_DCOMP_FIRST_DISK_BAD +Language=English + +FIRST disk bad or incompatible +. + +MessageId=10006 SymbolicName=MSG_DCOMP_SECOND_DISK_BAD +Language=English + +SECOND disk bad or incompatible +. + +MessageId=10007 SymbolicName=MSG_DCOMP_ANOTHER +Language=English + +Compare another disk (Y/N) ? %0 +. + +MessageId=10008 SymbolicName=MSG_DCOMP_COMPARING +Language=English + +Comparing %1 tracks +%2 sectors per track, %3 side(s) +. + +MessageId=10009 SymbolicName=MSG_DCOMP_NOT_COMPATIBLE +Language=English + +Drive types or disk types not compatible +. + +MessageId=10010 SymbolicName=MSG_10010 +Language=English + +Unrecoverable read error on drive %1 +side %2, track %3 +. + +MessageId=10011 SymbolicName=MSG_DCOMP_COMPARE_ERROR +Language=English + +Compare error on +side %1, track %2 +. + +MessageId=10012 SymbolicName=MSG_10012 +Language=English +Make sure a disk is inserted into +the drive and the door is closed. +. + +MessageId=10013 SymbolicName=MSG_DCOMP_ENDED +Language=English + +Compare process ended. +. + +MessageId=10014 SymbolicName=MSG_DCOMP_OK +Language=English + +Compare OK +. + +MessageId=10015 SymbolicName=MSG_10015 +Language=English + +. + +MessageId=10016 SymbolicName=MSG_DCOMP_INFO +Language=English +Compares the contents of two floppy disks. + +. + +MessageId=10017 SymbolicName=MSG_DCOMP_USAGE +Language=English +DISKCOMP [drive1: [drive2:]] + +. + + + +;//-------------------- +;// +;// Messages for tree +;// +;//-------------------- + + +MessageId=11000 SymbolicName=MSG_TREE_INVALID_SWITCH +Language=English +Invalid switch - /%1 +. + +MessageId=11001 SymbolicName=MSG_TREE_INVALID_PATH +Language=English +Invalid path - %1 +. + +MessageId=11002 SymbolicName=MSG_TREE_NO_SUBDIRECTORIES +Language=English +No subdirectories exist %1 +. + +MessageId=11003 SymbolicName=MSG_TREE_DIR_LISTING_NO_VOLUME_NAME +Language=English +Directory PATH listing +. + +MessageId=11004 SymbolicName=MSG_TREE_DIR_LISTING_WITH_VOLUME_NAME +Language=English +Directory PATH listing for volume %1 +. + +MessageId=11005 SymbolicName=MSG_TREE_32_BIT_SERIAL_NUMBER +Language=English +Volume serial number is %1-%2 +. + +MessageId=11006 SymbolicName=MSG_TREE_64_BIT_SERIAL_NUMBER +Language=English +Volume serial number is %1 %2:%3 +. + +MessageId=11007 SymbolicName=MSG_TREE_HELP_MESSAGE +Language=English +Graphically displays the directory structure of a drive or path. + +TREE [drive:][path] [/F] [/A] + + /F Display the names of the files in each directory. + /A Use ASCII instead of extended characters. + +. + +MessageId=11008 SymbolicName=MSG_TREE_SINGLE_BOTTOM_LEFT_CORNER +Language=English +€ +. + +MessageId=11009 SymbolicName=MSG_TREE_SINGLE_BOTTOM_HORIZONTAL +Language=English +ƒ +. + +MessageId=11010 SymbolicName=MSG_TREE_SINGLE_LEFT_T +Language=English +„ +. + +MessageId=11011 SymbolicName=MSG_TREE_PARAMETER_NOT_CORRECT +Language=English +Parameter format not correct - %1 +. + +MessageId=11012 SymbolicName=MSG_TREE_TOO_MANY_PARAMETERS +Language=English +Too many parameters - %1 +. + +MessageId=11013 SymbolicName=MSG_TREE_INVALID_DRIVE +Language=English +Invalid drive specification +. + +;//------------------- +;// +;// Find messages. +;// +;//------------------- + +MessageId=12000 SymbolicName=MSG_FIND +Language=English +FIND: %0 +. + +MessageId=12001 SymbolicName=MSG_FIND_INCORRECT_VERSION +Language=English +FIND: Incorrect Windows NT version +. + +MessageId=12002 SymbolicName=MSG_FIND_INVALID_SWITCH +Language=English +FIND: Invalid switch +. + +MessageId=12003 SymbolicName=MSG_FIND_INVALID_FORMAT +Language=English +FIND: Parameter format not correct +. + +MessageId=12004 SymbolicName=MSG_FIND_USAGE +Language=English +Searches for a text string in a file or files. + +FIND [/V] [/C] [/N] [/I] "string" [[drive:][path]filename[ ...]] + + /V Displays all lines NOT containing the specified string. + /C Displays only the count of lines containing the string. + /N Displays line numbers with the displayed lines. + /I Ignores the case of characters when searching for the string. + "string" Specifies the text string to find. + [drive:][path]filename + Specifies a file or files to search. + +If a path is not specified, FIND searches the text typed at the prompt +or piped from another command. +. + +MessageId=12005 SymbolicName=MSG_FIND_MISSING_PARM +Language=English +FIND: Required parameter missing +. + +MessageId=12006 SymbolicName=MSG_FIND_FILE_NOT_FOUND +Language=English +File not found - %1 +. + +MessageId=12007 SymbolicName=MSG_FIND_COUNT +Language=English +%1 +. + +MessageId=12008 SymbolicName=MSG_FIND_COUNT_BANNER +Language=English + +---------- %1: %2 +. + +MessageId=12009 SymbolicName=MSG_FIND_BANNER +Language=English + +---------- %1 +. + +MessageId=12010 SymbolicName=MSG_FIND_LINEONLY +Language=English +%1 +. + +MessageId=12011 SymbolicName=MSG_FIND_LINE_AND_NUMBER +Language=English +[%1]%2 +. + + +;//----------------- +;// +;// FC Messages +;// +;//----------------- + +MessageId=13000 SymbolicName=MSG_FC_HELP_MESSAGE +Language=English +Compares two files or sets of files and displays the differences between +them + + +FC [/A] [/C] [/L] [/LBn] [/N] [/T] [/U] [/W] [/nnnn] [drive1:][path1]filename1 + [drive2:][path2]filename2 +FC /B [drive1:][path1]filename1 [drive2:][path2]filename2 + + /A Displays only first and last lines for each set of differences. + /B Performs a binary comparison. + /C Disregards the case of letters. + /L Compares files as ASCII text. + /LBn Sets the maximum consecutive mismatches to the specified number of + lines. + /N Displays the line numbers on an ASCII comparison. + /T Does not expand tabs to spaces. + /U Compare files as UNICODE text files. + /W Compresses white space (tabs and spaces) for comparison. + /nnnn Specifies the number of consecutive lines that must match after a + mismatch. + +. +MessageId=13001 SymbolicName=MSG_FC_INCOMPATIBLE_SWITCHES +Language=English +FC: Incompatible Switches + +. +MessageId=13002 SymbolicName=MSG_FC_INVALID_SWITCH +Language=English +FC: Invalid Switch + +. +MessageId=13003 SymbolicName=MSG_FC_INSUFFICIENT_FILES +Language=English +FC: Insufficient number of file specifications + +. +MessageId=13004 SymbolicName=MSG_13004 +Language=English +Comparing files %1 and %2 +. +MessageId=13005 SymbolicName=MSG_FC_UNABLE_TO_OPEN +Language=English +FC: cannot open %1 - No such file or directory + +. +MessageId=13006 SymbolicName=MSG_FC_CANT_EXPAND_TO_MATCH +Language=English +%1 %2 +Could not expand second filename so as to match first + +. +MessageId=13007 SymbolicName=MSG_FC_NO_DIFFERENCES +Language=English +FC: no differences encountered + +. +MessageId=13008 SymbolicName=MSG_FC_COMPARING_FILES +Language=English +Comparing files %1 and %2 +. +MessageId=13009 SymbolicName=MSG_FC_FILES_NOT_FOUND +Language=English +File(s) not found : %1 + +. +MessageId=13010 SymbolicName=MSG_FC_DATA +Language=English +%1 +. +MessageId=13011 SymbolicName=MSG_FC_NUMBERED_DATA +Language=English +%1: %2 +. +MessageId=13012 SymbolicName=MSG_FC_OUTPUT_FILENAME +Language=English +***** %1 +. +MessageId=13013 SymbolicName=MSG_FC_DUMP_END +Language=English +***** + +. +MessageId=13014 SymbolicName=MSG_FC_FILES_DIFFERENT_LENGTH +Language=English +FC: %1 longer than %2 + + +. +MessageId=13015 SymbolicName=MSG_FC_RESYNC_FAILED +Language=English +Resync Failed. Files are too different +. +MessageId=13016 SymbolicName=MSG_FC_CANT_CREATE_STREAM +Language=English +FC: Unable to open %1. File unavailable for read access + +. +MessageId=13017 SymbolicName=MSG_FC_INCORRECT_VERSION +Language=English +FC: Incorrect Windows NT Version + +. +MessageId=13018 SymbolicName=MSG_FC_ABBREVIATE_SYMBOL +Language=English +... +. + +MessageId=13019 SymbolicName=MSG_FC_ABBREVIATE_SYMBOL_SHIFTED +Language=English + ... +. + +MessageId=13020 SymbolicName=MSG_FC_HEX_OUT +Language=English +%1: %2 %3 +. + +MessageId=13021 SymbolicName=MSG_FC_OUT_OF_MEMORY +Language=English +FC: Out of memory +. + + + +;//----------------- +;// +;// Comp Messages +;// +;//----------------- + +MessageId=14000 SymbolicName=MSG_COMP_HELP_MESSAGE +Language=English +Compares the contents of two files or sets of files. + +COMP [data1] [data2] [/D] [/A] [/L] [/N=number] [/C] + + data1 Specifies location and name(s) of first file(s) to compare. + data2 Specifies location and name(s) of second files to compare. + /D Displays differences in decimal format. This is the default + setting. + /A Displays differences in ASCII characters. + /L Displays line numbers for differences. + /N=number Compares only the first specified number of lines in each file. + /C Disregards case of ASCII letters when comparing files. + +To compare sets of files, use wildcards in data1 and data2 parameters. +. +MessageId=14001 SymbolicName=MSG_COMP_FILES_OK +Language=English +Files compare OK + +. +MessageId=14002 SymbolicName=MSG_COMP_NO_MEMORY +Language=English +No memory available. + +. +MessageId=14003 SymbolicName=MSG_COMP_UNABLE_TO_OPEN +Language=English +Can't find/open file: %1 + +. +MessageId=14004 SymbolicName=MSG_COMP_UNABLE_TO_READ +Language=English +Can't read file: %1 + +. +MessageId=14005 SymbolicName=MSG_COMP_BAD_COMMAND_LINE +Language=English +Bad command line syntax + +. +MessageId=14006 SymbolicName=MSG_COMP_BAD_NUMERIC_ARG +Language=English +Bad numeric argument : +%1 + +. +MessageId=14007 SymbolicName=MSG_COMP_COMPARE_ERROR +Language=English +Compare error at %1 %2 +file1 = %3 +file2 = %4 +. +MessageId=14008 SymbolicName=MSG_COMP_QUERY_FILE1 +Language=English +Name of first file to compare: %0 +. +MessageId=14009 SymbolicName=MSG_COMP_QUERY_FILE2 +Language=English +Name of second file to compare: %0 +. +MessageId=14010 SymbolicName=MSG_COMP_OPTION +Language=English +Option : %0 +. +MessageId=14011 SymbolicName=MSG_COMP_COMPARE_FILES +Language=English +Comparing %1 and %2... +. +MessageId=14012 SymbolicName=MSG_COMP_DIFFERENT_SIZES +Language=English +Files are different sizes. + +. +MessageId=14013 SymbolicName=MSG_COMP_NUMERIC_FORMAT +Language=English +Format for /n switch is /n=XXXX +. +MessageId=14014 SymbolicName=MSG_COMP_MORE +Language=English +Compare more files (Y/N) ? %0 +. +MessageId=14015 SymbolicName=MSG_COMP_UNABLE_TO_EXPAND +Language=English +%1 %2 +Could not expand second filename so as to match first + +. +MessageId=14016 SymbolicName=MSG_COMP_TOO_MANY_ERRORS +Language=English +10 Mismatches - ending compare + +. +MessageId=14017 SymbolicName=MSG_COMP_INCORRECT_VERSION +Language=English +Incorrect Windows NT version + +. +MessageId=14018 SymbolicName=MSG_COMP_UNEXPECTED_END +Language=English +Unexpected end of file + +. +MessageId=14019 SymbolicName=MSG_COMP_INVALID_SWITCH +Language=English +Invalid switch - %1 + +. +MessageId=14020 SymbolicName=MSG_COMP_FILE1_TOO_SHORT +Language=English + +File1 only has %1 lines + +. +MessageId=14021 SymbolicName=MSG_COMP_FILE2_TOO_SHORT +Language=English + +File2 only has %1 lines + +. +MessageId=14022 SymbolicName=MSG_COMP_WILDCARD_STRING +Language=English +*.*%0 +. + + +;//--------------------------- +;// +;// FAT/HPFS Recover messages. +;// +;//--------------------------- + + +MessageId=15000 SymbolicName=MSG_RECOV_FILE_NOT_FOUND +Language=English + +File not found +. + +MessageId=15001 SymbolicName=MSG_15001 +Language=English + +Cannot RECOVER an ASSIGNed or SUBSTed drive +. + +MessageId=15002 SymbolicName=MSG_INVALID_DRIVE +Language=English + +Invalid drive or file name +. + +MessageId=15004 SymbolicName=MSG_RECOV_CANT_NETWORK +Language=English + +Cannot RECOVER a network drive +. + +MessageId=15005 SymbolicName=MSG_15005 +Language=English + +%1 file(s) recovered. +. + +MessageId=15006 SymbolicName=MSG_RECOV_BYTES_RECOVERED +Language=English + +%1 of %2 bytes recovered. +. + +MessageId=15007 SymbolicName=MSG_RECOV_BEGIN +Language=English + +Press ENTER to begin recovery of the file on drive %1 + +. + +MessageId=15008 SymbolicName=MSG_RECOV_CANT_READ_FAT +Language=English + +Cannot read the file allocation table (FAT). +. + +MessageId=15009 SymbolicName=MSG_RECOV_CANT_WRITE_FAT +Language=English + +Cannot write the file allocation table (FAT). +. + +MessageId=15010 SymbolicName=MSG_15010 +Language=English + +. + +MessageId=15011 SymbolicName=MSG_RECOV_INFO +Language=English +Recovers readable information from a bad or defective disk. + +. + +MessageId=15012 SymbolicName=MSG_RECOV_USAGE +Language=English +RECOVER [drive:][path]filename +. + +MessageId=15013 SymbolicName=MSG_15013 +Language=English +RECOVER drive: + +. + +MessageId=15014 SymbolicName=MSG_RECOV_INFO2 +Language=English +Consult the online Command Reference in Windows NT Help +before using the RECOVER command. +. + +MessageId=15017 SymbolicName=MSG_RECOV_WRITE_ERROR +Language=English +Write error. +. + +MessageId=15018 SymbolicName=MSG_RECOV_INTERNAL_ERROR +Language=English +Internal consistency error. +. + +MessageId=15019 SymbolicName=MSG_RECOV_READ_ERROR +Language=English +Read error. +. + +MessageId=15020 SymbolicName=MSG_RECOV_NOT_SUPPORTED +Language=English +RECOVER on an entire volume is no longer supported. +To get equivalent functionality use CHKDSK. +. + + +;//---------------------------------- +;// +;// NTFS-specific recover messages +;// +;//---------------------------------- + +MessageId=15401 SymbolicName=MSG_NTFS_RECOV_SYSTEM_FILE +Language=English +NTFS RECOVER cannot be used to recover system files; use CHKDSK instead. +. + +MessageId=15402 SymbolicName=MSG_NTFS_RECOV_FAILED +Language=English +NTFS RECOVER failed. +. + +MessageId=15043 SymbolicName=MSG_NTFS_RECOV_CORRUPT_VOLUME +Language=English +NTFS RECOVER has detected that the volume is corrupt. Run CHKDSK /f +to fix it. +. + +MessageId=15044 SymbolicName=MSG_NTFS_RECOV_CANT_WRITE_ELEMENTARY +Language=English +NTFS Recover could not write elementary disk structures. The volume +may be corrupt; run CHKDSK /f to fix it. +. + +MessageId=15045 SymbolicName=MSG_NTFS_RECOV_WRONG_VERSION +Language=English +Files on this volume cannot be recovered with this version of UNTFS.DLL. +. + + + + +;//-------------------- +;// +;// Messages for Print +;// +;//-------------------- + + +MessageId=16000 SymbolicName=MSG_PRINT_INVALID_SWITCH +Language=English +Invalid switch - %1 +. + +MessageId=16001 SymbolicName=MSG_PRINT_NOT_IMPLEMENTED +Language=English +Switch %1 is not implemented +. + +MessageId=16002 SymbolicName=MSG_PRINT_NO_FILE +Language=English +No file to print +. + +MessageId=16003 SymbolicName=MSG_PRINT_UNABLE_INIT_DEVICE +Language=English +Unable to initialize device %1 +. + +MessageId=16004 SymbolicName=MSG_PRINT_FILE_NOT_FOUND +Language=English +Can't find file %1 +. + +MessageId=16005 SymbolicName=MSG_PRINT_PRINTING +Language=English +%1 is currently being printed +. + +MessageId=16006 SymbolicName=MSG_PRINT_HELP_MESSAGE +Language=English +Prints a text file. + +PRINT [/D:device] [[drive:][path]filename[...]] + + /D:device Specifies a print device. + +. + + + +;//--------------- +;// +;// Help Messages +;// +;//--------------- + +MessageId=17000 SymbolicName=MSG_HELP_HELP_MESSAGE +Language=English +Provides help information for Windows NT commands. + +HELP [command] + + command - displays help information on that command. + +. +MessageId=17001 SymbolicName=MSG_HELP_HELP_FILE_NOT_FOUND +Language=English +Help file could not be found. + +. +MessageId=17002 SymbolicName=MSG_HELP_HELP_FILE_ERROR +Language=English +Error reading help file. + +. +MessageId=17003 SymbolicName=MSG_HELP_GENERAL_HELP +Language=English + + +For more information on a specific command, type HELP command-name. +. +MessageId=17004 SymbolicName=MSG_HELP_HELP_UNAVAILABLE +Language=English +This command is not supported by the help utility. Try "%1 /?". +. +MessageId=17005 SymbolicName=MSG_HELP_HELP_COMMENT +Language=English +@ %0 +. +MessageId=17006 SymbolicName=MSG_HELP_EXECUTE_WITH_CMD +Language=English +cmd /c %1 /? %0 +. +MessageId=17007 SymbolicName=MSG_HELP_EXECUTE_WITHOUT_CMD +Language=English +%1 /? %0 +. +MessageId=17008 SymbolicName=MSG_HELP_HELP_FILE_NAME +Language=English +DosHelp.hlp%0 +. +MessageId=17009 SymbolicName=MSG_HELP_HELP_FILE_DATA +Language=English +%1 +. +MessageId=17010 SymbolicName=MSG_HELP_INCORRECT_VERSION +Language=English +Incorrect Windows NT version + +. +MessageId=17011 SymbolicName=MSG_HELP_MORE +Language=English +--- MORE ---%0 +. + + + +;//--------------- +;// +;// MORE messages. +;// +;//--------------- + + +MessageId=20001 SymbolicName=MORE_ENVIRONMENT_VARIABLE_NAME +Language=English +MORE%0 +. + +MessageId=20002 SymbolicName=MORE_PATTERN_SWITCH_EXTENDED +Language=English +/E%0 +. + +MessageId=20003 SymbolicName=MORE_PATTERN_SWITCH_CLEARSCREEN +Language=English +/C%0 +. + +MessageId=20004 SymbolicName=MORE_PATTERN_SWITCH_EXPANDFORMFEED +Language=English +/P%0 +. + +MessageId=20005 SymbolicName=MORE_PATTERN_SWITCH_SQUEEZEBLANKS +Language=English +/S%0 +. + +MessageId=20006 SymbolicName=MORE_PATTERN_SWITCH_HELP1 +Language=English +/?%0 +. + +MessageId=20007 SymbolicName=MORE_PATTERN_SWITCH_HELP2 +Language=English +/H%0 +. + +MessageId=20008 SymbolicName=MORE_PATTENR_ARG_STARTATLINE +Language=English ++*%0 +. + +MessageId=20010 SymbolicName=MORE_LEXEMIZER_MULTIPLESWITCH +Language=English +/ECPSH?%0 +. + +MessageId=20011 SymbolicName=MORE_LEXEMIZER_SWITCHES +Language=English +/-%0 +. + +MessageId=20020 SymbolicName=MORE_PROMPT +Language=English +-- More %1%2%3 -- %4%0 +. + +MessageId=20021 SymbolicName=MORE_PERCENT +Language=English +(%1%%)%0 +. + +MessageId=20022 SymbolicName=MORE_LINE +Language=English +[Line: %1]%0 +. + +MessageId=20023 SymbolicName=MORE_HELP +Language=English +[Options: psfq=<space><ret>]%0 +. + +MessageId=20024 SymbolicName=MORE_LINEPROMPT +Language=English +Lines: %0 +. + +MessageId=20030 SymbolicName=MORE_OPTION_DISPLAYLINES +Language=English +P%0 +. + +MessageId=20031 SymbolicName=MORE_OPTION_SKIPLINES +Language=English +S%0 +. + +MessageId=20032 SymbolicName=MORE_OPTION_SHOWLINENUMBER +Language=English +=%0 +. + +MessageId=20033 SymbolicName=MORE_OPTION_QUIT +Language=English +Q%0 +. + +MessageId=20034 SymbolicName=MORE_OPTION_HELP1 +Language=English +?%0 +. + +MessageId=20035 SymbolicName=MORE_OPTION_HELP2 +Language=English +H%0 +. + +MessageId=20036 SymbolicName=MORE_OPTION_NEXTFILE +Language=English +F%0 +. + +MessageId=20040 SymbolicName=MORE_MESSAGE_USAGE +Language=English +Displays output one screen at a time. + +MORE [/E [/C] [/P] [/S] [/Tn] [+n]] < [drive:][path]filename +command-name | MORE [/E [/C] [/P] [/S] [/Tn] [+n]] +MORE /E [/C] [/P] [/S] [/Tn] [+n] [files] + + [drive:][path]filename Specifies a file to display one + screen at a time. + + command-name Specifies a command whose output + will be displayed. + + /E Enable extended features + /C Clear screen before displaying page + /P Expand FormFeed characters + /S Squeeze multiple blank lines into a single line + /Tn Expand tabs to n spaces (default 8) + + Switches can be present in the MORE environment + variable. + + +n Start displaying the first file at line n + + files List of files to be displayed. Files in the list + are separated by blanks. + + If extended features are enabled, the following commands + are accepted at the -- More -- prompt: + + P n Display next n lines + S n Skip next n lines + F Display next file + Q Quit + = Show line number + ? Show help line + <space> Display next page + <ret> Display next line +. + +MessageId=20050 SymbolicName=MORE_ERROR_GENERAL +Language=English +Internal error. +. + +MessageId=20051 SymbolicName=MORE_ERROR_TOO_MANY_ARGUMENTS +Language=English +Too many arguments in command line. +. + +MessageId=20052 SymbolicName=MORE_ERROR_NO_MEMORY +Language=English +Not enough memory. +. + +MessageId=20053 SymbolicName=MORE_ERROR_CANNOT_ACCESS +Language=English +Cannot access file %1 +. + + + +;//------------------ +;// +;// REPLACE messages. +;// +;//------------------ + + +MessageId=21001 SymbolicName=REPLACE_PATTERN_SWITCH_ADD +Language=English +/A%0 +. + +MessageId=21002 SymbolicName=REPLACE_PATTERN_SWITCH_PROMPT +Language=English +/P%0 +. + +MessageId=21003 SymbolicName=REPLACE_PATTERN_SWITCH_READONLY +Language=English +/R%0 +. + +MessageId=21004 SymbolicName=REPLACE_PATTERN_SWITCH_SUBDIR +Language=English +/S%0 +. + +MessageId=21005 SymbolicName=REPLACE_PATTERN_SWITCH_COMPARETIME +Language=English +/U%0 +. + +MessageId=21006 SymbolicName=REPLACE_PATTERN_SWITCH_WAIT +Language=English +/W%0 +. + +MessageId=21007 SymbolicName=REPLACE_PATTERN_SWITCH_HELP +Language=English +/?%0 +. + +MessageId=21010 SymbolicName=REPLACE_LEXEMIZER_SWITCHES +Language=English +/-%0 +. + +MessageId=21011 SymbolicName=REPLACE_LEXEMIZER_MULTIPLESWITCH +Language=English +/APRSUW?%0 +. + +MessageId=21020 SymbolicName=REPLACE_MESSAGE_REPLACING +Language=English +Replacing %1 +. + +MessageId=21021 SymbolicName=REPLACE_MESSAGE_ADDING +Language=English +Adding %1 +. + +MessageId=21022 SymbolicName=REPLACE_MESSAGE_FILES_REPLACED +Language=English +%1 file(s) replaced +. + +MessageId=21023 SymbolicName=REPLACE_MESSAGE_FILES_ADDED +Language=English +%1 file(s) added +. + +MessageId=21024 SymbolicName=REPLACE_MESSAGE_NO_FILES_REPLACED +Language=English +No files replaced +. + +MessageId=21025 SymbolicName=REPLACE_MESSAGE_NO_FILES_ADDED +Language=English +No files added +. + +MessageId=21026 SymbolicName=REPLACE_MESSAGE_PRESS_ANY_KEY +Language=English +Press any key to continue . . . +. + +MessageId=21027 SymbolicName=REPLACE_MESSAGE_REPLACE_YES_NO +Language=English +Replace %1? (Y/N) %0 +. + +MessageId=21028 SymbolicName=REPLACE_MESSAGE_ADD_YES_NO +Language=English +Add %1? (Y/N) %0 +. + +MessageId=21029 SymbolicName=REPLACE_MESSAGE_USAGE +Language=English +Replaces files. + +REPLACE [drive1:][path1]filename [drive2:][path2] [/A] [/P] [/R] [/W] +REPLACE [drive1:][path1]filename [drive2:][path2] [/P] [/R] [/S] [/W] [/U] + + [drive1:][path1]filename Specifies the source file or files. + [drive2:][path2] Specifies the directory where files are to be + replaced. + /A Adds new files to destination directory. Cannot + use with /S or /U switches. + /P Prompts for confirmation before replacing a file or + adding a source file. + /R Replaces read-only files as well as unprotected + files. + /S Replaces files in all subdirectories of the + destination directory. Cannot use with the /A + switch. + /W Waits for you to insert a disk before beginning. + /U Replaces (updates) only files that are older than + source files. Cannot use with the /A switch. +. + +MessageId=21050 SymbolicName=REPLACE_ERROR_INCORRECT_OS_VERSION +Language=English +Incorrect Windows NT version +. + +MessageId=21051 SymbolicName=REPLACE_ERROR_SOURCE_PATH_REQUIRED +Language=English +Source path required +. + +MessageId=21052 SymbolicName=REPLACE_ERROR_SELF_REPLACE +Language=English +File cannot be copied onto itself +. + +MessageId=21053 SymbolicName=REPLACE_ERROR_NO_DISK_SPACE +Language=English +Insufficient disk space +. + +MessageId=21054 SymbolicName=REPLACE_ERROR_NO_FILES_FOUND +Language=English +No files found - %1 +. + +MessageId=21055 SymbolicName=REPLACE_ERROR_EXTENDED +Language=English +Extended Error %1 +. + +MessageId=21056 SymbolicName=REPLACE_ERROR_PARSE +Language=English +Parse Error %1 +. + +MessageId=21057 SymbolicName=REPLACE_ERROR_NO_MEMORY +Language=English +Out of memory +. + +MessageId=21058 SymbolicName=REPLACE_ERROR_INVALID_SWITCH +Language=English +Invalid switch - %1 +. + +MessageId=21059 SymbolicName=REPLACE_ERROR_INVALID_PARAMETER_COMBINATION +Language=English +Invalid parameter combination +. + +MessageId=21060 SymbolicName=REPLACE_ERROR_PATH_NOT_FOUND +Language=English +Path not found - %1 +. + +MessageId=21061 SymbolicName=REPLACE_ERROR_ACCESS_DENIED +Language=English +Access denied - %1 +. + + + +;//---------------- +;// +;// XCOPY messages. +;// +;//---------------- + + +MessageId=22001 SymbolicName=XCOPY_PATTERN_SWITCH_ARCHIVE +Language=English +/A%0 +. + +MessageId=22002 SymbolicName=XCOPY_PATTERN_SWITCH_DATE +Language=English +/D:*%0 +. + +MessageId=22003 SymbolicName=XCOPY_PATTERN_SWITCH_EMPTY +Language=English +/E%0 +. + +MessageId=22004 SymbolicName=XCOPY_PATTERN_SWITCH_MODIFY +Language=English +/M%0 +. + +MessageId=22005 SymbolicName=XCOPY_PATTERN_SWITCH_PROMPT +Language=English +/P%0 +. + +MessageId=22006 SymbolicName=XCOPY_PATTERN_SWITCH_SUBDIR +Language=English +/S%0 +. + +MessageId=22007 SymbolicName=XCOPY_PATTERN_SWITCH_VERIFY +Language=English +/V%0 +. + +MessageId=22008 SymbolicName=XCOPY_PATTERN_SWITCH_WAIT +Language=English +/W%0 +. + +MessageId=22009 SymbolicName=XCOPY_PATTERN_SWITCH_HELP +Language=English +/?%0 +. + +MessageId=22020 SymbolicName=XCOPY_LEXEMIZER_SWITCHES +Language=English +/-%0 +. + +MessageId=22021 SymbolicName=XCOPY_LEXEMIZER_MULTIPLESWITCH +Language=English +/AEMPSVW?%0 +. + +MessageId=22031 SymbolicName=XCOPY_ERROR_NO_MEMORY +Language=English +Insufficient memory +. + +MessageId=22032 SymbolicName=XCOPY_ERROR_INVALID_PARAMETER +Language=English +Invalid parameter - %1 +. + +MessageId=22034 SymbolicName=XCOPY_ERROR_INVALID_PATH +Language=English +Invalid path +. + +MessageId=22035 SymbolicName=XCOPY_ERROR_CYCLE +Language=English +Cannot perform a cyclic copy +. + +MessageId=22036 SymbolicName=XCOPY_ERROR_INVALID_DATE +Language=English +Invalid date +. + +MessageId=22037 SymbolicName=XCOPY_ERROR_CREATE_DIRECTORY +Language=English +Unable to create directory +. + +MessageId=22038 SymbolicName=XCOPY_ERROR_INVALID_DRIVE +Language=English +Invalid drive specification +. + +MessageId=22039 SymbolicName=XCOPY_ERROR_RESERVED_DEVICE +Language=English +Cannot XCOPY from a reserved device +. + +MessageId=22040 SymbolicName=XCOPY_ERROR_ACCESS_DENIED +Language=English +Access denied +. + +MessageId=22041 SymbolicName=XCOPY_ERROR_TOO_MANY_OPEN_FILES +Language=English +Too many open files +. + +MessageId=22042 SymbolicName=XCOPY_ERROR_GENERAL +Language=English +General failure +. + +MessageId=22043 SymbolicName=XCOPY_ERROR_SHARING_VIOLATION +Language=English +Sharing violation +. + +MessageId=22044 SymbolicName=XCOPY_ERROR_LOCK_VIOLATION +Language=English +Lock violation +. + +MessageId=22045 SymbolicName=XCOPY_ERROR_PATH_NOT_FOUND +Language=English +Path not found +. + +MessageId=22046 SymbolicName=XCOPY_ERROR_DISK_FULL +Language=English +Insufficient disk space +. + +MessageId=22047 SymbolicName=XCOPY_ERROR_SELF_COPY +Language=English +File cannot be copied onto itself +. + +MessageId=22048 SymbolicName=XCOPY_ERROR_INVALID_NUMBER_PARAMETERS +Language=English +Invalid number of parameters +. + +MessageId=22049 SymbolicName=XCOPY_ERROR_CREATE_DIRECTORY1 +Language=English +Unable to create directory - %1 +. + +MessageId=22050 SymbolicName=XCOPY_ERROR_FILE_NOT_FOUND +Language=English +File not found - %1 +. + +MessageId=22051 SymbolicName=XCOPY_ERROR_CANNOT_MAKE +Language=English +File creation error - %1 +. + +MessageId=22052 SymbolicName=XCOPY_ERROR_INVALID_SWITCH +Language=English +Invalid switch +. + +MessageId=22053 SymbolicName=XCOPY_ERROR_INVALID_PATH_PARTIAL_COPY +Language=English +Invalid Path, not all directories/files copied +. + +MessageId=22054 SymbolicName=XCOPY_ERROR_EXTENDED +Language=English +Extended Error %1 +. + +MessageId=22055 SymbolicName=XCOPY_ERROR_PARSE +Language=English +Parse Error +. + +MessageId=22056 SymbolicName=XCOPY_ERROR_WRITE_PROTECT +Language=English +Write protect error accessing drive. +. + +MessageId=22057 SymbolicName=XCOPY_ERROR_INVALID_SWITCH_SWITCH +Language=English +Invalid switch - %1 +. + +MessageId=22060 SymbolicName=XCOPY_MESSAGE_USAGE +Language=English +Copies files and directory trees. + +XCOPY source [destination] [/A | /M] [/D[:date]] [/P] [/S [/E]] [/V] [/W] + [/C] [/I] [/Q] [/F] [/L] [/H] [/R] [/T] [/U] + [/K] [/N] [/Z] + + source Specifies the file(s) to copy. + destination Specifies the location and/or name of new files. + /A Copies files with the archive attribute set, + doesn't change the attribute. + /M Copies files with the archive attribute set, + turns off the archive attribute. + /D:m-d-y Copies files changed on or after the specified date. + If no date is given, copies only those files whose + source time is newer than the destination time. + /P Prompts you before creating each destination file. + /S Copies directories and subdirectories except empty ones. + /E Copies directories and subdirectories, including empty ones. + Same as /S /E. May be used to modify /T. + /V Verifies each new file. + /W Prompts you to press a key before copying. + /C Continues copying even if errors occur. + /I If destination does not exist and copying more than one file, + assumes that destination must be a directory. + /Q Does not display file names while copying. + /F Displays full source and destination file names while copying. + /L Displays files that would be copied. + /H Copies hidden and system files also. + /R Overwrites read-only files. + /T Creates directory structure, but does not copy files. Does not + include empty directories or subdirectories. /T /E includes + empty directories and subdirectories. + /U Copies only files that already exist in destination. + /K Copies attributes. Normal Xcopy will reset read-only attributes. + /N Copies using the generated short names. + /Z Copies networked files in restartable mode. +. + +MessageId=22061 SymbolicName=XCOPY_MESSAGE_WAIT +Language=English +Press any key when ready to begin copying file(s)%0 +. + +MessageId=22062 SymbolicName=XCOPY_MESSAGE_CONFIRM +Language=English +%1 (Y/N)? %0 +. + +MessageId=22063 SymbolicName=XCOPY_MESSAGE_FILE_OR_DIRECTORY +Language=English +Does %1 specify a file name +or directory name on the target +(F = file, D = directory)? %0 +. + +MessageId=22064 SymbolicName=XCOPY_MESSAGE_FILES_COPIED +Language=English +%1 File(s) copied +. + +MessageId=22065 SymbolicName=XCOPY_MESSAGE_FILENAME +Language=English +%1 +. + +MessageId=22066 SymbolicName=XCOPY_MESSAGE_VERBOSE_COPY +Language=English +%1 -> %2 +. + +MessageId=22067 SymbolicName=XCOPY_MESSAGE_CHANGE_DISK +Language=English + +Insufficient disk space on current disk. +Insert another disk and type <Return> to continue... %0 +. + +MessageId=22070 SymbolicName=XCOPY_RESPONSE_FILE +Language=English +F%0 +. + +MessageId=22071 SymbolicName=XCOPY_RESPONSE_DIRECTORY +Language=English +D%0 +. + +MessageId=22072 SymbolicName=XCOPY_RESPONSE_YES +Language=English +Y%0 +. + +MessageId=22073 SymbolicName=XCOPY_RESPONSE_NO +Language=English +N%0 +. + +MessageId=22074 SymbolicName=XCOPY_MESSAGE_FILES +Language=English +%1 File(s) +. + +MessageId=22075 SymbolicName=XCOPY_ERROR_VERIFY_FAILED +Language=English +File verification failed. +. + +;//--------------- +;// +;// MODE messages. +;// +;//--------------- + + +MessageId=23050 SymbolicName=MODE_MESSAGE_REROUTED +Language=English +LPT%1: rerouted to COM%2: +. + +MessageId=23051 SymbolicName=MODE_MESSAGE_ACTIVE_CODEPAGE +Language=English +Active code page for device %1 is %2 +. + +MessageId=23052 SymbolicName=MODE_MESSAGE_HELP +Language=English +Configures system devices. + +Serial port: MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s] + [to=on|off] [xon=on|off] [odsr=on|off] + [octs=on|off] [dtr=on|off|hs] + [rts=on|off|hs|tg] [idsr=on|off] + +Device Status: MODE [device] [/STATUS] + +Redirect printing: MODE LPTn[:]=COMm[:] + +Select code page: MODE CON[:] CP SELECT=yyy + +Code page status: MODE CON[:] CP [/STATUS] + +Display mode: MODE CON[:] [COLS=c] [LINES=n] + +Typematic rate: MODE CON[:] [RATE=r DELAY=d] +. + +MessageId=23053 SymbolicName=MODE_MESSAGE_STATUS +Language=English +Status for device *:%0 +. + +MessageId=23055 SymbolicName=MODE_MESSAGE_STATUS_BAUD +Language=English + Baud: %1 +. + +MessageId=23056 SymbolicName=MODE_MESSAGE_STATUS_PARITY +Language=English + Parity: %1 +. + +MessageId=23057 SymbolicName=MODE_MESSAGE_STATUS_DATA +Language=English + Data Bits: %1 +. + +MessageId=23058 SymbolicName=MODE_MESSAGE_STATUS_STOP +Language=English + Stop Bits: %1 +. + +MessageId=23059 SymbolicName=MODE_MESSAGE_STATUS_TIMEOUT +Language=English + Timeout: %1 +. + +MessageId=23060 SymbolicName=MODE_MESSAGE_STATUS_XON +Language=English + XON/XOFF: %1 +. + +MessageId=23061 SymbolicName=MODE_MESSAGE_STATUS_OCTS +Language=English + CTS handshaking: %1 +. + +MessageId=23062 SymbolicName=MODE_MESSAGE_STATUS_ODSR +Language=English + DSR handshaking: %1 +. + +MessageId=23063 SymbolicName=MODE_MESSAGE_STATUS_IDSR +Language=English + DSR sensitivity: %1 +. + +MessageId=23064 SymbolicName=MODE_MESSAGE_STATUS_DTR +Language=English + DTR circuit: %1 +. + +MessageId=23065 SymbolicName=MODE_MESSAGE_STATUS_RTS +Language=English + RTS circuit: %1 +. + +MessageId=23070 SymbolicName=MODE_MESSAGE_STATUS_LINES +Language=English + Lines: %1 +. + +MessageId=23071 SymbolicName=MODE_MESSAGE_STATUS_COLS +Language=English + Columns: %1 +. +MessageId=23072 SymbolicName=MODE_MESSAGE_STATUS_CODEPAGE +Language=English + Code page: %1 +. + +MessageId=23073 SymbolicName=MODE_MESSAGE_STATUS_REROUTED +Language=English + Printer output is being rerouted to serial port %1 +. + +MessageId=23074 SymbolicName=MODE_MESSAGE_STATUS_NOT_REROUTED +Language=English + Printer output is not being rerouted. +. + +MessageId=23075 SymbolicName=MODE_MESSAGE_STATUS_RATE +Language=English + Keyboard rate: %1 +. + +MessageId=23076 SymbolicName=MODE_MESSAGE_STATUS_DELAY +Language=English + Keyboard delay: %1 +. + +MessageId=23079 SymbolicName=MODE_MESSAGE_LPT_USE_CONTROL_PANEL +Language=English +To change printer settings use the Printers option in Control Panel +. + +MessageId=23080 SymbolicName=MODE_ERROR_INCORRECT_OS_VERSION +Language=English +Incorrect operating system version +. + +MessageId=23081 SymbolicName=MODE_ERROR_INVALID_DEVICE_NAME +Language=English +Illegal device name - %1 +. + +MessageId=23082 SymbolicName=MODE_ERROR_INVALID_BAUD_RATE +Language=English +Invalid baud rate specified +. + +MessageId=23083 SymbolicName=MODE_ERROR_NOT_REROUTED +Language=English +%1: not rerouted +. + +MessageId=23084 SymbolicName=MODE_ERROR_INVALID_PARAMETER +Language=English +Invalid parameter - %1 +. + +MessageId=23085 SymbolicName=MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS +Language=English +Invalid number of parameters +. + +MessageId=23086 SymbolicName=MODE_ERROR_CANNOT_ACCESS_DEVICE +Language=English +Failure to access device: %1 +. + +MessageId=23087 SymbolicName=MODE_ERROR_CODEPAGE_OPERATION_NOT_SUPPORTED +Language=English +Code page operation not supported on this device +. + +MessageId=23088 SymbolicName=MODE_ERROR_CODEPAGE_NOT_SUPPORTED +Language=English +Current keyboard does not support this code page +. + +MessageId=23089 SymbolicName=MODE_ERROR_NO_MEMORY +Language=English +Out of memory +. + +MessageId=23090 SymbolicName=MODE_ERROR_PARSE +Language=English +Parse Error +. + +MessageId=23091 SymbolicName=MODE_ERROR_EXTENDED +Language=English +Extended error %1 +. + +MessageId=23092 SymbolicName=MODE_ERROR_SERIAL_OPTIONS_NOT_SUPPORTED +Language=English +The specified options are not supported by this serial device +. + +MessageId=23093 SymbolicName=MODE_ERROR_INVALID_SCREEN_SIZE +Language=English +The screen cannot be set to the number of lines and columns specified. +. + +MessageId=23094 SymbolicName=MODE_ERROR_LPT_CANNOT_SET +Language=English +The device cannot be set to the specified number of lines and/or columns. +. + +MessageId=23095 SymbolicName=MODE_ERROR_LPT_CANNOT_ENDREROUTE +Language=English +Cannot stop printer rerouting at this time. +. + +MessageId=23096 SymbolicName=MODE_ERROR_LPT_CANNOT_REROUTE +Language=English +Cannot reroute printer output to serial device %1. +. + +MessageId=23097 SymbolicName=MODE_ERROR_INVALID_RATE +Language=English +Invalid keyboard rate +. + +MessageId=23098 SymbolicName=MODE_ERROR_INVALID_DELAY +Language=English +Invalid keyboard delay +. + +MessageId=23099 SymbolicName=MODE_ERROR_FULL_SCREEN +Language=English +The number of lines and columns cannot be changed in a full screen. +. + +MessageId=23100 SymbolicName=MODE_ERROR_INVALID_CODEPAGE +Language=English +The code page specified is not valid. +. + +MessageId=23101 SymbolicName=MODE_ERROR_NOT_SUPPORTED +Language=English +The specified option is not supported. +. + +MessageId=23110 SymbolicName=MODE_MESSAGE_USED_DEFAULT_PARITY +Language=English +Default to even parity. +. + +MessageId=23111 SymbolicName=MODE_MESSAGE_USED_DEFAULT_DATA +Language=English +Default to %1 data bits. +. + +MessageId=23112 SymbolicName=MODE_MESSAGE_USED_DEFAULT_STOP +Language=English +Default to %1 stop bits. +. + +MessageId=23113 SymbolicName=MODE_MESSAGE_COM_NO_CHANGE +Language=English +No serial port setting changed. +. + +MessageId=23114 SymbolicName=MODE_MESSAGE_NOT_NEEDED +Language=English +This operation is not necessary under Windows NT. +. + +MessageId=23115 SymbolicName=MODE_ERROR_DEVICE_UNAVAILABLE +Language=English +Device %1 is not currently available. +. + + + + + + + + + + + +;//--------------- +;// +;// NTFS messages. +;// +;//--------------- + +MessageId=24000 SymbolicName=MSG_NTFS_UNREADABLE_BOOT_SECTOR +Language=English +The first NTFS boot sector is unreadable. +Reading second NTFS boot sector instead. +. + +MessageId=24001 SymbolicName=MSG_NTFS_ALL_BOOT_SECTORS_UNREADABLE +Language=English +All NTFS boot sectors are unreadable. Cannot continue. +. + +MessageId=24002 SymbolicName=MSG_NTFS_SECOND_BOOT_SECTOR_UNWRITEABLE +Language=English +The second NTFS boot sector is unwriteable. +. + +MessageId=24003 SymbolicName=MSG_NTFS_FIRST_BOOT_SECTOR_UNWRITEABLE +Language=English +The first NTFS boot sector is unwriteable. +. + +MessageId=24004 SymbolicName=MSG_NTFS_ALL_BOOT_SECTORS_UNWRITEABLE +Language=English +All NTFS boot sectors are unwriteable. Cannot continue. +. + +MessageId=24005 SymbolicName=MSG_NTFS_FORMAT_NO_FLOPPIES +Language=English +The NTFS file system does not function on floppy disks. +. + + +;//---------------------- +;// +;// NTFS CHKDSK messages. +;// +;//---------------------- + +MessageId=26000 SymbolicName=MSG_CHK_NTFS_BAD_FRS +Language=English +Deleting corrupt file record segment %1. +. + +MessageId=26001 SymbolicName=MSG_CHK_NTFS_BAD_ATTR +Language=English +Deleting corrupt attribute record (%1, %2) +from file record segment %3. +. + +MessageId=26002 SymbolicName=MSG_CHK_NTFS_FRS_TRUNC_RECORDS +Language=English +Truncating badly linked attribute records +from file record segment %1. +. + +MessageId=26003 SymbolicName=MSG_CHK_NTFS_UNSORTED_FRS +Language=English +Sorting attribute records for file record segment %1. +. + +MessageId=26004 SymbolicName=MSG_CHK_NTFS_DUPLICATE_ATTRIBUTES +Language=English +Deleting duplicate attribute records (%1, %2) +from file record segment %3. +. + +MessageId=26005 SymbolicName=MSG_CHK_NTFS_BAD_ATTR_LIST +Language=English +Deleted corrupt attribute list for file %1. +. + +MessageId=26006 SymbolicName=MSG_CHK_NTFS_CANT_READ_ATTR_LIST +Language=English +Deleted unreadable attribute list for file %1. +. + +MessageId=26007 SymbolicName=MSG_CHK_NTFS_BAD_ATTR_LIST_ENTRY +Language=English +Deleted corrupt attribute list entry +with type code %1 in file %2. +. + +MessageId=26008 SymbolicName=MSG_CHK_NTFS_ATTR_LIST_TRUNC +Language=English +Truncating corrupt attribute list for file %1. +. + +MessageId=26009 SymbolicName=MSG_CHK_NTFS_UNSORTED_ATTR_LIST +Language=English +Sorting attribute list for file %1. +. + +MessageId=26010 SymbolicName=MSG_CHK_NTFS_UNREADABLE_MFT +Language=English +Unreadable master file table. CHKDSK aborted. +. + +MessageId=26011 SymbolicName=MSG_CHK_NTFS_BAD_MFT +Language=English +Corrupt master file table. CHKDSK aborted. +. + +MessageId=26012 SymbolicName=MSG_CHK_NTFS_BAD_ATTR_DEF_TABLE +Language=English +Corrupt Attribute Definition Table. +CHKDSK is assuming the default. +. + +MessageId=26013 SymbolicName=MSG_NTFS_CHK_NOT_NTFS +Language=English +This is not an NTFS volume. +. + +MessageId=26014 SymbolicName=MSG_CHK_NTFS_UNREADABLE_FRS +Language=English +File record segment %1 is unreadable. +. + +MessageId=26015 SymbolicName=MSG_CHK_NTFS_ORPHAN_FRS +Language=English +Deleting orphan file record segment %1. +. + +MessageId=26016 SymbolicName=MSG_CHK_NTFS_CANT_HOTFIX_SYSTEM_FILES +Language=English +Insufficient disk space to hotfix unreadable system file %1. +CHKDSK Aborted. +. + +MessageId=26017 SymbolicName=MSG_CHK_NTFS_CANT_HOTFIX +Language=English +Insufficient disk space to hotfix unreadable user file %1. +. + +MessageId=26018 SymbolicName=MSG_CHK_NTFS_BAD_FIRST_FREE +Language=English +First free byte offset corrected in file record segment %1. +. + +MessageId=26019 SymbolicName=MSG_CHK_NTFS_CORRECTING_MFT_MIRROR +Language=English +Correcting errors in the Master File Table (MFT) mirror. +. + +MessageId=26020 SymbolicName=MSG_CHK_NTFS_CANT_FIX_MFT_MIRROR +Language=English +Insufficient disk space to repair master file table (MFT) mirror. +CHKDSK aborted. +. + +MessageId=26021 SymbolicName=MSG_CHK_NTFS_CANT_ADD_BAD_CLUSTERS +Language=English +Insufficient disk space to record bad clusters. +. + +MessageId=26022 SymbolicName=MSG_CHK_NTFS_CORRECTING_MFT_DATA +Language=English +Correcting errors in the master file table's (MFT) DATA attribute. +. + +MessageId=26023 SymbolicName=MSG_CHK_NTFS_CANT_FIX_MFT +Language=English +Insufficient disk space to fix master file table (MFT). CHKDSK aborted. +. + +MessageId=26024 SymbolicName=MSG_CHK_NTFS_CORRECTING_MFT_BITMAP +Language=English +Correcting errors in the master file table's (MFT) BITMAP attribute. +. + +MessageId=26025 SymbolicName=MSG_CHK_NTFS_CANT_FIX_VOLUME_BITMAP +Language=English +Insufficient disk space to fix volume bitmap. CHKDSK aborted. +. + +MessageId=26026 SymbolicName=MSG_CHK_NTFS_CORRECTING_VOLUME_BITMAP +Language=English +Correcting errors in the Volume Bitmap. +. + +MessageId=26027 SymbolicName=MSG_CHK_NTFS_CORRECTING_ATTR_DEF +Language=English +Correcting errors in the Attribute Definition Table. +. + +MessageId=26028 SymbolicName=MSG_CHK_NTFS_CANT_FIX_ATTR_DEF +Language=English +Insufficient disk space to fix the attribute definition table. +CHKDSK aborted. +. + +MessageId=26029 SymbolicName=MSG_CHK_NTFS_CORRECTING_BAD_FILE +Language=English +Correcting errors in the Bad Clusters File. +. + +MessageId=26030 SymbolicName=MSG_CHK_NTFS_CANT_FIX_BAD_FILE +Language=English +Insufficient disk space to fix the bad clusters file. +CHKDSK aborted. +. + +MessageId=26031 SymbolicName=MSG_CHK_NTFS_CORRECTING_BOOT_FILE +Language=English +Correcting errors in the Boot File. +. + +MessageId=26032 SymbolicName=MSG_CHK_NTFS_CANT_FIX_BOOT_FILE +Language=English +Insufficient disk space to fix the boot file. +CHKDSK aborted. +. + +MessageId=26033 SymbolicName=MSG_CHK_NTFS_ADDING_BAD_CLUSTERS +Language=English +Adding %1 bad clusters to the Bad Clusters File. +. + +MessageId=26034 SymbolicName=MSG_CHK_NTFS_TOTAL_DISK_SPACE +Language=English + +%1 kilobytes total disk space. +. + +MessageId=26035 SymbolicName=MSG_CHK_NTFS_USER_FILES +Language=English +%1 kilobytes in %2 user files. +. + +MessageId=26036 SymbolicName=MSG_CHK_NTFS_INDICES_REPORT +Language=English +%1 kilobytes in %2 indexes. +. + +MessageId=26037 SymbolicName=MSG_CHK_NTFS_BAD_SECTORS_REPORT +Language=English +%1 kilobytes in bad sectors. +. + +MessageId=26038 SymbolicName=MSG_CHK_NTFS_SYSTEM_SPACE +Language=English +%1 kilobytes in use by the system. +. + +MessageId=26039 SymbolicName=MSG_CHK_NTFS_AVAILABLE_SPACE +Language=English +%1 kilobytes available on disk. + +. + +MessageId=26040 SymbolicName=MSG_CHK_NTFS_ERROR_IN_INDEX +Language=English +Correcting error in index %2 for file %1. +. + +MessageId=26041 SymbolicName=MSG_CHK_NTFS_CANT_FIX_INDEX +Language=English +Insufficient disk space to correct errors +in index %2 of file %1. +. + +MessageId=26042 SymbolicName=MSG_CHK_NTFS_BAD_INDEX +Language=English +Removing corrupt index %2 in file %1. +. + +MessageId=26043 SymbolicName=MSG_CHK_NTFS_DELETING_DIRECTORY_ENTRIES +Language=English +Deleting directory entries in %1 +. + +MessageId=26044 SymbolicName=MSG_CHK_NTFS_CANT_DELETE_ALL_DIRECTORY_ENTRIES +Language=English +CHKDSK cannot delete all corrupt directory entries. +. + +MessageId=26045 SymbolicName=MSG_CHK_NTFS_RECOVERING_ORPHANS +Language=English +CHKDSK is recovering lost files. +. + +MessageId=26046 SymbolicName=MSG_CHK_NTFS_CANT_CREATE_ORPHANS +Language=English +Insufficient disk space for CHKDSK to recover lost files. +. + +MessageId=26047 SymbolicName=MSG_CHK_NTFS_CORRECTING_ERROR_IN_DIRECTORY +Language=English +Correcting error in directory %1 +. + +MessageId=26048 SymbolicName=MSG_CHK_NTFS_BADLY_ORDERED_INDEX +Language=English +Sorting index %2 in file %1. +. + +MessageId=26049 SymbolicName=MSG_CHK_NTFS_CORRECTING_EA +Language=English +Correcting extended attribute information in file %1. +. + +MessageId=26050 SymbolicName=MSG_CHK_NTFS_DELETING_CORRUPT_EA_SET +Language=English +Deleting corrupt extended attribute set in file %1. +. + +MessageId=26051 SymbolicName=MSG_CHK_NTFS_INACCURATE_DUPLICATED_INFORMATION +Language=English +Incorrect duplicate information in file %1. +. + +MessageId=26052 SymbolicName=MSG_CHK_NTFS_CREATING_ROOT_DIRECTORY +Language=English +CHKDSK is creating new root directory. +. + +MessageId=26053 SymbolicName=MSG_CHK_NTFS_CANT_CREATE_ROOT_DIRECTORY +Language=English +Insufficient disk space to create new root directory. +. + +MessageId=26054 SymbolicName=MSG_CHK_NTFS_RECOVERING_ORPHAN +Language=English +Recovering orphaned file %1 into directory file %2. +. + +MessageId=26055 SymbolicName=MSG_CHK_NTFS_CANT_RECOVER_ORPHAN +Language=English +Insufficient disk space to recover lost data. +. + +MessageId=26056 SymbolicName=MSG_CHK_NTFS_TOO_MANY_ORPHANS +Language=English +Too much lost data to recover it all. +. + +MessageId=26057 SymbolicName=MSG_CHK_NTFS_USING_MFT_MIRROR +Language=English +Fixing critical master file table (MFT) files with MFT mirror. +. + +MessageId=26058 SymbolicName=MSG_CHK_NTFS_MINOR_CHANGES_TO_FRS +Language=English +Correcting a minor error in file %1. +. + +MessageId=26059 SymbolicName=MSG_CHK_NTFS_BAD_UPCASE_TABLE +Language=English +Corrupt uppercase Table. +Using current system uppercase Table. +. + +MessageId=26060 SymbolicName=MSG_CHK_NTFS_CANT_GET_UPCASE_TABLE +Language=English +Cannot retrieve current system uppercase table. +CHKDSK aborted. +. + +MessageId=26061 SymbolicName=MSG_CHK_NTFS_MINOR_MFT_BITMAP_ERROR +Language=English +CHKDSK discovered free space marked as allocated in the +master file table (MFT) bitmap. +. + +MessageId=26062 SymbolicName=MSG_CHK_NTFS_MINOR_VOLUME_BITMAP_ERROR +Language=English +CHKDSK discovered free space marked as allocated in the volume bitmap. +. + +MessageId=26063 SymbolicName=MSG_CHK_NTFS_CORRECTING_UPCASE_FILE +Language=English +Correcting errors in the uppercase file. +. + +MessageId=26064 SymbolicName=MSG_CHK_NTFS_CANT_FIX_UPCASE_FILE +Language=English +Insufficient disk space to fix the uppercase file. +CHKDSK aborted. +. + +MessageId=26065 SymbolicName=MSG_CHK_NTFS_DELETING_INDEX_ENTRY +Language=English +Deleting index entry %3 in index %2 of file %1. +. + +MessageId=26066 SymbolicName=MSG_CHK_NTFS_SLASH_V_NOT_SUPPORTED +Language=English +Verbose output not supported by NTFS CHKDSK. +. + +MessageId=26067 SymbolicName=MSG_CHK_NTFS_READ_ONLY_MODE +Language=English +Warning! F parameter not specified +Running CHKDSK in read-only mode. +. + +MessageId=26068 SymbolicName=MSG_CHK_NTFS_ERRORS_FOUND +Language=English + +Errors found. CHKDSK cannot continue in read-only mode. +. + +MessageId=26069 SymbolicName=MSG_CHK_NTFS_CYCLES_IN_DIR_TREE +Language=English +Correcting cycles in directory tree. +. + +MessageId=26070 SymbolicName=MSG_CHK_NTFS_MINOR_FILE_NAME_ERRORS +Language=English +Correcting minor file name errors in file %1. +. + +MessageId=26071 SymbolicName=MSG_CHK_NTFS_MISSING_DATA_ATTRIBUTE +Language=English +Inserting data attribute into file %1. +. + +MessageId=26072 SymbolicName=MSG_CHK_NTFS_CANT_PUT_DATA_ATTRIBUTE +Language=English +Insufficient disk space to insert missing data attribute. +. + +MessageId=26073 SymbolicName=MSG_CHK_NTFS_CORRECTING_LOG_FILE +Language=English +Correcting errors in the Log File. +. + +MessageId=26074 SymbolicName=MSG_CHK_NTFS_CANT_FIX_LOG_FILE +Language=English +Insufficient disk space to fix the log file. +CHKDSK aborted. +. + +MessageId=26075 SymbolicName=MSG_CHK_NTFS_CHECKING_FILES +Language=English + +CHKDSK is verifying files... +. + +MessageId=26076 SymbolicName=MSG_CHK_NTFS_CHECKING_INDICES +Language=English +CHKDSK is verifying indexes... +. + +MessageId=26077 SymbolicName=MSG_CHK_NTFS_INDEX_VERIFICATION_COMPLETED +Language=English +Index verification completed. +. + +MessageId=26078 SymbolicName=MSG_CHK_NTFS_FILE_VERIFICATION_COMPLETED +Language=English +File verification completed. +. + +MessageId=26079 SymbolicName=MSG_CHK_NTFS_CHECKING_SECURITY +Language=English +CHKDSK is verifying security descriptors... +. + +MessageId=26080 SymbolicName=MSG_CHK_NTFS_SECURITY_VERIFICATION_COMPLETED +Language=English +Security descriptor verification completed. +. + +MessageId=26081 SymbolicName=MSG_CHK_NTFS_INVALID_SECURITY_DESCRIPTOR +Language=English +Replacing missing or invalid security descriptor for file %1. +. + +MessageId=26082 SymbolicName=MSG_CHK_NTFS_CANT_FIX_SECURITY +Language=English +Insufficient disk space for security descriptor for file %1. +. + +MessageId=26083 SymbolicName=MSG_CHK_NTFS_WRONG_VERSION +Language=English +This volume cannot be checked with this version of UNTFS.DLL. +. + +MessageId=26084 SymbolicName=MSG_CHK_NTFS_DELETING_GENERIC_INDEX_ENTRY +Language=English +Deleting an index entry from index %2 of file %1. +. + +MessageId=26085 SymbolicName=MSG_CHK_NTFS_CORRECTING_CROSS_LINK +Language=English +Correcting cross-link for file %1. +. + +MessageId=26086 SymbolicName=MSG_CHK_NTFS_VERIFYING_FILE_DATA +Language=English +CHKDSK is verifying file data... +. + +MessageId=26087 SymbolicName=MSG_CHK_NTFS_VERIFYING_FILE_DATA_COMPLETED +Language=English +File data verification completed. +. + +MessageId=26088 SymbolicName=MSG_CHK_NTFS_TOO_MANY_FILE_NAMES +Language=English +Index entries referencing file %1 will not be validated +because this file contains too many file names. +. + +MessageId=26089 SymbolicName=MSG_CHK_NTFS_RESETTING_LSNS +Language=English +CHKDSK is resetting recovery information... +. + +MessageId=26090 SymbolicName=MSG_CHK_NTFS_RESETTING_LOG_FILE +Language=English +CHKDSK is resetting the log file. +. + +MessageId=26091 SymbolicName=MSG_CHK_NTFS_RESIZING_LOG_FILE +Language=English +CHKDSK is adjusting the size of the log file. +. + +MessageId=26092 SymbolicName=MSG_CHK_NTFS_RESIZING_LOG_FILE_FAILED +Language=English +CHKDSK was unable to adjust the size of the log file. +. + +MessageId=26093 SymbolicName=MSG_CHK_NTFS_ADJUSTING_INSTANCE_TAGS +Language=English +Adjusting instance tags to prevent rollover on file %1. +. + +MessageId=26094 SymbolicName=MSG_CHK_NTFS_FIX_ATTR +Language=English +Fixing corrupt attribute record (%1, %2) +in file record segment %3. +. + +MessageId=26095 SymbolicName=MSG_CHK_NTFS_LOGFILE_SPACE +Language=English +%1 kilobytes occupied by the logfile. +. + +MessageId=26096 SymbolicName=MSG_CHK_READABLE_FRS_UNWRITEABLE +Language=English +Readable file record segment %1 is not writeable. +. + +MessageId=26097 SymbolicName=MSG_CHK_NTFS_DEFAULT_QUOTA_ENTRY_MISSING +Language=English +Inserting default quota record into index %2 in file %1. +. + +MessageId=26098 SymbolicName=MSG_CHK_NTFS_CREATING_DEFAULT_SECURITY_DESCRIPTOR +Language=English +Creating a default security descriptor. +. + +MessageId=26099 SymbolicName=MSG_CHK_NTFS_CANNOT_SET_QUOTA_FLAG_OUT_OF_DATE +Language=English +Unable to set the quota out of date flag. +. + +MessageId=26100 SymbolicName=MSG_CHK_NTFS_REPAIRING_INDEX_ENTRY +Language=English +Repairing an index entry in index %2 of file %1. +. + +MessageId=26101 SymbolicName=MSG_CHK_NTFS_INSERTING_INDEX_ENTRY +Language=English +Inserting an index entry into index %2 of file %1. +. + +MessageId=26102 SymbolicName=MSG_CHK_NTFS_CANT_FIX_SECURITY_DATA_STREAM +Language=English +Insufficient disk space to fix the security descriptors data stream. +. + +MessageId=26103 SymbolicName=MSG_CHK_NTFS_CANT_FIX_ATTRIBUTE +Language=English +Unable to write to attribute %1 of file %2. +. + +MessageId=26104 SymbolicName=MSG_CHK_NTFS_CANT_READ_SECURITY_DATA_STREAM +Language=English +Unable to read the security descriptors data stream. +. + +MessageId=26105 SymbolicName=MSG_CHK_NTFS_FIXING_SECURITY_DATA_STREAM_MIRROR +Language=English +Fixing mirror copy of the security descriptors data stream. +. + +MessageId=26106 SymbolicName=MSG_CHK_NTFS_FIXING_COLLATION_RULE +Language=English +Fixing collation rule value for index %1 of file %2. +. + +MessageId=26107 SymbolicName=MSG_CHK_NTFS_CREATE_INDEX +Language=English +Creating index %1 for file %2. +. + +MessageId=26108 SymbolicName=MSG_CHK_NTFS_REPAIRING_SECURITY_FRS +Language=English +Repairing the security file record segment. +. + +MessageId=26109 SymbolicName=MSG_CHK_NTFS_REPAIRING_UNREADABLE_SECURITY_DATA_STREAM +Language=English +Repairing the unreadable security descriptors data stream. +. + +MessageId=26110 SymbolicName=MSG_CHK_NTFS_CANT_FIX_OBJID +Language=English +Insufficient disk space to fix the object id file. +. + +MessageId=26111 SymbolicName=MSG_CHK_NTFS_CANT_FIX_QUOTA +Language=English +Insufficient disk space to fix the quota file. +. + +MessageId=26112 SymbolicName=MSG_CHK_NTFS_CREATE_OBJID +Language=English +Creating object id file. +. + +MessageId=26113 SymbolicName=MSG_CHK_NTFS_CREATE_QUOTA +Language=English +Creating quota file. +. + +MessageId=26114 SymbolicName=MSG_CHK_NTFS_FIX_FLAGS +Language=English +Fixing flags for file record segment %1. +. + +MessageId=26115 SymbolicName=MSG_CHK_NTFS_CANT_FIX_SYSTEM_FILE +Language=English +Unable to correct an error in system file %1. +. + +MessageId=26116 SymbolicName=MSG_CHK_NTFS_CANT_CREATE_INDEX +Language=English +Unable to create index %1 for file %2. +. + +MessageId=26117 SymbolicName=MSG_CHK_NTFS_INVALID_SECURITY_ID +Language=English +Replacing invalid security id with default security id for file %1. +. + +MessageId=26118 SymbolicName=MSG_CHK_NTFS_MULTIPLE_QUOTA_FILE +Language=English +Multiple quota file found. Ignoring extra quota files. +. + +MessageId=26119 SymbolicName=MSG_CHK_NTFS_MULTIPLE_OBJECTID_FILE +Language=English +Multiple Object ID file found. Ignoring extra object id files. +. + +MessageId=26120 SymbolicName=MSG_CHK_NTFS_TOO_BIG_LOGFILE_SIZE +Language=English +The size specified for the logfile is too big. +. + +;//--------------- +;// +;// Common messages. +;// +;//--------------- + +MessageId=30000 SymbolicName=MSG_UTILS_HELP +Language=English +There is no help for this utility. +. + +MessageId=30001 SymbolicName=MSG_UTILS_ERROR_FATAL +Language=English +Critical error encountered. +. + +MessageId=30002 SymbolicName=MSG_UTILS_ERROR_INVALID_VERSION +Language=English +Incorrect Windows NT version +. + +;//---------------------- +;// +;// Convert messages. +;// +;//---------------------- + +MessageId=30100 SymbolicName=MSG_CONV_USAGE +Language=English +Converts FAT volumes to NTFS. + +CONVERT drive: /FS:NTFS [/V] + + drive Specifies the drive to convert to NTFS. Note that + you cannot convert the current drive. + /FS:NTFS Specifies to convert the volume to NTFS. + /V Specifies that Convert should be run in verbose mode. +. + +MessageId=30101 SymbolicName=MSG_CONV_INVALID_PARAMETER +Language=English +Invalid Parameter - %1 +. + +MessageId=30102 SymbolicName=MSG_CONV_NO_FILESYSTEM_SPECIFIED +Language=English +Must specify a file system +. + +MessageId=30103 SymbolicName=MSG_CONV_INVALID_DRIVE +Language=English +Invalid drive - %1 +. + +MessageId=30104 SymbolicName=MSG_CONV_CANT_NETWORK +Language=English +Cannot CONVERT a network drive. +. + +MessageId=30105 SymbolicName=MSG_CONV_INVALID_FILESYSTEM +Language=English +%1 is not a valid file system +. + +MessageId=30106 SymbolicName=MSG_CONV_CONVERSION_NOT_AVAILABLE +Language=English +Cannot convert %1 volumes to %2. +. + +MessageId=30107 SymbolicName=MSG_CONV_WILL_CONVERT_ON_REBOOT +Language=English +The conversion will take place automatically the next time the +system restarts. +. + +MessageId=30108 SymbolicName=MSG_CONV_CANNOT_FIND_SYSTEM_DIR +Language=English +Cannot determine location of system directory. +. + +MessageId=30109 SymbolicName=MSG_CONV_CANNOT_FIND_FILE +Language=English +Could not find file %1 +Make sure that the required file exists and try again. +. + +MessageId=30110 SymbolicName=MSG_CONV_CANNOT_SCHEDULE +Language=English +Could not schedule an automatic conversion of the drive. +. + +MessageId=30111 SymbolicName=MSG_CONV_ALREADY_SCHEDULED +Language=English +The %1 drive is already scheduled for an automatic +conversion. +. + +MessageId=30112 SymbolicName=MSG_CONV_CONVERTING +Language=English +Converting drive %1 to %2 +. + +MessageId=30113 SymbolicName=MSG_CONV_ALREADY_CONVERTED +Language=English +Drive %1 is already %2. +. + +MessageId=30114 SymbolicName=MSG_CONV_CANNOT_AUTOCHK +Language=English +Could not check volume %1 for errors. +The conversion to %2 did not take place. +. + +MessageId=30115 SymbolicName=MSG_CONV_SLASH_C_INVALID +Language=English +The /C option is only valid with the /UNCOMPRESS option. +. + +MessageId=30120 SymbolicName=MSG_CONV_CHECKING_SPACE +Language=English +Determining disk space required for filesystem conversion +. + +MessageId=30121 SymbolicName=MSG_CONV_KBYTES_TOTAL +Language=English +Total disk space: %1 kilobytes. +. + +MessageId=30122 SymbolicName=MSG_CONV_KBYTES_FREE +Language=English +Free space on volume: %1 kilobytes. +. + +MessageId=30123 SymbolicName=MSG_CONV_KBYTES_NEEDED +Language=English +Space required for conversion: %1 kilobytes. +. + +MessageId=30124 SymbolicName=MSG_CONV_CONVERTING_FS +Language=English +Converting file system +. + +MessageId=30125 SymbolicName=MSG_CONV_PERCENT_COMPLETE +Language=English +%1 percent completed. %r%0 +. + +MessageId=30126 SymbolicName=MSG_CONV_CONVERSION_COMPLETE +Language=English +Conversion complete +. + +MessageId=30127 SymbolicName=MSG_CONV_CONVERSION_FAILED +Language=English +The conversion failed. +%1 was not converted to %2 +. + +MessageId=30150 SymbolicName=MSG_CONV_CANNOT_READ +Language=English +Error during disk read +. + +MessageId=30151 SymbolicName=MSG_CONV_CANNOT_WRITE +Language=English +Error during disk write +. + +MessageId=30152 SymbolicName=MSG_CONV_NO_MEMORY +Language=English +Insufficient Memory +. + +MessageId=30153 SymbolicName=MSG_CONV_NO_DISK_SPACE +Language=English +Insufficient disk space for conversion +. + +MessageId=30154 SymbolicName=MSG_CONV_CANNOT_RELOCATE +Language=English +Cannot relocate existing file system structures +. + +MessageId=30155 SymbolicName=MSG_CONV_CANNOT_CREATE_ELEMENTARY +Language=English +Cannot create the elementary file system structures. +. + +MessageId=30156 SymbolicName=MSG_CONV_ERROR_READING_DIRECTORY +Language=English +Error reading directory %1 +. + +MessageId=30157 SymbolicName=MSG_CONV_CANNOT_CONVERT_DIRECTORY +Language=English +Error converting directory %1 +. + +MessageId=30158 SymbolicName=MSG_CONV_CANNOT_CONVERT_FILE +Language=English +Error converting file %1 +. + +MessageId=30159 SymbolicName=MSG_CONV_CANNOT_CONVERT_DATA +Language=English +Error converting file data +. + +MessageId=30160 SymbolicName=MSG_CONV_CANNOT_CONVERT_EA +Language=English +Cannot convert an extended attribute +. + +MessageId=30161 SymbolicName=MSG_CONV_NO_EA_FILE +Language=English +A file contains extended attributes, +but the extended attribute file was not found. +. + +MessageId=30162 SymbolicName=MSG_CONV_CANNOT_MAKE_INDEX +Language=English +Cannot locate or create an NTFS index. +. + +MessageId=30163 SymbolicName=MSG_CONV_CANNOT_CONVERT_VOLUME +Language=English +This volume cannot be converted to %1. +Possible causes are: + 1.- Bad sectors in required areas of the volume. + 2.- %2 structures in areas required by %1. +. + +MessageId=30164 SymbolicName=MSG_CONVERT_ON_REBOOT_PROMPT +Language=English +Convert cannot gain exclusive access to the %1 drive, +so it cannot convert it now. Would you like to +schedule it to be converted the next time the +system restarts (Y/N)? %0 +. + +MessageId=30165 SymbolicName=MSG_CONVERT_FILE_SYSTEM_NOT_ENABLED +Language=English +The %1 file system is not enabled. The volume +will not be converted. +. + +MessageId=30166 SymbolicName=MSG_CONVERT_UNSUPPORTED_SECTOR_SIZE +Language=English +Unsupported sector size. Cannot convert volume to %1. +. + +MessageId=30167 SymbolicName=MSG_CONVERT_REBOOT +Language=English + +The file system has been converted. +Please wait while the system restarts. +. + +MessageId=30168 SymbolicName=MSG_CONV_ARC_SYSTEM_PARTITION +Language=English +The specified drive is the system partition on an ARC-compliant +system; its file system cannot be converted +. + +MessageId=30169 SymbolicName=MSG_CONV_GEOMETRY_MISMATCH +Language=English +The disk geometry recorded in the volume's Bios Parameter +Block differs from the geometry reported by the driver. +This volume cannot be converted to %1. +. + +MessageId=30170 SymbolicName=MSG_CONV_NAME_TABLE_NOT_SUPPORTED +Language=English +Name table translation is not available for conversion to %1. +. + +MessageId=30185 SymbolicName=MSG_CONV_VOLUME_TOO_FRAGMENTED +Language=English +The volume is too fragmented to be converted to NTFS. +. + +;//---------------------- +;// +;// Dblspace-specific Convert messages (cudbfs) +;// +;//---------------------- + +MessageId=30190 SymbolicName=MSG_DBLCONV_CANT_CREATE +Language=English +Cannot create the file %1 +. + +MessageId=30191 SymbolicName=MSG_DBLCONV_CVF_CORRUPT +Language=English +The Compressed Volume File is corrupt -- run SCANDISK +. + +MessageId=30192 SymbolicName=MSG_DBLCONV_CREATE_FILE +Language=English +Creating %1 +. + +MessageId=30193 SymbolicName=MSG_DBLCONV_FILE_CONFLICT +Language=English +A file in the Compressed Volume File would conflict with %1 +. + +MessageId=30194 SymbolicName=MSG_DBLCONV_NOT_ENOUGH_SPACE +Language=English +Not enough free space on host; need %1 clusters, have %2 +. + +MessageId=30195 SymbolicName=MSG_DBLCONV_AGAIN +Language=English +After the machine is rebooted, run CONVERT /UNCOMPRESS again. +. + +MessageId=30196 SymbolicName=MSG_DBLCONV_SPACE_EXHAUSTED +Language=English +All disk space on the host volume has been exhausted. Please delete +files from the host volume and run CONVERT /UNCOMPRESS again. +. + + +;//---------------------- +;// +;// DC messages. +;// +;//---------------------- + +MessageId=30200 SymbolicName=MSG_DISKCOPY_USAGE +Language=English +Usage: DC Src Dst [/v] [/h] +. + +MessageId=30201 SymbolicName=MSG_DISKCOPY_NO_MEMORY +Language=English +Out of memory +. + +MessageId=30202 SymbolicName=MSG_DISKCOPY_INVALID_PARAMETER +Language=English +Invalid parameter - %1 +. + + + + +;//---------------------- +;// +;// KEYB messages. +;// +;//---------------------- + +MessageId=30300 SymbolicName=MSG_KEYB_EXTENDED_ERROR +Language=English +Extended Error %1 +. + +MessageId=30301 SymbolicName=MSG_KEYB_TOO_MANY_PARAMETERS +Language=English +Too many parameters +. + +MessageId=30302 SymbolicName=MSG_KEYB_MISSING_PARAMETER +Language=English +Required parameter missing +. + +MessageId=30303 SymbolicName=MSG_KEYB_INVALID_SWITCH +Language=English +Invalid switch +. + +MessageId=30305 SymbolicName=MSG_KEYB_VALUE_OUT_OF_RANGE +Language=English +Parameter value not in allowed range +. + +MessageId=30307 SymbolicName=MSG_KEYB_INVALID_PARAMETER +Language=English +Invalid parameter +. + +MessageId=30308 SymbolicName=MSG_KEYB_PARSE_ERROR +Language=English +Parse Error %1 +. + +MessageId=30309 SymbolicName=MSG_KEYB_INCORRECT_VERSION +Language=English +Incorrect Windows NT version +. + +MessageId=30310 SymbolicName=MSG_KEYB_KEYBOARD_CODE +Language=English +Current keyboard code: %1 +. + +MessageId=30311 SymbolicName=MSG_KEYB_KEYBOARD_LAYOUT +Language=English +There is no two-letter keyboard code for the current +keyboard layout. + +Current keyboard Layout: Language %1 Sublanguage %2 +. + +MessageId=30312 SymbolicName=MSG_KEYB_KEYBOARD_ID +Language=English +Current keyboard ID: %1 +. + +MessageId=30313 SymbolicName=MSG_KEYB_CODE_PAGE +Language=English +code page: %1 +. + +MessageId=30314 SymbolicName=MSG_KEYB_CON_CODE_PAGE +Language=English +Current CON code page: %1 +. + +MessageId=30315 SymbolicName=MSG_KEYB_INVALID_CODE +Language=English +Invalid keyboard code specified +. + +MessageId=30316 SymbolicName=MSG_KEYB_INVALID_ID +Language=English +Invalid keyboard ID specified +. + +MessageId=30317 SymbolicName=MSG_KEYB_INVALID_CODE_PAGE +Language=English +Invalid code page specified +. +MessageId=30318 SymbolicName=MSG_KEYB_BAD_REGISTRY +Language=English +Keyboard Layout information missing from Registry +. + +MessageId=30327 SymbolicName=MSG_KEYB_USAGE +Language=English +Configures a keyboard for a specific language. + +KEYB [xx[,[yyy][,[drive:][path]filename]]] [/E] [/ID:nnn] + + xx Specifies a two-letter keyboard code. + yyy Specifies a console code page. + [drive:][path]filename Ignored + /E Ignored + /ID:nnn Ignored + +. + + +;//---------------------- +;// +;// CHCP messages. +;// +;//---------------------- + +MessageId=30350 SymbolicName=MSG_CHCP_INVALID_PARAMETER +Language=English +Parameter format not correct - %1 +. + +MessageId=30354 SymbolicName=MSG_CHCP_ACTIVE_CODEPAGE +Language=English +Active code page: %1 +. + +MessageId=30355 SymbolicName=MSG_CHCP_INVALID_CODEPAGE +Language=English +Invalid code page +. + +MessageId=30356 SymbolicName=MSG_CHCP_USAGE +Language=English +Displays or sets the active code page number. + +CHCP [nnn] + + nnn Specifies a code page number. + +Type CHCP without a parameter to display the active code page number. +. + +MessageId=30357 SymbolicName=MSG_CHCP_INTERNAL_ERROR +Language=English +Internal error. +. + +;//---------------- +;// +;// DOSKEY messages +;// +;//---------------- + + +MessageId=30503 SymbolicName=MSG_DOSKEY_INVALID_MACRO_DEFINITION +Language=English +Invalid macro definition. +. + +MessageId=30504 SymbolicName=MSG_DOSKEY_HELP +Language=English +Edits command lines, recalls Windows NT commands, and creates macros. + +DOSKEY [/REINSTALL] [/LISTSIZE=size] [/MACROS[:ALL | :exename]] + [/HISTORY] [/INSERT | /OVERSTRIKE] [/EXENAME=exename] [/MACROFILE=filename] + [macroname=[text]] + + /REINSTALL Installs a new copy of Doskey. + /LISTSIZE=size Sets size of command history buffer. + /MACROS Displays all Doskey macros. + /MACROS:ALL Displays all Doskey macros for all executables which have + Doskey macros. + /MACROS:exename Displays all Doskey macros for the given executable. + /HISTORY Displays all commands stored in memory. + /INSERT Specifies that new text you type is inserted in old text. + /OVERSTRIKE Specifies that new text overwrites old text. + /EXENAME=exename Specifies the executable. + /MACROFILE=filename Specifies a file of macros to install. + macroname Specifies a name for a macro you create. + text Specifies commands you want to record. + +UP and DOWN ARROWS recall commands; ESC clears command line; F7 displays +command history; ALT+F7 clears command history; F8 searches command +history; F9 selects a command by number; ALT+F10 clears macro definitions. + +The following are some special codes in Doskey macro definitions: +$T Command separator. Allows multiple commands in a macro. +$1-$9 Batch parameters. Equivalent to %%1-%%9 in batch programs. +$* Symbol replaced by everything following macro name on command line. +. + +MessageId=30505 SymbolicName=MSG_DOSKEY_CANT_DO_BUFSIZE +Language=English +To specify the size of the command history buffer under Window NT, +use the /listsize switch which sets the number of commands to remember. +. + +MessageId=30506 SymbolicName=MSG_DOSKEY_CANT_SIZE_LIST +Language=English +Insufficient memory to grow DOSKEY list. +. + + +;//---------------- +;// +;// SUBST messages +;// +;//---------------- + + +MessageId=30507 SymbolicName=MSG_SUBST_INFO +Language=English +Associates a path with a drive letter. + +. + +MessageId=30508 SymbolicName=MSG_SUBST_ALREADY_SUBSTED +Language=English +Drive already SUBSTed +. + +MessageId=30509 SymbolicName=MSG_SUBST_USAGE +Language=English +SUBST [drive1: [drive2:]path] +SUBST drive1: /D + + drive1: Specifies a virtual drive to which you want to assign a path. + [drive2:]path Specifies a physical drive and path you want to assign to + a virtual drive. + /D Deletes a substituted (virtual) drive. + +Type SUBST with no parameters to display a list of current virtual drives. +. + +MessageId=30510 SymbolicName=MSG_SUBST_SUBSTED_DRIVE +Language=English +%1: => %2 +. + +MessageId=30511 SymbolicName=MSG_SUBST_INVALID_PARAMETER +Language=English +Invalid parameter - %1 +. + +MessageId=30512 SymbolicName=MSG_SUBST_TOO_MANY_PARAMETERS +Language=English +Incorrect number of parameters - %1 +. + +MessageId=30513 SymbolicName=MSG_SUBST_PATH_NOT_FOUND +Language=English +Path not found - %1 +. + +MessageId=30514 SymbolicName=MSG_SUBST_ACCESS_DENIED +Language=English +Access denied - %1 +. + + +;//---------------- +;// +;// CHKNTFS messages +;// +;//---------------- + +MessageId=30520 SymbolicName=MSG_CHKNTFS_INVALID_FORMAT +Language=English +CHKNTFS: Incorrect command-line format. +. + +MessageId=30521 SymbolicName=MSG_CHKNTFS_INVALID_SWITCH +Language=English +Invalid parameter - %1 +. + +MessageId=30522 SymbolicName=MSG_CHKNTFS_NO_WILDCARDS +Language=English +CHKNTFS: drive specifiers may not contain wildcards. +. + +MessageId=30523 SymbolicName=MSG_CHKNTFS_USAGE +Language=English +CHKNTFS drive: [...] +CHKNTFS /D +CHKNTFS /X drive: [...] +CHKNTFS /C drive: [...] + + drive: Specifies a drive letter. + /D Restores the machine to the default behavior; all drives are + checked at boot time and chkdsk is run on those that are dirty. + This undoes the effect of the /X option. + /X Excludes a drive from the default boot-time check. Excluded + drives are not accumulated between command invocations. + /C Schedules chkdsk to be run at the next reboot. + +If no switches are specified, CHKNTFS will display the status of the +dirty bit for each drive. +. + +MessageId=30524 SymbolicName=MSG_CHKNTFS_ARGS_CONFLICT +Language=English +Specify only one of /D, /X, and /C. +. + +MessageId=30525 SymbolicName=MSG_CHKNTFS_REQUIRES_DRIVE +Language=English +You must specify at least one drive name. +. + +MessageId=30526 SymbolicName=MSG_CHKNTFS_BAD_ARG +Language=English +%1 is not a drive letter. +. + +MessageId=30527 SymbolicName=MSG_CHKNTFS_CANNOT_CHECK +Language=English +Cannot query state of drive %1 +. + +MessageId=30528 SymbolicName=MSG_CHKNTFS_DIRTY +Language=English +%1 is dirty. You may use the /C option to schedule chkdsk for + this drive. +. + +MessageId=30529 SymbolicName=MSG_CHKNTFS_CLEAN +Language=English +%1 is not dirty. +. + +MessageId=30530 SymbolicName=MSG_CHKNTFS_NONEXISTENT_DRIVE +Language=English +Drive %1 does not exist. +. + +MessageId=30531 SymbolicName=MSG_CHKNTFS_NO_NETWORK +Language=English +CHKNTFS cannot be used for the network drive %1. +. + +MessageId=30532 SymbolicName=MSG_CHKNTFS_NO_CDROM +Language=English +CHKNTFS cannot be used for the cdrom drive %1. +. + +MessageId=30533 SymbolicName=MSG_CHKNTFS_NO_RAMDISK +Language=English +CHKNTFS cannot be used for the ram disk %1. +. diff --git a/private/utils/ulib/src/screen.cxx b/private/utils/ulib/src/screen.cxx new file mode 100644 index 000000000..24ee4c384 --- /dev/null +++ b/private/utils/ulib/src/screen.cxx @@ -0,0 +1,1998 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + screen.cxx + +Abstract: + + This module contains the definitions of the member functions + of SCREEN class. + +Author: + + Jaime Sasson (jaimes) 24-Mar-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "stream.hxx" +#include "screen.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR ( SCREEN, STREAM, ULIB_EXPORT ); + +DEFINE_EXPORTED_CAST_MEMBER_FUNCTION( SCREEN, ULIB_EXPORT ); + + +ULIB_EXPORT +SCREEN::~SCREEN ( + ) + +/*++ + +Routine Description: + + Destroy a SCREEN (closes the screen handle). + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + CloseHandle( _ScreenHandle ); +} + + + +BOOLEAN +SCREEN::Initialize( + IN BOOLEAN CurrentActiveScreen, + IN USHORT NumberOfRows, + IN USHORT NumberOfColumns, + IN USHORT TextAttribute, + IN BOOLEAN ExpandAsciiControlSequence, + IN BOOLEAN WrapAtEndOfLine + ) + +/*++ + +Routine Description: + + Initializes an object of type SCREEN. + +Arguments: + + CurrentActiveScreen - Indicates if the client wants to use the screen + currently displayed (TRUE), or if a new screen + buffer is to be created (FALSE). + + NumberOfRows - Number of rows in the screen. + + NumberOfColumns - Number of columns in the screen. + + TextAttribute - Indicates the default text attribute. + + ExpandAsciiControlSequence - Indicates if expansion of ASCII control + sequences is allowed. + + WrapAtEndOfLine - Indicates if wrap at the end of a line is allowed. + +Return Value: + + BOOLEAN - Indicates if the initialization succeeded. + + +--*/ + + +{ + + + if( CurrentActiveScreen ) { + _ScreenHandle = CreateFile( (LPWSTR)L"CONOUT$", + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL ); + } else { + _ScreenHandle = CreateConsoleScreenBuffer(GENERIC_WRITE | GENERIC_READ, + 0, + NULL, + CONSOLE_TEXTMODE_BUFFER, + NULL ); + } + + + if( _ScreenHandle == INVALID_HANDLE_VALUE ) { + return( FALSE ); + } + + if( !GetConsoleMode( _ScreenHandle, (LPDWORD)&_ScreenMode ) ) { + return( FALSE ); + } + if( ExpandAsciiControlSequence ) { + _ScreenMode |= ENABLE_PROCESSED_OUTPUT; + } else { + _ScreenMode &= ~ENABLE_PROCESSED_OUTPUT; + } + if( WrapAtEndOfLine ) { + _ScreenMode |= ENABLE_WRAP_AT_EOL_OUTPUT; + } else { + _ScreenMode &= ~ENABLE_WRAP_AT_EOL_OUTPUT; + } + if( !ChangeScreenSize( NumberOfRows, NumberOfColumns ) ) { + return( FALSE ); + } + if( !ChangeTextAttribute( TextAttribute ) ) { + return( FALSE ); + } + if( !SetConsoleMode( _ScreenHandle, _ScreenMode ) ) { + return( FALSE ); + } + return( STREAM::Initialize() ); +} + + + +ULIB_EXPORT +BOOLEAN +SCREEN::Initialize( + ) + +/*++ + +Routine Description: + + Initializes an object of type SCREEN with default values. + This object will access the screen currently active, and all + values such as number of rows, columns, attributes, and mode + will be the ones defined in the currently active screen. + + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the initialization succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + _ScreenHandle = CreateFile( (LPWSTR)L"CONOUT$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL ); + if( _ScreenHandle == (HANDLE)-1 ) { + return( FALSE ); + } + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + if( !GetConsoleMode( _ScreenHandle, (LPDWORD)&_ScreenMode ) ) { + return( FALSE ); + } + _TextAttribute = ScreenBufferInfo.wAttributes; + return( STREAM::Initialize() ); +} + + + + +ULIB_EXPORT +BOOLEAN +SCREEN::ChangeScreenSize( + IN USHORT NumberOfRows, + IN USHORT NumberOfColumns, + OUT PBOOLEAN IsFullScreen + ) + +/*++ + +Routine Description: + + Changes the screen buffer size to the specified number of rows and + columns. And sets the window size accordingly. + +Arguments: + + NumberOfRows - Number of rows in the screen. + + NumberOfColumns - Number of columns in the screen. + + IsFullScreen - TRUE if in full screen mode. + + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + SMALL_RECT ScreenRect; + COORD ScreenSize; + COORD LargestScreenSize; + USHORT MaxRows; + USHORT MaxCols; + BOOLEAN WindowSet = FALSE; + + // + // Clear the screen + // + MoveCursorTo(0, 0); + EraseScreen(); + + if ( IsFullScreen ) { + *IsFullScreen = FALSE; + } + + // + // We obtain the current screen information. + // + if ( GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + + // + // Set the Window Size. The new size is the minimum of the + // buffer size or the screen size. + // + LargestScreenSize = GetLargestConsoleWindowSize( _ScreenHandle ); + + if ( (LargestScreenSize.X == 0) && (LargestScreenSize.Y == 0) ) { + + if ( IsFullScreen && (GetLastError() == ERROR_FULLSCREEN_MODE) ) { + *IsFullScreen = TRUE; + } + return FALSE; + } + + // + // If the desired window size is smaller than the current window + // size, we have to resize the current window first. (The buffer + // size cannot be smaller than the window size) + // + if ( ( NumberOfRows < (USHORT) + (ScreenBufferInfo.srWindow.Bottom - + ScreenBufferInfo.srWindow.Top + 1) ) || + ( NumberOfColumns < (USHORT) + (ScreenBufferInfo.srWindow.Right - + ScreenBufferInfo.srWindow.Left + 1) ) ) { + + + // + // Set the window to a size that will fit in the current + // screen buffer and that is no bigger than the size to + // which we want to grow the screen buffer or the largest window + // size. + // + MaxRows = (USHORT)min( (int)NumberOfRows, (int)(ScreenBufferInfo.dwSize.Y) ); + MaxRows = (USHORT)min( (int)MaxRows, (int)LargestScreenSize.Y ); + MaxCols = (USHORT)min( (int)NumberOfColumns, (int)(ScreenBufferInfo.dwSize.X) ); + MaxCols = (USHORT)min( (int)MaxCols, (int)LargestScreenSize.X ); + + ScreenRect.Top = 0; + ScreenRect.Left = 0; + ScreenRect.Right = MaxCols - (SHORT)1; + ScreenRect.Bottom = MaxRows - (SHORT)1; + + WindowSet = (BOOLEAN)SetConsoleWindowInfo( _ScreenHandle, TRUE, &ScreenRect ); + + if ( !WindowSet ) { + + DebugPrintf( "MODE: SetConsoleWindowInfo failed. Error %d\n", GetLastError() ); + if ( IsFullScreen && (GetLastError() == ERROR_FULLSCREEN_MODE) ) { + *IsFullScreen = TRUE; + } + return FALSE; + } + } + + // + // Set the screen buffer size to the desired size. + // + ScreenSize.X = NumberOfColumns; + ScreenSize.Y = NumberOfRows; + + if ( !SetConsoleScreenBufferSize( _ScreenHandle, ScreenSize ) ) { + + DebugPrintf( "MODE: SetConsoleScreenBufferSize failed (Y:%d X:%d ) Error: %d\n", + ScreenSize.Y, ScreenSize.X, GetLastError() ); + + if ( IsFullScreen && (GetLastError() == ERROR_FULLSCREEN_MODE) ) { + *IsFullScreen = TRUE; + } + + // + // Return the window to its original size. We ignore the return + // code because there is nothing we can do about it. + // + if ( !SetConsoleWindowInfo( _ScreenHandle, TRUE, &(ScreenBufferInfo.srWindow) )) { + DebugPrintf( "MODE: SetConsoleWindowInfo (2) failed. Error %d\n", GetLastError() ); + + } + + return FALSE; + } + + MaxRows = (USHORT)min( (int)NumberOfRows, (int)(LargestScreenSize.Y) ); + MaxCols = (USHORT)min( (int)NumberOfColumns, (int)(LargestScreenSize.X) ); + + ScreenRect.Top = 0; + ScreenRect.Left = 0; + ScreenRect.Right = MaxCols - (SHORT)1; + ScreenRect.Bottom = MaxRows - (SHORT)1; + + WindowSet = (BOOLEAN)SetConsoleWindowInfo( _ScreenHandle, TRUE, &ScreenRect ); + + if ( !WindowSet ) { + // + // We could not resize the window. We will leave the + // resized screen buffer. + // + DebugPrintf( "MODE: SetConsoleWindowInfo (3) failed. Error %d\n", GetLastError() ); + return FALSE; + } + + return TRUE; + + } else { + + DebugPrintf( "ULIB: Cannot get console screen buffer info, Error = %X\n", GetLastError() ); + } + + return FALSE; +} + + + + +BOOLEAN +SCREEN::ChangeTextAttribute( + IN USHORT Attribute + ) + +/*++ + +Routine Description: + + Set the attribute to be used when text is written using WriteFile() + (ie, when the stream API is used ). + +Arguments: + + Attribute - Attribute to be used + +Return Value: + + BOOLEAN - Indicates if the initialization succeeded. + + +--*/ + +{ + _TextAttribute = Attribute; + return( SetConsoleTextAttribute( _ScreenHandle, Attribute ) ); +} + + + +BOOLEAN +SCREEN::EnableAsciiControlSequence( + ) + +/*++ + +Routine Description: + + Set the screen in the line mode (allows expansion of control ASCII + sequences); + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + if( _ScreenMode & ENABLE_PROCESSED_OUTPUT ) { + return( TRUE ); + } + _ScreenMode |= ENABLE_PROCESSED_OUTPUT; + return( SetConsoleMode( _ScreenHandle, _ScreenMode ) ); +} + + + +BOOLEAN +SCREEN::DisableAsciiControlSequence( + ) + +/*++ + +Routine Description: + + Set the screen in the character mode (does not expansion of control + ASCII sequences); + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + if( !( _ScreenMode & ENABLE_PROCESSED_OUTPUT ) ) { + return( TRUE ); + } + _ScreenMode &= ~(ENABLE_PROCESSED_OUTPUT); + return( SetConsoleMode( _ScreenHandle, _ScreenMode ) ); +} + + + +BOOLEAN +SCREEN::EnableWrapMode( + ) + +/*++ + +Routine Description: + + Sets the screen in the wrap mode (characters are written in the next + line when cursor reaches the end of a line). + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + if( _ScreenMode & ENABLE_WRAP_AT_EOL_OUTPUT ) { + return( TRUE ); + } + _ScreenMode |= ENABLE_WRAP_AT_EOL_OUTPUT; + return( SetConsoleMode( _ScreenHandle, _ScreenMode ) ); +} + + + +BOOLEAN +SCREEN::DisableWrapMode( + ) + +/*++ + +Routine Description: + + Disables the wrap mode (cursor does not move to the beginning of + the next line when it reaches the eand of a line). + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + if( !( _ScreenMode & ENABLE_WRAP_AT_EOL_OUTPUT ) ) { + return( TRUE ); + } + _ScreenMode &= ~ENABLE_WRAP_AT_EOL_OUTPUT; + return( SetConsoleMode( _ScreenHandle, _ScreenMode ) ); +} + + + +BOOLEAN +SCREEN::IsAtEnd( + ) CONST + +/*++ + +Routine Description: + + Determines if the cursor is at the end of the screen. + +Arguments: + + None. + + +Return Value: + + BOOLEAN - Indicates if the cursor is at the end of the screen. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ); + return( ( ScreenBufferInfo.dwCursorPosition.X == + ScreenBufferInfo.dwSize.X ) && + ( ScreenBufferInfo.dwCursorPosition.Y == + ScreenBufferInfo.dwSize.Y ) ); +} + + + +BOOLEAN +SCREEN::SetScreenActive( + ) + +/*++ + +Routine Description: + + Makes the screen buffer defined in this class active. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + return( SetConsoleActiveScreenBuffer( _ScreenHandle ) ); +} + + + + +ULIB_EXPORT +BOOLEAN +SCREEN::MoveCursorTo( + IN USHORT Row, + IN USHORT Column + ) + +/*++ + +Routine Description: + + Moves the cursor to a particular position in the screen + +Arguments: + + USHORT - Row where the cursor is to be moved to. + + USHORT - Column where the cursor is to be moved to. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + COORD CursorPosition; + + CursorPosition.Y = Row; + CursorPosition.X = Column; + return( SetConsoleCursorPosition( _ScreenHandle, CursorPosition ) ); +} + + + +BOOLEAN +SCREEN::MoveCursorDown( + IN USHORT Rows + ) + +/*++ + +Routine Description: + + Moves the cursor down by a number of lines, keeping it in the same + column. + +Arguments: + + Rows - Number of lines to move the cursor. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + return( MoveCursorTo( ScreenBufferInfo.dwCursorPosition.Y + Rows, + ScreenBufferInfo.dwCursorPosition.X ) ); +} + + + +BOOLEAN +SCREEN::MoveCursorUp( + IN USHORT Rows + ) + +/*++ + +Routine Description: + + Moves the cursor up by a number of lines, keeping it in the same + column. + +Arguments: + + Rows - Number of lines to move the cursor. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + return( MoveCursorTo( ScreenBufferInfo.dwCursorPosition.Y - Rows, + ScreenBufferInfo.dwCursorPosition.X ) ); +} + + + +BOOLEAN +SCREEN::MoveCursorRight( + IN USHORT Columns + ) + +/*++ + +Routine Description: + + Moves the cursor right by a number of columns, keeping it in the same + line. + +Arguments: + + Columns - Number of columns to move the cursor. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + return( MoveCursorTo( ScreenBufferInfo.dwCursorPosition.Y, + ScreenBufferInfo.dwCursorPosition.X + Columns ) ); +} + + + +BOOLEAN +SCREEN::MoveCursorLeft( + IN USHORT Columns + ) + +/*++ + +Routine Description: + + Moves the cursor left by a number of columns, keeping it in the same + line. + +Arguments: + + Columns - Number of columns to move the cursor. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + return( MoveCursorTo( ScreenBufferInfo.dwCursorPosition.Y, + ScreenBufferInfo.dwCursorPosition.X - Columns ) ); +} + + + + +ULIB_EXPORT +DWORD +SCREEN::QueryCodePage( + ) + +/*++ + +Routine Description: + + Obtains the current console code page. + +Arguments: + + None + + +Return Value: + + The current console code page. + + +--*/ + + +{ + return GetConsoleCP( ); +} + + +DWORD +SCREEN::QueryOutputCodePage( + ) + +/*++ + +Routine Description: + + Obtains the current console code page. + +Arguments: + + None + + +Return Value: + + The current console code page. + + +--*/ + + +{ + return GetConsoleOutputCP( ); +} + + +BOOLEAN +SCREEN::QueryCursorPosition( + OUT PUSHORT Row, + OUT PUSHORT Column + ) + +/*++ + +Routine Description: + + Returns to the caller the current position of the cursor. + +Arguments: + + Row - Address of the variable that will contain the row. + + Column - Address of the variable that will contain the column. + + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + + *Row = ScreenBufferInfo.dwCursorPosition.Y; + *Column = ScreenBufferInfo.dwCursorPosition.X; + return( TRUE ); +} + + + +ULIB_EXPORT +BOOLEAN +SCREEN::SetCodePage( + IN DWORD CodePage + ) + +/*++ + +Routine Description: + + Sets the console codepage. + +Arguments: + + + CodePage - New codepage + + +Return Value: + + BOOLEAN - TRUE if codepage set, FALSE otherwise (most probably the + codepage is invalid). + + +--*/ + + +{ + return SetConsoleCP( CodePage ); +} + + +ULIB_EXPORT +BOOLEAN +SCREEN::SetOutputCodePage( + IN DWORD CodePage + ) + +/*++ + +Routine Description: + + Sets the console output codepage. + +Arguments: + + + CodePage - New codepage + + +Return Value: + + BOOLEAN - TRUE if codepage set, FALSE otherwise (most probably the + codepage is invalid). + + +--*/ + + +{ + return SetConsoleOutputCP( CodePage ); +} + + +BOOLEAN +SCREEN::SetCursorSize( + IN ULONG Size + ) + +/*++ + +Routine Description: + + Sets the size of the cursor. + +Arguments: + + Size - A number in the range 1-100 that indicates the percentage of + character cell to be filled. + + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_CURSOR_INFO CursorInfo; + + if( !GetConsoleCursorInfo( _ScreenHandle, &CursorInfo ) ) { + return( FALSE ); + } + CursorInfo.dwSize = Size; + return( SetConsoleCursorInfo( _ScreenHandle, &CursorInfo ) ); +} + + + +BOOLEAN +SCREEN::SetCursorOff( + ) + +/*++ + +Routine Description: + + Turns off the cursor. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_CURSOR_INFO CursorInfo; + + if( !GetConsoleCursorInfo( _ScreenHandle, &CursorInfo ) ) { + return( FALSE ); + } + CursorInfo.bVisible = FALSE; + return( SetConsoleCursorInfo( _ScreenHandle, &CursorInfo ) ); +} + + + +BOOLEAN +SCREEN::SetCursorOn( + ) + +/*++ + +Routine Description: + + Turns on the cursor. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_CURSOR_INFO CursorInfo; + + if( !GetConsoleCursorInfo( _ScreenHandle, &CursorInfo ) ) { + return( FALSE ); + } + CursorInfo.bVisible = TRUE; + return( SetConsoleCursorInfo( _ScreenHandle, &CursorInfo ) ); +} + + + +BOOLEAN +SCREEN::FillRegionCharacter( + IN USHORT StartRow, + IN USHORT StartColumn, + IN USHORT EndRow, + IN USHORT EndColumn, + IN CHAR Character + ) + +/*++ + +Routine Description: + + Fills a region in the screen with a particular character. Attributes + in this region are not changed. + +Arguments: + + StartRow - Row where the region starts. + + StartColumn - Column where the region starts. + + EndRow - Row where the region ends. + + EndColumn - Column where the region ends. + + Character - Character to fill the region. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + COORD Origin; + ULONG Length; + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + ULONG Columns; + ULONG NumberOfCharsWritten; + + + GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ); + Columns = ScreenBufferInfo.dwSize.X; + + if( EndRow == StartRow ) { + Length = EndColumn - StartColumn + 1; + } else { + Length = Columns - StartColumn + + Columns*( EndRow - StartRow - 1 ) + + EndColumn + 1; + } + Origin.Y = StartRow; + Origin.X = StartColumn; + if( !FillConsoleOutputCharacter( _ScreenHandle, + Character, + Length, + Origin, + &NumberOfCharsWritten ) || + NumberOfCharsWritten != Length) { + return( FALSE ); + } + return( TRUE ); +} + + + +BOOLEAN +SCREEN::FillRectangularRegionCharacter( + IN USHORT TopLeftRow, + IN USHORT TopLeftColumn, + IN USHORT BottomRightRow, + IN USHORT BottomRightColumn, + IN CHAR Character + ) + +/*++ + +Routine Description: + + Fills a rectangular region in the screen with a particular character. + Attributes in this region are not changed. + +Arguments: + + TopLeftRow - Row where the region starts. + + TopLeftColumn - Column where the region starts. + + BottomRightRow - Row where the region ends. + + BottomeRightColumn - Column where the region ends. + + Character - Character to fill the region. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + COORD Origin; + ULONG Length; + ULONG NumberOfRows; + ULONG NumberOfCharsWritten; + + NumberOfRows = BottomRightRow - TopLeftRow + 1; + Length = BottomRightColumn - TopLeftColumn + 1; + Origin.X = TopLeftColumn; + Origin.Y = TopLeftRow; + while( NumberOfRows-- ) { + if( !FillConsoleOutputCharacter( _ScreenHandle, + Character, + Length, + Origin, + &NumberOfCharsWritten ) || + NumberOfCharsWritten != Length ) { + return( FALSE ); + } + Origin.Y++; + } + return( TRUE ); +} + + + +BOOLEAN +SCREEN::FillRegionAttribute( + IN USHORT StartRow, + IN USHORT StartColumn, + IN USHORT EndRow, + IN USHORT EndColumn, + IN USHORT Attribute + ) + +/*++ + +Routine Description: + + Fills a region in the screen with a particular attribute. Characters + in this region are not changed. + +Arguments: + + StartRow - Row where the region starts. + + StartColumn - Column where the region starts. + + EndRow - Row where the region ends. + + EndColumn - Column where the region ends. + + Attribute - Attribute to fill the region. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + COORD Origin; + ULONG Length; + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + ULONG Columns; + ULONG NumberOfAttrsWritten; + + + GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ); + Columns = ScreenBufferInfo.dwSize.X; + + if( EndRow == StartRow ) { + Length = EndColumn - StartColumn + 1; + } else { + Length = Columns - StartColumn + + Columns*( EndRow - StartRow - 1 ) + + EndColumn + 1; + } + Origin.Y = StartRow; + Origin.X = StartColumn; + if( !FillConsoleOutputAttribute( _ScreenHandle, + Attribute, + Length, + Origin, + &NumberOfAttrsWritten ) || + NumberOfAttrsWritten != Length ) { + return( FALSE ); + } + return( TRUE ); +} + + + +BOOLEAN +SCREEN::FillRectangularRegionAttribute( + IN USHORT TopLeftRow, + IN USHORT TopLeftColumn, + IN USHORT BottomRightRow, + IN USHORT BottomRightColumn, + IN USHORT Attribute + ) + +/*++ + +Routine Description: + + Fills a rectangular region in the screen with a particular attribute. + Characters in this region are not changed. + +Arguments: + + TopLeftRow - Row where the region starts. + + TopLeftColumn - Column where the region starts. + + BottomRighhtRow - Row where the region ends. + + BottomRightColumn - Column where the region ends. + + Attribute - Attribute used to fill the region. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + COORD Origin; + ULONG Length; + ULONG NumberOfRows; + ULONG NumberOfAttrsWritten; + + NumberOfRows = BottomRightRow - TopLeftRow + 1; + Length = BottomRightColumn - TopLeftColumn + 1; + Origin.X = TopLeftColumn; + Origin.Y = TopLeftRow; + while( NumberOfRows-- ) { + if( !FillConsoleOutputAttribute( _ScreenHandle, + Attribute, + Length, + Origin, + &NumberOfAttrsWritten ) || + NumberOfAttrsWritten != Length ) { + return( FALSE ); + } + Origin.Y++; + } + return( TRUE ); +} + + + +BOOLEAN +SCREEN::EraseLine( + IN USHORT LineNumber + ) + +/*++ + +Routine Description: + + Erases a line in the screen. + +Arguments: + + LineNumber - Line number. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + return( FillRegionCharacter( LineNumber, + 0, + LineNumber, + ScreenBufferInfo.dwSize.X - 1, + 0x20 ) ); +} + + + +BOOLEAN +SCREEN::EraseToEndOfLine( + ) + +/*++ + +Routine Description: + + Erases the current line from the cursor position to the end of line. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + return( FillRegionCharacter( ScreenBufferInfo.dwCursorPosition.Y, + ScreenBufferInfo.dwCursorPosition.X, + ScreenBufferInfo.dwCursorPosition.Y, + ScreenBufferInfo.dwSize.X - 1, + 0x20 ) ); +} + + + +ULIB_EXPORT +BOOLEAN +SCREEN::EraseScreen( + ) + +/*++ + +Routine Description: + + Erases all characters in the screen. Attributes are not changed. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ); + return( FillRegionCharacter( 0, + 0, + ScreenBufferInfo.dwSize.Y - 1, + ScreenBufferInfo.dwSize.X - 1, + 0x20 ) ); +} + + + +ULIB_EXPORT +VOID +SCREEN::QueryScreenSize( + OUT PUSHORT NumberOfRows, + OUT PUSHORT NumberOfColumns, + OUT PUSHORT WindowRows, + OUT PUSHORT WindowColumns + ) CONST + +/*++ + +Routine Description: + + Returns to the caller the screen size, and optionally the window + size. + +Arguments: + + NumberOfRows - Points to the variable that will contain the + number of rows + + NumberOfColumns - Points to the variable that will contain the + number of columns + + WindowRows - Points to the variable that will contain the number + of rows in the window + + WindowColumns - Points to the variable that will contain the number + of columns in the window + +Return Value: + + None. + + +--*/ + + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ); + + // + // Get screen buffer size + // + *NumberOfRows = ScreenBufferInfo.dwSize.Y; + *NumberOfColumns = ScreenBufferInfo.dwSize.X; + + // + // Get window size + // + if ( WindowRows && WindowColumns ) { + *WindowColumns = ScreenBufferInfo.srWindow.Right - ScreenBufferInfo.srWindow.Left + 1; + *WindowRows = ScreenBufferInfo.srWindow.Bottom - ScreenBufferInfo.srWindow.Top + 1; + } +} + + + + +BOOLEAN +SCREEN::ScrollScreen( + IN USHORT Amount, + IN SCROLL_DIRECTION Direction + ) + +/*++ + +Routine Description: + + Scrolls the screen. + +Arguments: + + Amount - Number of rows or columns to scroll. + + Direction - Indicates if up, down, left or right. + +Return Value: + + BOOLEAN - Returns TRUE if the screen was scrolled. FALSE otherwise. + + +--*/ + + +{ + UNREFERENCED_PARAMETER( Amount ); + UNREFERENCED_PARAMETER( Direction ); + +/* + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + CONSOLE_SCROLL_INFO ConsoleScrollInfo; + + if( !GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ) ) { + return( FALSE ); + } + switch( Direction ) { + + case SCROLL_UP: + + ConsoleScrollInfo.ScrollRectangle.Left = 0; + ConsoleScrollInfo.ScrollRectangle.Top = Amount; + ConsoleScrollInfo.ScrollRectangle.Right = + ( SHORT )( ScreenBufferInfo.dwSize.X - 1 ); + ConsoleScrollInfo.ScrollRectangle.Bottom = + ( SHORT )( ScreenBufferInfo.dwSize.Y - 1 ); + ConsoleScrollInfo.dwDestinationOrigin.X = 0; + ConsoleScrollInfo.dwDestinationOrigin.Y = 0; + break; + + + case SCROLL_DOWN: + + ConsoleScrollInfo.ScrollRectangle.Left = 0; + ConsoleScrollInfo.ScrollRectangle.Top = 0; + ConsoleScrollInfo.ScrollRectangle.Right = + ( SHORT )( ScreenBufferInfo.dwSize.X - 1 ); + ConsoleScrollInfo.ScrollRectangle.Bottom = + ( SHORT )( ScreenBufferInfo.dwSize.Y - Amount - 1 ); + ConsoleScrollInfo.dwDestinationOrigin.X = 0; + ConsoleScrollInfo.dwDestinationOrigin.Y = Amount; + break; + + + case SCROLL_LEFT: + + ConsoleScrollInfo.ScrollRectangle.Left = Amount; + ConsoleScrollInfo.ScrollRectangle.Top = 0; + ConsoleScrollInfo.ScrollRectangle.Right = + ( SHORT )( ScreenBufferInfo.dwSize.X - 1 ); + ConsoleScrollInfo.ScrollRectangle.Bottom = + ( SHORT )( ScreenBufferInfo.dwSize.Y - 1 ); + ConsoleScrollInfo.dwDestinationOrigin.X = 0; + ConsoleScrollInfo.dwDestinationOrigin.Y = 0; + break; + + + case SCROLL_RIGHT: + + ConsoleScrollInfo.ScrollRectangle.Left = 0; + ConsoleScrollInfo.ScrollRectangle.Top = 0; + ConsoleScrollInfo.ScrollRectangle.Right = + ( SHORT )( ScreenBufferInfo.dwSize.X - Amount - 1 ); + ConsoleScrollInfo.ScrollRectangle.Bottom = + ( SHORT )( ScreenBufferInfo.dwSize.Y - 1 ); + ConsoleScrollInfo.dwDestinationOrigin.X = Amount; + ConsoleScrollInfo.dwDestinationOrigin.Y = 0; + break; + + } + + ConsoleScrollInfo.Fill.Char.AsciiChar = 0x20; + ConsoleScrollInfo.Fill.Attributes = ScreenBufferInfo.wAttributes; + return( ScrollConsoleScreenBuffer( _ScreenHandle, + &ConsoleScrollInfo ) ); +*/ +// +// jaimes - 07/08/91 +// ScrollConsoleScreenBuffer has chaged +// +return TRUE; +} + + + +BOOLEAN +SCREEN::Read( + OUT PBYTE Buffer, + IN ULONG BytesToRead, + OUT PULONG BytesRead + ) + +/*++ + +Routine Description: + + Reads bytes from the screen stream. + +Arguments: + + Buffer - Points that will receive the bytes read. + + BytesToRead - Number of bytes to read (buffer size) + + BytesRead - Points to the variable that will contain the total + number of bytes read. + +Return Value: + + Returns always FALSE since no data can be read from a screen stream. + + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(Buffer); + (void)(BytesToRead); + (void)(BytesRead); + + return( FALSE ); +} + + + +BOOLEAN +SCREEN::ReadChar( + OUT PWCHAR Char, + IN BOOLEAN Unicode + ) + +/*++ + +Routine Description: + + Reads a character from the screen stream. + +Arguments: + + Char - Supplies poinbter to wide character + +Return Value: + + Returns always FALSE since no data can be read from a screen stream. + + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(Char); + (void)(Unicode); + + return( FALSE ); +} + + + +BOOLEAN +SCREEN::ReadMbString( + IN PSTR String, + IN DWORD BufferSize, + INOUT PDWORD StringSize, + IN PSTR Delimiters, + IN BOOLEAN ExpandTabs, + IN DWORD TabExp + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(String); + (void)(BufferSize); + (void)(StringSize); + (void)(Delimiters); + (void)(ExpandTabs); + (void)(TabExp); + + return( FALSE ); +} + + + +BOOLEAN +SCREEN::ReadWString( + IN PWSTR String, + IN DWORD BufferSize, + INOUT PDWORD StringSize, + IN PWSTR Delimiters, + IN BOOLEAN ExpandTabs, + IN DWORD TabExp + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(String); + (void)(BufferSize); + (void)(StringSize); + (void)(Delimiters); + (void)(ExpandTabs); + (void)(TabExp); + + return( FALSE ); +} + + + +BOOLEAN +SCREEN::ReadString( + OUT PWSTRING String, + IN PWSTRING Delimiter, + IN BOOLEAN Unicode + ) + +/*++ + +Routine Description: + + Reads a STRING from the screen stream. + +Arguments: + + String - Pointer to a WSTRING object that will contain the string read. + + Delimiter - Pointer to a WSTRING object that contains the delimiters + of a string + +Return Value: + + Returns always FALSE since no data can be read from a screen stream. + + +--*/ + + +{ + // unreferenced parameters + (void)(this); + (void)(String); + (void)(Delimiter); + (void)(Unicode); + + return( FALSE ); +} + + + +STREAMACCESS +SCREEN::QueryAccess( + ) CONST + +/*++ + +Routine Description: + + Returns the access to the screen stream. + +Arguments: + + None. + +Return Value: + + Returns always WRITE_ACCESS. + + +--*/ + + +{ + (void)(this); + return( WRITE_ACCESS ); +} + + + +HANDLE +SCREEN::QueryHandle( + ) CONST + +/*++ + +Routine Description: + + Returns the handle to the screen. + +Arguments: + + None. + +Return Value: + + Returns a handle. + + +--*/ + + +{ + return( _ScreenHandle ); +} + + +#if 0 +// TMPTMP just for debug. + +#include <stdio.h> +#endif + + + + +BOOLEAN +SCREEN::WriteString( + IN PCWSTRING String, + IN CHNUM Position, + IN CHNUM Length, + IN CHNUM Granularity + ) + +/*++ + +Routine Description: + + Writes a string to the screen. + +Arguments: + + String - Pointer to a STRING object. + Position - Starting character within the string + Length - Number of characters to write + Granularity - The maximum number of bytes to write at one time. + A value of 0 indicates to write it all at once. + +Return Value: + + BOOLEAN - Returns TRUE if the write operation succeeded. + + +--*/ + + +{ + ULONG i, n, written, to_write; + PCWSTR p; + BOOLEAN r; + HANDLE h; + + DebugAssert(Position <= String->QueryChCount()); + + n = min(String->QueryChCount() - Position, Length); + p = String->GetWSTR() + Position; + h = QueryHandle(); + + if (!Granularity) { + Granularity = n; + } + + r = TRUE; + for (i = 0; r && i < n; i += Granularity) { + + to_write = min(Granularity, n - i); + + r = WriteConsole(h, p + i, to_write, + &written, NULL) && + to_write == written; + } + + return r; +} + + +BOOLEAN +SCREEN::WriteChar( + IN WCHAR Char + ) +/*++ + +Routine Description: + + This routine writes a character to the output. This routine + uses WriteConsoleW to avoid having to make the translation + from wide to narrow characters. + +Arguments: + + Char - Supplies the character to write. + +Return Value: + + TRUE - Success. + FALSE - Failure. + +--*/ +{ + ULONG written; + + if (!WriteConsole(QueryHandle(), &Char, 1, &written, NULL) || + written != 1) { + + return FALSE; + } + + return TRUE; +} + +#ifdef DBCS + +BOOLEAN +SCREEN::EraseScreenAndResetAttribute( + ) + +/*++ + +Routine Description: + + Erases all characters in the screen. Attributes are also reset. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the operation succeeded. + + +--*/ + +{ + CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo; + + GetConsoleScreenBufferInfo( _ScreenHandle, &ScreenBufferInfo ); + + return ( + FillRegionCharacter( + 0, + 0, + ScreenBufferInfo.dwSize.Y - 1, + ScreenBufferInfo.dwSize.X - 1, + 0x20 + ) + && + FillRegionAttribute( + 0, + 0, + ScreenBufferInfo.dwSize.Y - 1, + ScreenBufferInfo.dwSize.X - 1, + ScreenBufferInfo.wAttributes + ) + ); +} + +#endif // DBCS diff --git a/private/utils/ulib/src/seqcnt.cxx b/private/utils/ulib/src/seqcnt.cxx new file mode 100644 index 000000000..b3202cf4f --- /dev/null +++ b/private/utils/ulib/src/seqcnt.cxx @@ -0,0 +1,82 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + seqcnt.cxx + +Abstract: + + This module contains the definition for the SEQUENTIAL_CONTAINER class. + There exists no implementation, merely a constructor that acts as a link + between derived classes as SEQUENTIAL_CONTAINERs base class CONTAINER. + +Author: + + David J. Gilman (davegi) 02-Nov-1990 + +Environment: + + ULIB, User Mode + +[Notes:] + + optional-notes + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "iterator.hxx" +#include "seqcnt.hxx" + + +DEFINE_CONSTRUCTOR( SEQUENTIAL_CONTAINER, CONTAINER ); + +SEQUENTIAL_CONTAINER::~SEQUENTIAL_CONTAINER( + ) +{ +} + +ULIB_EXPORT +BOOLEAN +SEQUENTIAL_CONTAINER::DeleteAllMembers( + ) +/*++ + +Routine Description: + + This routine not only removes all members from the container + class, but also deletes all the objects themselves. + +Arguments: + + None. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + PITERATOR iter; + POBJECT pobj; + + if (!(iter = QueryIterator())) { + return FALSE; + } + + iter->GetNext(); + while (iter->GetCurrent()) { + pobj = Remove(iter); + DELETE(pobj); + } + DELETE(iter); + + return TRUE; +} diff --git a/private/utils/ulib/src/smsg.cxx b/private/utils/ulib/src/smsg.cxx new file mode 100644 index 000000000..3bdefd06d --- /dev/null +++ b/private/utils/ulib/src/smsg.cxx @@ -0,0 +1,607 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "smsg.hxx" +#include "array.hxx" +#include "arg.hxx" +#include "iterator.hxx" +#include "system.hxx" +#include "stream.hxx" +#include "keyboard.hxx" +#include "rtmsg.h" +#include "screen.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR(STREAM_MESSAGE, MESSAGE, ULIB_EXPORT) + + +VOID +STREAM_MESSAGE::Construct( + ) +/*++ + +Routine Description: + + Constructor for STREAM_MESSAGE. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _msgid = 0; + _msgtype = NORMAL_MESSAGE; + _out_stream = NULL; + _in_stream = NULL; + _err_stream = NULL; + _case_sensitive = FALSE; + _copy_input = FALSE; +} + + +ULIB_EXPORT +STREAM_MESSAGE::~STREAM_MESSAGE( + ) +/*++ + +Routine Description: + + Destructor for STREAM_MESSAGE. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + Destroy(); +} + + +ULIB_EXPORT +BOOLEAN +STREAM_MESSAGE::Initialize( + IN OUT PSTREAM OutputStream, + IN OUT PSTREAM InputStream, + IN OUT PSTREAM ErrorStream + ) +/*++ + +Routine Description: + + This routine initializes the STREAM_MESSAGE object to the specified stream. + +Arguments: + + OutputStream - Supplies the output stream for the object. + InputStream - Supplies the input stream for the object. + ErrorStream - Supplies the error stream for the object. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + Destroy(); + + DebugAssert(OutputStream); + DebugAssert(InputStream); + + _out_stream = OutputStream; + _in_stream = InputStream; + _err_stream = ErrorStream; + _copy_input = SCREEN::Cast(OutputStream) ? FALSE : TRUE; + + +#if defined JAPAN // v-junm - 08/11/93 +// Set TEB's LanguageId to either Japanese or US depending on the code page. +// If the code page is non-JP, then the message to display is assumed to be US. + + if ( GetConsoleOutputCP() == 932 ) + SetThreadLocale( + MAKELCID( + MAKELANGID( LANG_JAPANESE, SUBLANG_ENGLISH_US ), + SORT_DEFAULT + ) + ); + else + SetThreadLocale( + MAKELCID( + MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ), + SORT_DEFAULT + ) + ); + +#endif // JAPAN + return TRUE; +} + +ULIB_EXPORT +BOOLEAN +STREAM_MESSAGE::Set( + IN MSGID MsgId, + IN MESSAGE_TYPE MessageType, + IN ULONG MessageVisual + ) +/*++ + +Routine Description: + + This routine sets up the class to display the message with the + 'MsgId' resource identifier. + +Arguments: + + MsgId - Supplies the resource id of the message. + MessageType - Supplies the type of the message. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + _msgid = MsgId; + _msgtype = MessageType; + _msgvisual = MessageVisual; + return TRUE; +} + + +BOOLEAN +STREAM_MESSAGE::DisplayV( + IN PCSTR Format, + IN va_list VarPointer + ) +/*++ + +Routine Description: + + This routine displays the message with the specified parameters. + + The format string supports all printf options. + +Arguments: + + Format - Supplies a printf style list format string. + VarPointer - Supplies a varargs pointer to the arguments. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + if (! (_msgvisual & TEXT_MESSAGE) ) + { + return TRUE; + } + + if (!SYSTEM::QueryResourceStringV(&_display_string, _msgid, Format, + VarPointer)) { + return FALSE; + } + + return DisplayString(); +} + + +ULIB_EXPORT +BOOLEAN +STREAM_MESSAGE::IsYesResponse( + IN BOOLEAN Default + ) +/*++ + +Routine Description: + + This routine queries either a "yes" or "no" from the input stream. + +Arguments: + + Default - Supplies the default answer if neither "yes" nor "no" is the + recognized input. + +Return Value: + + FALSE - A "no" response. + TRUE - A "yes" response. + +--*/ +{ + DSTRING input; + DSTRING yes_message; + DSTRING no_message; + WCHAR w; + + Flush(); + + if (!SYSTEM::QueryResourceString(&yes_message, MSG_YES, "")) { + return Default; + } + + if (!SYSTEM::QueryResourceString(&no_message, MSG_NO, "")) { + return Default; + } + + for (;;) { + if (!ReadLine(&input)) { + return Default; + } + + if (!input.Strupr()) { + return Default; + } + + w = input.QueryChAt(0); + + if (w == no_message.QueryChAt(0)) { + return FALSE; + } + + if (w == yes_message.QueryChAt(0)) { + return TRUE; + } + + DisplayString(); + } +} + + +BOOLEAN +STREAM_MESSAGE::QueryStringInput( + OUT PWSTRING String + ) +/*++ + +Routine Description: + + This routine queries a string from the user. + +Arguments: + + String - Supplies a buffer to return the string into. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + return ReadLine(String); +} + + +BOOLEAN +STREAM_MESSAGE::WaitForUserSignal( + ) +/*++ + +Routine Description: + + This routine waits for a signal from the user. + +Arguments: + + None. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + DSTRING string; + + return (BOOLEAN) (Flush() && ReadLine(&string)); +} + + +MSGID +STREAM_MESSAGE::SelectResponse( + IN ULONG NumberOfSelections ... + ) +/*++ + +Routine Description: + + This routine queries input from the user in order to determine which + message was entered. It then returns the message id of the message + entered. + +Arguments: + + NumberOfSelections - Supplies the number of message ids. + ... - Supplies the message ids. + +Return Value: + + The message id of the message entered, or the first message id. + +--*/ +{ + va_list ap; + ARRAY lex_array; + ARRAY arg_array; + PFLAG_ARGUMENT flag_arg; + ARGUMENT_LEXEMIZER arg; + DSTRING input_string; + MSGID first; + PITERATOR arg_it; + ULONG i; + DSTRING match_string; + DSTRING del; + + va_start(ap, NumberOfSelections); + first = va_arg(ap, MSGID); + va_end(ap); + + if (!lex_array.Initialize() || !arg_array.Initialize()) { + return first; + } + + if (!arg.Initialize(&lex_array)) { + return first; + } + + arg.SetCaseSensitive(_case_sensitive); + + va_start(ap, NumberOfSelections); + for (i = 0; i < NumberOfSelections; i++) { + SYSTEM::QueryResourceString(&match_string, va_arg(ap, MSGID), ""); + + if (!(flag_arg = NEW FLAG_ARGUMENT) || + !flag_arg->Initialize(&match_string) || + !arg_array.Put(flag_arg)) { + va_end(ap); + return first; + } + } + va_end(ap); + + Flush(); + + if (!ReadLine(&input_string)) { + return first; + } + + if (!arg.PrepareToParse(&input_string)) { + return first; + } + + if (!arg.DoParsing(&arg_array)) { + return first; + } + + arg_it = arg_array.QueryIterator(); + va_start(ap, NumberOfSelections); + for (i = 0; i < NumberOfSelections; i++) { + flag_arg = (PFLAG_ARGUMENT) arg_it->GetNext(); + if (flag_arg->QueryFlag()) { + first = va_arg(ap, MSGID); + } else { + va_arg(ap, MSGID) ? 1 : 0; + } + DELETE(flag_arg); + } + va_end(ap); + + DELETE(arg_it); + + return first; +} + + +PMESSAGE +STREAM_MESSAGE::Dup( + ) +/*++ + +Routine Description: + + This routine returns a new MESSAGE of the same type. + +Arguments: + + None. + +Return Value: + + A pointer to a new MSG object. + +--*/ +{ + PSTREAM_MESSAGE p; + + if (!(p = NEW STREAM_MESSAGE)) { + return NULL; + } + + if (!p->Initialize(_out_stream, _in_stream)) { + DELETE(p); + return NULL; + } + + return p; +} + + +VOID +STREAM_MESSAGE::Destroy( + ) +/*++ + +Routine Description: + + This routine returns an STREAM_MESSAGE object to its initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _msgid = 0; + _msgtype = NORMAL_MESSAGE; + _out_stream = NULL; + _in_stream = NULL; + _err_stream = NULL; + _case_sensitive = FALSE; + _copy_input = FALSE; +} + + +BOOLEAN +STREAM_MESSAGE::ReadLine( + OUT PWSTRING String + ) +/*++ + +Routine Description: + + This routine reads a line from the input stream. + +Arguments: + + String - Returns the read in string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + DSTRING del; + WCHAR w; + + if (!del.Initialize("\r\n")) { + return FALSE; + } + + if (_in_stream->IsAtEnd()) { + return FALSE; + } + + String->Initialize( "" ); + + if (!_in_stream->ReadString(String, &del)) { + return FALSE; + } + + // Line feed is the last character on the line. + + for (;;) { + if (_in_stream->IsAtEnd()) { + return TRUE; + } + + if (!_in_stream->ReadChar(&w)) { + return FALSE; + } + + if (w == '\n') { + break; + } + } + + if (_copy_input) { + _out_stream->WriteString(String, 0, String->QueryChCount()); + _out_stream->WriteString(&del, 0, del.QueryChCount()); + } + + return TRUE; +} + + +BOOLEAN +STREAM_MESSAGE::Flush( + ) +/*++ + +Routine Description: + + This routine flushes the input stream of all previously typed input. + +Arguments: + + None. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + PKEYBOARD key; + + if (key = KEYBOARD::Cast(_in_stream)) { + return key->Flush(); + } + + return TRUE; +} + + +BOOLEAN +STREAM_MESSAGE::DisplayString( + ) +/*++ + +Routine Description: + + This routine prints this objects current string to the + appropriate output. + +Arguments: + + None. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + PSTREAM stream; + + if (! (_msgvisual & TEXT_MESSAGE) ) + { + return TRUE; + } + + if (_msgtype == ERROR_MESSAGE && _err_stream) { + stream = _err_stream; + } else { + stream = _out_stream; + } + + if (!stream->WriteString(&_display_string, 0, TO_END, 40)) { + return FALSE; + } + + return TRUE; +} diff --git a/private/utils/ulib/src/sortcnt.cxx b/private/utils/ulib/src/sortcnt.cxx new file mode 100644 index 000000000..9d0386b0a --- /dev/null +++ b/private/utils/ulib/src/sortcnt.cxx @@ -0,0 +1,37 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + sortcnt.cxx + +Abstract: + + This module contains the definition for the SORTABLE_CONTAINER class. + +Author: + + David J. Gilman (davegi) 02-Nov-1990 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "iterator.hxx" +#include "sortcnt.hxx" + + +DEFINE_CONSTRUCTOR( SORTABLE_CONTAINER, SEQUENTIAL_CONTAINER ); + +SORTABLE_CONTAINER::~SORTABLE_CONTAINER( + ) +{ +} diff --git a/private/utils/ulib/src/sortlist.cxx b/private/utils/ulib/src/sortlist.cxx new file mode 100644 index 000000000..c79824d42 --- /dev/null +++ b/private/utils/ulib/src/sortlist.cxx @@ -0,0 +1,373 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + sortlist.cxx + +Abstract: + + This module contains the definition for the SORTED_LIST class. + SORTED_LIST is a concrete implementation of a SORTABLE_CONTAINER, where + all the elements are maintained in sorted order. + +Author: + + Ramon J. San Andres (ramonsa) 29-Oct-1991 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "sortlist.hxx" + + +DEFINE_EXPORTED_CONSTRUCTOR( SORTED_LIST, SORTABLE_CONTAINER, ULIB_EXPORT ); + +DEFINE_CAST_MEMBER_FUNCTION( SORTED_LIST ); + +VOID +SORTED_LIST::Construct ( + ) + +/*++ + +Routine Description: + + Constructor for SORTED_LIST + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ +} + + + + + +ULIB_EXPORT +SORTED_LIST::~SORTED_LIST ( + ) + +/*++ + +Routine Description: + + Destructor for SORTED_LIST + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ +} + + + +ULIB_EXPORT +BOOLEAN +SORTED_LIST::Initialize ( + IN BOOLEAN Ascending + ) + +/*++ + +Routine Description: + + Initializes a SORTED_LIST object. + +Arguments: + + Ascending - Supplies ascending flag + +Return Value: + + BOOLEAN - TRUE if the SORTED_LIST is successfully initialized. + +--*/ + +{ + _Ascending = Ascending; + +#if DBG==1 + _IteratorCount = 0; +#endif + + return _Array.Initialize(); +} + + + + +ULIB_EXPORT +BOOLEAN +SORTED_LIST::DeleteAllMembers ( + ) + +/*++ + +Routine Description: + + Deletes all the members of the sorted list + +Arguments: + + None + +Return Value: + + BOOLEAN - TRUE if all members deleted + +--*/ + +{ + return _Array.DeleteAllMembers(); +} + + + + + +ULIB_EXPORT +BOOLEAN +SORTED_LIST::Put ( + IN OUT POBJECT Member + ) + +/*++ + +Routine Description: + + Puts an OBJECT in the sorted list, maintaining the list sorted + +Arguments: + + Member - Supplies the OBJECT to place in the array + +Return Value: + + BOOLEAN - TRUE if member put, FALSE otherwise + +--*/ + +{ + if ( _Array.QueryMemberCount() > 0 ) { + return _Array.Insert( Member, Search( Member, 0, _Array.QueryMemberCount()-1 ) ); + } else { + return _Array.Insert( Member, 0 ); + } +} + + + + +ULIB_EXPORT +PITERATOR +SORTED_LIST::QueryIterator ( + ) CONST + +/*++ + +Routine Description: + + Creates an iterator object for this sorted-list. + +Arguments: + + None. + +Return Value: + + PITERATOR - Pointer to an ITERATOR object. + +--*/ + +{ + + + + return (PITERATOR)_Array.QueryIterator(); +} + + + +ULIB_EXPORT +ULONG +SORTED_LIST::QueryMemberCount ( + ) CONST + +/*++ + +Routine Description: + + Obtains the number of elements in the list + +Arguments: + + None + +Return Value: + + ULONG - The number of members in the list + + +--*/ + +{ + return _Array.QueryMemberCount(); +} + + +POBJECT +SORTED_LIST::Remove ( + IN OUT PITERATOR Position + ) + +/*++ + +Routine Description: + + Removes a member from the list + +Arguments: + + Position - Supplies an iterator whose currency is to be removed + +Return Value: + + POBJECT - The object removed + + +--*/ + +{ + return _Array.Remove( Position ); +} + + + + +BOOLEAN +SORTED_LIST::Sort ( + IN BOOLEAN Ascending + ) + +/*++ + +Routine Description: + + Sorts the array + +Arguments: + + Ascending - Supplies ascending flag + +Return Value: + + BOOLEAN - TRUE if array sorted, FALSE otherwise + + +--*/ + +{ + if ( ( Ascending == _Ascending ) || + _Array.Sort( Ascending ) ) { + + _Ascending = Ascending; + return TRUE; + + } else { + + return FALSE; + } +} + + + + +ULONG +SORTED_LIST::Search( + IN PCOBJECT Key, + IN ULONG FirstIndex, + IN ULONG LastIndex + ) + +/*++ + +Routine Description: + + Searches an element that matches the supplied key. + If no such element is found, this method returns + the element one past the largest element less + than the given element. + +Arguments: + + Key - Supplies the key + FirstIndex - Supplies lowerbound for the search + LastIndex - Supplies upperbound for the search + +Return Value: + + ULONG - Index of the element that matched the key, or + LastIndex+1 if no match + +--*/ + +{ + LONG First, Middle, Last; + LONG Match; + + DebugPtrAssert( Key ); + DebugPtrAssert( FirstIndex < _Array.QueryMemberCount() ); + DebugPtrAssert( (LastIndex == INVALID_INDEX) || + (LastIndex < _Array.QueryMemberCount()) ); + DebugPtrAssert( FirstIndex <= LastIndex ); + + if (LastIndex == INVALID_INDEX) { + return 0; + } + + First = FirstIndex; + Last = LastIndex; + while (First <= Last) { + Middle = (First + Last)/2; + Match = _Array.CompareAscDesc((POBJECT) Key, + _Array.GetAt(Middle), + _Ascending); + + if (!Match) { + break; + } + + if (Match < 0) { + Last = Middle - 1; + } else { + First = ++Middle; + } + } + + return Middle; +} diff --git a/private/utils/ulib/src/sortlit.cxx b/private/utils/ulib/src/sortlit.cxx new file mode 100644 index 000000000..d9d9dc9cc --- /dev/null +++ b/private/utils/ulib/src/sortlit.cxx @@ -0,0 +1,316 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + sortlit.cxx + +Abstract: + + This file contains the definitions for the SORTED_LIST_ITERATOR class. + SORTED_LIST_ITERATOR is a concrete implementation of the abstract ITERATOR + class. + +Author: + + Ramon J. San Andres ( ramonsa) 29-Oct-1991 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "sortlist.hxx" +#include "sortlit.hxx" + + +DEFINE_CAST_MEMBER_FUNCTION( SORTED_LIST_ITERATOR ); + +DEFINE_CONSTRUCTOR( SORTED_LIST_ITERATOR, ITERATOR ); + + +VOID +SORTED_LIST_ITERATOR::Construct ( + ) + +/*++ + +Routine Description: + + Construct a SORTED_LIST_ITERATOR + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + _List = NULL; +} + + + +SORTED_LIST_ITERATOR::~SORTED_LIST_ITERATOR ( + ) +/*++ + +Routine Description: + + Destructor for the SORTED_LIST_ITERATOR class + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ +#if DBG==1 + if ( _List ) { + _List->_IteratorCount--; + } +#endif +} + + +POBJECT +SORTED_LIST_ITERATOR::FindNext( + IN PCOBJECT Key + ) +/*++ + +Routine Description: + + Finds the next object in the list that matches the given key + +Arguments: + + Key - Supplies the key + +Return Value: + + POBJECT - Pointer to next member of the list that matches the key + +--*/ + +{ + + ULONG Index; + + // + // Wrap if necessary + // + if ( _CurrentIndex == INVALID_INDEX ) { + _CurrentIndex = 0; + } + + // + // If we are not at the end of the list, look for the next object + // that matches the key. + // + if ( _CurrentIndex < _List->QueryMemberCount()-1 ) { + + Index = _List->Search( Key, _CurrentIndex+1, _List->QueryMemberCount()-1 ); + + // + // If an object was found, set our currency and return the object + // + if ( Index < _List->QueryMemberCount() && + !Key->Compare(_List->_Array.GetAt( Index ))) { + + _CurrentIndex = Index; + return _List->_Array.GetAt( Index ); + } + } + + // + // No match, return NULL + // + _CurrentIndex = INVALID_INDEX; + return NULL; +} + + +POBJECT +SORTED_LIST_ITERATOR::GetCurrent( + ) +/*++ + +Routine Description: + + Gets current member + +Arguments: + + None + +Return Value: + + POBJECT - Pointer to current member in the array + +--*/ + +{ + if ( _CurrentIndex == INVALID_INDEX ) { + return NULL; + } else { + return _List->_Array.GetAt( _CurrentIndex ); + } +} + + + + +POBJECT +SORTED_LIST_ITERATOR::GetNext( + ) +/*++ + +Routine Description: + + Gets next member in the array + +Arguments: + + None + +Return Value: + + POBJECT - Pointer to next member in the array + +--*/ + +{ + // + // Wrap if necessary. Note that this assumes that INVALID_INDEX + 1 == 0 + // + _CurrentIndex++; + + if ( _CurrentIndex >= _List->_Array.QueryMemberCount() ) { + _CurrentIndex = INVALID_INDEX; + } + + // + // Get next + // + return _List->_Array.GetAt( _CurrentIndex ); +} + + +POBJECT +SORTED_LIST_ITERATOR::GetPrevious( + ) +/*++ + +Routine Description: + + Gets previous member in the array + +Arguments: + + None + +Return Value: + + POBJECT - Pointer to previous member in the array + +--*/ + +{ + // + // Wrap if necessary. Note that this assumes that 0 - 1 == INVALID_INDEX + // + _CurrentIndex--; + + if ( _CurrentIndex == INVALID_INDEX ) { + _CurrentIndex = _List->_Array.QueryMemberCount() - 1; + } + + // + // Get next + // + return _List->_Array.GetAt( _CurrentIndex ); +} + + + +VOID +SORTED_LIST_ITERATOR::Reset( + ) + +/*++ + +Routine Description: + + Resets the iterator + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + _CurrentIndex = INVALID_INDEX; +} + + + + +BOOLEAN +SORTED_LIST_ITERATOR::Initialize ( + IN PSORTED_LIST List + ) + +/*++ + +Routine Description: + + Associate a SORTED_LIST with this SORTED_LIST_ITERATOR and + reset the current index + +Arguments: + + List - Supplies pointer to the sorted list object + +Return Value: + + BOOLEAN - Returns TRUE if the initialization was succesful. + +--*/ + +{ + DebugPtrAssert( List ); + +#if DBG==1 + if ( _List ) { + _List->_IteratorCount--; + } + List->_IteratorCount++; +#endif + _List = List; + _CurrentIndex = INVALID_INDEX; + + + return TRUE; +} diff --git a/private/utils/ulib/src/sources b/private/utils/ulib/src/sources new file mode 100644 index 000000000..d3054eaea --- /dev/null +++ b/private/utils/ulib/src/sources @@ -0,0 +1,139 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=utils +MINORCOMP=ulib + +TARGETNAME=ulib +TARGETPATH=obj +TARGETTYPE=DYNLINK +TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib \ + $(BASEDIR)\public\sdk\lib\*\user32.lib \ + $(BASEDIR)\public\sdk\lib\*\advapi32.lib +DLLENTRY=InitializeUlib + +USE_CRTDLL=1 +BLDCRT=1 + +MSC_WARNING_LEVEL=/W3 /WX + +SOURCES=rtmsg.rc \ + arg.cxx \ + array.cxx \ + arrayit.cxx \ + basesys.cxx \ + bitvect.cxx \ + bytestrm.cxx \ + bufstrm.cxx \ + clasdesc.cxx \ + cmem.cxx \ + comm.cxx \ + contain.cxx \ + dir.cxx \ + file.cxx \ + filestrm.cxx \ + filter.cxx \ + fsnode.cxx \ + hmem.cxx \ + iterator.cxx \ + keyboard.cxx \ + list.cxx \ + listit.cxx \ + machine.cxx \ + mbstr.cxx \ + mem.cxx \ + membmgr.cxx \ + message.cxx \ + newdel.cxx \ + object.cxx \ + path.cxx \ + pipe.cxx \ + pipestrm.cxx \ + program.cxx \ + prtstrm.cxx \ + screen.cxx \ + seqcnt.cxx \ + smsg.cxx \ + sortcnt.cxx \ + sortlist.cxx \ + sortlit.cxx \ + stream.cxx \ + stringar.cxx \ + system.cxx \ + timeinfo.cxx \ + ulib.cxx \ + wstring.cxx + +i386_SOURCES=i386\dosttr.c + +INCLUDES=..\inc + +PRECOMPILED_INCLUDE= pch.cxx + +# +# Debug support. +# +# We have 4 levels: +# +# 1.- FREE: Non-debug +# 2.- NTDBG: Debug, no memleak +# 3.- MEMLEAK: 2 + memleak +# 4.- STACK_TRACE 3 + stack trace +# +# +# By default, whenever the NTDEBUG symbol is defined, you get level +# 3. In order to get level 2 you have to define the symbol NOMEMLEAK. +# In order to get level 4, you have to the file the symbol STACK_TRACE +# +# In summary here is how to get each one: +# +# 1.- Undefine NTDEBUG +# 2.- define NTDEBUG, define NOMEMLEAK +# 3.- define NTDEBUG, undefine NOMEMLEAK +# 4.- define NTDEBUG, undefine NOMEMLEAK, define STACK_TRACE +# +NO_NOTHIN=-DNO_COMMDLGH -DNO_LZEXPANDH -DNO_MMSYSTEMH -DNO_NB30H +!IF "$(NTDEBUG)" == "cvp" || "$(NTDEBUG)" == "ntsd" +!IFDEF NOMEMLEAK +C_DEFINES=-DCONDITION_HANDLING=1 -DDBG=1 -DUNICODE=1 $(NO_NOTHIN) +!ELSE # NOMEMLEAK +!IFDEF STACK_TRACE +C_DEFINES=-DCONDITION_HANDLING=1 -DDBG=1 -DMEMLEAK -DSTACK_TRACE -DUNICODE=1 $(NO_NOTHIN) +!ELSE # STACK_TRACE +C_DEFINES=-DCONDITION_HANDLING=1 -DDBG=1 -DMEMLEAK -DUNICODE=1 $(NO_NOTHIN) +!ENDIF # STACK_TRACE +!ENDIF # NOMEMLEAK +!ELSE # NTDEBUG +C_DEFINES=-DCONDITION_HANDLING=1 -DDBG=0 -DUNICODE=1 $(NO_NOTHIN) +!ENDIF # NTDEBUG + +CXXFLAGS=+d +UMLIBS=obj\*\ulib.lib + +UMTYPE=console + +UMTEST= + +NTTARGETFILE0=..\inc\rtmsg.h +DLLDEF= diff --git a/private/utils/ulib/src/spackmsg.cxx b/private/utils/ulib/src/spackmsg.cxx new file mode 100644 index 000000000..6ee09ebdb --- /dev/null +++ b/private/utils/ulib/src/spackmsg.cxx @@ -0,0 +1,182 @@ +/*++ + +Copyright (c) 1991-1994 Microsoft Corporation + +Module Name: + + spackmsg.cxx + +Abstract: + + Contains the implementation of the SP_AUTOCHECK_MESSAGE subclass. + +Author: + + Lonny McMichael (lonnym) 09-Jun-94 + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "spackmsg.hxx" + + +DEFINE_CONSTRUCTOR(SP_AUTOCHECK_MESSAGE, AUTOCHECK_MESSAGE); + +SP_AUTOCHECK_MESSAGE::~SP_AUTOCHECK_MESSAGE( + ) +/*++ + +Routine Description: + + Destructor for SP_AUTOCHECK_MESSAGE. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + Destroy(); +} + + +VOID +SP_AUTOCHECK_MESSAGE::Construct( + ) +/*++ + +Routine Description: + + This routine initializes the object to a default initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + // + // nothing to do + // +} + + +VOID +SP_AUTOCHECK_MESSAGE::Destroy( + ) +/*++ + +Routine Description: + + This routine returns the object to a default initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + // + // nothing to do + // +} + + +BOOLEAN +SP_AUTOCHECK_MESSAGE::DisplayV( + IN PCSTR Format, + IN va_list VarPointer + ) +/*++ + +Routine Description: + + This routine outputs the message to the debugger (if checked build). + + The format string supports all printf options. + +Arguments: + + Format - Supplies a printf style format string. + VarPointer - Supplies a varargs pointer to the arguments. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + CHAR buffer[256]; + DSTRING display_string; + + if (!BASE_SYSTEM::QueryResourceStringV(&display_string, _msgid, Format, + VarPointer)) { + return FALSE; + } + + // + // Send the output to the debug port. + // + if( display_string.QuerySTR( 0, TO_END, buffer, 256, TRUE ) ) { + DebugPrint(buffer); + return TRUE; + } else { + return FALSE; + } +} + + +BOOLEAN +SP_AUTOCHECK_MESSAGE::IsYesResponse( + IN BOOLEAN Default + ) +/*++ + +Routine Description: + + This routine queries a response of yes or no. + +Arguments: + + Default - Supplies a default in the event that a query is not possible. + +Return Value: + + FALSE - The answer is no. + TRUE - The answer is yes. + +--*/ +{ + CHAR buffer[256]; + DSTRING string; + + if (!BASE_SYSTEM::QueryResourceString(&string, Default ? MSG_YES : MSG_NO, "")) { + return Default; + } + + // + // Send the output to the debug port. + // + if( string.QuerySTR( 0, TO_END, buffer, 256, TRUE ) ) { + DebugPrint(buffer); + } + + return Default; +} + diff --git a/private/utils/ulib/src/stream.cxx b/private/utils/ulib/src/stream.cxx new file mode 100644 index 000000000..d6cdc811c --- /dev/null +++ b/private/utils/ulib/src/stream.cxx @@ -0,0 +1,512 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + stream.cxx + +Abstract: + + This module contains the definitions of the member functions + of STREAM class. + +Author: + + Jaime Sasson (jaimes) 24-Mar-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "mbstr.hxx" +#include "wstring.hxx" +#include "stream.hxx" +#include "system.hxx" + +extern "C" { + #include <ctype.h> +} + +DEFINE_CONSTRUCTOR ( STREAM, OBJECT ); + + +STREAM::~STREAM ( + ) + +/*++ + +Routine Description: + + Destroy a STREAM. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ +} + + + +BOOLEAN +STREAM::ReadByte( + OUT PBYTE Data + ) + +/*++ + +Routine Description: + + Reads one byte from the stream. + +Arguments: + + Data - Address of the variable that will contain the byte read. + + +Return Value: + + BOOLEAN - Returns TRUE if the read operation succeeded. + + +--*/ + + +{ + ULONG BytesRead; + + DebugPtrAssert( Data ); + if( Read( Data, sizeof( BYTE ), &BytesRead ) && + ( BytesRead == sizeof( BYTE ) ) ) { + return( TRUE ); + } else { + return( FALSE ); + } +} + + + +ULIB_EXPORT +BOOLEAN +STREAM::ReadLine( + OUT PWSTRING String, + IN BOOLEAN Unicode + ) + +/*++ + +Routine Description: + + Reads a line from the stream. + A line is sequence of WCHARs, terminated by '\n' or '\r\n'. + The delimiters are not returned in the string, but are removed + from the stream. + +Arguments: + + String - Pointer to an initialized string object. This object + will contain the string read from the stream, without the + delimiters. + +Return Value: + + BOOLEAN - Returns TRUE if the operation succeeded, and String points to + a valid WSTRING. + Returns FALSE otherwise. + + +--*/ + + +{ + WCHAR Wchar; + CHNUM StringSize; + + DebugPtrAssert( String ); + // + // Read a string from the stream + // + if( !ReadString( String, &_Delimiter , Unicode) ) { + DebugAbort( "ReadString() failed \n" ); + return( FALSE ); + } + // + // If a string was successfully read, then we have to remove the + // delimiter from the stream + // + if( !IsAtEnd() ) { + // + // Read the delimiter + // + if( !ReadChar( &Wchar , Unicode) ) { + DebugAbort( "ReadChar() failed \n" ); + return( FALSE ); + } + } + // Also, we have to check if last character in the string is \r. + // If it is, then we remove it. + // + StringSize = String->QueryChCount(); + StringSize--; + if( String->QueryChAt( StringSize ) == ( WCHAR )'\r' ) { + String->Truncate( StringSize ); + } + + +/* + if( !IsAtEnd() ) { + // + // Read the first delimiter + // + if( !ReadChar( &Wchar, Unicode ) ) { + DebugAbort( "ReadChar() failed \n" ); + return( FALSE ); + } + if( Wchar == ( WCHAR )'\r' ) { + // + // If the delimiter read was '\r' then there is a second + // delimiter ('\n') and we have to remove it from the stream + // + if( !IsAtEnd() ) { + if( !ReadChar( &Wchar, Unicode ) ) { + DebugAbort( "ReadChar() failed \n" ); + return( FALSE ); + } + } + } + } +*/ + return( TRUE ); +} + + +ULIB_EXPORT +BOOLEAN +STREAM::ReadMbLine( + IN PSTR String, + IN DWORD BufferSize, + INOUT PDWORD StringSize, + IN BOOLEAN ExpandTabs, + IN DWORD TabExp + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + + +{ + + BYTE Char; + + + DebugPtrAssert( String ); + DebugPtrAssert( BufferSize ); + DebugPtrAssert( StringSize ); + + // + // Read a string from the stream + // Note that ReadMbString will remove the delimiter from the stream, + // in order to improve performance of FC and Find + // + if( !ReadMbString( String, BufferSize, StringSize, _MbDelimiter, ExpandTabs, TabExp ) ) { + DebugAbort( "ReadMbString() failed \n" ); + return( FALSE ); + } + + + // Also, we have to check if last character in the string is \r. + // If it is, then we remove it. + // + if ( (*StringSize > 0 ) && (String[*StringSize-1] == '\r') ) { + (*StringSize)--; + String[*StringSize] = '\0'; + } + + return( TRUE ); +} + + + +ULIB_EXPORT +BOOLEAN +STREAM::ReadWLine( + IN PWSTR String, + IN DWORD BufferSize, + INOUT PDWORD StringSize, + IN BOOLEAN ExpandTabs, + IN DWORD TabExp + ) + +/*++ + +Routine Description: + + +Arguments: + + +Return Value: + + +--*/ + + +{ + + WCHAR Char; + + + DebugPtrAssert( String ); + DebugPtrAssert( BufferSize ); + DebugPtrAssert( StringSize ); + + // + // Read a string from the stream + // Note that ReadWString will remove the delimiter from the stream, + // in order to improve performance of FC and Find + // + if( !ReadWString( String, BufferSize, StringSize, _WDelimiter, ExpandTabs, TabExp ) ) { + DebugAbort( "ReadWString() failed \n" ); + return( FALSE ); + } + + + // Also, we have to check if last character in the string is \r. + // If it is, then we remove it. + // + if ( (*StringSize > 0 ) && (String[*StringSize-1] == L'\r') ) { + (*StringSize)--; + String[*StringSize] = 0; + } + + return( TRUE ); +} + + + +BOOLEAN +STREAM::Write( + IN PCBYTE Buffer, + IN ULONG BytesToWrite, + OUT PULONG BytesWritten + ) + +/*++ + +Routine Description: + + Writes data to the stream. + +Arguments: + + Buffer - Points to the buffer that contains the data to be written. + + BytesToWrite - Indicates total number of bytes to write. + + BytesWritten - Points to the variable that will contain the number of + bytes actually written. + +Return Value: + + BOOLEAN - Returns TRUE if the write operation succeeded. + + +--*/ + + +{ + DebugPtrAssert( Buffer ); + DebugPtrAssert( BytesWritten ); + + if( QueryAccess() != READ_ACCESS ) { + return( WriteFile( QueryHandle(), + (LPVOID)Buffer, + BytesToWrite, + BytesWritten, + NULL + ) ); + } else { + return( FALSE ); + } +} + + + +ULIB_EXPORT +BOOLEAN +STREAM::WriteByte( + IN BYTE Data + ) + +/*++ + +Routine Description: + + Writes one byte to the stream. + +Arguments: + + Data - Byte to be written. + +Return Value: + + BOOLEAN - Returns TRUE if the write operation succeeded. + + +--*/ + + +{ + ULONG BytesWritten = 0; + + if( Write( &Data, sizeof( BYTE ), &BytesWritten ) && + ( BytesWritten == sizeof( BYTE ) ) ) { + return( TRUE ); + } else { + return( FALSE ); + } +} + + +BOOLEAN +STREAM::WriteChar( + IN WCHAR Char + ) + +/*++ + +Routine Description: + + Writes one character to the stream, Doing wide character - to - + multibyte conversion before writting + +Arguments: + + Char - Supplies character to be converted and written + +Return Value: + + TRUE if character converted and written. FALSE otherwise + + +--*/ + + +{ + + BYTE Buffer[ 2 ]; // FIX, FIX - can this be anything but 2? + USHORT BytesToWrite; + ULONG BytesWritten; + BOOLEAN Result = FALSE; + + BytesToWrite = (USHORT)wctomb( (char *)Buffer, (wchar_t)Char ); + + if ( BytesToWrite > 0 ) { + + Result = Write( Buffer, BytesToWrite, &BytesWritten ); + + if ( BytesWritten != BytesToWrite) { + Result =FALSE; + } + } + + return Result; +} + + + +BOOLEAN +STREAM::WriteString( + IN PCWSTRING String, + IN CHNUM Position, + IN CHNUM Length, + IN CHNUM Granularity + ) + +/*++ + +Routine Description: + + Writes a string to the stream. + +Arguments: + + String - Pointer to a STRING object. + Position - Starting character within the string + Length - Number of characters to write + Granularity - The maximum number of bytes to write at one time. + A value of 0 indicates to write it all at once. + +Return Value: + + BOOLEAN - Returns TRUE if the write operation succeeded. + + +--*/ + + +{ + ULONG BytesWritten = 0; + BOOLEAN Result = TRUE; + ULONG Size, i, to_write; + PBYTE Buffer; + + DebugPtrAssert( String ); +#if defined(DBCS) + // + // let convert unicode string to oem string with current console codepage. + // + String->SetConsoleConversions(); +#endif // defined(DBCS) + Buffer = (PBYTE)String->QuerySTR( Position, Length ); + + Size = strlen((char *)Buffer); + + if (!Granularity) { + Granularity = Size; + } + + Result = TRUE; + for (i = 0; Result && i < Size; i += Granularity) { + + to_write = min(Granularity, Size - i); + + Result = Write( Buffer + i, to_write, &BytesWritten ) && + to_write == BytesWritten; + } + +#if defined(DBCS) + // + // Reset/Back to conversion mode. + // + String->ResetConversions(); +#endif // defined(DBCS) + + FREE( Buffer ); + return( Result ); +} diff --git a/private/utils/ulib/src/string.cxx b/private/utils/ulib/src/string.cxx new file mode 100644 index 000000000..87070a83d --- /dev/null +++ b/private/utils/ulib/src/string.cxx @@ -0,0 +1,84 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + GENERIC_STRING + +Abstract: + + This module contains the implementation for the GENERIC_STRING class. + +Author: + + Ramon J. San Andres (ramonsa) 07-May-1991 + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "string.hxx" + + +DEFINE_CONSTRUCTOR( GENERIC_STRING, OBJECT ); + +DEFINE_CAST_MEMBER_FUNCTION( GENERIC_STRING ); + +GENERIC_STRING::~GENERIC_STRING( + ) +{ +} + +VOID +GENERIC_STRING::Construct ( + ) + +/*++ + +Routine Description: + + Constructs a GENERIC_STRING object + +Arguments: + + None. + +Return Value: + + None. + + +--*/ + +{ +} + +BOOLEAN +GENERIC_STRING::Initialize ( + ) + +/*++ + +Routine Description: + + Phase 2 of construction for a GENERIC_STRING. + +Arguments: + + none + +Return Value: + + TRUE if the string was successfully initialized, + FALSE otherwise. + +--*/ + +{ + return TRUE; +} diff --git a/private/utils/ulib/src/stringar.cxx b/private/utils/ulib/src/stringar.cxx new file mode 100644 index 000000000..bea260c91 --- /dev/null +++ b/private/utils/ulib/src/stringar.cxx @@ -0,0 +1,210 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + stringar.cxx + +Abstract: + + This module contains the implementation of the STRING_ARRAY class. + STRING_ARRAY is used only to store strings, and it provides a + method to sort the strings in ascending or descending order. + The sort methods uses the qsort() function of the C run time + library. + +Author: + + Jaime F. Sasson (jaimes) 01-May-1991 + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "array.hxx" +#include "wstring.hxx" +#include "stringar.hxx" + +#if defined( __BCPLUSPLUS__ ) + + #include <search.h> + +#else + + extern "C" { + #include <search.h> + }; + +#endif // __BCPLUSPLUS__ + +CHNUM STRING_ARRAY::_Position; +BOOLEAN STRING_ARRAY::_Ascending; + +DEFINE_EXPORTED_CONSTRUCTOR( STRING_ARRAY, ARRAY, ULIB_EXPORT ); + + +ULIB_EXPORT +BOOLEAN +STRING_ARRAY::Initialize ( + IN CHNUM Position, + IN ULONG Capacity, + IN ULONG CapacityIncrement + ) + +/*++ + +Routine Description: + + Initialize a STRING_ARRAY object by setting it's internal state to s + upplied or default values. + +Arguments: + + Position - Supplies the position in each string to be used as + strating position when sorting the array. + Capacity - Supplies the total number of WSTRINGs the + STRING_ARRAY can contain. + CapacityIncrement - Supplies the number of OBJECTs to make room for + when growing the STRING_ARRAY + + +Return Value: + + BOOLEAN - TRUE if the ARRAY is successfully initialized. + +--*/ + +{ + _Position = Position; + return( ARRAY::Initialize( Capacity, CapacityIncrement ) ); +} + + + +ULIB_EXPORT +BOOLEAN +STRING_ARRAY::Sort ( + BOOLEAN Ascending + ) + +/*++ + +Routine Description: + + Sorts the array in ascending or descending order, depending + on the parameter passed. + +Arguments: + + Ascending - Specifies if the sort is to be performed in ascending (TRUE) + or descending (FALSE) order. + +Return Value: + + BOOLEAN - + +--*/ + +{ + _Ascending = Ascending; + + qsort( GetObjectArray(), + ( size_t )QueryMemberCount(), + sizeof( PWSTRING ), + &STRING_ARRAY::StringCompare ); + + return( TRUE ); +} + + + +int _CRTAPI1 +STRING_ARRAY:: +StringCompare ( + IN const void * String1, + IN const void * String2 + ) + +/*++ + +Routine Description: + + This function is used by qsort(), and it compares *String1 + and *String2. The string used as key depends on the value + of _Ascending. + If _Ascending == TRUE, then it uses *String1 as a key. + If _Ascending == FALSE, then it uses *String2 as a key. + +Arguments: + + *String1 - Pointer to a string object. + + *String2 - Pointer to a string object. + +Return Value: + + Returns: + + if _Ascending == TRUE, then it returns + -1 if **String1 is less that **String2 + 0 if **String1 is equal to **String2 + 1 if **String1 is greater than **String2 + + if _Ascending == FALSE, then it returns + -1 if **String2 is less that **String1 + 0 if **String2 is equal to **String1 + 1 if **String2 is greater than **String1 + +--*/ + +{ + PCWSTRING St1; + PCWSTRING St2; + CHNUM Position1; + CHNUM Length1; + CHNUM Position2; + CHNUM Length2; +// char name[256]; +// LONG result; + + if( _Ascending ) { + St1 = *(PCWSTRING *)String1; + St2 = *(PCWSTRING *)String2; + } else { + St1 = *(PCWSTRING *)String2; + St2 = *(PCWSTRING *)String1; + } + Length1 = St1->QueryChCount(); + Position1 = ( Length1 >= _Position ) ? _Position : Length1; + Length1 -= Position1; + Length2 = St2->QueryChCount(); + Position2 = ( Length2 >= _Position ) ? _Position : Length2; + Length2 -= Position2; +/* + St1->QueryApiString(name, 256); + printf( "Length1 = %d, Position1 = %d, %s \n", Length1, Position1, name ); + St2->QueryApiString(name, 256); + printf( "Length2 = %d, Position2 = %d, %s \n", Length2, Position2, name ); + result = St1->StringCompare( Position1, + Length1, + St2, + Position2, + Length2, + CF_IGNORECASE ); + printf( "Result = %d \n", result ); + return( result ); +*/ + return( St1->Stricmp( St2, + Position1, + Length1, + Position2, + Length2 ) ); +} diff --git a/private/utils/ulib/src/substrng.cxx b/private/utils/ulib/src/substrng.cxx new file mode 100644 index 000000000..982719630 --- /dev/null +++ b/private/utils/ulib/src/substrng.cxx @@ -0,0 +1,1197 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + SUB_STRING + +Abstract: + + Implementation of the SUB_STRING class. + +Author: + + Stve Rowe (stever) + +Environment: + + ULIB, User Mode + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "substrng.hxx" + + +#if DBG==1 + #define SUBSTRING_SIGNATURE 0xADDCACA1 +#endif + + + + +DEFINE_CONSTRUCTOR( SUB_STRING, GENERIC_STRING ); + +DEFINE_CAST_MEMBER_FUNCTION( SUB_STRING ); + +VOID +SUB_STRING::Construct ( + ) + +/*++ + +Routine Description: + + Construct a SUBS_TRING by initializing it's internal state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + _BaseString = NULL; + +#if DBG==1 + _Signature = SUBSTRING_SIGNATURE; + _Initialized = FALSE; +#endif +} + +SUB_STRING::~SUB_STRING () + +{ + Destroy(); +} + +VOID +SUB_STRING::Destroy ( + ) + +/*++ + +Routine Description: + + Detaches this substring from the chain (if it belongs to one). + +Arguments: + + none + +Return Value: + + none + +--*/ + +{ + if ( _BaseString != NULL ) { + // + // We extract ourselves from the substring chain + // + if (_Previous) { + + // + // Update the previous in the chain + // + DebugAssert( _Previous->_Signature == SUBSTRING_SIGNATURE ); + _Previous->_Next = _Next; + + } + + if ( _Next ) { + + // + // Update the next in the chain + // + DebugAssert( _Next->_Signature == SUBSTRING_SIGNATURE ); + _Next->_Previous = _Previous; + + } + + } + + // + // Forget everything about our previous life + // + _BaseString = NULL; + _CountOfChars = 0; + _StartingPosition = 0; + _Next = _Previous = NULL; + +#if DBG==1 + _Initialized = FALSE; +#endif + +} + +BOOLEAN +SUB_STRING::InitializeChainHead ( + IN PGENERIC_STRING BaseString + ) + +/*++ + +Routine Description: + + Initializes the substring with a base string. This should be called + only for the head of the substring chain. + +Arguments: + + BaseString - Supplies pointer to base string + +Return Value: + + TRUE + +--*/ + +{ + DebugPtrAssert( BaseString ); + + DebugAssert( _BaseString == NULL ); + + Destroy(); + + GENERIC_STRING::Initialize(); + + _BaseString = BaseString; + +#if DBG==1 + _Initialized = TRUE; +#endif + + return TRUE; + +} + +BOOLEAN +SUB_STRING::InitializeChainNode ( + IN OUT PSUB_STRING SubString, + IN CHNUM Position, + IN CHNUM Length + ) + +/*++ + +Routine Description: + + Links this substring to a substring chain. + + This method should ONLY be used by a string class, who knows about string + chains. + +Arguments: + + SubString - Supplies pointer to a substring in the chain. + Position - Supplies the starting position value for this substring. + Note that this is relative to the BASE string. + Length - Supplies Number of Characters in substring. + +Return Value: + + TRUE + +--*/ + +{ + + // + // It is a bug to call this method on a substring that already belongs + // to a chain. + // + DebugAssert( SubString && (SubString->_Signature == SUBSTRING_SIGNATURE) ); + DebugAssert( _BaseString == NULL ); + + Destroy(); + + GENERIC_STRING::Initialize(); + + // + // Initialize our pointers and counters + // + _StartingPosition = Position; + _CountOfChars = Length; + + // + // Add ourselves to the substring chain + // + _BaseString = SubString->_BaseString; + _Next = SubString->_Next; + _Previous = SubString; + + SubString->_Next = this; + + if (_Next) { + DebugAssert( _Next->_Signature == SUBSTRING_SIGNATURE ); + _Next->_Previous = this; + } + +#if DBG==1 + _Initialized = TRUE; +#endif + + return TRUE; + +} + +PBYTE +SUB_STRING::GetInternalBuffer ( + IN CHNUM Position + ) CONST + +/*++ + +Routine Description: + + Gets pointer to buffer containing the string. + +Arguments: + + none + +Return Value: + + Pointer to the buffer + +--*/ +{ + + DebugAssert( Position < _CountOfChars ); + + return _BaseString->GetInternalBuffer( _StartingPosition + Position ); + +} + +BOOLEAN +SUB_STRING::IsChAt ( + IN WCHAR Ch, + IN CHNUM Position + ) CONST + +/*++ + +Routine Description: + + Finds out if a certain character is at the specified position. + +Arguments: + + Ch - Supplies the character to llok for + Position - Supplies the position to look at + +Return Value: + + TRUE if the character is at the specified position + +--*/ + +{ + DebugAssert( _StartingPosition + Position < _CountOfChars ); + + return ( QueryChAt( Position ) == Ch ); + +} + +BOOLEAN +SUB_STRING::MakeNumber ( + OUT PLONG Number, + IN CHNUM Position, + IN CHNUM Length + ) CONST + +/*++ + +Routine Description: + + Converts the string to a number. + +Arguments: + + Number - Pointer to returned number + Position - Supplies the starting position + Length - Supplies the length + + +Return Value: + + TRUE if made a valid number + FALSE otherwise + +--*/ + +{ + GetValidLength( Position, &Length ); + + return _BaseString->MakeNumber( Number, _StartingPosition + Position, Length ); +} + +ULONG +SUB_STRING::QueryByteCount ( + IN CHNUM Position, + IN CHNUM Length + ) CONST + +/*++ + +Routine Description: + + Gets the number of bytes in the buffer containing this substring + +Arguments: + + Position - Supplies the starting position + Length - Supplies the length + + +Return Value: + + Number of bytes in buffer. + +--*/ + +{ + + GetValidLength( Position, &Length ); + + return _BaseString->QueryByteCount( _StartingPosition + Position, Length ); +} + +CHNUM +SUB_STRING::QueryChCount ( + ) CONST + +/*++ + +Routine Description: + + Returns the number of characters in this substring. + +Arguments: + + None. + +Return Value: + + The number of characters in this substring. + +--*/ + +{ + DebugAssert( _Initialized ); + return _CountOfChars; +} + +WCHAR +SUB_STRING::QueryChAt( + IN CHNUM Position + ) CONST + +/*++ + +Routine Description: + + returns the character at the supplied position. + +Arguments: + + Position - Supplies the character position. + +Return Value: + + Returns the character at the supplied position. + +--*/ + +{ + DebugAssert( Position < _CountOfChars ); + + if ( Position < _CountOfChars ) { + return _BaseString->QueryChAt( _StartingPosition + Position ); + } else { + return INVALID_CHAR; + } +} + + +PGENERIC_STRING +SUB_STRING::QueryGenericString( + IN CHNUM Position, + IN CHNUM Length + ) CONST + +/*++ + +Routine Description: + + Obtains a string off this substring + +Arguments: + + Position - Supplies the character position. + Length - Supplies the length of the substring + +Return Value: + + Pointer to the string + +--*/ + +{ + GetValidLength( Position, &Length ); + + return _BaseString->QueryGenericString( _StartingPosition + Position, Length ); + +} + +PSTR +SUB_STRING::QuerySTR( + IN CHNUM Position, + IN CHNUM Length, + IN OUT PSTR Buffer, + IN ULONG BufferSize + ) CONST + + + +/*++ + +Routine Description: + + Obtains a null-terminated multibyte string ( PSTR ) + +Arguments: + + Position - Supplies starting position + Length - Supplies length (in characters) of substring desired + Buffer - Supplies optional pointer to buffer + BufferSize - Supplies length of the buffer (in bytes) + +Return Value: + + Pointer to PSTR + + +--*/ + +{ + + GetValidLength( Position, &Length ); + + return _BaseString->QuerySTR( _StartingPosition + Position, + Length, + Buffer, + BufferSize ); + + +} + +PSUB_STRING +SUB_STRING::QuerySubString( + IN CHNUM Position, + IN CHNUM Length, + OUT PSUB_STRING SubString + ) + +/*++ + +Routine Description: + + Obtains a substring of this string + +Arguments: + + Position - Supplies the character position. + Length - Supplies the length of the substring + SubString - Supplies optional pointer to SUB_STRING object + +Return Value: + + Pointer to the substring + +--*/ + +{ + GetValidLength( Position, &Length ); + + if (SubString == NULL) { + SubString = NEW SUB_STRING; + } + + if (SubString) { + + SubString->InitializeChainNode( this, _StartingPosition + Position, Length ); + + } + + return SubString; + +} + +PWSTR +SUB_STRING::QueryWSTR ( + IN CHNUM Position, + IN CHNUM Length, + IN OUT PWSTR Buffer, + IN ULONG BufferSize, + IN BOOLEAN ForceNull + ) CONST + +/*++ + +Routine Description: + + Obtains a null-terminated wide character string ( PWSTR ) + +Arguments: + + Position - Supplies starting position + Length - Supplies length (in characters) of substring desired + Buffer - Supplies optional pointer to buffer + BufferSize - Supplies length of the buffer (in bytes) + ForceNull - Supplies a flag which indicates, if TRUE, that the + returned string must be null-terminated. If this + flag is not FALSE, QueryWSTR will return as much + of the string as fits in the buffer; if it is TRUE, + QueryWSTR will return as much as fits in the buffer + minus one character for the terminating NULL. + + +Return Value: + + Pointer to PWSTR + + +--*/ + +{ + GetValidLength( Position, &Length ); + + return _BaseString->QueryWSTR( _StartingPosition + Position, + Length, + Buffer, + BufferSize, + ForceNull ); + +} + +CHNUM +SUB_STRING::Strchr ( + IN WCHAR Char, + IN CHNUM Position, + IN CHNUM Length + ) CONST + +/*++ + +Routine Description: + + Searches for first occurence of a character in the string + +Arguments: + + Char - Supplies character to match + Position - Supplies index of first character where search + will start. + Length - Supplies length of the subsequence in which to + search. + +Return Value: + + + Index within the string where the character was found. + +--*/ + +{ + CHNUM Pos; + + GetValidLength( Position, &Length ); + + Pos = _BaseString->Strchr( Char, + _StartingPosition + Position, + Length ); + + return (Pos == INVALID_CHNUM) ? INVALID_CHNUM : Pos - _StartingPosition; + +} + +LONG +SUB_STRING::Strcmp ( + IN PCGENERIC_STRING GenericString + ) CONST + +/*++ + +Routine Description: + + Does a case sensitive string compare. + +Arguments: + + GenericString - Supplies a pointer to string to compare against + +Return Value: + + == 0 - strings are equal + <0 - this string is less then StringToCompare + >0 - this string is greater then StringToCompare + +--*/ + +{ + return _BaseString->StringCompare( _StartingPosition, + _CountOfChars, + GenericString, + 0, + GenericString->QueryChCount() ); +} + +CHNUM +SUB_STRING::Strcspn ( + IN PCGENERIC_STRING GenericString, + IN CHNUM Position, + IN CHNUM Length + ) CONST + +/*++ + +Routine Description: + + Returns index of the first character that belongs to the set of + characters provided in the generic string. + +Arguments: + + GenericString - Supplies the string to match from + Position - Supplies position where match should start + Length - Supplies the length of the subsequence in which to + search. + + +Return Value: + + Index of the character that matched. + +--*/ + +{ + CHNUM Pos; + + GetValidLength( Position, &Length ); + + Pos = _BaseString->Strcspn( GenericString, + _StartingPosition + Position, + Length ); + + return (Pos == INVALID_CHNUM) ? INVALID_CHNUM : Pos - _StartingPosition; + +} + +LONG +SUB_STRING::Stricmp ( + IN PCGENERIC_STRING GenericString + ) CONST + +/*++ + +Routine Description: + + Does a case insensitive string compare. + +Arguments: + + String - Supplies a pointer to string to compare against + +Return Value: + + == 0 - strings are equal + <0 - this string is less then StringToCompare + >0 - this string is greater then StringToCompare + +--*/ + +{ + return _BaseString->StringCompare( _StartingPosition, + _CountOfChars, + GenericString, + 0, + GenericString->QueryChCount(), + COMPARE_IGNORECASE ); +} + +LONG +SUB_STRING::StringCompare ( + IN CHNUM Position1, + IN CHNUM Length1, + IN PCGENERIC_STRING GenericString2, + IN CHNUM Position2, + IN CHNUM Length2, + IN USHORT CompareFlags + ) CONST + +/*++ + +Routine Description: + + Compares this string with another one + +Arguments: + + Position1 - Supplies Index within this string + Length1 - Supplies Length within this string + GenericString2 - Supplies other string + Position2 - Supplies index within other string + Length2 - Supplies length of other string + CompareFlags - Supplies compare flags + +Return Value: + + < 0 if this string lexically less than other + 0 if both strings the same + > 0 if other string lexically more than this one + +--*/ +{ + GetValidLength( Position1, &Length1 ); + + return _BaseString->StringCompare( _StartingPosition + Position1, + Length1, + GenericString2, + Position2, + Length2, + CompareFlags ); +} + +CHNUM +SUB_STRING::Strrchr ( + IN WCHAR Char, + IN CHNUM Position, + IN CHNUM Length + ) CONST + +/*++ + +Routine Description: + + Finds last occurrence of the character to match in the string. + +Arguments: + + Char - Supplies the character to match + Position - Supplies the starting position + Length - Supplies length of subsequence in which to search. + +Return Value: + + Index of last occurence of the character + +--*/ + +{ + CHNUM Pos; + + GetValidLength( Position, &Length ); + + Pos = _BaseString->Strrchr( Char, + _StartingPosition + Position, + Length ); + + return (Pos == INVALID_CHNUM) ? INVALID_CHNUM : Pos - _StartingPosition; +} + +CHNUM +SUB_STRING::StrLen ( + ) CONST + +/*++ + +Routine Description: + + Returns the number of characters in this substring. + +Arguments: + + None. + +Return Value: + + The number of characters in this substring. + +--*/ + +{ + return _CountOfChars; +} + +CHNUM +SUB_STRING::Strspn ( + IN PCGENERIC_STRING GenericString, + IN CHNUM Position, + IN CHNUM Length + ) CONST + +/*++ + +Routine Description: + + Returns index of the first character in the string that + does not belong to the set of characters in the string to match. + +Arguments: + + String - Supplies pointer to string to match from + Position - Supplies initial position to start search + Length - Supplies length. + +Return Value: + + Index of the first character that does not belong to the set + of characters in the string passed. + +--*/ + +{ + CHNUM Pos; + + GetValidLength( Position, &Length ); + + Pos = _BaseString->Strspn( GenericString, + _StartingPosition + Position, + Length ); + + return (Pos == INVALID_CHNUM) ? INVALID_CHNUM : Pos - _StartingPosition; +} + +CHNUM +SUB_STRING::Strstr ( + IN PCGENERIC_STRING GenericString, + IN CHNUM Position, + IN CHNUM Length + ) CONST + +/*++ + +Routine Description: + + Returns the index of the first occurrence of a string within us. + +Arguments: + + GenericString - Supplies pointer to string to match from + Position - Supplies initial position to start search + Length - Supplies the length of the subsequence in which to + search. + +Return Value: + + Index of first occurence of the string + +--*/ + +{ + + CHNUM Pos; + + GetValidLength( Position, &Length ); + + Pos = _BaseString->Strstr( GenericString, + _StartingPosition + Position, + Length ); + + return (Pos == INVALID_CHNUM) ? INVALID_CHNUM : Pos - _StartingPosition; +} + + +BOOLEAN +SUB_STRING::Replace ( + IN PCGENERIC_STRING String2, + IN CHNUM Position, + IN CHNUM Length, + IN CHNUM Position2, + IN CHNUM Length2 + ) + +/*++ + +Routine Description: + + Illegal method in SUB_STRING + +Arguments: + + String2 - Supplies pointer to other string + Position - Suplies the starting position to start copy + Lengh - Supplies the length of the portion to replace + Position2 - Supplies position in other string + Length2 - Supplies length to copy + +Return Value: + + FALSE + +--*/ + +{ + UNREFERENCED_PARAMETER( String2 ); + UNREFERENCED_PARAMETER( Position ); + UNREFERENCED_PARAMETER( Length ); + UNREFERENCED_PARAMETER( Position2 ); + UNREFERENCED_PARAMETER( Length2 ); + + DebugAssert( FALSE ); + return FALSE; +} + +BOOLEAN +SUB_STRING::SetChAt( + IN WCHAR Char, + IN CHNUM Position, + IN CHNUM Length + ) + +/*++ + +Routine Description: + + Illegal method in SUB_STRING + +Arguments: + + Char - Supplies the character to set. + Position - Supplies the character position to set. + Length - Supplies the number of characters to set. + +Return Value: + + FALSE + +--*/ + +{ + UNREFERENCED_PARAMETER( Char ); + UNREFERENCED_PARAMETER( Position ); + UNREFERENCED_PARAMETER( Length ); + + DebugAssert( FALSE ); + return FALSE; + +} + +BOOLEAN +SUB_STRING::Update ( + IN CHNUM Length + ) + +/*++ + +Routine Description: + + Updates a substring. When the length of the base string changes, the + new length has to be propagated along the substring chain, so that + substrings are maintained up-to-date. Each substring is responsible + for propagating the new length to its successors in the chain. + + +Arguments: + + Length - Supplies the new length of the base string + + +Return Value: + + TRUE if updated, FALSE otherwise. + +--*/ + +{ + + // + // Set the new starting position + // + _StartingPosition = min ( _StartingPosition, Length - 1); + + // + // Set the new length + // + if ( _StartingPosition + _CountOfChars > Length ) { + + _CountOfChars = Length - _StartingPosition; + } + + // + // Propagate along the chain + // + if ( _Next ) { + + DebugAssert( _Next->_Signature == SUBSTRING_SIGNATURE ); + return _Next->Update( Length ); + } + + return TRUE; + +} + + +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + DYNAMIC_SUB_STRING + +Abstract: + + Implementation of the DYNAMIC_SUB_STRING class. + +Author: + + Stve Rowe (stever) + +Environment: + + ULIB, User Mode + +--*/ + +DEFINE_CONSTRUCTOR( DYNAMIC_SUB_STRING, SUB_STRING); + +VOID +DYNAMIC_SUB_STRING::Construct ( + ) + +{ + UNREFERENCED_PARAMETER( (void)this ); +} + +BOOLEAN +DYNAMIC_SUB_STRING::Copy ( + IN PCGENERIC_STRING GenericString + ) +/*++ + +Routine Description: + + Copies one substring to another. The size of the substring changes + +Arguments: + + None. + +Return Value: + + TRUE if copied, false otherwise + +--*/ + +{ + + DebugPtrAssert( GenericString ); + + if ( GetBaseString()->Replace( GenericString, + QueryStartingPosition(), + QueryChCount(), + 0, + GenericString->QueryChCount() )) { + // + // Update the length + // + SetChCount( GenericString->QueryChCount()); + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +DYNAMIC_SUB_STRING::SetChAt( + IN WCHAR Char, + IN CHNUM Position, + IN CHNUM Length + ) + +/*++ + +Routine Description: + + Sets the specified number of characters, starting at a certain + position, with the supplied character. + +Arguments: + + Char - Supplies the character to set. + Position - Supplies the character position to set. + Length - Supplies the number of characters to set. + +Return Value: + + BOOLEAN - Returns TRUE if the characters were succesfully set. + +--*/ + +{ + + GetValidLength( Position, &Length ); + + return GetBaseString()->SetChAt( Char, + QueryStartingPosition() + Position, + Length ); + +} + +CHNUM +DYNAMIC_SUB_STRING::Truncate( + IN CHNUM Position + ) + +/*++ + +Routine Description: + + Truncates the substring at the specified position. The corresponding + part of the base string is chopped out. + +Arguments: + + Position - Supplies the character position where truncation is to + occur. + +Return Value: + + CHNUM - Returns new size of the substring + +--*/ + +{ + + + DebugAssert( Position < QueryStartingPosition() + QueryChCount() ); + + if ( GetBaseString()->Replace( NULL, + QueryStartingPosition() + Position, + QueryChCount() - Position, + 0, + 0 )) { + // + // Update the length + // + SetChCount( Position ); + + } + + return QueryChCount(); + +} diff --git a/private/utils/ulib/src/system.cxx b/private/utils/ulib/src/system.cxx new file mode 100644 index 000000000..df7d7ec2f --- /dev/null +++ b/private/utils/ulib/src/system.cxx @@ -0,0 +1,1339 @@ +#include <pch.cxx> + +#define _ULIB_MEMBER_ +#include "ulib.hxx" +#include "system.hxx" + +extern "C" { + #include <stdio.h> + #include <string.h> +} + +#include "dir.hxx" +#include "file.hxx" +#include "path.hxx" +#include "wstring.hxx" +#include "timeinfo.hxx" + + + +ULIB_EXPORT +BOOLEAN +SYSTEM::IsCorrectVersion ( + ) + +/*++ + +Routine Description: + + Verify that the version of the operating system is correct. + +Arguments: + + None + +Return Value: + + BOOLEAN - TRUE is the version is correct + - FALSE if wrong version + +--*/ + +{ + // It makes more sense to just allow this binary to run. + // Future version of Windows NT will have to be backward + // compatible. + return TRUE; + // return (GetVersion()&0x0000FFFF) == 0x0A03; // Windows 3.10 +} + + + +ULIB_EXPORT +PFSN_DIRECTORY +SYSTEM::MakeDirectory ( + IN PCPATH Path, + IN PCPATH TemplatePath + ) + +/*++ + +Routine Description: + + Creates a Directory and returs the corresponging FSN_Directory object. + +Arguments: + + Path - Supplies the Path of thedirectory to be created. + TemplatePath - Supplies the template directory from which to + copy alternate data streams. + +Return Value: + + PFSN_DIRECTORY - A pointer to the object of the directory created. + +--*/ + +{ + PCWSTR PathString, TemplateString; + BOOL r; + + DebugAssert(Path); + + PathString = Path->GetPathString()->GetWSTR(); + DebugAssert(PathString); + if (TemplatePath) { + TemplateString = TemplatePath->GetPathString()->GetWSTR(); + } else { + TemplateString = NULL; + } + + if (TemplateString) { + r = CreateDirectoryEx((PWSTR) TemplateString, (PWSTR) PathString, NULL); + } else { + r = CreateDirectory((PWSTR) PathString, NULL); + } + + if (!r) { + return NULL; + } + + return QueryDirectory( Path ); +} + +ULIB_EXPORT +PFSN_FILE +SYSTEM::MakeFile ( + IN PCPATH Path + ) + +/*++ + +Routine Description: + + Creates a File and returs the corresponging FSN_FILE object. + + If the file already exists, its contents are destroyed. + + Note that all the subdirectories along the path must exist (this + method does not create directories). + +Arguments: + + Path - Supplies the Path of the file to be created. + +Return Value: + + PFSN_FILE - A pointer to the FSN_FILE object of the file created. + +--*/ + +{ + + HANDLE Handle; + PCWSTR PathString; + PFSN_FILE File = NULL; + + DebugPtrAssert( Path ); + + PathString = Path->GetPathString()->GetWSTR(); + + DebugPtrAssert( PathString ); + + if ( PathString ) { + + Handle = CreateFile( (LPWSTR) PathString, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + 0 ); + + + DebugAssert( Handle != INVALID_HANDLE_VALUE ); + + if ( Handle != INVALID_HANDLE_VALUE ) { + + // + // Now that we know that the file exists, we use the + // QueryFile method to obtain the FSN_FILE object. + // + CloseHandle( Handle ); + + File = QueryFile( Path ); + + } + } + + return File; + +} + +ULIB_EXPORT +PFSN_FILE +SYSTEM::MakeTemporaryFile ( + IN PCWSTRING PrefixString, + IN PCPATH Path + ) + +/*++ + +Routine Description: + + Creates a file with a unique name using the provided path and + prefix string. If the path is NULL, then the defult path for + temporary files is used. + +Arguments: + + PrefixString - Supplies the file prefix used for creating the + file name. + + Path - Supplies the Path of the directory to contain the + temporary file. + + +Return Value: + + PFSN_FILE - A pointer to the FSN_FILE object of the file created. + +--*/ + +{ + DWORD BufferSize; + LPWSTR TempPath; + PCWSTR TempPrefix; + + WCHAR FileName[ MAX_PATH ]; + + PFSN_FILE File = NULL; + PATH FilePath; + + + DebugPtrAssert( PrefixString ); + + TempPrefix = PrefixString->GetWSTR(); + + DebugPtrAssert( TempPrefix ); + + if ( TempPrefix ) { + + // + // Get the STR representation of the directory for temporary files + // + if ( !Path ) { + + // + // Path not supplied, we will use the default + // + BufferSize = GetTempPath( 0, NULL ); + TempPath = (LPWSTR)MALLOC( (unsigned int)BufferSize * 2 ); + + if (!GetTempPath( BufferSize, TempPath )) { + FREE( TempPath ); + TempPath = NULL; + } + + } else { + + // + // We will use the supplied path (and it better exist) + // + TempPath = Path->GetPathString()->QueryWSTR(); + + } + + DebugPtrAssert( TempPath ); + + if ( TempPath ) { + + // + // Now get the file name of the Temporary File. + // + if (!GetTempFileName( TempPath, (LPWSTR) TempPrefix, 0, FileName )) { + FREE( TempPath ); + return NULL; + } + + // + // Now create the file + // + FilePath.Initialize( FileName ); + + File = MakeFile( &FilePath ); + + FREE( TempPath ); + + + } + } + + return File; + +} + +ULIB_EXPORT +BOOLEAN +SYSTEM::RemoveNode ( + IN OUT PFSNODE *PointerToNode, + IN BOOLEAN Force + ) + +/*++ + +Routine Description: + + DDeletes nodes and directories. + + Read-only files are deleted only if the supplied "Force" flag + is true. + +Arguments: + + Node - Supplies a pointer to a pointer to the node + + Force - Supplies a flag which if TRUE means that the file + should be deleted even if it is read-only. + + +Return Value: + + BOOLEAN - Returns TRUE if the file was deleted successfully. + +--*/ + +{ + + PFSN_FILE File; + PFSN_DIRECTORY Dir; + BOOLEAN ReadOnly; + PCWSTR FileName; + BOOLEAN Deleted = FALSE; + + DebugPtrAssert( PointerToNode ); + DebugPtrAssert( *PointerToNode ); + + + File = FSN_FILE::Cast( *PointerToNode ); + + if ( File ) { + + // + // The node is a file + // + + // + // We delete the file if it is not read-only or if the Force flag + // is set. + // + if ( Force || !(ReadOnly = File->IsReadOnly()) ) { + + // + // If readonly, we reset the read only attribute. + // + if ( ReadOnly ) { + + File->ResetReadOnlyAttribute(); + + } + + // + // Now we delete the file + // + FileName = File->GetPath()->GetPathString()->GetWSTR(); + + DebugPtrAssert( FileName ); + + if ( FileName ) { + + Deleted = DeleteFile( (LPWSTR) FileName ); + + if ( Deleted ) { + + // + // The file has been deleted, now we have to get rid of + // the file object, which is no longer valid. + // + DELETE( File ); + *PointerToNode = NULL; + + } + } + + } + + } else { + + Dir = FSN_DIRECTORY::Cast( *PointerToNode ); + + if ( Dir ) { + + // + // We remove the directory if it is not read-only or if the Force flag + // is set. + // + if ( Force || !(ReadOnly = Dir->IsReadOnly()) ) { + + // + // If readonly, we reset the read only attribute. + // + if ( ReadOnly ) { + + Dir->ResetReadOnlyAttribute(); + + } + + // + // Now we remove the directory + // + FileName = Dir->GetPath()->GetPathString()->GetWSTR(); + + DebugPtrAssert( FileName ); + + if ( FileName ) { + + Deleted = RemoveDirectory( (LPWSTR) FileName ); + + if ( Deleted ) { + + // + // The directory has been removed, now we have + // to get rid of + // the directory object, which is no longer valid. + // + DELETE( Dir ); + *PointerToNode = NULL; + + } + } + + } + + } else { + + DebugAssert( FALSE ); + + } + + } + return Deleted; + +} + +ULIB_EXPORT +PFSN_DIRECTORY +SYSTEM::QueryDirectory ( + IN PCPATH Path, + IN BOOLEAN GetWhatYouCan + ) + +/*++ + +Routine Description: + + Construct, initialize and return a FSN_DIRECTORY object. + +Arguments: + + Path - Supplies a PATH object to construct as a FSN_DIRECTORY. + **** IMPORTANT **** + If Path represents a drive (ie, C: ) the it must be terminated + by '\'. Otherwise the return value (PFSN_DIRECTORY will + contain information about the current directory, and not + the root directory. + + GetWhatYouCan - Supplies a flag which if TRUE causes QueryDirectory to + backtrack along the path until it finds something + that it can open. + +Return Value: + + PFSN_DIRECTORY - Returns a pointer to a FSN_DIRECTORY, NULL if the + supplied path name does not point to an existing directory. + +--*/ + +{ + WIN32_FIND_DATA FindData; + HANDLE Handle; + PPATH TempPath; + PFSN_DIRECTORY Directory; + PATH Parent; + PCWSTRING TempString; + PWSTRING DeviceString; + BOOLEAN IsRoot; + FSTRING TmpString; + PCWSTR RootString = NULL; + PATH FullPath; + + DebugPtrAssert( Path ); + + // + // Initialize the FSN_DIRECTORY and PATH pointers + // + Directory = NULL; + TempPath = NULL; + + if ( !Path->HasWildCard() ) { + + // + // If the supplied path exists and it references an existing entry + // in the file system and it's a directory + // + + TempPath = Path->QueryPath(); + DebugPtrAssert( TempPath ); + FullPath.Initialize( TempPath, TRUE ); + + + if ( TempPath != NULL ) { + + DeviceString = FullPath.QueryDevice(); + + if ( DeviceString ) { + IsRoot = (FullPath.IsRoot() || !FullPath.GetPathString()->Stricmp( DeviceString ) ); + DELETE( DeviceString ); + } else { + IsRoot = TempPath->IsRoot(); + } + + if( !IsRoot ) { + // + // If path does not represent the root directory, then let it + // call FindFirstFile() + // + if( ( Handle = FindFirstFile( TempPath, &FindData )) != INVALID_HANDLE_VALUE ) { + + // + // Terminate the search + // + FindClose( Handle ); + + if( FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) { + + if ( !((( Directory = NEW FSN_DIRECTORY ) != NULL ) && + Directory->Initialize( TempPath->GetPathString( ), &FindData ))) { + + DELETE( Directory ); + } + } + } + } else { + + // + // So we have a root directory. We have to determine if it + // is a valid drive. We used to call FindFirstFile on it, + // but it so happens that FindFirstFile may fail if the + // volume in question is empty (we don't even get the + // "." or ".." entries!) + // + if ( TmpString.Initialize( (PWSTR) L"." ) && + TempPath->AppendBase( &TmpString ) && + (RootString = TempPath->GetPathString()->GetWSTR()) && + (GetFileAttributes( (LPWSTR) RootString ) != -1) ) { + // + // Path represents the root directory. We don't use the information + // obtained by FindFirstFile because that refers to the first entry + // in the root directory, not the root directory itself. + // This is not a bug in the API, but the way it is specified. + // + // The concept of WIN32_FIND_DATA does not apply to the root directory. + // For this reason I will do the initialization of FindData. + // Everything in FindData will be initialized, but the FILETIMEs will + // be initialized with zero. + // + // It is important that Path is contains a '\' at the end + // if it represents a drive. + + TempPath->TruncateBase(); + + FindData.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + FindData.ftCreationTime.dwLowDateTime = 0; + FindData.ftCreationTime.dwHighDateTime = 0; + FindData.ftLastAccessTime.dwLowDateTime = 0; + FindData.ftLastAccessTime.dwHighDateTime = 0; + FindData.ftLastWriteTime.dwLowDateTime = 0; + FindData.ftLastWriteTime.dwHighDateTime = 0; + FindData.nFileSizeHigh = 0; + FindData.nFileSizeLow = 0; + + TempString = TempPath->GetPathString(); + DebugPtrAssert( TempString ); + TempString->QueryWSTR( 0, TO_END, (LPWSTR)FindData.cFileName, MAX_PATH ); + if ( !((( Directory = NEW FSN_DIRECTORY ) != NULL ) && + Directory->Initialize( TempPath->GetPathString( ), &FindData ))) { + + DELETE( Directory ); + } + } + } + } + + DELETE( TempPath ); + } + + if (!Directory && GetWhatYouCan && !Path->IsDrive() && !Path->IsRoot()) { + // + // The path is not that of an existing directory. + // take off the base and try again. + // + Parent.Initialize( Path ); + Parent.TruncateBase(); + + Directory = QueryDirectory( &Parent, GetWhatYouCan ); + } + + return Directory; +} + + + +ULIB_EXPORT +PPATH +SYSTEM::QuerySystemDirectory ( + ) + +/*++ + +Routine Description: + + Returns the directory where the system files are located. + +Arguments: + + None + +Return Value: + + PPATH - Path of the system directory. + +--*/ + +{ + WCHAR Buffer[MAX_PATH]; + DSTRING PathName; + PPATH Path = NULL; + DWORD Cb; + + Cb = GetSystemDirectory( Buffer, MAX_PATH ); + + if ( (Cb != 0) || (Cb < MAX_PATH) ) { + + if ( !PathName.Initialize( (PWSTR)Buffer) || + !(Path = NEW PATH) || + !Path->Initialize( &PathName ) + ) { + + DELETE( Path ); + + } + } + + return Path; +} + + + +const MaxEnvVarLen = 256; + +ULIB_EXPORT +PWSTRING +SYSTEM::QueryEnvironmentVariable ( + IN PCWSTRING Variable + ) + +/*++ + +Routine Description: + + Obtains the value of an environment variable + +Arguments: + + Variable - Supplies the variable to look for + +Return Value: + + Value of the environment variable, NULL if not defined + +--*/ + +{ + + PCWSTR Buffer; + WCHAR Value[MaxEnvVarLen]; + PWSTRING pString; + ULONG ValueLength; + + if (!Variable) { + return NULL; + } + + // + // Get the ApiString of the variable to look for + // + Buffer = Variable->GetWSTR(); + + // + // Look for the variable + // + ValueLength = GetEnvironmentVariable( (LPWSTR) Buffer, Value, MaxEnvVarLen ); + + if ( ValueLength == 0 ) { + + // + // The environment variable is not defined + // + return NULL; + } + + // + // Got the value, form a string with it and return it + // + if ( (pString = NEW DSTRING) != NULL ) { + + if (pString->Initialize( Value )) { + + return pString; + + } + + DELETE( pString ); + } + + return NULL; + +} + +ULIB_EXPORT +PPATH +SYSTEM::SearchPath( + PWSTRING pFileName, + PWSTRING pSearchPath + ) +/*++ + +Routine Description: + + Search a given path for a file name. If the input path is NULL, the + routine searches the default path. + +Arguments: + + pSearchPath - Supplies a set of semicolon terminated paths. + pFileName - The name of the file to search for. + +Return Value: + + A pointer to a path containing the first occurance of pFileName. If the + name isn't found, the path is NULL. + +--*/ +{ + CHNUM cb; + WSTR ReturnPath[ MAX_PATH + 1 ]; + PPATH pFullPath; + LPWSTR pFilePart; + PCWSTR pPath; + PCWSTR pName; + + if( pSearchPath != NULL ) { + // Extract the path from pSearchPath for the API call... + pPath = pSearchPath->GetWSTR(); + } else { + pPath = NULL; + } + if( pFileName == NULL ) { + DebugPrint( "The input filename is NULL - Can't find it...\n" ); + return( NULL ); + } + // Extract the filename from the pFileName string... + pName = pFileName->GetWSTR(); + + // + // Call the API ... + // + cb = ::SearchPath( (LPWSTR) pPath, + (LPWSTR) pName, + NULL, // The extension must be specified as part of the file name... + MAX_PATH, + ReturnPath, + &pFilePart + ); + + + if( !cb ) { + DebugPrint( "File name not found...\n" ); + return( NULL ); + } + + // + // Create a new path and Initialize it with the buffer resulting + // + if( ( pFullPath = NEW PATH ) == NULL ) { + DebugPrint( "Unable to allocate the path to return the data...\n" ); + return( NULL ); + } + + if( !pFullPath->Initialize( ReturnPath, FALSE ) ) { + DebugPrint( "Unable to initialize the new path!\n" ); + return( NULL ); + } + + // + // The path should now be constucted... + // + return( pFullPath ); +} + +ULIB_EXPORT +PFSN_FILE +SYSTEM::QueryFile ( + IN PCPATH Path + ) + +/*++ + +Routine Description: + + Construct, initialize and return a FSN_FILE object. + +Arguments: + + Path - Supplies a PATH object to construct as a FSN_FILE. + +Return Value: + + A pointer to a FSN_FILE. + +--*/ + +{ + + PFSN_FILE File = NULL; + PPATH FullPath = NULL; + HANDLE Handle; + WIN32_FIND_DATA FindData; + + DebugPtrAssert( Path ); + + if ( Path && + !Path->HasWildCard() && + ((FullPath = Path->QueryFullPath()) != NULL ) && + ((Handle = FindFirstFile( FullPath, &FindData )) != INVALID_HANDLE_VALUE) ) { + + FindClose( Handle ); + + if( !(FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) { + + if ((File = NEW FSN_FILE) != NULL) { + if ( !(File->Initialize(FullPath->GetPathString(), &FindData)) ) { + DELETE( File ); + File = NULL; + } + } + } + } + + DELETE( FullPath ); + + return File; +} + + +BOOLEAN +SYSTEM::PutStandardStream( + IN DWORD StdHandle, + IN PSTREAM pStream + ) +/*++ + +Routine Description: + + Redirect a standard stream. + +Arguments: + + StdHandle - An identifier for the Standard Handle to modify. + pStream - The standard stream is redirected to this stream. + +Return Value: + + TRUE if successful. + +--*/ +{ + // + // First, set the system standard handle to the stream + // + if( !SetStdHandle( StdHandle, pStream->QueryHandle() ) ) { + DebugPrint( "Unable to redirect the system handle - nothing changed!\n" ); + return( FALSE ); + } + + + // + // Get a pointer to the stream to change... + // + switch( StdHandle ) { + case STD_INPUT_HANDLE: + Standard_Input_Stream = pStream; + break; + case STD_OUTPUT_HANDLE: + Standard_Output_Stream = pStream; + break; + case STD_ERROR_HANDLE: + Standard_Error_Stream = pStream; + break; + default: + DebugPrint( "Unrecognized Standard Handle Type - Returning Error!\n" ); + return( FALSE ); + } + return( TRUE ); +} + + +ULIB_EXPORT +BOOLEAN +SYSTEM::QueryCurrentDosDriveName( + OUT PWSTRING DosDriveName + ) +/*++ + +Routine Description: + + This routine returns the name of the current drive. + +Arguments: + + DosDriveName - Returns the name of the current drive. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + PATH path; + PWSTRING p; + + if (!path.Initialize( (LPWSTR)L"foo", TRUE)) { + return FALSE; + } + + if (!(p = path.QueryDevice())) { + return FALSE; + } + + if (!DosDriveName->Initialize(p)) { + return FALSE; + } + + DELETE(p); + + return TRUE; +} + + +ULIB_EXPORT +DRIVE_TYPE +SYSTEM::QueryDriveType( + IN PCWSTRING DosDriveName + ) +/*++ + +Routine Description: + + This routine computes the type of drive pointed to by 'DosDriveName'. + +Arguments: + + DosDriveName - Supplies the dos name of the drive. + +Return Value: + + The type of drive that is pointed to by 'DosDriveName'. + +--*/ +{ + DSTRING wstring; + DSTRING slash; + PCWSTR p; + DRIVE_TYPE r; + + if (!wstring.Initialize(DosDriveName)) { + return UnknownDrive; + } + + if (!slash.Initialize("\\")) { + return UnknownDrive; + } + + wstring.Strcat(&slash); + + if (!(p = wstring.GetWSTR())) { + return UnknownDrive; + } + + switch (GetDriveType((LPWSTR) p)) { + case DRIVE_REMOVABLE: + r = RemovableDrive; + break; + + case DRIVE_FIXED: + r = FixedDrive; + break; + + case DRIVE_REMOTE: + r = RemoteDrive; + break; + + case DRIVE_CDROM: + r = CdRomDrive; + break; + + case DRIVE_RAMDISK: + r = RamDiskDrive; + break; + + default: + r = UnknownDrive; + break; + + } + + return r; +} + +ULIB_EXPORT +FILE_TYPE +SYSTEM::QueryFileType( + IN PCWSTRING DosFileName + ) +/*++ + +Routine Description: + + This routine computes the type of filee pointed to by 'DosFileName'. + +Arguments: + + DosFileName - Supplies the dos name of the file. + +Return Value: + + The type of file that is pointed to by 'DosFileName'. + +--*/ +{ + DSTRING wstring; + PCWSTR p; + FILE_TYPE r; + HANDLE Handle; + + if (!wstring.Initialize(DosFileName)) { + return UnknownFile; + } + + if (!(p = wstring.GetWSTR())) { + return UnknownFile; + } + + Handle = CreateFile( (LPWSTR) p, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, + NULL ); + + if ( Handle != INVALID_HANDLE_VALUE ) { + + switch ( GetFileType( Handle ) ) { + + case FILE_TYPE_DISK: + r = DiskFile; + break; + + case FILE_TYPE_CHAR: + r = CharFile; + break; + + case FILE_TYPE_PIPE: + r = PipeFile; + break; + + default: + r = UnknownFile; + break; + + } + + CloseHandle( Handle ); + + } else { + + r = UnknownFile; + } + + return r; +} + + + +ULIB_EXPORT +PWSTRING +SYSTEM::QueryVolumeLabel( + IN PPATH Path, + OUT PVOL_SERIAL_NUMBER VolSerialNumber + ) +/*++ + +Routine Description: + + Returns the name and serial number of a volume. + +Arguments: + + Path - Path in the file system whose volume information is to be + retrieved. + + VolSerialNumber - Pointer to a structure that will contain the + serial number + +Return Value: + + PWSTRING - Pointer to a WSTRING that will contain the volume name, or + NULL if an error occurs. + + +--*/ +{ + PWSTRING VolumeName; + PWSTRING RootString; + PCWSTR RootName; + WCHAR VolumeNameBuffer[ MAX_PATH ]; + ULONG SerialNumber[2]; + + DebugPtrAssert( Path ); + DebugPtrAssert( VolSerialNumber ); + RootString = Path->QueryRoot(); + DebugPtrAssert( RootString ); + RootName = RootString->GetWSTR(); + if( !GetVolumeInformation( (LPWSTR) RootName, + (LPWSTR)VolumeNameBuffer, + MAX_PATH, + ( PDWORD )SerialNumber, + NULL, + NULL, + NULL, + 0 ) ) { + DELETE( RootString ); + return( NULL ); + } + VolSerialNumber->LowOrder32Bits = SerialNumber[ 0 ]; + VolSerialNumber->HighOrder32Bits = SerialNumber[ 1 ]; + VolumeName=NEW( DSTRING ); + DebugPtrAssert( VolumeName ); + VolumeName->Initialize( VolumeNameBuffer ); + DELETE( RootString ); + return( VolumeName ); +} + + + +const MaximumLibraryNameLength = 256; +const MaximumEntryPointNameLength = 128; + +ULIB_EXPORT +FARPROC +SYSTEM::QueryLibraryEntryPoint( + IN PCWSTRING LibraryName, + IN PCWSTRING EntryPointName, + OUT PHANDLE LibraryHandle + ) +/*++ + +Routine Description: + + Loads a dynamically-linked library and returns an + entry point into it. + +Arguments: + + LibraryName -- name of the library to load + + EntryPointName -- name of the entry point to get + + LibraryHandle -- receives handle of loaded library + +Return Value: + + Pointer to the requested function; NULL to indicate failure. + +--*/ +{ + WCHAR AnsiLibraryName[MaximumLibraryNameLength+1]; + CHAR AnsiEntryPointName[MaximumEntryPointNameLength+1]; + FARPROC EntryPoint; + + + LibraryName->QueryWSTR( 0, TO_END, AnsiLibraryName, MaximumLibraryNameLength + 1); + + EntryPointName->QuerySTR( 0, TO_END, AnsiEntryPointName, + MaximumEntryPointNameLength + 1 ); + + if( (*LibraryHandle = (HANDLE)LoadLibrary( AnsiLibraryName )) != NULL && + (EntryPoint = GetProcAddress( (HINSTANCE)*LibraryHandle, + (LPSTR)AnsiEntryPointName )) != NULL ) { + + return EntryPoint; + + } else { + + if( *LibraryHandle != NULL ) { + + FreeLibrary( (HMODULE)*LibraryHandle ); + *LibraryHandle = NULL; + } + + return NULL; + } +} + + +ULIB_EXPORT +VOID +SYSTEM::FreeLibraryHandle( + HANDLE LibraryHandle + ) +/*++ + +Routine Description: + + Frees a library handle gotten by QueryLibraryEntryPoint + +Arguments: + + LibraryHandle -- handle to free + +Return Value: + + None. + +--*/ +{ + FreeLibrary( (HMODULE)LibraryHandle ); +} + + +ULIB_EXPORT +BOOLEAN +SYSTEM::QueryLocalTimeFromUTime( + IN PCTIMEINFO UTimeInfo, + OUT PTIMEINFO LocalTimeInfo + ) +/*++ + +Routine Description: + + This routine computes the local time from the given + universal time. + +Arguments: + + UTimeInfo - Supplies the universal time to convert. + LocalTimeInfo - Returns the corresponding local time. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + FILETIME filetime; + + DebugAssert(UTimeInfo->GetFileTime()); + + if (!FileTimeToLocalFileTime(UTimeInfo->GetFileTime(), &filetime)) { + return FALSE; + } + + return LocalTimeInfo->Initialize(&filetime); +} + + +BOOLEAN +SYSTEM::QueryUTimeFromLocalTime( + IN PCTIMEINFO LocalTimeInfo, + OUT PTIMEINFO UTimeInfo + ) +/*++ + +Routine Description: + + This routine computes the universal time from the given + local time. + +Arguments: + + LocalTimeInfo - Supplies the local time to convert. + UTimeInfo - Returns the corresponding universal time. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + FILETIME filetime; + + DebugAssert(LocalTimeInfo->GetFileTime()); + + if (!LocalFileTimeToFileTime(LocalTimeInfo->GetFileTime(), &filetime)) { + return FALSE; + } + + return UTimeInfo->Initialize(&filetime); +} + + +ULIB_EXPORT +BOOLEAN +SYSTEM::QueryWindowsErrorMessage( + IN ULONG WindowsErrorCode, + OUT PWSTRING ErrorMessage + ) +/*++ + +Routine Description: + + This routine returns the text corresponding to the given + windows error message. + +Arguments: + + WindowsErrorCode - Supplies the windows error code. + ErrorMessage - Returns the error message for this error code. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + WCHAR buffer[MAX_PATH]; + + if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, + WindowsErrorCode, 0, buffer, MAX_PATH, NULL)) { + + return FALSE; + } + + return ErrorMessage->Initialize(buffer); +} diff --git a/private/utils/ulib/src/timeinfo.cxx b/private/utils/ulib/src/timeinfo.cxx new file mode 100644 index 000000000..7c89b6674 --- /dev/null +++ b/private/utils/ulib/src/timeinfo.cxx @@ -0,0 +1,1213 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + time.cxx + +Abstract: + + This module contains the definitions of the member functions + of TIMEINFO class. + +Author: + + Jaime Sasson (jaimes) 13-Mar-1991 + +Environment: + + ULIB, User Mode + + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "wstring.hxx" +#include "timeinfo.hxx" + +extern "C" { + #include <stdio.h> +} + + +// +// The following two tables map a month index to the number of days preceding +// the month in the year. Both tables are zero based. For example, 1 (Feb) +// has 31 days preceding it. To help calculate the maximum number of days +// in a month each table has 13 entries, so the number of days in a month +// of index i is the table entry of i+1 minus the table entry of i. +// + +USHORT LeapYearDaysPrecedingMonth[13] = { + 0, // January + 31, // February + 31+29, // March + 31+29+31, // April + 31+29+31+30, // May + 31+29+31+30+31, // June + 31+29+31+30+31+30, // July + 31+29+31+30+31+30+31, // August + 31+29+31+30+31+30+31+31, // September + 31+29+31+30+31+30+31+31+30, // October + 31+29+31+30+31+30+31+31+30+31, // November + 31+29+31+30+31+30+31+31+30+31+30, // December + 31+29+31+30+31+30+31+31+30+31+30+31}; + +USHORT NormalYearDaysPrecedingMonth[13] = { + 0, // January + 31, // February + 31+28, // March + 31+28+31, // April + 31+28+31+30, // May + 31+28+31+30+31, // June + 31+28+31+30+31+30, // July + 31+28+31+30+31+30+31, // August + 31+28+31+30+31+30+31+31, // September + 31+28+31+30+31+30+31+31+30, // October + 31+28+31+30+31+30+31+31+30+31, // November + 31+28+31+30+31+30+31+31+30+31+30, // December + 31+28+31+30+31+30+31+31+30+31+30+31}; + + + +// +// The tables below contain the number of days in each month of +// a year (leap and normal year) +// + +USHORT LeapYearDaysInMonth[12] = { + 31, // January + 29, // February + 31, // March + 30, // April + 31, // May + 30, // June + 31, // July + 31, // August + 30, // September + 31, // October + 30, // November + 31 // December + }; + +USHORT NormalYearDaysInMonth[12] = { + 31, // January + 28, // February + 31, // March + 30, // April + 31, // May + 30, // June + 31, // July + 31, // August + 30, // September + 31, // October + 30, // November + 31 // December + }; + + + + +DEFINE_EXPORTED_CONSTRUCTOR ( TIMEINFO, OBJECT, ULIB_EXPORT ); + +VOID +TIMEINFO::Construct ( + ) + +/*++ + +Routine Description: + + Contructs a TIMEINFO. + +Arguments: + + None. + +Return Value: + + None. + + +--*/ + +{ + // unreferenced parameters + (void)(this); +} + + + + +BOOLEAN +TIMEINFO::Initialize( + ) + +/*++ + +Routine Description: + + This function initializes the data members of TIMEINFO class with + the current date and time. + +Arguments: + + None. + +Return Value: + + BOOLEAN - Indicates if the data members were correctly initialized. + + +--*/ + + +{ + SYSTEMTIME st; + + GetSystemTime( &st ); + return( this->Initialize( &st ) ); +} + + + + +ULIB_EXPORT +BOOLEAN +TIMEINFO::Initialize( + IN PFILETIME FileTime + ) + +/*++ + +Routine Description: + + This function initializes the data members of TIMEINFO class with + the date and time stored in the structured pointed by FileTime. + +Arguments: + + FileTime - Pointer to a FILETIME structure that contains the + date and time to be used in the initialization of the + date members. + +Return Value: + + BOOLEAN - Indicates if the data members were correctly initialized. + + +--*/ + + +{ + _FileTime = *FileTime; + return( FileTimeToSystemTime( &_FileTime, &_SystemTime ) ); +} + + +BOOLEAN +TIMEINFO::Initialize( + IN PSYSTEMTIME SystemTime + ) + +/*++ + +Routine Description: + + This function initializes the data members of TIMEINFO class with + the date and time stored in the structured pointed by SystemTime. + +Arguments: + + SystemTime - Pointer to a SYSTEMTIME structure that contains the + date and time to be used in the initialization of the + data members. + +Return Value: + + BOOLEAN - Indicates if the data members were correctly initialized. + + +--*/ + + +{ + BOOLEAN Result; + + _SystemTime = *SystemTime; + Result = (BOOLEAN)SystemTimeToFileTime( &_SystemTime, &_FileTime ); +// +// The call below is necessary in order to make sure that +// SystemTime.wDayOfWeek is correctly initialized +// + Result &= FileTimeToSystemTime( &_FileTime, &_SystemTime ); + return( Result ); +} + + +ULIB_EXPORT +VOID +TIMEINFO::Initialize( + IN PCTIMEINFO TimeInfo + ) + +/*++ + +Routine Description: + + This function initializes the data members of TIMEINFO class with + the date and time stored in the class pointed by pTimeInfo. + +Arguments: + + TimeInfo - Pointer to a TIMEINFO class that contains the + date and time to be used in the initialization of the + data members in this class. + +Return Value: + + None. + + +--*/ + + +{ + _FileTime = TimeInfo->_FileTime; + _SystemTime = TimeInfo->_SystemTime; +} + + + +BOOLEAN +TIMEINFO::Initialize( + IN USHORT Year, + IN USHORT Month, + IN USHORT Day, + IN USHORT Hour, + IN USHORT Minute, + IN USHORT Second, + IN USHORT Milliseconds + ) + +/*++ + +Routine Description: + + This function initializes the data members of TIMEINFO class with + the date and time information received as parameter. + +Arguments: + + Year - A number indicating the year + Month - A number indicating the month + Day - A number indicating the day + Hour - Number of hours + Minute - Number of minutes + Second - Number of seconds + Milliseconds - Number of milliseconds + +Return Value: + + BOOLEAN - Indicates if the data members were correctly initialized. + + +--*/ + + +{ + SYSTEMTIME st; + st.wYear = Year; + st.wMonth = Month; + st.wDay = Day; + st.wHour = Hour; + st.wMinute = Minute; + st.wSecond = Second; + st.wMilliseconds = Milliseconds; + + return( this->Initialize( &st ) ); +} + + +SHORT +TIMEINFO::CompareTimeInfo( + IN PFILETIME FileTime + ) CONST + + +/*++ + +Routine Description: + + This function compares the date and time information stored in + this class, with one pointed by FileTime. + +Arguments: + + FileTime - Pointer to a FILETIME structure that contains the + date and time to be used in the comparison. + +Return Value: + + -1: - Indicates that the time information in this class is less + than the time information pointed by FileTime. + + 0: - Indicates that the time information in this class is equal + to the time information pointed by FileTime. + + 1: - Indicates that the time information in this class is greater + than the time information pointed by FileTime. + + +--*/ + +{ + FILETIME ft1; + + ft1 = _FileTime; + return( (SHORT)CompareFileTime( &ft1, FileTime ) ) ; +} + + + +SHORT +TIMEINFO::CompareTimeInfo( + IN PSYSTEMTIME SystemTime + ) CONST + + +/*++ + +Routine Description: + + This function compares the date and time information stored in + this class, with the one pointed by SysteTime. + +Arguments: + + SystemTime - Pointer to a FILETIME structure that contains the + date and time to be used in the comparison. + +Return Value: + + -1: - Indicates that the time information in this class is less + than the time information pointed by SystemTime. + + 0: - Indicates that the time information in this class is equal + to the time information pointed by SystemTime. + + 1: - Indicates that the time information in this class is greater + than the time information pointed by SystemTime. + + +--*/ + +{ + FILETIME ft1; + FILETIME ft2; + + ft1 = _FileTime; + SystemTimeToFileTime( SystemTime, &ft2 ); + return( (SHORT)CompareFileTime( &ft1, &ft2 ) ); +} + + + +USHORT +TIMEINFO::QueryDayOffset( + ) CONST + +/*++ + +Routine Description: + + This function determines the offset in year of the day stored in + this class. + +Arguments: + + None. + +Return Value: + + USHORT - Offset in year of the current day. + + +--*/ + +{ + USHORT Offset; + + if( IsLeapYear( (USHORT)_SystemTime.wYear ) ) { + Offset = LeapYearDaysPrecedingMonth[ _SystemTime.wMonth ]; + } + else { + Offset = NormalYearDaysPrecedingMonth[ _SystemTime.wMonth ]; + } + Offset += _SystemTime.wDay; + return( Offset ); +} + + + +USHORT +TIMEINFO::QueryDaysInMonth( + ) CONST + +/*++ + +Routine Description: + + This function determines the number of days in the month of the + date stored in this class. + +Arguments: + + None. + +Return Value: + + USHORT - Number of days in the month. + + +--*/ + +{ + USHORT NumberOfDays; + + if( IsLeapYear( (USHORT)_SystemTime.wYear ) ) { + NumberOfDays = LeapYearDaysInMonth[ _SystemTime.wMonth ]; + } + else { + NumberOfDays = NormalYearDaysInMonth[ _SystemTime.wMonth ]; + } + return( NumberOfDays ); +} + + + +USHORT +TIMEINFO::QueryDaysInYear( + ) CONST + +/*++ + +Routine Description: + + This function determines the total number of days in the year + stored in this class. + +Arguments: + + None. + +Return Value: + + USHORT - Number of days in the year. + + +--*/ + +{ + if( IsLeapYear( (USHORT)_SystemTime.wYear ) ) { + return( LeapYearDaysPrecedingMonth[ 12 ] ); + } + else { + return( NormalYearDaysPrecedingMonth[ 12 ] ); + } +} + + + +BOOLEAN +TIMEINFO::SetDate( + USHORT Year, + USHORT Month, + USHORT Day + ) + +/*++ + +Routine Description: + + This function sets the date of the TIMEINFO object (the time + remains unchanged). + +Arguments: + + Year - A number that indicates the year. + Month - A number that indicates the month. + Day - A number that indicates the day. + +Return Value: + + BOOLEAN - A boolean value indicating if the date was set correctly. + + +--*/ + +{ + SYSTEMTIME TempSystemTime; + + TempSystemTime = _SystemTime; + TempSystemTime.wYear = Year; + TempSystemTime.wMonth = Month; + TempSystemTime.wDay = Day; + return( this->Initialize( &TempSystemTime ) ); +} + + + +BOOLEAN +TIMEINFO::SetDate( + PCWSTRING Date + ) + +/*++ + +Routine Description: + + This function sets the date of a TIMEINFO object (the time remains + unchanged). + +Arguments: + + Date - A string that contains the date. + +Return Value: + + BOOLEAN - A boolean value indicating if the date was set correctly. + +Notes: + + BUGBUG - jaimes - 05/10/91 + + THE CURRENT IMPLEMENTATION IS JUST A TEMPORARY ONE, UNTIL WE HAVE + THE WINNLS APIs READY. + THE IMPLEMENTATION BELOW ASSUMES THAT THE DATE REPRESENTED IN THE + STRING HAS THE FORM: m-d-y or m/d/y, where: + + m: represents the month (1 or 2 characters); + d: represents the day (1 or 2 characters); + y: represents the year (any number of characters) + + +--*/ + +{ + SYSTEMTIME TempSystemTime; + CHNUM FirstDelimiter; + CHNUM SecondDelimiter; + FSTRING Delimiters; + USHORT Day; + USHORT Month; + USHORT Year; + BOOLEAN IsNumber; + LONG Number; + + + // + // Check if the string is a valid one ( must contain two separators ) + // + if( !Delimiters.Initialize( (PWSTR) L"/-" ) ) { + return( FALSE ); + } + if( ( FirstDelimiter = Date->Strcspn( &Delimiters ) ) == INVALID_CHNUM ) { + return( FALSE ); + } + if( ( SecondDelimiter = Date->Strcspn( &Delimiters, + FirstDelimiter + 1 ) ) == INVALID_CHNUM ) { + return( FALSE ); + } + if( Date->Strcspn( &Delimiters, SecondDelimiter + 1 ) != INVALID_CHNUM ) { + return( FALSE ); + } + // + // At this point we know that the string has two delimiters and + // three numeric fields. + // We now have to extract the numbers that represent the date, + // and validate these numbers. + // + + if (!(IsNumber = Date->QueryNumber(&Number, 0, FirstDelimiter ))) { + return FALSE; + } + Month = (USHORT)Number; + + if (!(IsNumber = Date->QueryNumber(&Number, FirstDelimiter+1, SecondDelimiter-FirstDelimiter-1))) { + return FALSE; + } + Day = (USHORT)Number; + + if (!(IsNumber = Date->QueryNumber(&Number, SecondDelimiter+1))) { + return FALSE; + } + Year = (USHORT)Number; + + if( ( Month == 0 ) || ( Month > 12 ) ) { + return( FALSE ); + } + // + // Years in the range 00 - 79 are transformed to 2000-2079 + // Years in the range 80 - 99 are transformed to 1980-1999 + if( ( Year >= 80 ) && ( Year < 100 ) ) { + Year += 1900; + } else { + if( Year <= 79 ) { + Year += 2000; + } + + } + if( ( Day > 31 ) || + ( ( Day == 31 ) && ( ( Month % 2 ) == 0 ) && ( Month != 8 ) ) || + ( ( Day == 29 ) && (Month == 2) && IsLeapYear( Year ) ) ) { + return( FALSE ); + } + + TempSystemTime = _SystemTime; + TempSystemTime.wYear = ( USHORT )Year; + TempSystemTime.wMonth = ( USHORT )Month; + TempSystemTime.wDay = ( USHORT )Day; + return( this->Initialize( &TempSystemTime ) ); +} + + +BOOLEAN +TIMEINFO::SetDateAndTime ( + IN PCWSTRING DateAndTime + ) + +/*++ + +Routine Description: + + This function sets the date or time of a TIMEINFO object. + +Arguments: + + DateAndTime - A string that contains the date or time. + +Return Value: + + BOOLEAN - A boolean value indicating if the date or time was set + correctly. + +Notes: + + BUGBUG - ramonsa - 05/10/91 + + THIS IMPLEMENTATION SETS ONLY THE DATE OR THE TIME, BUT NOT BOTH. + IT RELIES ON HACKS UNTIL THE WINNLS SUPPORT IS AVAILABLE FOR + TRANSFORMING STRINGS INTO DATES AND TIMES. + +--*/ + +{ + if( DateAndTime->Strchr( (WCHAR)':' ) == INVALID_CHNUM ) { + // + // We assume that we have a date + // + if( !SetDate( DateAndTime ) ) { + return( FALSE ); + } + // + // Sets the time to the earliest time in the day + // + return( SetTime( 0, 0, 0, 0 ) ); + } else { + // + // We assume that we have a time + // + return SetTime( DateAndTime ); + } +} + + +BOOLEAN +TIMEINFO::SetTime( + USHORT Hour, + USHORT Minute, + USHORT Second, + USHORT Milliseconds + ) + +/*++ + +Routine Description: + + This function sets the time of of a TIMEINFO object (the date + remains unchanged). + +Arguments: + + Hour - Number of hours. + Minute - Number of minutes. + Second - Number of seconds. + Milliseconds - Number of milliseconds + +Return Value: + + BOOLEAN - A boolean value indicating if the time was set correctly. + + +--*/ + +{ + SYSTEMTIME TempSystemTime; + + TempSystemTime = _SystemTime; + TempSystemTime.wHour = Hour; + TempSystemTime.wMinute = Minute; + TempSystemTime.wSecond = Second; + TempSystemTime.wMilliseconds = Milliseconds; + return( this->Initialize( &TempSystemTime ) ); +} + + + +BOOLEAN +TIMEINFO::SetTime( + PCWSTRING Time + ) + +/*++ + +Routine Description: + + This function sets the time of a TIMEINFO object (the date remains + unchanged). + +Arguments: + + Date - A string that contains the time. This string must have + one of the following formats: + + h:m + h:m:s + + Where: + + h: represents the hour (1 or 2 digits) + m: represents the minutes (1 or 2 digits) + s: represents the seconds (1 or 2 digits) + + +Return Value: + + BOOLEAN - A boolean value indicating if the time was set correctly. + +Notes: + + BUGBUG - jaimes - 05/10/91 + + THE CURRENT IMPLEMENTATION IS JUST A TEMPORARY ONE, UNTIL WE HAVE + THE WINNLS APIs READY. + + +--*/ + +{ + CHNUM FirstDelimiter; + CHNUM SecondDelimiter; + USHORT Hour; + USHORT Minute; + USHORT Second; + BOOLEAN IsNumber; + LONG Number; + FSTRING Delimiters; + SYSTEMTIME TempSystemTime; + + // + // Check if the string is a valid one + // + FirstDelimiter = INVALID_CHNUM; + SecondDelimiter = INVALID_CHNUM; + + if( !Delimiters.Initialize( (LPWSTR) L":" ) ) { + return( FALSE ); + } + if( ( FirstDelimiter = Time->Strcspn( &Delimiters ) ) == INVALID_CHNUM ) { + return( FALSE ); + } + SecondDelimiter = Time->Strcspn( &Delimiters, FirstDelimiter + 1 ); + + // + // At this point we know that the string has one or two delimiters, and + // two or three numeric fields. + // We now have to extract the numbers that represent the time, + // and validate these numbers. + // + + if (!(IsNumber = Time->QueryNumber(&Number, 0, FirstDelimiter ))) { + return FALSE; + } + Hour = (USHORT)Number; + + if( SecondDelimiter == INVALID_CHNUM ) { + if (!(IsNumber = Time->QueryNumber(&Number, FirstDelimiter+1))) { + return FALSE; + } + Minute = (USHORT)Number; + Second = 0; + } else { + if (!(IsNumber = Time->QueryNumber(&Number, FirstDelimiter+1, SecondDelimiter-FirstDelimiter-1))) { + return FALSE; + } + Minute = (USHORT)Number; + + if (!(IsNumber = Time->QueryNumber(&Number, SecondDelimiter+1))) { + return FALSE; + } + Second = (USHORT)Number; + } + + // + // Check if the time is valid + // + if( ( Hour >= 24 ) || ( Minute >= 60 ) || ( Second >= 60 ) ) { + return( FALSE ); + } + + TempSystemTime = _SystemTime; + TempSystemTime.wHour = ( USHORT )Hour; + TempSystemTime.wMinute = ( USHORT )Minute; + TempSystemTime.wSecond = ( USHORT )Second; + TempSystemTime.wMilliseconds = 0; + return( this->Initialize( &TempSystemTime ) ); +} + + +ULIB_EXPORT +BOOLEAN +TIMEINFO::QueryTime( + OUT PWSTRING FormattedTimeString + ) CONST +/*++ + +Routine Description: + + This routine computes the correct time string for this TIMEINFO. + +Arguments: + + FormattedTimeString - Returns a formatted time string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + WSTR buf[50]; + + return( GetTimeFormatW( GetSystemDefaultLCID(), + TIME_NOSECONDS, + &_SystemTime, + NULL, + buf, + 50 ) && + FormattedTimeString->Initialize(buf) ); + +} + + +NONVIRTUAL +ULIB_EXPORT +BOOLEAN +TIMEINFO::QueryDate( + OUT PWSTRING FormattedDateString + ) CONST +/*++ + +Routine Description: + + This routine computes the correct date string for this TIMEINFO. + +Arguments: + + FormattedTimeString - Returns a formatted date string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + WSTR buf[50]; + + return( GetDateFormatW( GetSystemDefaultLCID(), + DATE_SHORTDATE, + &_SystemTime, + NULL, + buf, + 50 ) != 0 && + FormattedDateString->Initialize(buf) ); +} + + +BOOLEAN +TIMEINFO::operator== ( + IN TIMEINFO TimeInfo + ) CONST + +/*++ + +Routine Description: + + This function determines if the time information contained in this + class is equal to the time information received as parameter. + +Arguments: + + TimeInfo - An object of type TIMEINFO that contains the time + information to be compared. + +Return Value: + + BOOLEAN - A boolean value indicating if the time information in this + object is equal to the information in the object received + as parameter. + + +--*/ + + +{ + FILETIME ft; + + ft = _FileTime; + switch( CompareFileTime( &ft, TimeInfo.GetFileTime() ) ) { + case 0: + return( TRUE ); + + default: + return( FALSE ); + } +} + + + +BOOLEAN +TIMEINFO::operator!= ( + IN TIMEINFO TimeInfo + ) CONST + +/*++ + +Routine Description: + + This function determines if the time information contained in this + class is different than the time information received as parameter. + +Arguments: + + TimeInfo - An object of type TIMEINFO that contains the time + information to be compared. + +Return Value: + + BOOLEAN - A boolean value indicating if the time information in this + object is different than the information in the object received + as parameter. + + +--*/ + + +{ + FILETIME ft; + + ft = _FileTime; + switch( CompareFileTime( &ft, TimeInfo.GetFileTime() ) ) { + + case 0: + return( FALSE ); + + default: + return( TRUE ); + } +} + + + +ULIB_EXPORT +BOOLEAN +TIMEINFO::operator< ( + IN TIMEINFO TimeInfo + ) CONST + +/*++ + +Routine Description: + + This function determines if the time information contained in this + class is smaller than the time information received as parameter. + +Arguments: + + TimeInfo - An object of type TIMEINFO that contains the time + information to be compared. + +Return Value: + + BOOLEAN - A boolean value indicating if the time information in this + object is smaller than the information in the object received + as parameter. + + +--*/ + + +{ + FILETIME ft; + + ft = _FileTime; + switch( CompareFileTime( &ft, TimeInfo.GetFileTime() ) ) { + + case -1: + return( TRUE ); + + default: + return( FALSE ); + } +} + + + +ULIB_EXPORT +BOOLEAN +TIMEINFO::operator> ( + IN TIMEINFO TimeInfo + ) CONST + +/*++ + +Routine Description: + + This function determines if the time information contained in this + class is greter than the time information received as parameter. + +Arguments: + + TimeInfo - An object of type TIMEINFO that contains the time + information to be compared. + +Return Value: + + BOOLEAN - A boolean value indicating if the time information in this + object is greater than the information in the object received + as parameter. + + +--*/ + + +{ + FILETIME ft; + + ft = _FileTime; + switch( CompareFileTime( &ft, TimeInfo.GetFileTime() ) ) { + + case 1: + return( TRUE ); + + default: + return( FALSE ); + } +} + + + +BOOLEAN +TIMEINFO::operator<= ( + IN TIMEINFO TimeInfo + ) CONST + +/*++ + +Routine Description: + + This function determines if the time information contained in this + class is less or equal than the time information received as parameter. + +Arguments: + + TimeInfo - An object of type TIMEINFO that contains the time + information to be compared. + +Return Value: + + BOOLEAN - A boolean value indicating if the time information in this + object is less or equal than the information in the object + received as parameter. + + +--*/ + + +{ + FILETIME ft; + + ft = _FileTime; + switch( CompareFileTime( &ft, TimeInfo.GetFileTime() ) ) { + + case -1: + case 0: + return( TRUE ); + + default: + return( FALSE ); + } +} + + + +BOOLEAN +TIMEINFO::operator>= ( + IN TIMEINFO TimeInfo + ) CONST + +/*++ + +Routine Description: + + This function determines if the time information contained in this + class is greater or equal than the time information received as + parameter. + +Arguments: + + TimeInfo - An object of type TIMEINFO that contains the time + information to be compared. + +Return Value: + + BOOLEAN - A boolean value indicating if the time information in this + object is greater or equal than the information in the object + received as parameter. + + +--*/ + + +{ + FILETIME ft; + + ft = _FileTime; + switch( CompareFileTime( &ft, TimeInfo.GetFileTime() ) ) { + + case 0: + case 1: + return( TRUE ); + + default: + return( FALSE ); + } +} diff --git a/private/utils/ulib/src/ulib.cxx b/private/utils/ulib/src/ulib.cxx new file mode 100644 index 000000000..10c785150 --- /dev/null +++ b/private/utils/ulib/src/ulib.cxx @@ -0,0 +1,681 @@ +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + ulib.cxx + +Abstract: + + This module contains run-time, global support for the ULIB class library. + This support includes: + + - creation of CLASS_DESCRIPTORs + - Global objects + - Ulib to Win32 API mapping functions + +Author: + + David J. Gilman (davegi) 05-Dec-1990 + +Environment: + + ULIB, User Mode + +Notes: + +--*/ + +#include <pch.cxx> + +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "error.hxx" + +#if !defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ ) + +#include "system.hxx" +#include "array.hxx" +#include "arrayit.hxx" +#include "bitvect.hxx" +#include "dir.hxx" +#include "file.hxx" +#include "filestrm.hxx" +#include "filter.hxx" +#include "keyboard.hxx" +#include "message.hxx" +#include "wstring.hxx" +#include "path.hxx" +#include "pipestrm.hxx" +#include "prtstrm.hxx" +#include "screen.hxx" +#include "stream.hxx" +#include "timeinfo.hxx" + +extern "C" { +#include <locale.h> +} + +#endif // _AUTOCHECK_ || _SETUP_LOADER_ + + +// +// Constants +// + +CONST CLASS_ID NIL_CLASS_ID = 0; + +#if !defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ ) + +#if DBG==1 + +// +// UlibGlobalFlag is used to selectively enable debugging options at +// run-time. +// + +ULONG UlibGlobalFlag = 0x00000000; + +ULIB_EXPORT +VOID +DebugPrintf( + IN PCSTR Format, + IN ... + ) + +/*++ + +Routine Description: + + Printf to the debug console. + +Arguments: + + Format - Supplies a printf style format string. + +Return Value: + + None. + +--*/ + +{ + STR Buffer[ 512 ]; + va_list args; + + va_start( args, Format ); + vsprintf( Buffer, Format, args ); + va_end( args ); + OutputDebugStringA( Buffer ); +} + +#endif // DBG +// +// GLobal object pointers. +// + +// Clients of the DLL cannot access the DLL's +// global data yet, so I have the delightful hacks to get at it. + +ULIB_EXPORT +PSTREAM +Get_Standard_Input_Stream( + ) +{ + return Standard_Input_Stream; +} + +ULIB_EXPORT +PSTREAM +Get_Standard_Output_Stream( + ) +{ + return Standard_Output_Stream; +} + +ULIB_EXPORT +PSTREAM +Get_Standard_Error_Stream( + ) +{ + return Standard_Error_Stream; +} + +PSTREAM Standard_Input_Stream; +PSTREAM Standard_Output_Stream; +PSTREAM Standard_Error_Stream; + +#endif // _AUTOCHECK_ || _SETUP_LOADER_ + +// Note: Who put this here? Currently it is being defined +// by applications. Something has to be done about this. +ERRSTACK* perrstk; + + +// +// Declare class descriptors for all classes. +// + +DECLARE_CLASS( CLASS_DESCRIPTOR ); + +DECLARE_CLASS( ARGUMENT ); +DECLARE_CLASS( ARGUMENT_LEXEMIZER ); +DECLARE_CLASS( ARRAY ); +DECLARE_CLASS( ARRAY_ITERATOR ); +DECLARE_CLASS( BITVECTOR ); +DECLARE_CLASS( BUFFER_STREAM ); +DECLARE_CLASS( BYTE_STREAM ); +DECLARE_CLASS( COMM_DEVICE ); +DECLARE_CLASS( CONT_MEM ); +DECLARE_CLASS( CONTAINER ); +DECLARE_CLASS( DSTRING ); +DECLARE_CLASS( FILE_STREAM ); +DECLARE_CLASS( FLAG_ARGUMENT ); +DECLARE_CLASS( FSNODE ); +DECLARE_CLASS( FSN_DIRECTORY ); +DECLARE_CLASS( FSN_FILE ); +DECLARE_CLASS( FSN_FILTER ); +DECLARE_CLASS( FSTRING ); +DECLARE_CLASS( HMEM ); +DECLARE_CLASS( ITERATOR ); +DECLARE_CLASS( KEYBOARD ); +DECLARE_CLASS( LIST ); +DECLARE_CLASS( LIST_ITERATOR ); +DECLARE_CLASS( LONG_ARGUMENT ); +DECLARE_CLASS( MEM ); +DECLARE_CLASS( MESSAGE ); +DECLARE_CLASS( MULTIPLE_PATH_ARGUMENT ); +DECLARE_CLASS( OBJECT ); +DECLARE_CLASS( PATH ); +DECLARE_CLASS( PATH_ARGUMENT ); +DECLARE_CLASS( PIPE ); +DECLARE_CLASS( PIPE_STREAM ); +DECLARE_CLASS( PROGRAM ); +DECLARE_CLASS( PRINT_STREAM ); +DECLARE_CLASS( REST_OF_LINE_ARGUMENT ); +DECLARE_CLASS( SCREEN ); +DECLARE_CLASS( SEQUENTIAL_CONTAINER ); +DECLARE_CLASS( SORTABLE_CONTAINER ); +DECLARE_CLASS( SORTED_LIST ); +DECLARE_CLASS( SORTED_LIST_ITERATOR ); +DECLARE_CLASS( STREAM_MESSAGE ); +DECLARE_CLASS( STACK ); +DECLARE_CLASS( STREAM ); +DECLARE_CLASS( WSTRING ); +DECLARE_CLASS( STRING_ARGUMENT ); +DECLARE_CLASS( STRING_ARRAY ); +DECLARE_CLASS( TIMEINFO ); +DECLARE_CLASS( TIMEINFO_ARGUMENT ); +DECLARE_CLASS( STATIC_MEM_BLOCK_MGR ); +DECLARE_CLASS( MEM_BLOCK_MGR ); + + +#if defined( _AUTOCHECK_ ) + + DECLARE_CLASS( AUTOCHECK_MESSAGE ); + +#endif // _AUTOCHECK_ + + + + + +// +// Local prototypes +// +STATIC +BOOLEAN +DefineClassDescriptors ( + ); + +#if !defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ ) + +BOOLEAN +CreateStandardStreams ( + ); + +PSTREAM +GetStandardStream ( + IN HANDLE Handle, + IN STREAMACCESS Access + ); + +#endif // _AUTOCHECK_ || _SETUP_LOADER_ + + +BOOLEAN +InitializeUlib ( + IN HANDLE DllHandle, + IN ULONG Reason, + IN PVOID Reserved + ) + +/*++ + +Routine Description: + + Initilize Ulib by constructing and initializing all global objects. These + include: + + - all CLASS_DESCRIPTORs (class_cd) + - SYSTEM (System) + - Standard streams + +Arguments: + + DllHandle - Not used. + Reason - Supplies the reason why the entry point was called. + Reserved - Not used. + +Return Value: + + BOOLEAN - Returns TRUE if all global objects were succesfully constructed + and initialized. + +--*/ + +{ + + STATIC BOOLEAN fInit = FALSE; + + UNREFERENCED_PARAMETER( DllHandle ); + UNREFERENCED_PARAMETER( Reason ); + UNREFERENCED_PARAMETER( Reserved ); + + + if ( fInit ) { + return( TRUE ); + } + + fInit = TRUE; + +#if defined( _AUTOCHECK_ ) || defined( _SETUP_LOADER_ ) + + if( !DefineClassDescriptors() ) { + return( FALSE ); + } + +#else // _AUTOCHECK_ and _SETUP_LOADER_ not defined + // + // Initialization of ULIB can no longer depend on + // the initialization of the standard streams since they don't seem + // to exist for Windows programs (no console...) + // + + if( !DefineClassDescriptors() ) { + DebugAbort( "Ulib initialization failed!!!\n" ); + return( FALSE ); + } + + CreateStandardStreams(); + + setlocale(LC_ALL, ""); + +#endif // _AUTOCHECK || _SETUP_LOADER_ + + return( TRUE ); + +} + +STATIC +BOOLEAN +DefineClassDescriptors ( + ) + +/*++ + +Routine Description: + + Defines all the class descriptors used by ULIB + +Arguments: + + None. + +Return Value: + + BOOLEAN - Returns TRUE if all class descriptors were succesfully + constructed and initialized. + +--*/ + +{ + + // This is broken up into many ifs because of compiler limitations. + + BOOLEAN Success = TRUE; + + if (Success && + DEFINE_CLASS_DESCRIPTOR( ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( ARGUMENT_LEXEMIZER ) && + DEFINE_CLASS_DESCRIPTOR( ARRAY ) && + DEFINE_CLASS_DESCRIPTOR( ARRAY_ITERATOR ) && + DEFINE_CLASS_DESCRIPTOR( BITVECTOR ) && + DEFINE_CLASS_DESCRIPTOR( BYTE_STREAM ) && + DEFINE_CLASS_DESCRIPTOR( COMM_DEVICE ) && + DEFINE_CLASS_DESCRIPTOR( CONTAINER ) && + DEFINE_CLASS_DESCRIPTOR( DSTRING ) && + DEFINE_CLASS_DESCRIPTOR( FLAG_ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( FSNODE ) && + DEFINE_CLASS_DESCRIPTOR( FSN_DIRECTORY ) && + DEFINE_CLASS_DESCRIPTOR( FSN_FILE ) && + DEFINE_CLASS_DESCRIPTOR( FSN_FILTER ) && + DEFINE_CLASS_DESCRIPTOR( ITERATOR ) && + DEFINE_CLASS_DESCRIPTOR( LIST ) && + DEFINE_CLASS_DESCRIPTOR( LIST_ITERATOR ) && + DEFINE_CLASS_DESCRIPTOR( LONG_ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( MULTIPLE_PATH_ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( PATH ) && + DEFINE_CLASS_DESCRIPTOR( PATH_ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( PROGRAM ) && + DEFINE_CLASS_DESCRIPTOR( SEQUENTIAL_CONTAINER ) && + DEFINE_CLASS_DESCRIPTOR( SORTABLE_CONTAINER ) && + DEFINE_CLASS_DESCRIPTOR( SORTED_LIST ) && + DEFINE_CLASS_DESCRIPTOR( SORTED_LIST_ITERATOR ) && + DEFINE_CLASS_DESCRIPTOR( WSTRING ) && + DEFINE_CLASS_DESCRIPTOR( STRING_ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( STRING_ARRAY ) && + DEFINE_CLASS_DESCRIPTOR( TIMEINFO ) && + DEFINE_CLASS_DESCRIPTOR( TIMEINFO_ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( MESSAGE ) && + TRUE ) { + } else { + Success = FALSE; + } + + if (Success && + DEFINE_CLASS_DESCRIPTOR( BUFFER_STREAM ) && + DEFINE_CLASS_DESCRIPTOR( CONT_MEM ) && + TRUE ) { + } else { + Success = FALSE; + } + + if (Success && + DEFINE_CLASS_DESCRIPTOR( FILE_STREAM ) && + DEFINE_CLASS_DESCRIPTOR( FSTRING ) && + DEFINE_CLASS_DESCRIPTOR( HMEM ) && + DEFINE_CLASS_DESCRIPTOR( STATIC_MEM_BLOCK_MGR ) && + DEFINE_CLASS_DESCRIPTOR( MEM_BLOCK_MGR ) && + TRUE ) { + } else { + Success = FALSE; + } + + if (Success && + DEFINE_CLASS_DESCRIPTOR( KEYBOARD ) && + DEFINE_CLASS_DESCRIPTOR( MEM ) && + DEFINE_CLASS_DESCRIPTOR( PATH_ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( PIPE ) && + DEFINE_CLASS_DESCRIPTOR( PIPE_STREAM ) && + DEFINE_CLASS_DESCRIPTOR( PRINT_STREAM ) && + + + DEFINE_CLASS_DESCRIPTOR( REST_OF_LINE_ARGUMENT ) && + DEFINE_CLASS_DESCRIPTOR( SCREEN ) && + DEFINE_CLASS_DESCRIPTOR( STREAM ) && + DEFINE_CLASS_DESCRIPTOR( STREAM_MESSAGE ) && + +#if defined( _AUTOCHECK_ ) + + DEFINE_CLASS_DESCRIPTOR( AUTOCHECK_MESSAGE ) && + +#endif // _AUTOCHECK_ + + TRUE ) { + } else { + Success = FALSE; + } + + + if (Success && + TRUE ) { + } else { + Success = FALSE; + } + + if (!Success) { + DebugPrint( "Could not initialize class descriptors!"); + } + return Success; + +} + + +#if !defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ ) + +BOOLEAN +CreateStandardStreams ( + ) + +/*++ + +Routine Description: + + Creates the standard streams + +Arguments: + + None. + +Return Value: + + TRUE if the streams were successfully created, + FALSE otherwise + +--*/ + +{ + + Standard_Input_Stream = GetStandardStream( GetStdHandle( STD_INPUT_HANDLE), + READ_ACCESS ); + + Standard_Output_Stream = GetStandardStream( GetStdHandle( STD_OUTPUT_HANDLE), + WRITE_ACCESS ); + + Standard_Error_Stream = GetStandardStream( GetStdHandle( STD_ERROR_HANDLE), + WRITE_ACCESS ); + + + return ( (Standard_Input_Stream != NULL) && + (Standard_Output_Stream != NULL) && + (Standard_Error_Stream != NULL) ); +} + +PSTREAM +GetStandardStream ( + IN HANDLE Handle, + IN STREAMACCESS Access + ) + +/*++ + +Routine Description: + + Creates a standard stream out of a standard handle + +Arguments: + + Handle - Supplies the standard handle + Access - Supplies the access. + +Return Value: + + Pointer to the stream object created. + +--*/ + + +{ + PSTREAM Stream = NULL; + PFILE_STREAM FileStream; + PPIPE_STREAM PipeStream; + PKEYBOARD Keyboard; + PSCREEN Screen; + + + switch ( GetFileType( Handle ) ) { + + case (DWORD)FILE_TYPE_DISK: + + if ((FileStream = NEW FILE_STREAM) != NULL ) { + if ( !FileStream->Initialize( Handle, Access ) ) { + DELETE( FileStream ); + } + Stream = (PSTREAM)FileStream; + } + break; + + + case (DWORD)FILE_TYPE_CHAR: + + // + // BUGBUG RamonSA this type refers to all character devices, not + // just the console. I will add some hacks to see if + // the handle refers to the console or not. This + // information should be given in a clean way by the + // API (talk with MarkL) + // + switch ( Access ) { + + case READ_ACCESS: + + // + // BUGBUG Jaimes See if this is a console handle + // + { + DWORD Mode; + if (!GetConsoleMode( Handle, &Mode )) { + // + // This is not a console, but some other character + // device. Create a pipe stream for it. + // + if ((PipeStream = NEW PIPE_STREAM) != NULL ) { + if ( !PipeStream->Initialize( Handle, Access ) ) { + DELETE( PipeStream ); + } + Stream = (PSTREAM)PipeStream; + } + break; + } + } + if ((Keyboard = NEW KEYBOARD) != NULL ) { + if ( !Keyboard->Initialize() ) { + DELETE( Keyboard ); + } + Stream = (PSTREAM)Keyboard; + } + break; + + case WRITE_ACCESS: + + // + // BUGBUG Ramonsa See if this is a console handle + // + { + DWORD Mode; + if (!GetConsoleMode( Handle, &Mode )) { + // + // This is not a console, but some other character + // device. Create a file stream for it. + // + if ((FileStream = NEW FILE_STREAM) != NULL ) { + if ( !FileStream->Initialize( Handle, Access ) ) { + DELETE( FileStream ); + } + Stream = (PSTREAM)FileStream; + } + break; + } + } + + if ((Screen = NEW SCREEN) != NULL ) { + if ( !Screen->Initialize() ) { + DELETE( Screen ); + } + Stream = (PSTREAM)Screen; + } + break; + + default: + break; + } + + break; + + case (DWORD)FILE_TYPE_PIPE: + + if ((PipeStream = NEW PIPE_STREAM) != NULL ) { + if ( !PipeStream->Initialize( Handle, Access ) ) { + DELETE( PipeStream ); + } + Stream = (PSTREAM)PipeStream; + } + break; + + case (DWORD)FILE_TYPE_UNKNOWN: + // Probably a windows app. Don't print anything to debug. + break; + + default: + DebugPrintf( "ERROR: FileType for standard stream %lx is invalid (%lx)\n", Handle, GetFileType(Handle) ); + break; + + } + + return Stream; + +} + +NONVIRTUAL +ULIB_EXPORT +HANDLE +FindFirstFile ( + IN PCPATH Path, + OUT PWIN32_FIND_DATA FileFindData + ) + +/*++ + +Routine Description: + + Perform a FindFirst file given a PATH rather tha a PSTR. + +Arguments: + + Path - Supplies a pointer to the PATH to search. + FileFindData - Supplies a pointer where the results of the find is + returned. + +Return Value: + + HANDLE - Returns the results of the call to the Win32 FindFirstFile API. + +--*/ + +{ + PWSTR p; + + // + // If the supplied pointers are non-NULL and an OEM representation + // (i.e. API ready) of the PATH is available, return the + // HANDLE returned by the Win32 FindFirstFile API + // + + DebugPtrAssert( Path ); + DebugPtrAssert( FileFindData ); + if (!Path || !FileFindData) { + return INVALID_HANDLE_VALUE; + } + + p = (PWSTR) Path->GetPathString()->GetWSTR(); + if (!p) { + return INVALID_HANDLE_VALUE; + } + + return FindFirstFile(p, FileFindData); +} + +#endif // _AUTOCHECK_ || _SETUP_LOADER_ diff --git a/private/utils/ulib/src/ulib.rc b/private/utils/ulib/src/ulib.rc new file mode 100644 index 000000000..85a680014 --- /dev/null +++ b/private/utils/ulib/src/ulib.rc @@ -0,0 +1,10 @@ +#include <windows.h> +#include <ntverp.h> + +#define VER_FILETYPE VFT_DLL +#define VER_FILESUBTYPE VFT2_UNKNOWN +#define VER_FILEDESCRIPTION_STR "File Utilities Support DLL" +#define VER_INTERNALNAME_STR "ulib.dll" +#define VER_ORIGINALFILENAME_STR "ulib.dll" + +#include "common.ver" diff --git a/private/utils/ulib/src/usa-ms.msg b/private/utils/ulib/src/usa-ms.msg new file mode 100644 index 000000000..055d66676 --- /dev/null +++ b/private/utils/ulib/src/usa-ms.msg @@ -0,0 +1,1588 @@ +0408 +COMMON 00000006 0038 +0001 U 0000 "Incorrect DOS version",CR,LF +0002 U 0000 "%1 already installed",CR,LF +0003 U 0000 "%1 bytes available on disk",CR,LF +0004 U 0000 "%1 bytes free",CR,LF +0005 U 0000 "%1 bytes in bad sectors",CR,LF +0006 U 0000 "%1 bytes total disk space",CR,LF +0007 U 0000 "%1 bytes total memory",CR,LF +0008 U 0000 "%1 bytes used by system",CR,LF +0009 U 0000 "%1 installed",CR,LF +0010 U 0000 "%1 not installed",CR,LF +0011 U 0000 "%1 not installed",CR,LF +0012 U 0000 "Cannot %1 a network drive",CR,LF +0013 U 0000 "", +0014 U 0000 "Cannot %1 a SUBSTed or ASSIGNed drive",CR,LF +0015 U 0000 "Cannot execute %1",CR,LF +0016 U 0000 "Expanded Memory not available",CR,LF +0017 U 0000 "File allocation table bad, drive %1",CR,LF +0018 U 0000 "File cannot be copied onto itself",CR,LF +0019 U 0000 "Insert target disk in drive %1",CR,LF +0020 U 0000 "Insufficient disk space",CR,LF +0021 U 0000 "Invalid characters in volume label",CR,LF +0022 U 0000 "Invalid code page",CR,LF +0023 U 0000 "Invalid date",CR,LF +0024 U 0000 "Invalid time",CR,LF +0025 U 0000 "Invalid path",CR,LF +0026 U 0000 "No source drive specified",CR,LF +0027 U 0000 "No target drive specified",CR,LF +0028 U 0000 "Press any key to continue . . .",CR,LF +0029 U 0000 "Source path required",CR,LF +0030 U 0000 "System transferred",CR,LF +0031 U 0000 "", +0032 U 0000 "Unable to create directory",CR,LF +0033 U 0000 "Volume in drive %1 has no label",CR,LF +0034 U 0000 "Volume in drive %1 is %2",CR,LF +0035 U 0001 "Volume label (11 characters, ENTER for none)? " +0036 U 0000 "Volume Serial Number is %1-%2",CR,LF +0037 U 0000 "Incorrect file type",CR,LF +0038 U 0001 CR,LF +EXTEND 00000689 0090 +0001 U 0003 "Invalid function" +0002 U 0000 "File not found" +0003 U 0000 "Path not found" +0004 U 0000 "Too many open files" +0005 U 0000 "Access denied " +0006 U 0000 "Invalid handle" +0007 U 0000 "Memory control blocks destroyed" +0008 U 0000 "Insufficient memory" +0009 U 0000 "Invalid memory block address" +0010 U 0000 "Invalid Environment" +0011 U 0000 "Invalid format" +0012 U 0000 "Invalid function parameter" +0013 U 0000 "Invalid data" +0014 U 0000 "", +0015 U 0000 "Invalid drive specification" +0016 U 0000 "Attempt to remove current directory" +0017 U 0000 "Not same device" +0018 U 0000 "No more files" +0019 U 0000 "Write protect error" +0020 U 0000 "Invalid unit" +0021 U 0000 "Not ready" +0022 U 0000 "Invalid device request" +0023 U 0000 "Data error" +0024 U 0000 "Invalid device request parameters" +0025 U 0000 "Seek error" +0026 U 0000 "Invalid media type" +0027 U 0000 "Sector not found" +0028 U 0000 "Printer out of paper error" +0029 U 0000 "Write fault error" +0030 U 0000 "Read fault error" +0031 U 0000 "General failure" +0032 U 0000 "Sharing violation" +0033 U 0000 "Lock violation" +0034 U 0000 "Invalid disk change" +0035 U 0000 "FCB unavailable" +0036 U 0000 "System resource exhausted" +0037 U 0000 "Code page mismatch" +0038 U 0000 "Out of input" +0039 U 0000 "Insufficient disk space" +0040 U 0000 "", +0041 U 0000 "", +0042 U 0000 "", +0043 U 0000 "", +0044 U 0000 "", +0045 U 0000 "", +0046 U 0000 "", +0047 U 0000 "", +0048 U 0000 "", +0049 U 0000 "", +0050 U 0000 "NET809: Network request not supported" +0051 U 0000 "NET801: Remote computer not listening" +0052 U 0000 "NET802: Duplicate name on network" +0053 U 0000 "NET803: Network path not found" +0054 U 0000 "NET804: Network busy" +0055 U 0000 "NET805: Network device no longer exists" +0056 U 0000 "NET806: NETBIOS command limit exceeded" +0057 U 0000 "NET807: System error; NETBIOS error" +0058 U 0000 "NET808: Incorrect response from network" +0059 U 0000 "NET810: Unexpected network error" +0060 U 0000 "NET811: Incompatible remote adapter" +0061 U 0000 "NET812: Print queue full" +0062 U 0000 "NET813: Not enough space for print file" +0063 U 0000 "NET814: Print file was cancelled" +0064 U 0000 "NET815: Network name was deleted" +0065 U 0000 "Access denied" +0066 U 0000 "NET817: Network device type incorrect" +0067 U 0000 "NET818: Network name not found" +0068 U 0000 "NET819: Network name limit exceeded" +0069 U 0000 "NET820: NETBIOS session limit exceeded" +0070 U 0000 "NET821: Sharing temporarily paused" +0071 U 0000 "NET823: Network request not accepted" +0072 U 0000 "NET822: Print or disk redirection is paused" +0073 U 0000 "NET476: Netbeui not loaded" +0074 U 0000 "NET477: Unexpected adapter close" +0075 U 0000 "", +0076 U 0000 "", +0077 U 0004 "", +0078 U 0004 "", +0079 U 0004 "", +0080 U 0004 "File exists" +0081 U 0004 "", +0082 U 0004 "Cannot make directory entry" +0083 U 0004 "Fail on INT 24" +0084 U 0004 "Too many redirections" +0085 U 0004 "Duplicate redirection" +0086 U 0004 "Invalid password" +0087 U 0004 "Invalid parameter" +0088 U 0004 "Network data fault" +0089 U 0004 "Function not supported by network" +0090 U 0002 "Required system component not installed" +PARSE 0000131d 0011 +0001 U 0000 "Too many parameters" +0002 U 0000 "Required parameter missing" +0003 U 0000 "Invalid switch" +0004 U 0000 "Invalid keyword" +0005 U 0000 "", +0006 U 0000 "Parameter value not in allowed range" +0007 U 0000 "Parameter value not allowed" +0008 U 0000 "Parameter value not allowed" +0009 U 0000 "Parameter format not correct" +0010 U 0000 "Invalid parameter" +0011 U 0000 "Invalid parameter combination" +COMMAND 000014d4 0147 +1002 U 0000 "Duplicate file name or file not found",CR,LF +1003 U 0000 "Invalid path or file name",CR,LF +1007 U 0000 "Out of environment space",CR,LF +1008 U 0000 "File creation error",CR,LF +1009 U 0000 "Batch file missing",CR,LF +1010 U 0000 CR,LF,"Insert disk with batch file",CR,LF +1011 U 0000 "Bad command or file name",CR,LF +1016 U 0000 "Content of destination lost before copy",CR,LF +1017 U 0000 "Invalid filename or file not found",CR,LF +1018 U 0000 "%1 file(s) copied",CR,LF +1019 U 0000 "%1 file(s) " +1022 U 0000 "Code page %1 not prepared for system",CR,LF +1023 U 0000 "Code page %1 not prepared for all devices",CR,LF +1024 U 0000 "Active code page: %1",CR,LF +1025 U 0000 "NLSFUNC not installed",CR,LF +1027 U 0000 "Current drive is no longer valid" +1029 U 0000 "Label not found",CR,LF +1030 U 0000 "Syntax error",CR,LF +1032 U 0000 "Current date is %1 %2",CR,LF +1033 U 0000 "SunMonTueWedThuFriSat" +1034 U 0000 "Enter new date (%1): " +1036 U 0000 "Current time is %1",CR,LF +1037 U 0000 "Enter new time: " +1038 U 0000 ", Delete (Y/N)?" +1039 U 0000 "All files in directory will be deleted!",CR,LF,"Are you sure (Y/N)?" +1040 U 0000 "MS-DOS Version %1.%2" +1044 U 0000 "Invalid directory",CR,LF +1046 U 0000 "Invalid path, not directory,",CR,LF,"or directory not empty",CR,LF +1047 U 0000 "Must specify ON or OFF",CR,LF +1048 U 0000 "Directory of %1",CR,LF +1049 U 0000 "No Path",CR,LF +1050 U 0000 "Invalid drive in search path",CR,LF +1051 U 0000 "Invalid device",CR,LF +1052 U 0000 "FOR cannot be nested",CR,LF +1053 U 0000 "Intermediate file error during pipe",CR,LF +1054 U 0000 "Cannot do binary reads from a device",CR,LF +1055 U 0000 "BREAK is %1",CR,LF +1056 U 0000 "VERIFY is %1",CR,LF +1057 U 0000 "ECHO is %1",CR,LF +1059 U 0000 "off",0 +1060 U 0000 "on",0 +1061 U 0000 "Error writing to device",CR,LF +1063 U 0000 "%1" +1064 U 0000 "%1" +1065 U 0000 "%1" +1066 U 0000 "%1" +1067 U 0000 9 +1068 U 0000 " <DIR> " +1069 U 0000 8," ",8 +1070 U 0000 CR,LF +1071 U 0000 "%1" +1072 U 0000 "mm-dd-yy" +1073 U 0000 "dd-mm-yy" +1074 U 0000 "yy-mm-dd" +1075 U 0000 "%1 %2" +1076 U 0000 "%1" +1077 U 0000 " %1 %2" +1078 U 0000 "Directory already exists",CR,LF +1079 U 0000 "%1 bytes",CR,LF +1080 U 0000 "Total files listed:",CR,LF +1081 U 0000 "(Error occurred in environment variable)",CR,LF +1084 U 0000 "(continuing %1)" +1090 U 0000 "Revision %1",CR,LF +1091 U 0000 "DOS is in ROM" +1092 U 0000 "DOS is in HMA" +1093 U 0000 "DOS is in low memory" +1094 U 0000 "Cannot Loadhigh batch file",CR,LF +1095 U 0000 "LoadHigh: Invalid filename",CR,LF +1096 U 0000 "Cannot open specified country information file",CR,LF +1300 U 0000 "Sets or clears extended CTRL+C checking.",CR,LF,CR,LF + "BREAK [ON | OFF]",CR,LF,CR,LF + "Type BREAK without a parameter to display the current BREAK setting.",CR,LF +1320 U 0000 "Displays or sets the active code page number.",CR,LF,CR,LF + "CHCP [nnn]",CR,LF,CR,LF +1321 U 0000 " nnn Specifies a code page number.",CR,LF,CR,LF + "Type CHCP without a parameter to display the active code page number.",CR,LF +1340 U 0000 "Displays the name of or changes the current directory.",CR,LF,CR,LF + "CHDIR [drive:][path]",CR,LF + "CHDIR[..]",CR,LF +1341 U 0000 "CD [drive:][path]",CR,LF + "CD[..]",CR,LF,CR,LF + " .. Specifies that you want to change to the parent directory.",CR,LF,CR,LF +1342 U 0000 "Type CD drive: to display the current directory in the specified drive.",CR,LF + "Type CD without parameters to display the current drive and directory.",CR,LF +1360 U 0000 "Clears the screen.",CR,LF,CR,LF + "CLS",CR,LF +1400 U 0000 "Copies one or more files to another location.",CR,LF,CR,LF + "COPY [/A | /B] source [/A | /B] [+ source [/A | /B] [+ ...]] [destination",CR,LF + " [/A | /B]] [/V]",CR,LF,CR,LF +1401 U 0000 " source Specifies the file or files to be copied.",CR,LF + " /A Indicates an ASCII text file.",CR,LF +1402 U 0000 " /B Indicates a binary file.",CR,LF + " destination Specifies the directory and/or filename for the new file(s).",CR,LF +1403 U 0000 " /V Verifies that new files are written correctly.",CR,LF,CR,LF +1404 U 0000 "To append files, specify a single file for destination, but multiple files",CR,LF + "for source (using wildcards or file1+file2+file3 format).",CR,LF +1420 U 0000 "Changes the terminal device used to control your system.",CR,LF,CR,LF + "CTTY device",CR,LF,CR,LF + " device The terminal device you want to use, such as COM1.",CR,LF +1440 U 0000 "Displays or sets the date.",CR,LF,CR,LF + "DATE [date]",CR,LF,CR,LF +1441 U 0000 "Type DATE without parameters to display the current date setting and",CR,LF + "a prompt for a new one. Press ENTER to keep the same date.",CR,LF +1460 U 0000 "Deletes one or more files.",CR,LF,CR,LF + "DEL [drive:][path]filename [/P]",CR,LF + "ERASE [drive:][path]filename [/P]",CR,LF,CR,LF +1461 U 0000 " [drive:][path]filename Specifies the file(s) to delete. Specify multiple",CR,LF + " files by using wildcards.",CR,LF +1462 U 0000 " /P Prompts for confirmation before deleting each file.",CR,LF +1480 U 0000 "Displays a list of files and subdirectories in a directory.",CR,LF,CR,LF + "DIR [drive:][path][filename] [/P] [/W] [/A[[:]attributes]]",CR,LF + " [/O[[:]sortorder]] [/S] [/B] [/L]",CR,LF,CR,LF +1481 U 0000 " [drive:][path][filename]",CR,LF + " Specifies drive, directory, and/or files to list.",CR,LF +1482 U 0000 " /P Pauses after each screenful of information.",CR,LF + " /W Uses wide list format.",CR,LF +1483 U 0000 " /A Displays files with specified attributes.",CR,LF + " attributes D Directories R Read-only files",CR,LF +1484 U 0000 " H Hidden files A Files ready for archiving",CR,LF + " S System files - Prefix meaning ""not""",CR,LF + " /O List by files in sorted order.",CR,LF +1485 U 0000 " sortorder N By name (alphabetic) S By size (smallest first)",CR,LF + " E By extension (alphabetic) D By date & time (earliest first)",CR,LF +1486 U 0000 " G Group directories first - Prefix to reverse order",CR,LF + " /S Displays files in specified directory and all subdirectories.",CR,LF +1487 U 0000 " /B Uses bare format (no heading information or summary).",CR,LF + " /L Uses lowercase.",CR,LF,CR,LF +1488 U 0000 "Switches may be preset in the DIRCMD environment variable. Override",CR,LF + "preset switches by prefixing any switch with - (hyphen)--for example, /-W.",CR,LF +1500 U 0000 "Quits the COMMAND.COM program (command interpreter).",CR,LF,CR,LF + "EXIT",CR,LF +1520 U 0000 "Creates a directory.",CR,LF,CR,LF + "MKDIR [drive:]path",CR,LF + "MD [drive:]path",CR,LF +1540 U 0000 "Displays or sets a search path for executable files.",CR,LF,CR,LF + "PATH [[drive:]path[;...]]",CR,LF + "PATH ;",CR,LF,CR,LF +1541 U 0000 "Type PATH ; to clear all search-path settings and direct MS-DOS to search",CR,LF + "only in the current directory.",CR,LF +1542 U 0000 "Type PATH without parameters to display the current path.",CR,LF +1560 U 0000 "Changes the MS-DOS command prompt.",CR,LF,CR,LF + "PROMPT [text]",CR,LF,CR,LF +1561 U 0000 " text Specifies a new command prompt.",CR,LF,CR,LF + "Prompt can be made up of normal characters and the following special codes:",CR,LF,CR,LF +1562 U 0000 " $Q = (equal sign)",CR,LF + " $$ $ (dollar sign)",CR,LF +1563 U 0000 " $T Current time",CR,LF + " $D Current date",CR,LF +1564 U 0000 " $P Current drive and path",CR,LF + " $V MS-DOS version number",CR,LF +1565 U 0000 " $N Current drive",CR,LF + " $G > (greater-than sign)",CR,LF +1566 U 0000 " $L < (less-than sign)",CR,LF + " $B | (pipe)",CR,LF +1567 U 0000 " $H Backspace (erases previous character)",CR,LF + " $E Escape code (ASCII code 27)",CR,LF + " $_ Carriage return and linefeed",CR,LF,CR,LF +1568 U 0000 "Type PROMPT without parameters to reset the prompt to the default setting.",CR,LF +1580 U 0000 "Removes (deletes) a directory.",CR,LF,CR,LF + "RMDIR [drive:]path",CR,LF + "RD [drive:]path",CR,LF +1600 U 0000 "Renames a file or files.",CR,LF,CR,LF +1601 U 0000 "RENAME [drive:][path]filename1 filename2",CR,LF + "REN [drive:][path]filename1 filename2",CR,LF,CR,LF +1602 U 0000 "Note that you cannot specify a new drive or path for your destination file.",CR,LF +1620 U 0000 "Displays, sets, or removes MS-DOS environment variables.",CR,LF,CR,LF + "SET [variable=[string]]",CR,LF,CR,LF +1621 U 0000 " variable Specifies the environment-variable name.",CR,LF + " string Specifies a series of characters to assign to the variable.",CR,LF,CR,LF +1622 U 0000 "Type SET without parameters to display the current environment variables.",CR,LF +1640 U 0000 "Displays or sets the system time.",CR,LF,CR,LF + "TIME [time]",CR,LF,CR,LF +1641 U 0000 "Type TIME with no parameters to display the current time setting and a prompt",CR,LF + "for a new one. Press ENTER to keep the same time.",CR,LF +1660 U 0000 "Displays the contents of a text file.",CR,LF,CR,LF + "TYPE [drive:][path]filename",CR,LF +1680 U 0000 "Displays the MS-DOS version.",CR,LF,CR,LF + "VER",CR,LF +1700 U 0000 "Tells MS-DOS whether to verify that your files are written correctly to a",CR,LF + "disk.",CR,LF,CR,LF + "VERIFY [ON | OFF]",CR,LF,CR,LF + "Type VERIFY without a parameter to display the current VERIFY setting.",CR,LF +1720 U 0000 "Displays the disk volume label and serial number, if they exist.",CR,LF,CR,LF + "VOL [drive:]",CR,LF +1740 U 0000 "Calls one batch program from another.",CR,LF,CR,LF + "CALL [drive:][path]filename [batch-parameters]",CR,LF,CR,LF +1741 U 0000 " batch-parameters Specifies any command-line information required by the",CR,LF + " batch program.",CR,LF +1760 U 0000 "Records comments (remarks) in a batch file or CONFIG.SYS.",CR,LF,CR,LF + "REM [comment]",CR,LF +1780 U 0000 "Suspends processing of a batch program and displays the message ""Press any",CR,LF + "key to continue....""",CR,LF,CR,LF + "PAUSE",CR,LF +1800 U 0000 "Displays messages, or turns command-echoing on or off.",CR,LF,CR,LF + " ECHO [ON | OFF]",CR,LF +1801 U 0000 " ECHO [message]",CR,LF,CR,LF + "Type ECHO without parameters to display the current echo setting.",CR,LF +1820 U 0000 "Directs MS-DOS to a labelled line in a batch program.",CR,LF,CR,LF + "GOTO label",CR,LF,CR,LF +1821 U 0000 " label Specifies a text string used in the batch program as a label.",CR,LF,CR,LF + "You type a label on a line by itself, beginning with a colon.",CR,LF +1840 U 0000 "Changes the position of replaceable parameters in a batch file.",CR,LF,CR,LF + "SHIFT",CR,LF +1860 U 0000 "Performs conditional processing in batch programs.",CR,LF,CR,LF + "IF [NOT] ERRORLEVEL number command",CR,LF +1861 U 0000 "IF [NOT] string1==string2 command",CR,LF + "IF [NOT] EXIST filename command",CR,LF,CR,LF +1862 U 0000 " NOT Specifies that MS-DOS should carry out the command only",CR,LF + " if the condition is false.",CR,LF +1863 U 0000 " ERRORLEVEL number Specifies a true condition if the last program run returned",CR,LF + " an exit code equal to or greater than the number specified.",CR,LF +1864 U 0000 " command Specifies the command to carry out if the condition is",CR,LF + " met.",CR,LF +1865 U 0000 " string1==string2 Specifies a true condition if the specified text strings",CR,LF + " match.",CR,LF +1866 U 0000 " EXIST filename Specifies a true condition if the specified filename",CR,LF + " exists.",CR,LF +1880 U 0000 "Runs a specified command for each file in a set of files.",CR,LF,CR,LF + "FOR %variable IN (set) DO command [command-parameters]",CR,LF,CR,LF +1881 U 0000 " %variable Specifies a replaceable parameter.",CR,LF + " (set) Specifies a set of one or more files. Wildcards may be used.",CR,LF +1882 U 0000 " command Specifies the command to carry out for each file.",CR,LF + " command-parameters",CR,LF +1883 U 0000 " Specifies parameters or switches for the specified command.",CR,LF,CR,LF + "To use the FOR command in a batch program, specify %%variable instead of",CR,LF + "%variable.",CR,LF +1900 U 0000 "Reserved command name",CR,LF +1920 U 0000 "Loads a program into the upper memory area.",CR,LF,CR,LF +1921 U 0000 "LOADHIGH [drive:][path]filename [parameters]",CR,LF + "LH [drive:][path]filename [parameters]",CR,LF,CR,LF +1922 U 0000 " parameters Specifies any command-line information required by the",CR,LF + " program you want to load.",CR,LF +ANSI 000046c0 0001 +0010 U 0000 "Invalid parameter - %1",CR,LF +APPEND 00004704 0026 +0001 U 0000 "Incorrect APPEND version",CR,LF +0002 U 0000 "Invalid path",CR,LF +0003 U 0000 "Invalid parameter",CR,LF +0004 U 0000 "Invalid combination of parameters",CR,LF +0005 U 0000 "No Append",CR,LF +0006 U 0000 "APPEND / ASSIGN Conflict",CR,LF +0007 U 0000 "APPEND / TopView Conflict",CR,LF +0008 U 0000 "Incorrect DOS version",CR,LF +0009 U 0000 "APPEND already installed",CR,LF +0300 U 0000 "Allows programs to open data files in specified directories as if they were in",CR,LF +0301 U 0000 "the current directory.",CR,LF,CR,LF +0302 U 0000 "APPEND [[drive:]path[;...]] [/X[:ON | :OFF]] [/PATH:ON | /PATH:OFF] [/E]",CR,LF +0303 U 0000 "APPEND ;",CR,LF,CR,LF +0304 U 0000 " [drive:]path Specifies a drive and directory to append.",CR,LF +0305 U 0000 " /X:ON Applies appended directories to file searches and",CR,LF +0306 U 0000 " application execution.",CR,LF +0307 U 0000 " /X:OFF Applies appended directories only to requests to open files.",CR,LF +0308 U 0000 " /X:OFF is the default setting.",CR,LF +0309 U 0000 " /PATH:ON Applies appended directories to file requests that already",CR,LF +0310 U 0000 " specify a path. /PATH:ON is the default setting.",CR,LF +0311 U 0000 " /PATH:OFF Turns off the effect of /PATH:ON.",CR,LF +0312 U 0000 " /E Stores a copy of the appended directory list in an environment",CR,LF +0313 U 0000 " variable named APPEND. /E may be used only the first time",CR,LF +0314 U 0000 " you use APPEND after starting your system.",CR,LF,CR,LF +0315 U 0000 "Type APPEND ; to clear the appended directory list.",CR,LF +0316 U 0000 "Type APPEND without parameters to display the appended directory list.",CR,LF +ASSIGN 00004df2 0007 +0002 U 0000 "Original %1: set to %2:",cr,lf +0300 U 0000 "Redirects requests for disk operations on one drive to a different drive.",CR,LF,CR,LF +0301 U 0000 "ASSIGN [x[:]=y[:][...]]",CR,LF + "ASSIGN /STATUS",CR,LF,CR,LF +0302 U 0000 " x Specifies the drive letter to reassign.",CR,LF +0303 U 0000 " y Specifies the drive that x: will be assigned to.",CR,LF +0304 U 0000 " /STATUS Displays current drive assignments.",CR,LF,CR,LF +0305 U 0000 "Type ASSIGN without parameters to reset all drive letters to original",CR,LF + "assignments.",CR,LF +ATTRIB 0000503d 0027 +0004 U 0000 "Invalid number of parameters",CR,LF +0005 U 0000 "Invalid path or file not found",CR,LF +0006 U 0000 "Syntax error",CR,LF +0008 U 0000 " %1" +0009 U 0000 "%1 %2",CR,LF +0010 U 0000 "%1",CR,LF,"%2",CR,LF +0011 U 0000 "%1, Code page mismatch",CR,LF,"Are you sure (Y/N)?" +0012 U 0000 "%1",CR,LF +0014 U 0000 CR,LF +0015 U 0000 "Invalid file type value",CR,LF +0199 U 0000 "Extended attribute error",CR,LF +0201 U 0000 "Extended attribute name not found",CR,LF +0204 U 0000 "Extended attribute name cannot be set",CR,LF +0205 U 0000 "Extended attribute name known to this file system but not supported",CR,LF +0206 U 0000 "Extended attribute type mismatch",CR,LF +0208 U 0000 "Extended attribute value not supported",CR,LF +0216 U 0000 "Not resetting system file %1",CR,LF +0217 U 0000 "Not resetting hidden file %1",CR,LF +0300 U 0000 "Displays or changes file attributes.",CR,LF,CR,LF +0301 U 0000 "ATTRIB [+R | -R] [+A | -A] [+S | -S] [+H | -H] [[drive:][path]filename] [/S]",CR,LF,CR,LF +0302 U 0000 " + Sets an attribute.",CR,LF +0303 U 0000 " - Clears an attribute.",CR,LF +0304 U 0000 " R Read-only file attribute.",CR,LF +0305 U 0000 " A Archive file attribute.",CR,LF +0306 U 0000 " S System file attribute.",CR,LF +0307 U 0000 " H Hidden file attribute.",CR,LF +0308 U 0000 " /S Processes files in all directories in the specified path.",CR,LF +BACKUP 000055c2 0040 +0002 U 0000 CR,LF,"Insufficient memory",CR,LF +0006 U 0000 CR,LF,"Invalid drive specification",CR,LF +0014 U 0000 CR,LF,"Source and target drives are the same",CR,LF +0015 U 0001 CR,LF,"Error executing FORMAT",CR,LF +0016 U 0001 CR,LF,"Cannot find FORMAT.COM",CR,LF +0017 U 0000 CR,LF,"Error opening logfile",CR,LF +0018 U 0000 CR,LF,"Logging to file %1",CR,LF +0019 U 0000 CR,LF,"Last backup diskette not inserted",CR,LF +0020 U 0000 CR,LF,"WARNING! Files in the target drive",CR,LF + "%1:\ root directory will be erased",CR,LF +0021 U 0000 CR,LF,"WARNING! Files in the target drive",CR,LF + "%1:\BACKUP directory will be erased",CR,LF +0022 U 0000 CR,LF,"*** Backing up files to drive %1: ***",CR,LF +0023 U 0000 "Diskette Number: %1",CR,LF +0024 U 0000 CR,LF,"WARNING! No files were found to back up",CR,LF +0025 U 0000 CR,LF,"Insert backup source diskette in drive %1:",CR,LF +0026 U 0000 CR,LF,"Insert backup diskette %1 in drive %2:",CR,LF +0027 U 0000 CR,LF,"*** Not able to backup file ***",CR,LF +0028 U 0000 CR,LF,"Insert last backup diskette in drive %1:",CR,LF +0029 U 0000 CR,LF,"Target cannot be used for backup",CR,LF +0030 U 0000 CR,LF,"*** Last file not backed up ***",CR,LF +0031 U 0000 CR,LF,"Fixed backup device %1: is full",CR,LF +0032 U 0000 CR,LF,"Disk full error writing to BACKUP Log File",CR,LF +0034 U 0000 CR,LF +0035 U 0001 CR,LF,"Cannot FORMAT nonremovable drive %1:",CR,LF +0040 U 0000 CR, LF, "Because your source drive is either ASSIGNed, JOINed, or SUBSTed", CR, LF, "it is actually the same as the target drive", CR, LF +0041 U 0000 CR, LF, "Because your target drive is either ASSIGNed, JOINed, or SUBSTed", CR, LF, "it is actually the same as the source drive", CR, LF +0042 U 0000 "Your target diskette is unformatted and " +0043 U 0000 "No FORMAT program was found.",CR,LF + "Do you have another diskette with FORMAT on it (Y/N)? " +0044 U 0000 CR,LF,"Insert the diskette with FORMAT in drive A:",CR,LF +0045 U 0000 CR,LF,"Do you want to continue by inserting a new disk (Y/N)? " +0300 U 0000 "Backs up one or more files from one disk to another.",CR,LF,CR,LF +0301 U 0000 "BACKUP source destination-drive: [/S] [/M] [/A] [/F[:size]]",CR,LF + " [/D:date[/T:time]] [/L[:[drive:][path]logfile]]",CR,LF,CR,LF +0302 U 0000 " source Specifies the file(s), drive, or directory to back up.",CR,LF +0303 U 0000 " destination-drive: Specifies the drive to save backup copies onto.",CR,LF +0304 U 0000 " /S Backs up contents of subdirectories.",CR,LF +0305 U 0000 " /M Backs up only files that have changed since the last",CR,LF + " backup.",CR,LF +0306 U 0000 " /A Adds backup files to an existing backup disk.",CR,LF +0307 U 0000 " /F:[size] Specifies the size of the disk to be formatted.",CR,LF +0308 U 0000 " /D:date Backs up only files changed on or after the specified",CR,LF + " date.",CR,LF +0309 U 0000 " /T:time Backs up only files changed at or after the specified",CR,LF + " time.",CR,LF +0310 U 0000 " /L[:[drive:][path]logfile]",CR,LF + " Creates a log file and entry to record the backup",CR,LF + " operation.",CR,LF +BASIC 0000629a 0001 +0001 U 0001 "Cannot exec BASICA.COM" +BOOT 000062d8 0001 +0001 U 0000 13,10,"Non-System disk or disk error",13,10 + "Replace and press any key when ready",13,10,0 +CHKDSK 0000635a 0071 +0003 U 0000 "Convert lost chains to files (Y/N)?" +0004 U 0000 "Unrecoverable error in directory" +0005 U 0000 "Convert directory to file (Y/N)?" +0007 U 0000 "%1 bytes total disk space" +0008 U 0000 "%1 bytes in bad sectors" +0009 U 0000 "%1 bytes in %2 hidden files" +0010 U 0000 "%1 bytes in %2 directories" +0011 U 0000 "%1 bytes in %2 user files" +0012 U 0000 "%1 bytes in %2 recovered files" +0013 U 0000 "%1 bytes would be in %2 recovered files" +0014 U 0000 "%1 bytes available on disk" +0015 U 0000 "%1 total bytes memory" +0016 U 0000 "%1 bytes free" +0017 U 0000 "Cannot CHKDSK a network drive" +0018 U 0000 "Cannot CHKDSK a SUBSTed or ASSIGNed drive" +0019 U 0000 "Probable non-DOS disk",CR,LF,"Continue (Y/N)?" +0020 U 0000 "Disk error reading FAT %1",CR,LF +0021 U 0000 "Directory %1" +0022 U 0000 "%1 Contains %2 non-contiguous blocks" +0023 U 0000 "All specified file(s) are contiguous" +0024 U 0000 "Errors found, F parameter not specified",CR,LF,"Corrections will not be written to disk" +0025 U 0000 " Processing cannot continue %1%2" +0026 U 0000 " File allocation table bad, drive %1" +0029 U 0000 " CHDIR .. failed, trying alternate method" +0030 U 0001 " Has invalid allocation unit, file truncated" +0031 U 0000 " Invalid sub-directory entry" +0032 U 0000 " Does not exist" +0033 U 0001 " First allocation unit is invalid, entry truncated" +0034 U 0000 " Allocation error, size adjusted" +0035 U 0000 " Cannot recover .. entry, processing continued" +0036 U 0000 " Directory is totally empty, no . or .." +0037 U 0000 " Directory is joined" +0038 U 0000 " Cannot recover .. entry" +0039 U 0000 " Entry has a bad link" +0040 U 0000 " Entry has a bad attribute" +0041 U 0000 " Entry has a bad size" +0042 U 0001 " Is cross linked on allocation unit %1" +0043 U 0000 " Cannot CHDIR to %1,",CR,LF,"tree past this point not processed" +0044 U 0000 " tree past this point not processed" +0045 U 0000 "%1 bytes disk space freed" +0046 U 0000 "%1 bytes disk space would be freed" +0047 U 0000 "Volume %1 created %2 %3",CR,LF +0048 U 0000 "%1 total allocation units on disk" +0049 U 0000 "%1 bytes in each allocation unit" +0050 U 0000 "CHKDSK not available on drive %1" +0053 U 0000 "Invalid parameter" +0055 U 0000 "Path not found" +0056 U 0000 "File not found" +0058 U 0001 " %1 lost allocation units found in %2 chains." +0059 U 0000 CR,LF +0060 U 0000 " Cannot CHDIR to root",CR,LF +0061 U 0000 " Disk error writing FAT %1" +0062 U 0000 "%1" ;C05 +0063 U 0000 "Invalid current directory",0 +0064 U 0000 "%1",CR,LF +0065 U 0000 " Insufficient room in root directory",CR,LF," Move files from root directory and repeat CHKDSK" +0066 U 0000 "%1 %2 %3" +0067 U 0000 "%1 %2, %3" +0068 U 0000 "%1%2%3%4%5" +0069 U 0000 "%1%2%3%4" +0070 U 0000 "%1 available allocation units on disk" +0075 U 0000 "CHKDSK /F cannot be done in a Windows/DosShell Command Prompt",CR,LF +0076 U 0000 " - Insufficient Memory",0 +0077 U 0000 " - File allocation table bad",0 +0300 U 0000 "Checks a disk and displays a status report.",CR,LF,CR,LF +0301 U 0000 "CHKDSK [drive:][[path]filename] [/F] [/V]",CR,LF,CR,LF +0302 U 0000 " [drive:][path] Specifies the drive and directory to check.",CR,LF +0303 U 0000 " filename Specifies the file(s) to check for fragmentation.",CR,LF +0304 U 0000 " /F Fixes errors on the disk.",CR,LF +0305 U 0000 " /V Displays the full path and name of every file on the disk.",CR,LF,CR,LF +0306 U 0000 "Type CHKDSK without parameters to check the current disk.",CR,LF +DEBUG 000071a0 0068 +0004 U 0000 "Allocation failed or specified buffer too small",CR,LF +0006 U 0000 "Bad device name" +0007 U 0000 "Cannot open list device PRN",CR,LF + "Enter name of list device? " +0008 U 0000 CR,LF +0009 U 0000 CR,LF,"Program terminated normally",CR,LF +0010 U 0001 "Invalid drive specification",CR,LF +0012 U 0001 "File creation error",CR,LF +0013 U 0001 "Insufficient space on disk",CR,LF +0014 U 0001 "Disk error reading drive %1",CR,LF +0015 U 0001 "Disk error writing drive %1",CR,LF +0016 U 0001 "Write protect error reading drive %1",CR,LF +0017 U 0001 "Write protect error writing drive %1",CR,LF +0019 U 0000 "%1^ Error" +0020 U 0001 "Error in EXE or HEX file",CR,LF +0021 U 0001 "EXE and HEX files cannot be written",CR,LF +0022 U 0000 "EXEC failure" +0023 U 0001 "(W)rite error, no destination defined",CR,LF +0024 U 0001 "Access denied",CR,LF +0025 U 0000 "Parity error or nonexistent memory error detected" +0026 U 0000 "-" +0027 U 0000 "%1 -" +0032 U 0000 "%1%2" +0033 U 0000 "%1:%2 %3" +0034 U 0000 "%1 %2" +0035 U 0000 "%1 %2",CR,LF,":" +0036 U 0000 "%1=%2 " +0037 U 0000 "%1 Error" +0038 U 0000 "Writing %2%1 bytes" ;C02 +0039 U 0000 "%1:%2=" +0040 U 0000 "%1" +0041 U 0000 "%1" +0042 U 0000 "%1:%2 %3 %4 %5:%6" +0044 U 0000 32,8 +0046 U 0000 "%1" +0047 U 0000 "%1" +0050 U 0000 "%1 of a total %2 EMS pages have been allocated",cr,lf +0051 U 0000 "%1 of a total %2 EMS handles have been allocated",cr,lf +0055 U 0000 "Handle created = %1 ",cr,lf +0056 U 0000 "Logical page %1 mapped to physical page %2 ",cr,lf +0057 U 0001 "EMS hardware/software failure",cr,lf +0058 U 0000 "Handle not found",cr,lf +0059 U 0000 "Invalid function code",cr,lf +0060 U 0000 "No free handles",cr,lf +0061 U 0000 "Save/Restore error",cr,lf +0062 U 0000 "Total pages exceeded",cr,lf +0063 U 0000 "Free pages exceeded",cr,lf +0064 U 0000 "Parameter error",cr,lf +0065 U 0000 "Logical Page out of range",cr,lf +0066 U 0000 "Physical Page out of range",cr,lf +0067 U 0000 "Save area already in use",cr,lf +0068 U 0000 "Save area not in use",cr,lf +0070 U 0001 "General EMS error",cr,lf +0071 U 0000 "Missing or invalid EMS parameter",cr,lf +0072 U 0000 "Handle %1 has %2 pages allocated",cr,lf +0075 U 0000 "Physical page %1 = Frame segment %2",cr,lf +0076 U 0003 "Handle %1 deallocated",cr,lf +0078 U 0000 "EMS not installed",cr,lf +0090 U 0000 "Runs Debug, a program testing and editing tool.",cr,lf,cr,lf +0091 U 0000 "DEBUG [[drive:][path]filename [testfile-parameters]]",cr,lf,cr,lf +0092 U 0000 " [drive:][path]filename Specifies the file you want to test.", cr,lf +0093 U 0000 " testfile-parameters Specifies command-line information required by",cr,lf + " the file you want to test.",cr,lf,cr,lf +0094 U 0000 "After Debug starts, type ? to display a list of debugging commands.",cr,lf +0100 U 0000 "assemble A [address]",CR,LF + "compare C range address",CR,LF + "dump D [range]",CR,LF + "enter E address [list]",CR,LF +0101 U 0000 "fill F range list",CR,LF + "go G [=address] [addresses]",CR,LF + "hex H value1 value2",CR,LF + "input I port",CR,LF +0102 U 0000 "load L [address] [drive] [firstsector] [number]",CR,LF + "move M range address",CR,LF + "name N [pathname] [arglist]",CR,LF + "output O port byte",CR,LF +0103 U 0000 "proceed P [=address] [number]",CR,LF + "quit Q",CR,LF + "register R [register]",CR,LF + "search S range list",CR,LF +0104 U 0000 "trace T [=address] [value]",CR,LF + "unassemble U [range]",CR,LF + "write W [address] [drive] [firstsector] [number]",CR,LF +0105 U 0000 "allocate expanded memory XA [#pages]",CR,LF + "deallocate expanded memory XD [handle]",CR,LF + "map expanded memory pages XM [Lpage] [Ppage] [handle]",CR,LF + "display expanded memory status XS",CR,LF +DISKCOMP 0000810a 0020 +0004 U 0000 "Do not specify filename(s)",CR,LF + "Command format: DISKCOMP [drive1: [drive2:]] [/1] [/8]",LF,CR +0005 U 0000 CR,LF,"Invalid drive specification",CR,LF + "Specified drive does not exist",CR,LF + "or is non-removable",CR,LF +0006 U 0000 CR,LF,"Cannot DISKCOMP to or from",CR,LF + "a network drive",CR,LF +0007 U 0000 CR,LF,"Insert FIRST diskette in drive %1:",CR,LF +0008 U 0000 CR,LF,"Insert SECOND diskette in drive %1:",CR,LF +0009 U 0000 CR,LF,"FIRST diskette bad or incompatible",CR,LF +0010 U 0000 CR,LF,"SECOND diskette bad or incompatible",CR,LF +0014 U 0000 CR,LF,"Compare another diskette (Y/N) ?" +0015 U 0000 CR,LF,"Comparing %1 tracks",CR,LF + "%2 sectors per track, %3 side(s)",CR,LF +0016 U 0000 CR,LF,"Drive types or diskette types",CR,LF + "not compatible",CR,LF +0017 U 0000 CR,LF,"Unrecoverable read error on drive %2",CR,LF + "side %3, track %4",CR,LF +0018 U 0000 CR,LF,"Compare error on",CR,LF,"side %3, track %4",CR,LF +0019 U 0000 "Make sure a diskette is inserted into",CR,LF + "the drive and the door is closed",CR,LF +0020 U 0000 CR,LF,"Compare process ended",CR,LF +0021 U 0000 CR,LF,"Compare OK",CR,LF +0022 U 0000 CR,LF +0300 U 0000 "Compares the contents of two floppy disks.",CR,LF,CR,LF +0301 U 0000 "DISKCOMP [drive1: [drive2:]] [/1] [/8]",CR,LF,CR,LF +0302 U 0000 " /1 Compares the first side of the disks.",CR,LF +0303 U 0000 " /8 Compares only the first eight sectors of each track.",CR,LF +DISKCOPY 000086ca 0025 +0002 U 0000 CR,LF +0004 U 0000 "Do not specify filename(s)",CR,LF + "Command Format: DISKCOPY [drive1: [drive2:]] [/1] [/V]",CR,LF +0005 U 0000 CR,LF,"Invalid drive specification",CR,LF + "Specified drive does not exist",CR,LF + "or is non-removable",CR,LF +0006 U 0000 CR,LF,"Cannot DISKCOPY to or from",CR,LF + "a network drive",CR,LF +0007 U 0000 CR,LF,"Formatting while copying",CR,LF +0008 U 0000 CR,LF,"Insert SOURCE diskette in drive %1:",CR,LF +0009 U 0000 CR,LF,"Insert TARGET diskette in drive %1:",CR,LF +0010 U 0000 "Make sure a diskette is inserted into",CR,LF + "the drive and the door is closed",CR,LF +0011 U 0000 CR,LF,"Target diskette may be unusable",CR,LF +0012 U 0000 CR,LF,"Target diskette unusable",CR,LF +0016 U 0000 CR,LF,"Copy another diskette (Y/N)? " +0017 U 0000 CR,LF,"Copying %1 tracks",CR,LF + "%2 sectors per track, %3 side(s)",CR,LF +0018 U 0000 CR,LF,"Drive types or diskette types",CR,LF + "not compatible",CR,LF +0019 U 0000 CR,LF,"Unrecoverable read error on drive %1",CR,LF + "Side %2, track %3",CR,LF +0020 U 0000 CR,LF,"Unrecoverable write error on drive %1",CR,LF + "Side %2, track %3",CR,LF +0021 U 0000 CR,LF,"Copy process ended",CR,LF +0022 U 0000 CR,LF,"SOURCE diskette bad or incompatible" +0023 U 0000 CR,LF,"TARGET diskette bad or incompatible" +0030 U 0000 CR,LF,"TARGET media has lower capacity than SOURCE",CR,LF + "Continue anyway (Y/N)?" +0031 U 0000 CR,LF,"Press CTRL+C to abort,",CR,LF + "or correct this problem and press any other key to continue . . .",CR,LF +0300 U 0000 "Copies the contents of one floppy disk to another.",CR,LF,CR,LF +0301 U 0000 "DISKCOPY [drive1: [drive2:]] [/1] [/V]",CR,LF,CR,LF +0302 U 0000 " /1 Copies only the first side of the disk.",CR,LF +0303 U 0000 " /V Verifies that the information is copied correctly.",CR,LF,CR,LF +0304 U 0000 "The two floppy disks must be the same type.",CR,LF + "You may specify the same drive for drive1 and drive2.",CR,LF +DISPLAY 00008e7b 0003 +0002 U 0000 "%1 code page driver cannot be initialized",CR,LF,BELL +0008 U 0000 "Too many code pages specified",CR,LF,BELL +0012 U 0000 "Invalid syntax on DISPLAY.SYS code page driver",CR,LF,BELL +DOSKEY 00008f58 0010 +0001 U 0000 7,"An incompatible DOSKey is already installed.$" +0002 U 0000 7,"Cannot change BUFSIZE.$" +0003 U 0000 "DOSKey installed.$" +0004 U 0000 "Invalid macro definition.$" +0005 U 0000 "Edits command lines, recalls MS-DOS commands, and creates macros.",CR,LF,CR,LF + "DOSKEY [/REINSTALL] [/BUFSIZE=size] [/MACROS] [/HISTORY]",CR,LF + " [/INSERT | /OVERSTRIKE] [macroname=[text]]",CR,LF,CR,LF + " /REINSTALL Installs a new copy of Doskey.",CR,LF + " /BUFSIZE=size Sets size of command history buffer.",CR,LF + " /MACROS Displays all Doskey macros.",CR,LF + " /HISTORY Displays all commands stored in memory.",CR,LF + " /INSERT Specifies that new text you type is inserted in old text.",CR,LF + " /OVERSTRIKE Specifies that new text overwrites old text.",CR,LF + " macroname Specifies a name for a macro you create.",CR,LF + " text Specifies commands you want to record.",CR,LF,CR,LF + "UP and DOWN ARROWS recall commands; ESC clears command line; F7 displays",CR,LF + "command history; ALT+F7 clears command history; F8 searches command",CR,LF + "history; F9 selects a command by number; ALT+F10 clears macro definitions.",CR,LF,CR,LF + "The following are some special codes in Doskey macro definitions:",CR,LF + "$T Command separator. Allows multiple commands in a macro.",CR,LF + "$1-$9 Batch parameters. Equivalent to %1-%9 in batch programs.",CR,LF + "$* Symbol replaced by everything following macro name on command line.",CR,LF,0 +0006 U 0000 7,"Insufficent memory to store macro. Use the DOSKEY command with the /BUFSIZE",CR,LF + "switch to increase available memory.$",0 +0007 U 0000 7,"Incorrect DOS version$" +0008 U 0000 CR,LF,'$' +0020 U 0000 CR,LF,"-- More --",0 +0021 U 0000 "Line number: ",0 +DRIVER 00009659 0002 +0002 U 0000 "No drive specified",CR,LF +0003 U 0000 "Loaded External Disk Driver for Drive %1",CR,LF +EDLIN 000096d7 0035 +0006 U 0000 "*" +0007 U 0000 "Invalid drive or file name",CR,LF +0008 U 0000 "File name must be specified",CR,LF +0010 U 0000 "File is READ-ONLY",CR,LF +0011 U 0000 "File Creation Error",CR,LF +0012 U 0000 "Too many files open",CR,LF +0013 U 0000 "Read error in:",CR,LF,"%1",CR,LF +0014 U 0000 "Cannot edit .BAK file--rename file",CR,LF +0015 U 0000 "No room in directory for file",CR,LF +0016 U 0000 "Disk full. Edits lost.",CR,LF +0017 U 0000 "File not found",CR,LF +0018 U 0000 "Entry error",CR,LF +0019 U 0000 "New file",CR,LF +0020 U 0000 "Not found",CR,LF +0021 U 0000 "O.K.? " +0022 U 0000 "Line too long",CR,LF +0023 U 0000 "End of input file",CR,LF +0024 U 0000 "Abort edit (Y/N)? " +0025 U 0000 "Must specify destination line number",CR,LF +0026 U 0000 "Not enough room to merge the entire file",CR,LF +0027 U 0000 CR,LF +0028 U 0000 LF +0029 U 0000 "Continue (Y/N)?" +0030 U 0000 "Unable to print message",CR,LF +0031 U 0000 "%1" +0032 U 0000 "%1:%2" +0033 U 0000 "Cannot merge - code page mismatch",CR,LF +0300 U 0000 "Starts Edlin, a line-oriented text editor.",CR,LF,CR,LF + "EDLIN [drive:][path]filename [/B]",CR,LF,CR,LF + " /B Ignores end-of-file (CTRL+Z) characters.",CR,LF +0301 U 0000 "Edit line line#",CR,LF + "Append [#lines]A",CR,LF +0302 U 0000 "Copy [startline],[endline],toline[,times]C",CR,LF + "Delete [startline][,endline]D",CR,LF +0303 U 0000 "End (save file) E",CR,LF + "Insert [line]I",CR,LF +0304 U 0000 "List [startline][,endline]L",CR,LF + "Move [startline],[endline],tolineM",CR,LF +0305 U 0000 "Page [startline][,endline]P",CR,LF + "Quit (throw away changes) Q",CR,LF +0306 U 0000 "Replace [startline][,endline][?]R[oldtext][CTRL+Znewtext]",CR,LF + "Search [startline][,endline][?]Stext",CR,LF +0307 U 0000 "Transfer [toline]T[drive:][path]filename",CR,LF + "Write [#lines]W",CR,LF +EXE2BIN 00009f1b 0012 +0002 U 0000 "Insufficient memory",CR,LF +0003 U 0000 "Cannot find messages",CR,LF +0004 U 0000 "Access denied",CR,LF +0005 U 0000 "File cannot be converted",CR,LF +0006 U 0000 "File not found",CR,LF +0007 U 0000 "File creation error",CR,LF +0008 U 0000 "Fix-ups needed - base segment (hex):" +0012 U 0000 "File name must be specified",CR,LF +0300 U 0000 "Converts .EXE (executable) files to binary format.",CR,LF,CR,LF +0301 U 0000 "EXE2BIN [drive1:][path1]input-file [[drive2:][path2]output-file]",CR,LF,CR,LF +0302 U 0000 " input-file Specifies the .EXE file to be converted.",CR,LF +0303 U 0000 " output-file Specifies the binary file to be created.",CR,LF +FASTOPEN 0000a1cd 0021 +0004 U 0000 CR,LF,"FASTOPEN installed",CR,LF +0005 U 0000 CR,LF,"FASTOPEN already installed",CR,LF +0006 U 0000 CR,LF,"Incorrect parameter",CR,LF +0007 U 0000 CR,LF,"Too many drive entries",CR,LF +0008 U 0000 CR,LF,"Same drive specified more than once",CR,LF +0009 U 0000 CR,LF,"Invalid parameter",CR,LF +0010 U 0000 CR,LF,"Invalid switch type",CR,LF +0012 U 0001 CR,LF,"Invalid number of file/directory entries",CR,LF +0013 U 0000 CR,LF,"Cannot setup expanded memory",CR,LF +0014 U 0000 CR,LF,"Expanded memory not available",CR,LF +0015 U 0000 CR,LF,"Invalid drive specification %1",CR,LF +0016 U 0002 CR,LF,"FASTOPEN EMS entry count exceeded. Use fewer entries",CR,LF +0017 U 0000 CR,LF,"Cannot use FASTOPEN for drive %1",CR,LF +0019 U 0000 CR,LF,"Too many file/directory entries",CR,LF +0020 U 0000 CR,LF,"FASTOPEN cannot be installed under DosShell",CR,LF +0300 U 0000 "Decreases the amount of time needed to open frequently used files",CR,LF +0301 U 0000 "and directories.",CR,LF,CR,LF +0302 U 0000 "FASTOPEN drive:[[=]n] [drive:[[=]n][ ...]] [/X]",CR,LF,CR,LF +0303 U 0000 " drive: Specifies the hard disk drive you want Fastopen to work with.",CR,LF +0304 U 0000 " n Specifies the maximum number of file locations Fastopen retains",CR,LF + " in its filename cache.",CR,LF +0305 U 0000 " /X Creates the filename cache in expanded memory.",CR,LF +FDISK 0000a746 0140 +0004 U 0000 "Cannot FDISK with network loaded",CR,LF +0005 U 0000 "No fixed disks present",CR,LF +0006 U 0000 "Error reading fixed disk",CR,LF +0007 U 0000 "Error writing fixed disk",CR,LF +0009 U 0003 "Y",0 +0010 U 0003 "N",0 +0011 U 0000 "The master boot code has NOT been updated.",CR,LF +0300 U 0000 "Configures a hard disk for use with MS-DOS.",CR,LF,CR,LF +0301 U 0000 "FDISK",CR,LF +1001 U 0000 " MS-DOS Version 5.00" +1002 U 0000 " Fixed Disk Setup Program" +1003 U 0000 " (C)Copyright Microsoft Corp. 1983 - 1991" +1004 U 0000 " FDISK Options" +1005 U 0000 "1. <R>Create DOS partition or Logical DOS Drive" +1006 U 0000 "2. <R>Set active partition" +1007 U 0000 "3. <R>Delete partition or Logical DOS Drive" +1008 U 0000 "4. <R>Display partition information" +1009 U 0000 "Press <H>Esc<R> to exit FDISK" +1010 U 0000 "Choose one of the following:" +1011 U 0000 "5. <R>Change current fixed disk drive" +1012 U 0000 "Current fixed disk drive: <H><I>" +1013 U 0000 "WARNING! <R>No partitions are set active - disk 1 is not startable unless" +1014 U 0000 "a partition is set active" +1015 U 0000 "Enter choice: <H>[<S> ]" +1016 U 0000 " Create DOS Partition or Logical DOS Drive" +1017 U 0000 "1. <R>Create Primary DOS Partition" +1018 U 0000 "2. <R>Create Extended DOS Partition" +1019 U 0000 "3. <R>Create Logical DOS Drive(s) in the Extended DOS Partition" +1020 U 0000 "Press <H>Esc<R> to return to FDISK Options" +1021 U 0000 " Create Primary DOS Partition" +1022 U 0000 "Do you wish to use the maximum available size for a Primary DOS Partition" +1023 U 0000 "and make the partition active (<Y>/<N>).....................? <H>[<S> ]" +1024 U 0000 "(<Y>/<N>)...................................................? <H>[<S> ]" +1025 U 0000 "Partition Status Type Volume Label Mbytes System Usage" ;C25 +1026 U 0000 "Total disk space is <HIIIIR> Mbytes (1 Mbyte = 1048576 bytes)" +1027 U 0000 "Maximum space available for partition is <HIIIIR> Mbytes (<HIIIIR>)" +1028 U 0000 "Enter partition size in Mbytes or percent of disk space (%) to" +1029 U 0000 "create a Primary DOS Partition.................................: <H>[<IIISI>]" +1030 U 0000 " Create Extended DOS Partition" +1031 U 0000 "create an Extended DOS Partition..............................: <H>[<IIISI>]" +1032 U 0000 "Press <H>Esc<R> to continue<S>" +1033 U 0000 " Create Logical DOS Drive(s) in the Extended DOS Partition" +1034 U 0000 "Drv Volume Label Mbytes System Usage" +1035 U 0000 "Total Extended DOS Partition size is <HIIIIR> Mbytes (1 MByte = 1048576 bytes)" +1036 U 0000 "Maximum space available for logical drive is <HIIIIR> Mbytes <H>(<IIII>)" +1037 U 0000 "Enter logical drive size in Mbytes or percent of disk space (%)...<H>[<IIISI>]" +1038 U 0000 " Set Active Partition" +1039 U 0000 "Enter the number of the partition you want to make active...........: <H>[<S> ]" +1040 U 0000 " Delete DOS Partition or Logical DOS Drive" +1041 U 0000 "1. <R>Delete Primary DOS Partition" +1042 U 0000 "2. <R>Delete Extended DOS Partition" +1043 U 0000 "3. <R>Delete Logical DOS Drive(s) in the Extended DOS Partition" +1044 U 0000 " Delete Primary DOS Partition" +1045 U 0000 "WARNING! <OR>Data in the deleted Primary DOS Partition will be lost." +1046 U 0000 "Do you wish to continue (<Y>/<N>).................? <H>[<S> ]" +1047 U 0000 " Delete Extended DOS Partition" +1048 U 0000 "WARNING! <OR>Data in the deleted Extended DOS Partition will be lost." +1049 U 0000 "Do you wish to continue (<Y>/<N>).................? <H>[<S> ]" +1050 U 0000 " Delete Logical DOS Drive(s) in the Extended DOS Partition" +1051 U 0000 "WARNING! <OR>Data in a deleted Logical DOS Drive will be lost." +1052 U 0000 "What drive do you want to delete...............................? <H>[<S> ]" +1053 U 0000 "Are you sure (<Y>/<N>)..............................? <H>[<S> ]" +1054 U 0000 "Enter Volume Label..............................? <H>[<S> ]" +1055 U 0000 " Display Partition Information" +1056 U 0000 "The Extended DOS Partition contains Logical DOS Drives." +1057 U 0000 "Do you want to display the logical drive information (<Y>/<N>)......?<H>[<S> ]" +1058 U 0000 " Display Logical DOS Drive Information" +1059 U 0000 "System will now restart" +1060 U 0001 "Insert DOS system diskette in drive A:" +1061 U 0000 "Press any key when ready . . .<S>" +1062 U 0000 "Primary DOS Partition deleted" +1063 U 0000 "Extended DOS Partition deleted" +1064 U 0000 "Drive deleted" +1065 U 0000 "Partition <I> made active" +1066 U 0000 "Primary DOS Partition created" +1067 U 0000 "Extended DOS Partition created" +1068 U 0000 "Logical DOS Drive created, drive letters changed or added<W>" +1069 U 0000 "No partitions defined" +1070 U 0000 "No logical drives defined" +1071 U 0000 "Drive letters have been changed or deleted<W>" +1072 U 0000 "Drive redirected" +1073 U 0000 "Primary DOS Partition created, drive letters changed or added" +1074 U 0000 "No fixed disks present." +1075 U 0000 "Error reading fixed disk." +1076 U 0000 "Error writing fixed disk." +1077 U 0000 "Incorrect DOS version." +1078 U 0000 "Cannot FDISK with network loaded." +1079 U 0000 "No Primary DOS Partition to delete." +1080 U 0000 "No Extended DOS Partition to delete." +1081 U 0000 "Primary DOS Partition already exists." +1082 U 0000 "Extended DOS Partition already exists." +1083 U 0000 "No space to create a DOS partition." +1084 U 0000 "Requested logical drive size exceeds the maximum available space.<W>" +1085 U 0000 "Requested partition size exceeds the maximum available space.<W>" +1086 U 0000 "No partitions to delete." +1087 U 0000 "The only startable partition on Drive 1 is already set active.<W>" +1088 U 0000 "No partitions to make active." +1089 U 0000 "Partition selected (<I>) is not startable, active partition not changed.<W>" +1090 U 0000 "Cannot create Extended DOS Partition without" +1091 U 0000 "Primary DOS Partition on disk 1.<W>" +1092 U 0000 "All available space in the Extended DOS Partition" +1093 U 0000 "is assigned to logical drives.<W>" +1094 U 0000 "Cannot delete Extended DOS Partition while logical drives exist.<W>" +1095 U 0000 "All logical drives deleted in the Extended DOS Partition.<W>" +1096 U 0000 " is not a choice. Please enter <III>.<W>" +1097 U 0000 "WARNING! The partition set active is not startable.<W>" +1098 U 0000 " Only non-startable partitions exist." +1099 U 0000 "Only partitions on Drive 1 can be made active.<W>" +1100 U 0000 "Maximum number of Logical DOS Drives installed.<W>" +1101 U 0000 "Cannot create a zero size partition." +1102 U 0000 "Drive <II> already deleted." +1103 U 0000 "Unable to access Drive <I>.<OW>" +1104 U 0000 "Invalid entry, please enter <III>.<W>" +1105 U 0000 "Cannot delete Primary DOS Partition on drive 1 " +1106 U 0000 "when an Extended DOS Partition exists.<W>" +1107 U 0000 "Invalid entry.<W>" +1108 U 0000 "Volume label does not match.<W>" +1109 U 0000 "Cannot create Logical DOS Drive without" +1110 U 0000 "an Extended DOS Partition on the current drive.<W>" +1111 U 0000 "No Logical DOS Drive(s) to delete." +1112 U 0000 "Message string error <I>. See header of FDISKC.MSG for error definition" +1113 U 0000 "Internal error" +1114 U 0001 "Invalid partition table",0 +1115 U 0001 "Error loading operating system",0 +1116 U 0001 "Missing operating system",0 +1117 U 0000 " Change Current Fixed Disk Drive" +1118 U 0000 " Disk Drv Mbytes Free Usage" +1119 U 0000 "(1 MByte = 1048576 bytes)" +1120 U 0000 "Enter Fixed Disk Drive Number (1-<I>).......................<H>[<SI>]" +1121 U 0000 "* Remote * ",0 +1122 U 0000 " Fixed Disk Drive Status" +1123 U 0000 "What primary partition do you want to delete..? <H>[<S> ]<R>" ;C01 +1124 U 0000 "Partition selected is not a Primary DOS Partition" ;C01 +1125 U 0000 "4. <R>Delete Non-DOS Partition" ;C14 +1126 U 0000 " Delete Non-DOS Partition" ;C14 +1127 U 0000 "WARNING! <OR>Data in the deleted Non-DOS Partition will be lost." ;C14 +1128 U 0000 "What Non-DOS partition do you want to delete..? <H>[<S> ]<R>" ;C14 +1129 U 0000 "Non-DOS Partition deleted" ;C14 +1130 U 0000 "No Non-DOS Partition to delete." ;C14 +1131 U 0000 "Partition selected is not a Non-DOS Partition" ;C14 +FIND 0000c938 0012 +0004 U 0000 "FIND: " +0300 U 0000 "Searches for a text string in a file or files.",CR,LF,CR,LF +0301 U 0000 "FIND [/V] [/C] [/N] [/I] ""string"" [[drive:][path]filename[ ...]]",CR,LF,CR,LF +0302 U 0000 " /V Displays all lines NOT containing the specified string.",CR,LF +0303 U 0000 " /C Displays only the count of lines containing the string.",CR,LF +0304 U 0000 " /N Displays line numbers with the displayed lines.",CR,LF +0305 U 0000 " /I Ignores the case of characters when searching for the string.",CR,LF +0306 U 0000 " ""string"" Specifies the text string to find.",CR,LF +0307 U 0000 " [drive:][path]filename",CR,LF +0308 U 0000 " Specifies a file or files to search.",CR,LF,CR,LF +0309 U 0000 "If a pathname is not specified, FIND searches the text typed at the prompt",CR,LF +0310 U 0000 "or piped from another command.",CR,LF +FORMAT 0000ccc4 0082 +0002 U 0000 CR,"%1 percent completed. ",CR ; max 39 chars (not counting CR,LF) +0004 U 0003 CR,"Format complete. ",CR,LF ; padded with blanks to 1 more than length of 0002 (%1 takes 3 characters) +0007 U 0000 "Insert new diskette for drive %1:",CR,LF +0009 U 0000 "Reinsert diskette for drive %1:",CR,LF +0011 U 0000 CR,"Format not supported on drive %1:", CR,LF +0012 U 0000 CR,"Invalid device parameters from device driver.",CR,LF +0013 U 0000 CR,"Error in IOCTL call. ",CR,LF +0014 U 0000 CR,"Not a block device. ",CR,LF +0015 U 0000 CR,"Error writing FAT. ",CR,LF +0016 U 0000 CR,"Error writing directory.",CR,LF +0017 U 0000 CR,"Cannot format an ASSIGNed or SUBSTed drive. ",CR,LF +0018 U 0000 CR,"Cannot find System Files.",CR,LF +0019 U 0000 CR,"Cannot format a network drive.",CR,LF +0021 U 0000 CR,"Parameters not supported.",CR,LF +0022 U 0003 CR,"Format terminated. ",CR,LF +0023 U 0000 CR,"Disk unsuitable for system disk.",CR,LF +0024 U 0000 CR,"Invalid media or Track 0 bad - disk unusable.",CR,LF +0025 U 0000 CR,"Unable to write BOOT. ",CR,LF +0026 U 0000 CR,"Error reading directory.",CR,LF +0028 U 0000 CR,"and press ENTER when ready..." +0029 U 0000 CR,"Invalid Volume ID. ",CR,LF +0031 U 0000 CR,"Enter current volume label for drive %1: " +0032 U 0000 CR,"Parameters not compatible",CR,LF,"with fixed disk.",CR,LF +0035 U 0000 CR,"Error reading partition table.",CR,LF +0037 U 0000 CR,"Format broken.",CR,LF +0038 U 0000 CR,"Format not available on drive %1:",CR,LF +0039 U 0000 CR,"Non-System disk or disk error.",CR,LF +0040 U 0000 CR,"Bad Partition Table. ",CR,LF +0041 U 0000 CR,"Parameters not supported by drive.",CR,LF +0042 U 0000 CR,LF +0043 U 0000 CR,LF,LF +0044 U 0000 CR,"Insert DOS disk in drive %1:",CR,LF +0045 U 0000 CR,LF,"WARNING, ALL DATA ON NON-REMOVABLE DISK",CR,LF + "DRIVE %1: WILL BE LOST!",CR,LF + "Proceed with Format (Y/N)?" +0046 U 0000 CR,"Format another (Y/N)?" +0047 U 0000 CR,"Error reading partition table.",CR,LF +0048 U 0000 CR,"Error writing partition table.",CR,LF +0049 U 0000 CR,"Parameters not compatible.", CR,LF +0050 U 0000 "%1 allocation units available on disk.",CR,LF +0051 U 0000 "%1 bytes in each allocation unit.",CR,LF +0052 U 0000 CR, "Error writing partition table.",CR,LF +0053 U 0000 CR,"Same parameter entered twice.",CR,LF +0054 U 0000 CR,"Must enter both /T and /N parameters.",CR,LF +0055 U 0000 CR,"Trying to recover allocation unit %1. ",CR +0056 U 0000 CR,"There is not enough room to create a restore file.",CR,LF + "You will not be able to use the unformat utility.",CR,LF + "Proceed with Format (Y/N)?" +0057 U 0000 CR,"There is not enough disk space for system files. ",CR,LF +0058 U 0000 CR,"Disk was formatted under a different version of DOS.",CR,LF + "This disk cannot be unformatted.",CR,LF + "Proceed with Format (Y/N)?" +0059 U 0000 CR,"There was an error creating the format recovery file.",CR,LF + "This disk cannot be unformatted.",CR,LF + "Proceed with Format (Y/N)?" +0060 U 0000 CR,"Volume label is not supported with /8 parameter.",CR,LF +0070 U 0000 CR,"Insufficient memory to load system files.",CR,LF +0071 U 0000 CR,"Insufficient memory.",CR,LF +0075 U 0000 CR,"QuickFormat another (Y/N)?" +0076 U 0000 CR,"Existing format differs from that specified.",CR,LF + "This disk cannot be unformatted.",CR,LF + "Proceed with Format (Y/N)?" +0077 U 0000 CR,"Invalid existing format.",CR,LF + "This disk cannot be QuickFormatted.",CR,LF + "Proceed with Unconditional Format (Y/N)?" +0078 U 0000 CR,"Formatting %1K",CR,LF +0079 U 0000 CR,"Formatting %1M",CR,LF +0080 U 0000 CR,"Formatting %1.%2M",CR,LF +0081 U 0000 CR,"WARNING: This disk cannot be unformatted if system files are transferred.",CR,LF + "Proceed with system transfer anyway (Y/N)?" +0082 U 0000 CR,"Verifying %1K",CR,LF +0083 U 0000 CR,"Verifying %1M",CR,LF +0084 U 0000 CR,"Verifying %1.%2M",CR,LF +0085 U 0000 CR,"Saving UNFORMAT information.",CR,LF +0086 U 0000 CR,"Checking existing disk format.",CR,LF +0087 U 0000 CR,"QuickFormatting %1K",CR,LF +0088 U 0000 CR,"QuickFormatting %1M",CR,LF +0089 U 0000 CR,"QuickFormatting %1.%2M",CR,LF +0300 U 0000 "Formats a disk for use with MS-DOS.",CR,LF,CR,LF +0301 U 0000 "FORMAT drive: [/V[:label]] [/Q] [/U] [/F:size] [/B | /S]",CR,LF +0302 U 0000 "FORMAT drive: [/V[:label]] [/Q] [/U] [/T:tracks /N:sectors] [/B | /S]",CR,LF +0303 U 0000 "FORMAT drive: [/V[:label]] [/Q] [/U] [/1] [/4] [/B | /S]",CR,LF +0304 U 0000 "FORMAT drive: [/Q] [/U] [/1] [/4] [/8] [/B | /S]",CR,LF,CR,LF +0305 U 0000 " /V[:label] Specifies the volume label.",CR,LF +0306 U 0000 " /Q Performs a quick format.",CR,LF +0307 U 0000 " /U Performs an unconditional format.",CR,LF +0308 U 0000 " /F:size Specifies the size of the floppy disk to format (such ",CR,LF +0309 U 0000 " as 160, 180, 320, 360, 720, 1.2, 1.44, 2.88).",CR,LF +0310 U 0000 " /B Allocates space on the formatted disk for system files.",CR,LF +0311 U 0000 " /S Copies system files to the formatted disk.",CR,LF +0312 U 0000 " /T:tracks Specifies the number of tracks per disk side.",CR,LF +0313 U 0000 " /N:sectors Specifies the number of sectors per track.",CR,LF +0314 U 0000 " /1 Formats a single side of a floppy disk.",CR,LF +0315 U 0000 " /4 Formats a 5.25-inch 360K floppy disk in a high-density drive.",CR,LF +0316 U 0000 " /8 Formats eight sectors per track.",CR,LF +GRAFTABL 0000e2d0 0008 +0002 U 0000 "Active Code Page: %1",CR,LF +0003 U 0000 "Previous Code Page: %1",CR,LF +0004 U 0000 "None",NULL +0005 U 0000 "Non-standard",NULL +0300 U 0000 "Enables MS-DOS to display an extended character set in graphics mode.",CR,LF,CR,LF +0301 U 0000 "GRAFTABL [xxx]",CR,LF + "GRAFTABL /STATUS",CR,LF,CR,LF +0302 U 0000 " xxx Specifies a code page number.",CR,LF +0303 U 0000 " /STATUS Displays the current code page selected for use with GRAFTABL.",CR,LF +GRAPHICS 0000e4bb 0020 +0005 U 0000 "Invalid parameter: %1",CR,LF +0007 U 0000 "Duplicate parameters not allowed",CR,LF +0009 U 0000 "Cannot find GRAPHICS profile",CR,LF +0010 U 0000 "Required profile statement missing before line %1",CR,LF +0011 U 0000 "Invalid profile statement on line %1",CR,LF +0012 U 0000 "Profile statement out of sequence on line %1",CR,LF +0013 U 0000 "Error reading GRAPHICS profile",CR,LF +0014 U 0000 "Syntax errors in GRAPHICS profile",CR,LF +0015 U 0000 "Printbox ID not in GRAPHICS profile",CR,LF +0016 U 0000 "Printer type not in GRAPHICS profile",CR,LF +0017 U 0000 "/B invalid with a black and white printer",CR,LF +0018 U 0000 "Unable to reload with profile supplied",CR,LF +0300 U 0000 "Loads a program that can print graphics.",CR,LF,CR,LF +0301 U 0000 "GRAPHICS [type] [[drive:][path]filename] [/R] [/B] [/LCD]",CR,LF + " [/PRINTBOX:STD | /PRINTBOX:LCD]",CR,LF,CR,LF +0302 U 0000 " type Specifies a printer type (see User's Guide and Reference).",CR,LF +0303 U 0000 " [drive:][path]filename",CR,LF + " Specifies the file containing information on supported printers.",CR,LF +0304 U 0000 " /R Prints white on black as seen on the screen.",CR,LF +0305 U 0000 " /B Prints the background in color for COLOR4 and COLOR8 printers.",CR,LF +0306 U 0000 " /LCD Prints using LCD aspect ratio.",CR,LF +0307 U 0000 " /PRINTBOX:STD | /PRINTBOX:LCD",CR,LF + " Specifies the print-box size, either STD or LCD.",CR,LF +JOIN 0000eaa5 0009 +0002 U 0001 "Directory not empty",CR,LF +0300 U 0000 "Joins a disk drive to a directory on another drive.",CR,LF,CR,LF +0301 U 0000 "JOIN [drive1: [drive2:]path]",CR,LF +0302 U 0000 "JOIN drive1: /D",CR,LF,CR,LF +0303 U 0000 " drive1: Specifies a disk drive that will appear as a directory on",CR,LF + " drive2.",CR,LF +0304 U 0000 " drive2: Specifies a drive to which you want to join drive1.",CR,LF +0305 U 0000 " path Specifies the directory to which you want to join drive1. It",CR,LF + " must be empty and cannot be the root directory.",CR,LF +0306 U 0000 " /D Cancels any previous JOIN commands for the specified drive.",CR,LF,CR,LF +0307 U 0000 "Type JOIN without parameters to list currently joined drives.",CR,LF +KEYB 0000edd8 0023 +0002 U 0000 "Current keyboard code: %1" +0003 U 0000 "Current keyboard ID: %1" +0004 U 0000 " code page: %1",CR,LF +0005 U 0000 "Current CON code page: %1",CR,LF +0006 U 0000 "Invalid keyboard code specified",CR,LF +0007 U 0000 "Invalid keyboard ID specified",CR,LF +0008 U 0000 "Invalid code page specified",CR,LF +0009 U 0000 "Bad or missing Keyboard Definition File",CR,LF +0010 U 0000 "KEYB has not been installed",CR,LF +0011 U 0000 "Active code page not available from CON device",CR,LF +0012 U 0000 "Code page specified has not been prepared",CR,LF +0013 U 0000 "One or more CON code pages invalid for given keyboard code",CR,LF +0014 U 0000 "Code page requested (%1) is not valid for given keyboard code",CR,LF +0015 U 0000 "Code page specified is inconsistent with the selected code page",CR,LF +0016 U 0001 "Keyboard ID specified is inconsistent with the selected keyboard layout",CR,LF +0017 U 0000 "Unable to create KEYB table in resident memory",CR,LF +0300 U 0000 "Configures a keyboard for a specific language.",CR,LF,CR,LF +0301 U 0000 "KEYB [xx[,[yyy][,[drive:][path]filename]]] [/E] [/ID:nnn]",CR,LF,CR,LF +0302 U 0000 " xx Specifies a two-letter keyboard code.",CR,LF +0303 U 0000 " yyy ÿ Specifies the code page for the character set.",CR,LF +0304 U 0000 " [drive:][path]filename Specifies the keyboard definition file.",CR,LF +0305 U 0000 " /E Specifies that an enhanced keyboard is installed.",CR,LF +0306 U 0000 " /ID:nnn Specifies the keyboard in use.",CR,LF +MEM 0000f40f 0066 +0010 U 0000 CR,LF +0011 U 0000 " Address Name Size Type ",CR,LF +0012 U 0000 " ------- -------- ------ ------",CR,LF +0013 U 0000 " Handle EMS Name Size ",CR,LF +0014 U 0000 " ------- -------- ------ ",CR,LF +0015 U 0000 " %1 %2 %3 %4",CR,LF +0016 U 0000 " %1 %2 %3 ",CR,LF +0017 U 0000 " %1 %2 ",CR,LF +0018 U 0000 "%1 bytes total conventional memory",CR,LF +0019 U 0000 "%1 bytes available to MS-DOS",CR,LF +0020 U 0000 "%1 largest executable program size",CR,LF +0021 U 0000 "%1 bytes total EMS memory",CR,LF +0022 U 0000 "%1 bytes free EMS memory",CR,LF +0023 U 0000 "%1 bytes total contiguous extended memory",CR,LF +0024 U 0000 "Interrupt Vector",0 +0025 U 0000 "ROM Communication Area",0 +0026 U 0000 "DOS Communication Area",0 +0027 U 0000 "IO",0 +0028 U 0000 "MSDOS",0 +0029 U 0000 "System Data",0 +0030 U 0000 "System Program",0 +0031 U 0000 "System Device Driver",0 +0032 U 0000 "Installed Device Driver",0 +0033 U 0000 "%1:",0 +0034 U 0000 "%1: - %2:",0 +0035 U 0000 "BUFFERS=",0 +0036 U 0000 "FILES=",0 +0037 U 0000 "FCBS=",0 +0038 U 0000 "STACKS=",0 +0039 U 0000 "DEVICE=",0 +0040 U 0000 "IFS=",0 +0041 U 0000 "LASTDRIVE=",0 +0042 U 0000 "----------",0 +0043 U 0000 " ",0 +0044 U 0000 " %1 %2 %3",CR,LF +0045 U 0001 "INSTALL=",0 +0046 U 0001 "%1 bytes available contiguous extended memory",CR,LF +0047 U 0000 "System Stacks",0 +0048 U 0000 "-- Free --",0 +0049 U 0000 "Program",0 +0050 U 0000 "Environment",0 +0051 U 0000 "Data",0 +0052 N 0000 "%1 bytes available XMS memory",CR,LF +0053 N 0000 " 64Kb High Memory Area available",CR,LF +0054 N 0000 " High Memory Area in use",CR,LF +0055 N 0000 " MS-DOS resident in High Memory Area",CR,LF +0056 U 0000 "IBMBIO",0 ;*EGH +0057 U 0000 "IBMDOS",0 ;*EGH +0058 N 0000 " MS-DOS resident in ROM using High Memory Area",CR,LF +0059 U 0000 "Conventional Memory :",CR,LF +0060 U 0000 "Upper Memory :",CR,LF +0061 U 0000 "Total FREE : %1 %2 ",CR,LF +0062 U 0000 "FREE",0 +0063 U 0000 " Name Size in Decimal Size in Hex",CR,LF +0064 U 0000 "------------- --------------------- -------------",CR,LF +0065 U 0000 "Total bytes available to programs (Conventional+Upper) : %1 %2",CR,LF +0066 U 0000 "Largest executable program size : %1 %2",CR,LF +0067 U 0000 "Largest available upper memory block : %1 %2",CR,LF +0068 U 0000 "Too much of memory fragmentation; MEM /C cannot be done",CR,LF +0069 U 0000 "SYSTEM",0 +0070 U 0000 "Total bytes available to programs : %1 %2",CR,LF +0300 U 0000 "Displays the amount of used and free memory in your system.",CR,LF,CR,LF +0301 U 0000 "MEM [/PROGRAM | /DEBUG | /CLASSIFY]",CR,LF,CR,LF +0302 U 0000 " /PROGRAM or /P Displays status of programs currently loaded in memory.",CR,LF +0303 U 0000 " /DEBUG or /D Displays status of programs, internal drivers, and other",CR,LF + " information.",CR,LF +0304 U 0000 " /CLASSIFY or /C Classifies programs by memory usage. Lists the size of",CR,LF + " programs, provides a summary of memory in use, and lists",CR,LF + " largest memory block available.",CR,LF +MODE 000101cb 0079 +0003 U 0000 CR,LF,"Must specify COM1, COM2, COM3 or COM4",CR,LF +0004 U 0000 CR,LF,"Resident portion of MODE loaded",CR,LF +0005 U 0000 CR,LF,"Illegal device name",CR,LF +0006 U 0000 CR,LF,"Printer error",CR,LF +0007 U 0000 CR,LF,"LPT%1: set for 80",CR,LF +0008 U 0000 CR,LF,"LPT%1: set for 132",CR,LF +0009 U 0000 CR,LF,"Printer lines per inch set",CR,LF +0010 U 0000 CR,LF,"Invalid baud rate specified",CR,LF +0011 U 0000 CR,LF,"COM%1: %2,%3,%4,%5,%6",CR,LF +0012 U 0000 "0123456789" +0013 U 0001 CR,LF,"Do you see the %1? (Y/N) " +0015 U 0000 "LPT%1: rerouted to COM%2:",CR,LF +0016 U 0000 "LPT%1: not rerouted",CR,LF +0017 U 0000 CR,LF,"%1 retry on parallel printer time-out",CR,LF +0018 U 0000 CR,LF," Unable to shift screen %1",CR,LF +0020 U 0000 CR,LF,"Invalid number of parameters",CR,LF +0021 U 0000 CR,LF,"NET 042: Unable to do requested command",CR,LF +0022 U 0001 CR,LF,"Infinite retry not supported on network printer",CR,LF +0023 U 0001 CR,LF,"Failure to access code page font file",cr,lf +0024 U 0000 CR,LF,"Failure to access device: %1",CR,LF +0025 U 0001 CR,LF,"Device or code page missing from font file",CR,LF +0026 U 0000 CR,LF,"Font file contents invalid",CR,LF +0027 U 0001 CR,LF,"Previously prepared code page replaced",CR,LF +0028 U 0001 CR,LF,"Active code page for device %1 is %2",CR,LF +0029 U 0000 CR,LF,"Device %1 not prepared",CR,LF +0030 U 0001 "%1 code pages:",CR,LF +0031 U 0001 " code page %1",CR,LF +0032 U 0001 CR,LF,"MODE %1 code page function completed",CR,LF +0033 U 0002 CR,LF,"Current code page settings:",CR,LF +0034 U 0002 " %1 - %2 code page",CR,LF +0035 U 0002 " code page not prepared",CR,LF +0036 U 0002 CR,LF,"Code page operation not supported on this device",CR,LF +0037 U 0002 CR,LF,"No code page has been selected",CR,LF +0038 U 0002 "Device error during %1",CR,LF +0039 U 0002 "Code page not prepared",CR,LF +0040 U 0002 CR,LF,"Current keyboard does not support this code page",CR,LF +0041 U 0002 CR,LF,"Error during read of font file",CR,LF +0042 U 0002 CR,LF,"Unable to perform refresh operation",CR,LF +0043 U 0002 CR,LF +0044 U 0002 CR,LF,"Status for device %1:",CR,LF +0045 U 0002 "------------------" +0046 U 0002 "----",CR,LF +0047 U 0002 "-----",CR,LF +0048 U 0002 "Lines=%1",CR,LF +0049 U 0002 "Columns=%1",CR,LF +0050 U 0002 CR,LF,"Rate and delay must be specified together",CR,LF +0051 U 0002 "Rate=%1",CR,LF +0052 U 0002 "Delay=%1",CR,LF +0053 U 0002 CR,LF,"Function not supported on this computer - %1",CR,LF +0054 U 0002 CR,LF,"Required font not loaded",CR,LF +0055 U 0002 CR,LF,"ANSI.SYS must be installed to perform requested function",CR,LF +0056 U 0002 CR,LF,"Baud rate required",CR,LF +0057 U 0002 "Retry=%1",CR,LF +0059 U 0002 "rightmost 9",0 +0060 U 0002 "leftmost 0",0 +0061 U 0002 "No",0 +0062 U 0002 "Infinite",0 +0063 U 0002 "left",0 +0064 U 0002 "right",0 +0065 U 0002 "Hardware",0 +0066 U 0002 "Prepared",0 +0067 U 0002 "status",0 +0068 U 0002 "prepare",0 +0069 U 0002 "select",0 +0070 U 0002 "refresh",0 +0071 U 0002 "write of font file to device",0 +0072 U 0002 "selected",0 +0073 U 0002 "system",0 +0300 U 0000 "Configures system devices.",CR,LF,CR,LF +0301 U 0000 "Printer port: MODE LPTn[:] [COLS=c] [LINES=l] [RETRY=r]",CR,LF +0302 U 0000 "Serial port: MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s] [RETRY=r]",CR,LF +0303 U 0000 "Device Status: MODE [device] [/STATUS]",CR,LF +0304 U 0000 "Redirect printing: MODE LPTn[:]=COMm[:]",CR,LF +0305 U 0000 "Prepare code page: MODE device CP PREPARE=((yyy[...]) [drive:][path]filename)",CR,LF +0306 U 0000 "Select code page: MODE device CP SELECT=yyy",CR,LF +0307 U 0000 "Refresh code page: MODE device CP REFRESH",CR,LF +0308 U 0000 "Code page status: MODE device CP [/STATUS]",CR,LF +0309 U 0000 "Display mode: MODE [display-adapter][,n]",CR,LF + " MODE CON[:] [COLS=c] [LINES=n]",CR,LF +0310 U 0000 "Typematic rate: MODE CON[:] [RATE=r DELAY=d]",CR,LF +MORE 00011148 0007 +0002 U 0000 "-- More --" +0003 U 0000 "Too many arguments in command line",CR,LF +0300 U 0000 "Displays output one screen at a time.",CR,LF,CR,LF +0301 U 0000 "MORE < [drive:][path]filename",CR,LF +0302 U 0000 "command-name | MORE",CR,LF,CR,LF +0303 U 0000 " [drive:][path]filename Specifies a file to display one screen at a time.",CR,LF +0304 U 0000 " command-name Specifies a command whose output will be displayed.",CR,LF +MSBIO 00011319 0023 +0003 U 0000 13,10,"Unrecognized command in CONFIG.SYS" +0004 U 0000 13,10,"$" +0005 U 0000 13,10,"Sector size too large in file $" +0006 U 0000 13,10,"Bad or missing $" +0007 U 0000 "Command Interpreter",0 +0008 U 0000 13,10,"Invalid country code or code page",13,10,"$" +0009 U 0000 13,10,"Error in COUNTRY command",13,10,"$" +0010 U 0000 13,10, "Insufficient memory for COUNTRY.SYS file",13,10,"$" +0011 U 0000 13,10,"Configuration too large for memory",13,10,"$" +0012 U 0000 13,10,"Too many block devices",13,10,"$" +0013 U 0000 13,10,"Invalid STACK parameters",13,10,"$" +0014 U 0000 13,10,"Incorrect order in CONFIG.SYS line ","$" +0015 U 0000 "Error in CONFIG.SYS line ","$" +0016 U 0000 13,10,"Memory allocation error ","$" +0017 U 0001 0DH,0AH,7,0DH,0AH, "Internal stack overflow",0DH,0AH + "System halted",0DH,0AH,"$" +0018 U 0000 "HMA not available : Loading DOS low",13,10,"$" +0019 U 0000 13,10,"failed to boot - missing local driver $" +0020 U 0000 13,10,"Insert diskette for drive " +0021 U 0000 "A: and press any key when ready",13,10,10,0 +0022 U 0000 13,10,"Bad command or parameters - $" +0023 U 0000 "Fatal Error:Cannot allocate Memory for DOS", 13, 10, "$" +0024 U 0000 "WARNING! Logical drives past Z: exist and will be ignored",13,10,"$" +0025 U 0000 "This version of DOS will boot only on IBM machines",13,10,0 +MSDOS 00011869 0007 +0001 U 0001 13,10,"Divide overflow",13,10 +0002 U 0002 "y" +0003 U 0002 "n" +0004 U 0003 13,10,"A20 Hardware Error",13,10,"$" +0005 U 0000 "Y" +0006 U 0000 "N" +0007 U 0000 "You must have the file WINA20.386 in the root of your boot drive",13,10 + "to run Windows in Enhanced Mode",13,10 +NLSFUNC 000119a2 0003 +0300 U 0000 "Loads country-specific information.",CR,LF,CR,LF +0301 U 0000 "NLSFUNC [[drive:][path]filename]",CR,LF,CR,LF +0302 U 0000 " [drive:][path]filename Specifies the file containing country-specific",CR,LF + " information.",CR,LF +PRINT 00011ac6 0034 +0002 U 0000 CR,LF +0006 U 0000 " error reading file",CR,LF,"$" +0007 U 0000 "File not found",CR,LF,"$" +0008 U 0000 CR,LF,LF,"File $" +0009 U 0000 " canceled by operator$" +0010 U 0000 CR,LF,LF,"All files canceled by operator$" +0011 U 0000 "File allocation table bad drive " +0012 U 0000 "A.",CR,LF,"$" +0013 U 0000 "List output is not assigned to a device",CR,LF +0014 U 0000 "Resident part of PRINT installed",CR,LF +0015 U 0000 "Cannot use PRINT - Use NET PRINT",CR,LF +0017 U 0000 "PRINT queue is full",CR,LF +0018 U 0000 "PRINT queue is empty",CR,LF +0019 U 0000 "Access denied",CR,LF +0020 U 0000 "Invalid drive specification",CR,LF +0021 U 0000 "Errors on list device indicate that it",CR,LF + "may be off-line. Please check it.",CR,LF +0022 U 0000 CR,LF,LF," %1 is currently being printed",CR,LF +0023 U 0000 " %1 is in queue",CR,LF +0025 U 0001 "Pathname too long",CR,LF +0026 U 0001 "File not in PRINT queue",CR,LF +0027 U 0000 "Name of list device [PRN]: " +0300 U 0000 "Prints a text file while you are using other MS-DOS commands.",CR,LF,CR,LF +0301 U 0000 "PRINT [/D:device] [/B:size] [/U:ticks1] [/M:ticks2] [/S:ticks3]",CR,LF +0302 U 0000 " [/Q:qsize] [/T] [[drive:][path]filename[ ...]] [/C] [/P]",CR,LF,CR,LF +0303 U 0000 " /D:device Specifies a print device.",CR,LF +0304 U 0000 " /B:size Sets the internal buffer size, in bytes.",CR,LF +0305 U 0000 " /U:ticks1 Waits the specified maximum number of clock ticks for the printer",CR,LF + " to be available.",CR,LF +0306 U 0000 " /M:ticks2 Specifies the maximum number of clock ticks it takes to print a",CR,LF + " character.",CR,LF +0307 U 0000 " /S:ticks3 Allocates the scheduler the specified number of clock ticks for",CR,LF + " background printing.",CR,LF +0308 U 0000 " /Q:qsize Specifies the maximum number of files allowed in the print queue.",CR,LF +0309 U 0000 " /T Removes all files from the print queue.",CR,LF +0310 U 0000 " /C Cancels printing of the preceding filename and subsequent",CR,LF + " filenames.",CR,LF +0311 U 0000 " /P Adds the preceding filename and subsequent filenames to the print",CR,LF + " queue.",CR,LF,CR,LF +0312 U 0000 "Type PRINT without parameters to display the contents of the print queue.",CR,LF +PRINTER 000123f8 0002 +0002 U 0000 "%1 code page driver cannot be initialized",CR,LF,BELL +0012 U 0000 "Invalid syntax on PRINTER.SYS code page driver",CR,LF,BELL +RECOVER 0001249d 0017 +0002 U 0000 CR,LF,"File not found",CR,LF +0003 U 0000 CR,LF,"Cannot RECOVER an ASSIGNed or SUBSTed drive",CR,LF +0004 U 0000 CR,LF,"Invalid drive or file name",CR,LF +0005 U 0000 CR,LF,"WARNING - directory full",CR,LF +0006 U 0000 CR,LF,"Cannot RECOVER a network drive", CR,LF +0008 U 0000 CR,LF,"%1 file(s) recovered",CR,LF +0009 U 0000 CR,LF,"%1 of %2 bytes recovered",CR,LF +0010 U 0000 CR,LF,"Press any key to begin recovery of the",CR,LF,"file(s) on drive %1",CR,LF,CR,LF +0011 U 0000 CR,LF,"Cannot read file allocation table",CR,LF +0012 U 0000 CR,LF,"Cannot write file allocation table",CR,LF +0013 U 0000 CR,LF +0300 U 0000 "Recovers readable information from a bad or defective disk.",CR,LF,CR,LF +0301 U 0000 "RECOVER [drive:][path]filename",CR,LF +0302 U 0000 "RECOVER drive:",CR,LF,CR,LF +0303 U 0000 "Consult your User's Guide and Reference before using the RECOVER command.",CR,LF +0400 U 0000 "The current directory structure will be destroyed.",CR,LF + "All files will be placed in the root directory.",CR,LF + "Are you sure (Y/N)? " +0401 U 0000 "The entire drive will be reconstructed,",CR,LF + "directory structures will be destroyed.", CR, LF + "Are you sure (Y/N)? " +REPLACE 0001295a 0019 +0003 U 0000 CR,LF,"No files replaced",CR,LF +0004 U 0000 CR,LF,"No files added",CR,LF +0013 U 0000 CR,LF,"Replacing %1",CR,LF +0014 U 0000 CR,LF,"Adding %1",CR,LF +0015 U 0000 CR,LF,"%1 file(s) replaced",CR,LF +0016 U 0000 CR,LF,"%1 file(s) added",CR,LF +0017 U 0000 CR,LF,"No files found - %1",CR,LF +0022 U 0000 CR,LF,"Replace %1? (Y/N)" +0023 U 0000 CR,LF,"Add %1? (Y/N)" +0300 U 0000 "Replaces files.",CR,LF,CR,LF +0301 U 0000 "REPLACE [drive1:][path1]filename [drive2:][path2] [/A] [/P] [/R] [/W]",CR,LF + "REPLACE [drive1:][path1]filename [drive2:][path2] [/P] [/R] [/S] [/W] [/U]",CR,LF,CR,LF +0302 U 0000 " [drive1:][path1]filename Specifies the source file or files.",CR,LF +0303 U 0000 " [drive2:][path2] Specifies the directory where files are to be",CR,LF + " replaced.",CR,LF +0304 U 0000 " /A Adds new files to destination directory. Cannot",CR,LF + " use with /S or /U switches.",CR,LF +0305 U 0000 " /P Prompts for confirmation before replacing a file or",CR,LF + " adding a source file.",CR,LF +0306 U 0000 " /R Replaces read-only files as well as unprotected",CR,LF + " files.",CR,LF +0307 U 0000 " /S Replaces files in all subdirectories of the",CR,LF + " destination directory. Cannot use with the /A",CR,LF + " switch.",CR,LF +0308 U 0000 " /W Waits for you to insert a disk before beginning.",CR,LF +0309 U 0000 " /U Replaces (updates) only files that are older than",CR,LF + " source files. Cannot use with the /A switch.",CR,LF +RESTORE 00013069 0035 +0002 U 0000 CR,LF,"Source and target drives are the same",CR,LF +0003 U 0000 CR,LF,"Invalid number of parameters",CR,LF +0006 U 0000 CR,LF,"Invalid drive specification",CR,LF +0007 U 0000 CR,LF,"WARNING! No files were found to restore",CR,LF +0008 U 0000 CR,LF,"Insert backup diskette %1 in drive %2:",CR,LF +0009 U 0000 CR,LF,"Insert restore target in drive %1:",CR,LF +0011 U 0000 CR,LF,"WARNING! Diskette is out of sequence",CR,LF + "Replace diskette or continue if OK",CR,LF +0012 U 0000 CR,LF,"The last file was not restored",CR,LF +0013 U 0000 CR,LF,"*** Files were backed up %1 ***",CR,LF +0014 U 0000 CR,LF,"Source does not contain backup files",CR,LF +0015 U 0000 CR,LF,"Insufficient memory",CR,LF +0016 U 0000 CR,LF,"WARNING! File %1",CR,LF + "is a read-only file",CR,LF + "Replace the file (Y/N)?" +0017 U 0000 CR,LF,"Restore file sequence error",CR,LF +0018 U 0000 CR,LF,"File creation error",CR,LF +0019 U 0000 CR,LF,"Insufficient disk space",CR,LF +0020 U 0000 CR,LF,"*** Not able to restore file ***",CR,LF +0021 U 0000 CR,LF,"*** Restoring files from drive %1: ***",CR,LF +0022 U 0000 CR,LF,"WARNING! File %1",CR,LF + "was changed after it was backed up",CR,LF + "Replace the file (Y/N)?",CR,LF +0023 U 0000 "Diskette: %1",CR,LF +0032 U 0000 CR,LF,"*** Listing files on drive %1: ***",CR,LF +0300 U 0000 "Restores files that were backed up by using the BACKUP command.",CR,LF,CR,LF +0301 U 0000 "RESTORE drive1: drive2:[path[filename]] [/S] [/P] [/B:date] [/A:date] [/E:time]",CR,LF +0302 U 0000 " [/L:time] [/M] [/N] [/D]",CR,LF,CR,LF +0303 U 0000 " drive1: Specifies the drive on which the backup files are stored.",CR,LF +0304 U 0000 " drive2:[path[filename]]",CR,LF + " Specifies the file(s) to restore.",CR,LF +0305 U 0000 " /S Restores files in all subdirectories in the path.",CR,LF +0306 U 0000 " /P Prompts before restoring read-only files or files changed since",CR,LF +0307 U 0000 " the last backup (if appropriate attributes are set).",CR,LF +0308 U 0000 " /B Restores only files last changed on or before the specified date.",CR,LF +0309 U 0000 " /A Restores only files changed on or after the specified date.",CR,LF + " /E Restores only files last changed at or earlier than the specified",CR,LF +0310 U 0000 " time.",CR,LF +0311 U 0000 " /L Restores only files changed at or later than the specified time.",CR,LF +0312 U 0000 " /M Restores only files changed since the last backup.",CR,LF +0313 U 0000 " /N Restores only files that no longer exist on the destination disk.",CR,LF +0314 U 0000 " /D Displays files on the backup disk that match specifications.",CR,LF +SHARE 00013b08 0005 +0003 U 0000 "SHARE cannot be installed under DOSSHELL.",CR,LF +0300 U 0000 "Installs file-sharing and locking capabilities on your hard disk.",CR,LF,CR,LF +0301 U 0000 "SHARE [/F:space] [/L:locks]",CR,LF,CR,LF +0302 U 0000 " /F:space Allocates file space (in bytes) for file-sharing information.",CR,LF +0303 U 0000 " /L:locks Sets the number of files that can be locked at one time.",CR,LF +SORT 00013cae 0009 +0005 U 0000 "SORT: " +0300 U 0000 "Sorts input and writes results to the screen, a file, or another device.",CR,LF,CR,LF +0301 U 0000 "SORT [/R] [/+n] < [drive1:][path1]filename1 [> [drive2:][path2]filename2]",CR,LF +0302 U 0000 "[command |] SORT [/R] [/+n] [> [drive2:][path2]filename2]",CR,LF,CR,LF +0303 U 0000 " /R Reverses the sort order; that is, sorts Z to A,",CR,LF + " then 9 to 0.",CR,LF +0304 U 0000 " /+n Sorts the file according to characters in",CR,LF + " column n.",CR,LF +0305 U 0000 " [drive1:][path1]filename1 Specifies a file to be sorted.",CR,LF +0306 U 0000 " [drive2:][path2]filename2 Specifies a file where the sorted input is to be ",CR,LF + " stored.",CR,LF +0307 U 0000 " command Specifies a command whose output is to be sorted.",CR,LF +SUBST 0001405f 0009 +0002 U 0001 "Incorrect number of parameters",CR,LF +0005 U 0000 "Drive already SUBSTed",CR,LF +0300 U 0000 "Associates a path with a drive letter.",CR,LF,CR,LF +0301 U 0000 "SUBST [drive1: [drive2:]path]",CR,LF +0302 U 0000 "SUBST drive1: /D",CR,LF,CR,LF +0303 U 0000 " drive1: Specifies a virtual drive to which you want to assign a path.",CR,LF +0304 U 0000 " [drive:2]path Specifies a physical drive and path you want to assign to",CR,LF + " a virtual drive.",CR,LF +0305 U 0000 " /D Deletes a substituted (virtual) drive.",CR,LF,CR,LF +0306 U 0000 "Type SUBST with no parameters to display a list of current virtual drives.",CR,LF +SYS 0001431a 0015 +0004 U 0000 "Invalid drive specification",CR,LF +0007 U 0000 "No room for system on destination disk",CR,LF +0008 U 0001 "Invalid path or System files not found",CR,LF +0010 U 0000 "No system on default drive",CR,LF +0011 U 0000 "Cannot specify default drive",CR,LF +0012 U 0000 "Write failure, diskette unusable",CR,LF +0014 U 0000 "Insert system disk in drive %1",CR,LF +0016 U 0000 "Not able to SYS to %1 file system",CR,LF +0019 U 0000 "Source path and target drive cannot be the same",CR,LF ;C04 +0025 U 0000 CR,LF,"Could not copy COMMAND.COM onto target disk",CR,LF +0026 U 0000 "Insufficient memory",CR,LF +0300 U 0000 "Copies MS-DOS system files and command interpreter to a disk you specify.",CR,LF,CR,LF +0301 U 0000 "SYS [drive1:][path] drive2:",CR,LF,CR,LF +0302 U 0000 " [drive1:][path] Specifies the location of the system files.",CR,LF +0303 U 0000 " drive2: Specifies the drive the files are to be copied to.",CR,LF +TREE 000146e8 0008 +0002 U 0000 "Directory PATH listing for Volume %1",CR,LF +0003 U 0000 "Directory PATH listing",CR,LF +0004 U 0000 "No sub-directories exist",CR,LF,LF +0007 U 0000 "ÀÄó" +0300 U 0000 "Graphically displays the directory structure of a drive or path.",CR,LF,CR,LF +0301 U 0000 "TREE [drive:][path] [/F] [/A]",CR,LF,CR,LF +0302 U 0000 " /F Displays the names of the files in each directory.",CR,LF +0303 U 0000 " /A Uses ASCII instead of extended characters.",CR,LF +XCOPY 000148d6 0033 +0004 U 0000 "Does %1 specify a file name",CR,LF + "or directory name on the target",CR,LF + "(F = file, D = directory)?" +0005 U 0000 "Press any key to begin copying file(s)" +0006 U 0000 "Path too long",CR,LF +0008 U 0000 "Cannot perform a cyclic copy",CR,LF +0012 U 0000 "Cannot XCOPY from a reserved device",CR,LF +0021 U 0000 "Invalid number of parameters",CR,LF +0022 U 0000 "Cannot XCOPY to a reserved device",CR,LF +0024 U 0000 "File creation error",CR,LF +0025 U 0000 "Reading source file(s)...",CR,LF +0026 U 0000 CR,LF +0027 U 0000 "%1 File(s) copied",CR,LF +0028 U 0000 "%1 File not found",CR,LF +0029 U 0000 "F D " +0030 U 0000 "%1%2",CR,LF +0031 U 0000 "%1\%2",CR,LF +0032 U 0000 "%1",CR,LF +0033 U 0000 "%1%2 (Y/N)?" +0034 U 0000 "%1\%2 (Y/N)?" +0036 U 0000 "Invalid Path, not all directories/files copied",CR,LF ;C02 +0300 U 0000 "Copies files (except hidden and system files) and directory trees.",CR,LF,CR,LF +0301 U 0000 "XCOPY source [destination] [/A | /M] [/D:date] [/P] [/S [/E]] [/V] [/W]",CR,LF,CR,LF +0302 U 0000 " source Specifies the file(s) to copy.",CR,LF +0303 U 0000 " destination Specifies the location and/or name of new files.",CR,LF +0304 U 0000 " /A Copies files with the archive attribute set,",CR,LF +0305 U 0000 " doesn't change the attribute.",CR,LF +0306 U 0000 " /M Copies files with the archive attribute set,",CR,LF +0307 U 0000 " turns off the archive attribute.",CR,LF +0308 U 0000 " /D:date Copies files changed on or after the specified date.",CR,LF +0309 U 0000 " /P Prompts you before creating each destination file.",CR,LF +0310 U 0000 " /S Copies directories and subdirectories except empty ones.",CR,LF +0311 U 0000 " /E Copies any subdirectories, even if empty.",CR,LF +0312 U 0000 " /V Verifies each new file.",CR,LF +0313 U 0000 " /W Prompts you to press a key before copying.",CR,LF diff --git a/private/utils/ulib/src/winnls.old b/private/utils/ulib/src/winnls.old new file mode 100644 index 000000000..f34273d1d --- /dev/null +++ b/private/utils/ulib/src/winnls.old @@ -0,0 +1,183 @@ +#include "ulib.hxx" + + +extern "C" { + + #include "string.h" + +} + + +BOOL +GetQualifiedLocale( + WORD wType, + LPVOID lpInput, + LPLC_ID lpOutID, + LPLC_STRINGS lpOutStr + ) + +{ + + char Unknown[] = "UNKNOWN"; + + // unreferenced parameters + (void)(wType); + (void)(lpInput); + (void)(lpOutID); + (void)(lpOutStr); + + if ( lpOutID ) { + + PLC_ID Locale = lpOutID; + + Locale->wLanguage = 0; + Locale->wCountry = 0; + Locale->wCodePage = 0; + } + + if ( lpOutStr ) { + + strcpy( lpOutStr->szLanguage, Unknown ); + strcpy( lpOutStr->szCountry, Unknown ); + strcpy( lpOutStr->szCodePage, Unknown ); + } + + return( TRUE ); +} + +HLOCALE +OpenLocale( + LPLC_ID lpLCID + ) + +{ + // unreferenced parameters + (void)(lpLCID); + + return( 1 ); +} + +int +CompareString( + HLOCALE hLocale, + DWORD dwCmpFlags, + LPWSTR lpwstrString1, + int nCount1, + LPWSTR lpwstrString2, + int nCount2 + ) + +{ + + register int result; + + // unreferenced parameters + (void)(hLocale); + + + DbgPtrAssert( lpwstrString1 ); + DbgPtrAssert( lpwstrString2 ); + + if( nCount1 == -1 ) { + nCount1 = strlen(( PCCCHAR ) lpwstrString1 ); + } + + if( nCount2 == -1 ) { + nCount2 = strlen(( PCCCHAR ) lpwstrString2 ); + } + + if( dwCmpFlags & CF_IGNORECASE ) { + result = strnicmp(( PCCCHAR ) lpwstrString1, + ( PCCCHAR ) lpwstrString2, min( nCount1, nCount2 )); + } else { + result = strncmp(( PCCCHAR ) lpwstrString1, + ( PCCCHAR ) lpwstrString2, min( nCount1, nCount2 )); + } + + if( result < 0 ) { + result = 1; + } else if( result == 0 ) { + result = 2; + } else { + result = 3; + } + + if(( result != 2 ) || ( nCount1 == nCount2 )) { + return( result ); + } else { + return nCount1 < nCount2 ? 1 : 3; + } +} + +int +WideCharToMultiByte ( + WORD wCodePage, + LPWSTR lpWideCharStr, + int nWideChar, + LPSTR lpMultiByteStr, + int nChar, + LPCHAR lpDefaultChar + ) +{ + int i; + PCHAR pWccString = (PCHAR)lpWideCharStr; + + // unreferenced parameters + (void)(wCodePage); + (void)(lpDefaultChar); + + if (!lpWideCharStr) { + return 0; + } + + if (nWideChar == -1) { + nWideChar = strlen((PCCCHAR)pWccString)+1; + } + + if (nChar == 0) { + return nWideChar; + } + + for (i = 0; (i < nChar) && (nWideChar--); i++) { + lpMultiByteStr[i] = pWccString[i]; + } + + return i; + +} + + +int +MultiByteToWideChar( + WORD wCodePage, + LPSTR lpMultiByteStr, + int nChar, + LPWSTR lpWideCharStr, + int nWideChar + ) + +{ + int i = 0; + PCHAR pWccString = (PCHAR)lpWideCharStr; + + // unreferenced parameters + (void)(wCodePage); + + if (!lpMultiByteStr) { + return 0; + } + + if( nChar == -1 ) { + nChar = strlen(( PCCCHAR ) lpMultiByteStr )+1; + } + + if (nWideChar == 0) { + return nChar; + } + + for ( i = 0; (i < nWideChar) && (nChar--) ; i++ ) { + pWccString[ i ] = ( CHAR ) lpMultiByteStr[i]; + } + + return i; +} diff --git a/private/utils/ulib/src/wstring.cxx b/private/utils/ulib/src/wstring.cxx new file mode 100644 index 000000000..dd3b3e0c8 --- /dev/null +++ b/private/utils/ulib/src/wstring.cxx @@ -0,0 +1,1606 @@ +/*++ + +Copyright (c) 1992 Microsoft Corporation + +Module Name: + + wstring.cxx + +Author: + + Norbert P. Kusters (norbertk) 6-Aug-92 + +--*/ + +#include <pch.cxx> + +#define _NTAPI_ULIB_ +#define _ULIB_MEMBER_ + +#include "ulib.hxx" +#include "wstring.hxx" + +#include <stdio.h> +#include <wchar.h> + +BOOLEAN WSTRING::_UseAnsiConversions = FALSE; +BOOLEAN WSTRING::_UseConsoleConversions = FALSE; +#if defined DBCS +BOOLEAN WSTRING::_UseAnsiConversionsPrev = FALSE; +BOOLEAN WSTRING::_UseConsoleConversionsPrev = FALSE; +#endif // DBCS + +// Helper functions for OEM/Unicode conversion. Note that these +// are abstracted to private functions to make it easier to set +// them up for various environments. +// +#if defined( _AUTOCHECK_ ) + +INLINE +BOOLEAN +WSTRING::ConvertOemToUnicodeN( + PWSTR UnicodeString, + ULONG MaxBytesInUnicodeString, + PULONG BytesInUnicodeString, + PCHAR OemString, + ULONG BytesInOemString + ) +{ + return _UseAnsiConversions ? + NT_SUCCESS(RtlMultiByteToUnicodeN( UnicodeString, + MaxBytesInUnicodeString, + BytesInUnicodeString, + OemString, + BytesInOemString )) : + NT_SUCCESS(RtlOemToUnicodeN( UnicodeString, + MaxBytesInUnicodeString, + BytesInUnicodeString, + OemString, + BytesInOemString )); +} + +INLINE +BOOLEAN +WSTRING::ConvertUnicodeToOemN( + PCHAR OemString, + ULONG MaxBytesInOemString, + PULONG BytesInOemString, + PWSTR UnicodeString, + ULONG BytesInUnicodeString + ) +{ + return _UseAnsiConversions ? + NT_SUCCESS(RtlUnicodeToMultiByteN( OemString, + MaxBytesInOemString, + BytesInOemString, + UnicodeString, + BytesInUnicodeString )) : + NT_SUCCESS(RtlUnicodeToOemN( OemString, + MaxBytesInOemString, + BytesInOemString, + UnicodeString, + BytesInUnicodeString )); +} + +#else // _AUTOCHECK_ not defined + +INLINE +BOOLEAN +ConvertToUnicodeWithConsoleCP( + PWSTR UnicodeString, + ULONG MaxBytesInUnicodeString, + PULONG BytesInUnicodeString, + PCHAR OemString, + ULONG BytesInOemString + ) +{ + int result; + + *BytesInUnicodeString = + MultiByteToWideChar( GetConsoleCP(), + MB_PRECOMPOSED, + OemString, + BytesInOemString, + UnicodeString, + MaxBytesInUnicodeString/sizeof(WCHAR) ) * + sizeof(WCHAR); + + return( *BytesInUnicodeString != 0 ); +} + +#if defined DBCS // ConvertToOemWithConsoleCP() +INLINE +BOOLEAN +ConvertToOemWithConsoleCP( + PCHAR OemString, + ULONG MaxBytesInOemString, + PULONG BytesInOemString, + PWSTR UnicodeString, + ULONG BytesInUnicodeString + ) +{ + int result; + + *BytesInOemString = + WideCharToMultiByte( GetConsoleCP(), + 0, + UnicodeString, + BytesInUnicodeString/sizeof(WCHAR), + OemString, + MaxBytesInOemString, + NULL, + NULL ); + + return( *BytesInOemString != 0 ); +} +#endif // DBCS + +INLINE +BOOLEAN +WSTRING::ConvertOemToUnicodeN( + PWSTR UnicodeString, + ULONG MaxBytesInUnicodeString, + PULONG BytesInUnicodeString, + PCHAR OemString, + ULONG BytesInOemString + ) +{ + return + _UseConsoleConversions ? + ConvertToUnicodeWithConsoleCP( UnicodeString, + MaxBytesInUnicodeString, + BytesInUnicodeString, + OemString, + BytesInOemString ) : + _UseAnsiConversions ? + NT_SUCCESS(RtlMultiByteToUnicodeN( UnicodeString, + MaxBytesInUnicodeString, + BytesInUnicodeString, + OemString, + BytesInOemString )) : + NT_SUCCESS(RtlOemToUnicodeN( UnicodeString, + MaxBytesInUnicodeString, + BytesInUnicodeString, + OemString, + BytesInOemString )); +} + +INLINE +BOOLEAN +WSTRING::ConvertUnicodeToOemN( + PCHAR OemString, + ULONG MaxBytesInOemString, + PULONG BytesInOemString, + PWSTR UnicodeString, + ULONG BytesInUnicodeString + ) +{ +#if defined DBCS // WSTRING::ConvertUnicodeToOemN() + return + _UseConsoleConversions ? + ConvertToOemWithConsoleCP( OemString, + MaxBytesInOemString, + BytesInOemString, + UnicodeString, + BytesInUnicodeString ) : + _UseAnsiConversions ? +#else + return _UseAnsiConversions ? +#endif // DBCS + NT_SUCCESS(RtlUnicodeToMultiByteN( OemString, + MaxBytesInOemString, + BytesInOemString, + UnicodeString, + BytesInUnicodeString )) : + NT_SUCCESS(RtlUnicodeToOemN( OemString, + MaxBytesInOemString, + BytesInOemString, + UnicodeString, + BytesInUnicodeString )); +} + + +#endif // not autochk + +// Implement wcscoll and wcsicoll for AUTOCHECK, +// since they're not in LIBCNT.LIB + +#if defined( _AUTOCHECK_ ) + +int _CRTAPI1 wcscoll(const wchar_t * left, const wchar_t * right) +{ + return wcscmp(left, right); +} + +int _CRTAPI1 _wcsicoll(const wchar_t * left, const wchar_t * right) +{ + return _wcsicmp(left, right); +} + +#endif // _AUTOCHECK_ + +INLINE +VOID +WSTRING::Construct( + ) +{ + _s = NULL; + _l = 0; +} + + +DEFINE_CONSTRUCTOR( WSTRING, OBJECT ); + + +ULIB_EXPORT +BOOLEAN +WSTRING::Initialize( + IN PCWSTRING InitialString, + IN CHNUM Position, + IN CHNUM Length + ) +/*++ + +Routine Description: + + This routine initializes the current string by copying the contents + of the given string. + +Arguments: + + InitialString - Supplies the initial string. + Position - Supplies the position in the given string to start at. + Length - Supplies the length of the string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + DebugAssert(Position <= InitialString->_l); + + Length = min(Length, InitialString->_l - Position); + + if (!NewBuf(Length)) { + return FALSE; + } + + memcpy(_s, InitialString->_s + Position, (UINT) Length*sizeof(WCHAR)); + + return TRUE; +} + + +ULIB_EXPORT +BOOLEAN +WSTRING::Initialize( + IN PCWSTR InitialString, + IN CHNUM StringLength + ) +/*++ + +Routine Description: + + This routine initializes the current string by copying the contents + of the given string. + +Arguments: + + InitialString - Supplies the initial string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + if (StringLength == TO_END) { + StringLength = wcslen(InitialString); + } + + if (!NewBuf(StringLength)) { + return FALSE; + } + + memcpy(_s, InitialString, (UINT) StringLength*sizeof(WCHAR)); + + return TRUE; +} + + +ULIB_EXPORT +BOOLEAN +WSTRING::Initialize( + IN PCSTR InitialString, + IN CHNUM StringLength + ) +/*++ + +Routine Description: + + This routine initializes the current string by copying the contents + of the given string. + +Arguments: + + InitialString - Supplies the initial string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + CHNUM length; + BOOLEAN status; + + if (StringLength == TO_END) { + StringLength = strlen(InitialString); + } + + if (!StringLength) { + return Resize(0); + } + + + // We want to avoid making two calls to RtlOemToUnicodeN so + // try to guess an adequate size for the buffer. + + if (!NewBuf(StringLength)) { + return FALSE; + } + + status = ConvertOemToUnicodeN(_s, _l*sizeof(WCHAR), + &length, (PSTR) InitialString, + StringLength); + length /= sizeof(WCHAR); + + if (status) { + return Resize(length); + } + + + // We didn't manage to make in one try so ask exactly how much + // we need and then make the call. + + status = ConvertOemToUnicodeN(NULL, 0, &length, (PSTR) InitialString, + StringLength); + length /= sizeof(WCHAR); + + if (!status || !NewBuf(length)) { + return FALSE; + } + + status = ConvertOemToUnicodeN(_s, _l*sizeof(WCHAR), + &length, (PSTR) InitialString, StringLength); + + if (!status) { + return FALSE; + } + + DebugAssert(length == _l*sizeof(WCHAR)); + + return TRUE; +} + + +ULIB_EXPORT +BOOLEAN +WSTRING::Initialize( + IN LONG Number + ) +/*++ + +Routine Description: + + This routine initializes the current string by copying the contents + of the given string. + +Arguments: + + Number - Supplies the number to initialize the string to. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + CHAR tmp[64]; + + sprintf(tmp, "%d", Number); + return Initialize(tmp); +} + + +NONVIRTUAL +ULIB_EXPORT +PWSTRING +WSTRING::QueryString( + IN CHNUM Position, + IN CHNUM Length + ) CONST +/*++ + +Routine Description: + + This routine returns a copy of this string from the specified + coordinates. + +Arguments: + + Position - Supplies the initialize position of the string. + Length - Supplies the length of the string. + +Return Value: + + A pointer to a string or NULL. + +--*/ +{ + PWSTRING p; + + if (!(p = NEW DSTRING) || + !p->Initialize(this, Position, Length)) { + + DELETE(p); + } + + return p; +} + + +ULIB_EXPORT +BOOLEAN +WSTRING::QueryNumber( + OUT PLONG Number, + IN CHNUM Position, + IN CHNUM Length + ) CONST +/*++ + +Routine Description: + + This routine queries a number from the string. + +Arguments: + + Number - Returns the number parsed out of the string. + Position - Supplies the position of the number. + Length - Supplies the length of the number. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + FSTRING String; + PSTR p; + CHNUM spn; + + if (Position >= _l) { + return FALSE; + } + + Length = min(Length, _l - Position); + + // + // Note that 123+123 will be a number! + // + String.Initialize((PWSTR) L"1234567890+-"); + + spn = Strspn(&String, Position); + + if ((spn == INVALID_CHNUM || spn >= Position + Length) && + (p = QuerySTR(Position, Length))) { + + *Number = atol(p); + + DELETE(p); + return TRUE; + } + + return FALSE; +} + + +ULIB_EXPORT +VOID +WSTRING::DeleteChAt( + IN CHNUM Position, + IN CHNUM Length + ) +/*++ + +Routine Description: + + This routine removes the character at the given position. + +Arguments: + + Position - Supplies the position of the character to remove. + Length - Supplies the number of characters to remove. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + DebugAssert(Position <= _l); + + Length = min(Length, _l - Position); + + memmove(_s + Position, _s + Position + Length, + (UINT) (_l - Position - Length)*sizeof(WCHAR)); + + Resize(_l - Length); +} + + +NONVIRTUAL +ULIB_EXPORT +BOOLEAN +WSTRING::InsertString( + IN CHNUM AtPosition, + IN PCWSTRING String, + IN CHNUM FromPosition, + IN CHNUM FromLength + ) +/*++ + +Routine Description: + + This routine inserts the given string at the given position in + this string. + +Arguments: + + AtPosition - Supplies the position at which to insert the string. + String - Supplies the string to insert. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + CHNUM old_length; + + DebugAssert(AtPosition <= _l); + DebugAssert(FromPosition <= String->_l); + + FromLength = min(FromLength, String->_l - FromPosition); + + old_length = _l; + if (!Resize(_l + FromLength)) { + return FALSE; + } + + memmove(_s + AtPosition + FromLength, _s + AtPosition, + (UINT) (old_length - AtPosition)*sizeof(WCHAR)); + + memcpy(_s + AtPosition, String->_s + FromPosition, + (UINT) FromLength*sizeof(WCHAR)); + + return TRUE; +} + + +NONVIRTUAL +ULIB_EXPORT +BOOLEAN +WSTRING::Replace( + IN CHNUM AtPosition, + IN CHNUM AtLength, + IN PCWSTRING String, + IN CHNUM FromPosition, + IN CHNUM FromLength + ) +/*++ + +Routine Description: + + This routine replaces the contents of this string from + 'Position' to 'Length' with the contents of 'String2' + from 'Position2' to 'Length2'. + +Arguments: + + AtPosition - Supplies the position to replace at. + AtLength - Supplies the length to replace at. + String - Supplies the string to replace with. + FromPosition - Supplies the position to replace from in String2. + FromLength - Supplies the position to replace from in String2. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + CHNUM old_length; + + DebugAssert(AtPosition <= _l); + DebugAssert(FromPosition <= String->_l); + + AtLength = min(AtLength, _l - AtPosition); + FromLength = min(FromLength, String->_l - FromPosition); + + // Make sure up front that we have the room but don't disturb + // the string. + + if (FromLength > AtLength) { + old_length = _l; + if (!Resize(_l + FromLength - AtLength)) { + return FALSE; + } + Resize(old_length); + } + + DeleteChAt(AtPosition, AtLength); + if (!InsertString(AtPosition, String, FromPosition, FromLength)) { + DebugAbort("This absolutely can never happen\n"); + return FALSE; + } + + return TRUE; +} + + +ULIB_EXPORT +PWSTR +WSTRING::QueryWSTR( + IN CHNUM Position, + IN CHNUM Length, + OUT PWSTR Buffer, + IN CHNUM BufferLength, + IN BOOLEAN ForceNull + ) CONST +/*++ + +Routine Description: + + This routine makes a copy of this string into the provided + buffer. If this string is not provided then a buffer is + allocated on the heap. + +Arguments: + + Position - Supplies the position within this string. + Length - Supplies the length of this string to take. + Buffer - Supplies the buffer to copy to. + BufferLength - Supplies the number of characters in the buffer. + ForceNull - Specifies whether or not to force the final character + of the buffer to be NULL in the case when there + isn't enough room for the whole string including + the NULL. + +Return Value: + + A pointer to a NULL terminated string. + +--*/ +{ + DebugAssert(Position <= _l); + + Length = min(Length, _l - Position); + + if (!Buffer) { + BufferLength = Length + 1; + if (!(Buffer = (PWCHAR) MALLOC(BufferLength*sizeof(WCHAR)))) { + return NULL; + } + } + + if (BufferLength > Length) { + memcpy(Buffer, _s + Position, (UINT) Length*sizeof(WCHAR)); + Buffer[Length] = 0; + } else { + memcpy(Buffer, _s + Position, (UINT) BufferLength*sizeof(WCHAR)); + if (ForceNull) { + Buffer[BufferLength - 1] = 0; + } + } + + return Buffer; +} + + +ULIB_EXPORT +PSTR +WSTRING::QuerySTR( + IN CHNUM Position, + IN CHNUM Length, + OUT PSTR Buffer, + IN CHNUM BufferLength, + IN BOOLEAN ForceNull + ) CONST +/*++ + +Routine Description: + + This routine computes a multi-byte version of the current + unicode string. If the buffer is not supplied then it + will be allocated by this routine. + +Arguments: + + Position - Supplies the position within this string. + Length - Supplies the length of this string to take. + Buffer - Supplies the buffer to convert into. + BufferLength - Supplies the number of characters in this buffer. + ForceNull - Specifies whether or not to force a NULL even + when the buffer is too small for the string. + +Return Value: + + A pointer to a NULL terminated multi byte string. + +--*/ +{ + ULONG ansi_length; + + DebugAssert(Position <= _l); + + Length = min(Length, _l - Position); + + + // First special case the empty result. + + if (!Length) { + + if (!Buffer) { + if (!(Buffer = (PSTR) MALLOC(1))) { + return NULL; + } + } else if (!BufferLength) { + return NULL; + } + + Buffer[0] = 0; + return Buffer; + } + + + // Next case is that the buffer is not provided and thus + // we have to figure out what size it should be. + + if (!Buffer) { + + // We want to avoid too many calls to RtlUnicodeToOemN + // so we'll estimate a correct size for the buffer and + // hope that that works. + + BufferLength = 2*Length + 1; + if (!(Buffer = (PSTR) MALLOC(BufferLength))) { + return NULL; + } + + if (ConvertUnicodeToOemN(Buffer, BufferLength - 1, + &ansi_length, _s + Position, + Length*sizeof(WCHAR))) { + Buffer[ansi_length] = 0; + return Buffer; + } + + + // We failed to estimate the necessary size of the buffer. + // So ask the correct size and try again. + + FREE(Buffer); + + if (!ConvertUnicodeToOemN(NULL, 0, &ansi_length, + _s + Position, Length*sizeof(WCHAR))) { + return NULL; + } + + BufferLength = ansi_length + 1; + if (!(Buffer = (PSTR) MALLOC(BufferLength))) { + return NULL; + } + } + + if (!ConvertUnicodeToOemN(Buffer, BufferLength, &ansi_length, + _s + Position, Length*sizeof(WCHAR))) { + return NULL; + } + + if (BufferLength > ansi_length) { + Buffer[ansi_length] = 0; + } else { + if (ForceNull) { + Buffer[BufferLength - 1] = 0; + } + } + + return Buffer; +} + + +ULIB_EXPORT +BOOLEAN +WSTRING::Strcat( + IN PCWSTRING String + ) +/*++ + +Routine Description: + + This routine concatenates the given string onto this one. + +Arguments: + + String - Supplies the string to concatenate to this one. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + CHNUM old_length; + + old_length = _l; + if (!Resize(_l + String->_l)) { + return FALSE; + } + + memcpy(_s + old_length, String->_s, (UINT) String->_l*sizeof(WCHAR)); + + return TRUE; +} + + +NONVIRTUAL +PWSTRING +WSTRING::Strupr( + IN CHNUM StartPosition, + IN CHNUM Length + ) +/*++ + +Routine Description: + + This routine upcases a portion of this string. + +Arguments: + + StartPosition - Supplies the start position of the substring to upcase. + Length - Supplies the length of the substring to upscase. + +Return Value: + + A pointer to this string. + +--*/ +{ + WCHAR c; + + DebugAssert(StartPosition <= _l); + + Length = min(Length, _l - StartPosition); + + c = _s[StartPosition + Length]; + _s[StartPosition + Length] = 0; + + _wcsupr(_s + StartPosition); + + _s[StartPosition + Length] = c; + + return this; +} + + +NONVIRTUAL +ULIB_EXPORT +PWSTRING +WSTRING::Strlwr( + IN CHNUM StartPosition, + IN CHNUM Length + ) +/*++ + +Routine Description: + + This routine lowercases a portion of this string. + +Arguments: + + StartPosition - Supplies the start position of the substring to lowercase. + Length - Supplies the length of the substring to lowercase. + +Return Value: + + A pointer to this string. + +--*/ +{ + WCHAR c; + + DebugAssert(StartPosition <= _l); + + Length = min(Length, _l - StartPosition); + + c = _s[StartPosition + Length]; + _s[StartPosition + Length] = 0; + + _wcslwr(_s + StartPosition); + + _s[StartPosition + Length] = c; + + return this; +} + + +NONVIRTUAL +LONG +WSTRING::Strcmp( + IN PCWSTRING String, + IN CHNUM LeftPosition, + IN CHNUM LeftLength, + IN CHNUM RightPosition, + IN CHNUM RightLength + ) CONST +/*++ + +Routine Description: + + This routine compares two substrings. + +Arguments: + + String - Supplies the string to compare this one to. + LeftPosition - Supplies the postion for the left substring. + LeftLength - Supplies the length of the left substring. + LeftPosition - Supplies the postion for the left substring. + LeftLength - Supplies the length of the left substring. + +Return Value: + + <0 - Left substring is less than right substring. + 0 - Left and Right substrings are equal + >0 - Left substring is greater than right substring. + +--*/ +{ + WCHAR c, d; + LONG r; + + DebugAssert(LeftPosition <= _l); + DebugAssert(RightPosition <= String->_l); + + LeftLength = min(LeftLength, _l - LeftPosition); + RightLength = min(RightLength, String->_l - RightPosition); + + c = _s[LeftPosition + LeftLength]; + d = String->_s[RightPosition + RightLength]; + _s[LeftPosition + LeftLength] = 0; + String->_s[RightPosition + RightLength] = 0; + + r = wcscoll(_s + LeftPosition, String->_s + RightPosition); + + _s[LeftPosition + LeftLength] = c; + String->_s[RightPosition + RightLength] = d; + + return r; +} + + +NONVIRTUAL +ULIB_EXPORT +LONG +WSTRING::Stricmp( + IN PCWSTRING String, + IN CHNUM LeftPosition, + IN CHNUM LeftLength, + IN CHNUM RightPosition, + IN CHNUM RightLength + ) CONST +/*++ + +Routine Description: + + This routine compares two substrings insensitive of case. + +Arguments: + + String - Supplies the string to compare this one to. + LeftPosition - Supplies the postion for the left substring. + LeftLength - Supplies the length of the left substring. + LeftPosition - Supplies the postion for the left substring. + LeftLength - Supplies the length of the left substring. + +Return Value: + + <0 - Left substring is less than right substring. + 0 - Left and Right substrings are equal + >0 - Left substring is greater than right substring. + +--*/ +{ + WCHAR c, d; + LONG r; + + DebugAssert(LeftPosition <= _l); + DebugAssert(RightPosition <= String->_l); + + LeftLength = min(LeftLength, _l - LeftPosition); + RightLength = min(RightLength, String->_l - RightPosition); + + c = _s[LeftPosition + LeftLength]; + d = String->_s[RightPosition + RightLength]; + _s[LeftPosition + LeftLength] = 0; + String->_s[RightPosition + RightLength] = 0; + +#if !defined _AUTOCHECK_ + + // This works around a bug in the libc version of wcsicoll, where + // it doesn't specify STRINGSORT to CompareString(). To reproduce the + // bug, try sorting 1 and -1. (-1 should sort before 1.) -mjb. + // + + r = CompareString(GetUserDefaultLCID(), + NORM_IGNORECASE | SORT_STRINGSORT, + _s + LeftPosition, + -1, + String->_s + RightPosition, + -1 + ); + + + if (r >= 1) { + + // + // return codes 1, 2, and 3 map to -1, 0, and 1. + // + + _s[LeftPosition + LeftLength] = c; + String->_s[RightPosition + RightLength] = d; + return r - 2; + } + + // If 'r' is 0, this indicates failure and we'll fall through and + // call wcsicoll. + // + +#endif // _AUTOCHECK_ + + r = _wcsicoll(_s + LeftPosition, String->_s + RightPosition); + + _s[LeftPosition + LeftLength] = c; + String->_s[RightPosition + RightLength] = d; + + return r; +} + + +PWSTR +WSTRING::SkipWhite( + IN PWSTR p + ) +{ +#ifdef DBCS + + while (*p) { + + if (iswspace(*p)) + p++; + else if ( *p == 0x3000 ) + { + *p++ = TEXT(' '); + } + else + break; + } + +#else + while (iswspace(*p)) { + p++; + } +#endif + + return p; + +} + + +/**************************************************************************/ +/* Compare two strings, ignoring white space, case is significant, return */ +/* 0 if identical, <>0 otherwise. Leading and trailing white space is */ +/* ignored, internal white space is treated as single characters. */ +/**************************************************************************/ +ULIB_EXPORT +INT +WSTRING::Strcmps ( + IN PWSTR p1, + IN PWSTR p2 + ) +{ + WCHAR *q; + + p1 = WSTRING::SkipWhite(p1); /* skip any leading white space */ + p2 = WSTRING::SkipWhite(p2); + + while (TRUE) + { + if (*p1 == *p2) + { + if (*p1++ == 0) /* quit if at the end */ + return (0); + else + p2++; + +#ifdef DBCS + if (CheckSpace(p1)) +#else + if (iswspace(*p1)) /* compress multiple spaces */ +#endif + { + q = WSTRING::SkipWhite(p1); + p1 = (*q == 0) ? q : q - 1; + } + +#ifdef DBCS + if (CheckSpace(p2)) +#else + if (iswspace(*p2)) +#endif + { + q = WSTRING::SkipWhite(p2); + p2 = (*q == 0) ? q : q - 1; + } + } + else + return *p1-*p2; + } +} + + + + + +/**************************************************************************/ +/* Compare two strings, ignoring white space, case is not significant, */ +/* return 0 if identical, <>0 otherwise. Leading and trailing white */ +/* space is ignored, internal white space is treated as single characters.*/ +/**************************************************************************/ +ULIB_EXPORT +INT +WSTRING::Strcmpis ( + IN PWSTR p1, + IN PWSTR p2 + ) +{ + WCHAR *q; +#ifdef DBCS + WCHAR c1,c2; +#endif + + p1 = WSTRING::SkipWhite(p1); /* skip any leading white space */ + p2 = WSTRING::SkipWhite(p2); + + while (TRUE) + { + if (towupper(*p1) == towupper(*p2)) + { + if (*p1++ == 0) /* quit if at the end */ + return (0); + else + p2++; +#ifdef DBCS + if (CheckSpace(p1)) +#else + if (iswspace(*p1)) /* compress multiple spaces */ +#endif + { + q = SkipWhite(p1); + p1 = (*q == 0) ? q : q - 1; + } +#ifdef DBCS + if (CheckSpace(p2)) +#else + if (iswspace(*p2)) +#endif + { + q = WSTRING::SkipWhite(p2); + p2 = (*q == 0) ? q : q - 1; + } + } + else + return *p1-*p2; + } +} + +#ifdef DBCS + +/**************************************************************************/ +/* Routine: CheckSpace */ +/* Arguments: an arbitrary string */ +/* Function: Determine whether there is a space in the string. */ +/* Side effects: none */ +/**************************************************************************/ +INT +WSTRING::CheckSpace( + IN PWSTR s + ) +{ + if (iswspace(*s) || *s == 0x3000 ) + return (TRUE); + else + return (FALSE); +} + +#endif + + +DEFINE_EXPORTED_CONSTRUCTOR( FSTRING, WSTRING, ULIB_EXPORT ); + + +ULIB_EXPORT +BOOLEAN +FSTRING::Resize( + IN CHNUM NewStringLength + ) +/*++ + +Routine Description: + + This routine implements the WSTRING Resize routine by using + the buffer supplied at initialization time. + +Arguments: + + NewStringLength - Supplies the new length of the string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + return NewBuf(NewStringLength); +} + + +BOOLEAN +FSTRING::NewBuf( + IN CHNUM NewStringLength + ) +/*++ + +Routine Description: + + This routine implements the WSTRING NewBuf routine by using + the buffer supplied at initialization time. + +Arguments: + + NewStringLength - Supplies the new length of the string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + if (NewStringLength >= _buffer_length) { + return FALSE; + } + + PutString((PWSTR) GetWSTR(), NewStringLength); + + return TRUE; +} + + +INLINE +VOID +DSTRING::Construct( + ) +/*++ + +Routine Description: + + This routine initializes the string to a valid initial state. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + _buf = NULL; + _length = 0; +} + + +DEFINE_EXPORTED_CONSTRUCTOR( DSTRING, WSTRING, ULIB_EXPORT ); + + +ULIB_EXPORT +DSTRING::~DSTRING( + ) +/*++ + +Routine Description: + + Destructor for DSTRING. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ + FREE(_buf); +} + + +BOOLEAN +DSTRING::Resize( + IN CHNUM NewStringLength + ) +/*++ + +Routine Description: + + This routine resizes this string to the specified new size. + +Arguments: + + NewStringLength - Supplies the new length of the string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + PWSTR new_buf; + + if (NewStringLength >= _length) { + + if (_buf) { + if (!(new_buf = (PWSTR) + REALLOC(_buf, (NewStringLength + 1)*sizeof(WCHAR)))) { + + return FALSE; + } + } else { + if (!(new_buf = (PWSTR) + MALLOC((NewStringLength + 1)*sizeof(WCHAR)))) { + + return FALSE; + } + } + + _buf = new_buf; + _length = NewStringLength + 1; + } + + PutString(_buf, NewStringLength); + + return TRUE; +} + + +BOOLEAN +DSTRING::NewBuf( + IN CHNUM NewStringLength + ) +/*++ + +Routine Description: + + This routine resizes this string to the specified new size. + +Arguments: + + NewStringLength - Supplies the new length of the string. + +Return Value: + + FALSE - Failure. + TRUE - Success. + +--*/ +{ + PWSTR new_buf; + + if (NewStringLength >= _length) { + + if (!(new_buf = (PWSTR) + MALLOC((NewStringLength + 1)*sizeof(WCHAR)))) { + + return FALSE; + } + + _buf = new_buf; + _length = NewStringLength + 1; + } + + PutString(_buf, NewStringLength); + + return TRUE; +} + +#if defined DBCS +ULIB_EXPORT +VOID +WSTRING::ResetConversions( + ) +{ + _UseAnsiConversions = _UseAnsiConversionsPrev; + _UseConsoleConversions = _UseConsoleConversionsPrev; +} +#endif // DBCS + +ULIB_EXPORT +VOID +WSTRING::SetAnsiConversions( + ) +/*++ + +Routine Description: + + This routine declares that all conversions from multi byte + to unicode will take place using the ANSI code page. Note + that this is a STATIC method. Therefore this switch affects + *all* WSTRINGs. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +#if defined DBCS + _UseAnsiConversionsPrev = _UseAnsiConversions; + _UseConsoleConversionsPrev = _UseConsoleConversions; +#endif // DBCS + + _UseAnsiConversions = TRUE; + _UseConsoleConversions = FALSE; +} + + +ULIB_EXPORT +VOID +WSTRING::SetOemConversions( + ) +/*++ + +Routine Description: + + This routine declares that all conversions from multi byte + to unicode will take place using the OEM code page. Note + that this is a STATIC method. Therefore this switch affects + *all* WSTRINGs. + + This is the default if neither this nor the above function is + called. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +#if defined DBCS + _UseAnsiConversionsPrev = _UseAnsiConversions; + _UseConsoleConversionsPrev = _UseConsoleConversions; +#endif // DBCS + + _UseAnsiConversions = FALSE; + _UseConsoleConversions = FALSE; +} + +ULIB_EXPORT +VOID +WSTRING::SetConsoleConversions( + ) +/*++ + +Routine Description: + + This routine declares that all conversions from multi byte + to unicode will take place using the current console code page. + Note that this is a STATIC method. Therefore this switch + affects *all* WSTRINGs. + +Arguments: + + None. + +Return Value: + + None. + +--*/ +{ +#if defined DBCS + _UseAnsiConversionsPrev = _UseAnsiConversions; + _UseConsoleConversionsPrev = _UseConsoleConversions; +#endif // DBCS + _UseAnsiConversions = FALSE; + _UseConsoleConversions = TRUE; +} + +#if defined DBCS +CHNUM +WSTRING::QueryByteCount( + ) CONST +/*++ + +Routine Description: + + This routine returns the number of ANSI bytes the UNICODE string + consists of. + +Arguments: + + None. + +Return Value: + + Number of ANSI bytes the UNICODE string is made from, or INVALID_CHNUM + on error. + +--*/ + +{ + ULONG ansi_length; + ULONG BufferLen = _l * sizeof(WCHAR) + 1; + PSTR Buffer; + BOOLEAN success; + + if ( !_l ) { + return( (CHNUM)0 ); + } + + if (NULL == (Buffer = (PSTR)MALLOC( BufferLen ))) { + return( INVALID_CHNUM ); + } + + success = ConvertUnicodeToOemN( Buffer, BufferLen - 1, &ansi_length, + _s, BufferLen - 1 ); + + FREE( Buffer ); + + if (!success) { + return INVALID_CHNUM; + } + return ansi_length; +} +#endif // DBCS |