summaryrefslogtreecommitdiffstats
path: root/private/utils/ulib
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/utils/ulib
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to '')
-rw-r--r--private/utils/ulib/dirs16
-rw-r--r--private/utils/ulib/inc/achkmsg.hxx164
-rw-r--r--private/utils/ulib/inc/arg.hxx1668
-rw-r--r--private/utils/ulib/inc/array.hxx390
-rw-r--r--private/utils/ulib/inc/arrayit.hxx125
-rw-r--r--private/utils/ulib/inc/basesys.hxx57
-rw-r--r--private/utils/ulib/inc/bitvect.hxx447
-rw-r--r--private/utils/ulib/inc/buffer.hxx183
-rw-r--r--private/utils/ulib/inc/bufstrm.hxx217
-rw-r--r--private/utils/ulib/inc/bytestrm.hxx169
-rw-r--r--private/utils/ulib/inc/clasdesc.hxx183
-rw-r--r--private/utils/ulib/inc/classes.xlsbin0 -> 11546 bytes
-rw-r--r--private/utils/ulib/inc/cmem.hxx66
-rw-r--r--private/utils/ulib/inc/comm.hxx564
-rw-r--r--private/utils/ulib/inc/contain.hxx95
-rw-r--r--private/utils/ulib/inc/cstring.h174
-rw-r--r--private/utils/ulib/inc/dir.hxx150
-rw-r--r--private/utils/ulib/inc/error.hxx392
-rw-r--r--private/utils/ulib/inc/file.hxx127
-rw-r--r--private/utils/ulib/inc/filestrm.hxx208
-rw-r--r--private/utils/ulib/inc/filter.hxx274
-rw-r--r--private/utils/ulib/inc/findleak.hxx47
-rw-r--r--private/utils/ulib/inc/fsnode.hxx1018
-rw-r--r--private/utils/ulib/inc/hmem.hxx152
-rw-r--r--private/utils/ulib/inc/ifsentry.hxx93
-rw-r--r--private/utils/ulib/inc/ifsserv.hxx109
-rw-r--r--private/utils/ulib/inc/iterator.hxx78
-rw-r--r--private/utils/ulib/inc/keyboard.hxx201
-rw-r--r--private/utils/ulib/inc/list.hxx115
-rw-r--r--private/utils/ulib/inc/listit.hxx118
-rw-r--r--private/utils/ulib/inc/machine.hxx77
-rw-r--r--private/utils/ulib/inc/mbstr.hxx434
-rw-r--r--private/utils/ulib/inc/mem.hxx50
-rw-r--r--private/utils/ulib/inc/membmgr.hxx258
-rw-r--r--private/utils/ulib/inc/message.hxx203
-rw-r--r--private/utils/ulib/inc/newdelp.hxx73
-rw-r--r--private/utils/ulib/inc/object.hxx343
-rw-r--r--private/utils/ulib/inc/path.hxx508
-rw-r--r--private/utils/ulib/inc/pipe.hxx121
-rw-r--r--private/utils/ulib/inc/pipestrm.hxx112
-rw-r--r--private/utils/ulib/inc/program.hxx146
-rw-r--r--private/utils/ulib/inc/prtstrm.hxx143
-rw-r--r--private/utils/ulib/inc/screen.hxx484
-rw-r--r--private/utils/ulib/inc/seqcnt.hxx83
-rw-r--r--private/utils/ulib/inc/smsg.hxx173
-rw-r--r--private/utils/ulib/inc/sortcnt.hxx79
-rw-r--r--private/utils/ulib/inc/sortlist.hxx153
-rw-r--r--private/utils/ulib/inc/sortlit.hxx98
-rw-r--r--private/utils/ulib/inc/spackmsg.hxx64
-rw-r--r--private/utils/ulib/inc/stack.hxx233
-rw-r--r--private/utils/ulib/inc/stream.hxx244
-rw-r--r--private/utils/ulib/inc/string.hxx464
-rw-r--r--private/utils/ulib/inc/stringar.hxx83
-rw-r--r--private/utils/ulib/inc/substrng.hxx632
-rw-r--r--private/utils/ulib/inc/system.hxx253
-rw-r--r--private/utils/ulib/inc/timeinfo.hxx631
-rw-r--r--private/utils/ulib/inc/ulib.hxx152
-rw-r--r--private/utils/ulib/inc/ulibcl.hxx40
-rw-r--r--private/utils/ulib/inc/ulibdef.hxx460
-rw-r--r--private/utils/ulib/inc/winnls.old292
-rw-r--r--private/utils/ulib/inc/wstring.hxx1250
-rw-r--r--private/utils/ulib/memtrace/makefile6
-rw-r--r--private/utils/ulib/memtrace/memtrace.c225
-rw-r--r--private/utils/ulib/memtrace/memtrace.def6
-rw-r--r--private/utils/ulib/memtrace/memtrace.h65
-rw-r--r--private/utils/ulib/memtrace/sources37
-rw-r--r--private/utils/ulib/src/achkmsg.cxx550
-rw-r--r--private/utils/ulib/src/arg.cxx2707
-rw-r--r--private/utils/ulib/src/array.cxx760
-rw-r--r--private/utils/ulib/src/arrayit.cxx261
-rw-r--r--private/utils/ulib/src/basesys.cxx249
-rw-r--r--private/utils/ulib/src/bitvect.cxx595
-rw-r--r--private/utils/ulib/src/buffer.cxx457
-rw-r--r--private/utils/ulib/src/bufstrm.cxx1041
-rw-r--r--private/utils/ulib/src/bytestrm.cxx189
-rw-r--r--private/utils/ulib/src/clasdesc.cxx124
-rw-r--r--private/utils/ulib/src/cmem.cxx107
-rw-r--r--private/utils/ulib/src/comm.cxx700
-rw-r--r--private/utils/ulib/src/contain.cxx38
-rw-r--r--private/utils/ulib/src/dir.cxx939
-rw-r--r--private/utils/ulib/src/error.cxx510
-rw-r--r--private/utils/ulib/src/file.cxx251
-rw-r--r--private/utils/ulib/src/filestrm.cxx937
-rw-r--r--private/utils/ulib/src/filter.cxx719
-rw-r--r--private/utils/ulib/src/fsnode.cxx459
-rw-r--r--private/utils/ulib/src/hmem.cxx247
-rw-r--r--private/utils/ulib/src/i386/dosttr.c76
-rw-r--r--private/utils/ulib/src/iterator.cxx63
-rw-r--r--private/utils/ulib/src/keyboard.cxx920
-rw-r--r--private/utils/ulib/src/list.cxx336
-rw-r--r--private/utils/ulib/src/listit.cxx45
-rw-r--r--private/utils/ulib/src/machine.cxx312
-rw-r--r--private/utils/ulib/src/makefile6
-rw-r--r--private/utils/ulib/src/makefile.inc4
-rw-r--r--private/utils/ulib/src/mbstr.cxx597
-rw-r--r--private/utils/ulib/src/mem.cxx8
-rw-r--r--private/utils/ulib/src/membmgr.cxx415
-rw-r--r--private/utils/ulib/src/message.cxx400
-rw-r--r--private/utils/ulib/src/newdel.cxx260
-rw-r--r--private/utils/ulib/src/object.cxx94
-rw-r--r--private/utils/ulib/src/path.cxx1449
-rw-r--r--private/utils/ulib/src/pch.cxx75
-rw-r--r--private/utils/ulib/src/pipe.cxx165
-rw-r--r--private/utils/ulib/src/pipestrm.cxx356
-rw-r--r--private/utils/ulib/src/prnthack.cxx16
-rw-r--r--private/utils/ulib/src/program.cxx453
-rw-r--r--private/utils/ulib/src/prtstrm.cxx392
-rw-r--r--private/utils/ulib/src/rtmsg.dbl387
-rw-r--r--private/utils/ulib/src/rtmsg.mc4851
-rw-r--r--private/utils/ulib/src/screen.cxx1998
-rw-r--r--private/utils/ulib/src/seqcnt.cxx82
-rw-r--r--private/utils/ulib/src/smsg.cxx607
-rw-r--r--private/utils/ulib/src/sortcnt.cxx37
-rw-r--r--private/utils/ulib/src/sortlist.cxx373
-rw-r--r--private/utils/ulib/src/sortlit.cxx316
-rw-r--r--private/utils/ulib/src/sources139
-rw-r--r--private/utils/ulib/src/spackmsg.cxx182
-rw-r--r--private/utils/ulib/src/stream.cxx512
-rw-r--r--private/utils/ulib/src/string.cxx84
-rw-r--r--private/utils/ulib/src/stringar.cxx210
-rw-r--r--private/utils/ulib/src/substrng.cxx1197
-rw-r--r--private/utils/ulib/src/system.cxx1339
-rw-r--r--private/utils/ulib/src/timeinfo.cxx1213
-rw-r--r--private/utils/ulib/src/ulib.cxx681
-rw-r--r--private/utils/ulib/src/ulib.rc10
-rw-r--r--private/utils/ulib/src/usa-ms.msg1588
-rw-r--r--private/utils/ulib/src/winnls.old183
-rw-r--r--private/utils/ulib/src/wstring.cxx1606
128 files changed, 52152 insertions, 0 deletions
diff --git a/private/utils/ulib/dirs b/private/utils/ulib/dirs
new file mode 100644
index 000000000..c4db5a979
--- /dev/null
+++ b/private/utils/ulib/dirs
@@ -0,0 +1,16 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+!ENDIF
+
+DIRS= src
diff --git a/private/utils/ulib/inc/achkmsg.hxx b/private/utils/ulib/inc/achkmsg.hxx
new file mode 100644
index 000000000..5c7f1f58f
--- /dev/null
+++ b/private/utils/ulib/inc/achkmsg.hxx
@@ -0,0 +1,164 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ achkmsg.hxx
+
+Abstract:
+
+
+Author:
+
+ Norbert P. Kusters (norbertk) 3-Jun-91
+
+--*/
+
+#if !defined( _AUTOCHECK_MESSAGE_DEFN_ )
+
+#define _AUTOCHECK_MESSAGE_DEFN_
+
+#include "message.hxx"
+#include "hmem.hxx"
+
+DECLARE_CLASS( AUTOCHECK_MESSAGE );
+
+class AUTOCHECK_MESSAGE : public MESSAGE {
+
+ public:
+
+ DECLARE_CONSTRUCTOR( AUTOCHECK_MESSAGE );
+
+ VIRTUAL
+ ~AUTOCHECK_MESSAGE(
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN BOOLEAN DotsOnly DEFAULT FALSE
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Set(
+ IN MSGID MsgId,
+ IN MESSAGE_TYPE MessageType DEFAULT NORMAL_MESSAGE,
+ IN ULONG MessageVisual DEFAULT NORMAL_VISUAL
+ );
+
+ VIRTUAL
+ BOOLEAN
+ DisplayV(
+ IN PCSTR Format,
+ IN va_list VarPointer
+ );
+
+ VIRTUAL
+ BOOLEAN
+ IsYesResponse(
+ IN BOOLEAN Default DEFAULT TRUE
+ );
+
+ VIRTUAL
+ PMESSAGE
+ Dup(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ IsLoggingEnabled(
+ );
+
+ VIRTUAL
+ VOID
+ SetLoggingEnabled(
+ IN BOOLEAN Enable DEFAULT TRUE
+ );
+
+ VIRTUAL
+ VOID
+ ResetLoggingIterator(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ QueryNextLoggedMessage(
+ OUT PFSTRING MessageText
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetDotsOnly(
+ IN BOOLEAN DotsState
+ );
+
+ VIRTUAL
+ BOOLEAN
+ WaitForUserSignal(
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy(
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ LogMessage(
+ PCWSTRING Message
+ );
+
+ HMEM _log_buffer;
+ ULONG _logged_chars;
+ ULONG _next_message_offset;
+ BOOLEAN _dots_only;
+ BOOLEAN _logging_enabled;
+
+ protected:
+
+ MSGID _msgid;
+
+};
+
+
+INLINE
+BOOLEAN
+AUTOCHECK_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 message id.
+
+Return Value:
+
+ FALSE - Failure.
+ TRUE - Success.
+
+--*/
+{
+ (void) MessageType;
+ (void) MessageVisual;
+ _msgid = MsgId;
+ return TRUE;
+}
+
+#endif // _AUTOCHECK_MESSAGE_DEFN_
diff --git a/private/utils/ulib/inc/arg.hxx b/private/utils/ulib/inc/arg.hxx
new file mode 100644
index 000000000..50babee11
--- /dev/null
+++ b/private/utils/ulib/inc/arg.hxx
@@ -0,0 +1,1668 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ARGUMENT_LEXEMIZER
+
+Abstract:
+
+
+ This module contains the definition for the ARGUMENT_LEXEMIZER
+ class. The argument lexemizer is the engine of command-line
+ argument parsing.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+Environment:
+
+ user
+
+Notes:
+
+ The argument lexemizer divides the command line arguments into
+ a series of lexemes, which are then matched argument patterns.
+
+ The way in which the command line is lexed is determined by
+ a few parameters, which are user-settable:
+
+ * White space
+ * Switch characters
+ * Separators
+ * Start of quote
+ * End of quote
+ * Multiple switches (i.e. what switches can be grouped)
+ * Metacharacters (used to escape the following character)
+ * Case sensitivity for switches
+ * "Glomming" of switches (see note at "GLOMMING").
+ * No space between tokens (specifically for xcopy)
+
+ The class provides defaults for all of the above.
+
+ After the command line has been lexed, the lexemizer is
+ given an ARRAY of argument objects. Each argument provides:
+
+ 1.- A pattern to match
+ 2.- A method for setting the argument value
+
+ The lexemizer will try to match each lexeme agains all the
+ arguments. When a match is found, the corresponding argument
+ value is set, the lexeme is consumed and it proceeds with the
+ next lexeme.
+
+ Schematically:
+
+
+
+
+ < Command Line >
+
+ |
+ | Argument
+ | ARRAY
+ v __________
+ +-----------+ [__________]
+ Settings--->| Lexemizer |<-------> [__________]
+ +-----------+ ^ [__________]
+ |
+ |
+ v
+ ( Matcher )
+
+
+
+
+ The matcher will try to match the lexeme provided by the
+ lexemizer and the pattern provided by the argument. If they
+ match, then the matcher asks the argument to set its value
+ (at this point, the argument might consume more lexemes from
+ the lexemizer). If the argument does not set its value, then
+ we will consider this a "no match", and the lexemizer will
+ try to match the lexeme against the following argument in
+ the ARRAY.
+
+ So, this is how to use this thing:
+
+
+ 1.- Initialize the lexemizer (with an empty ARRAY object):
+
+
+ ARGUMENT_LEXEMIZER ArgLex;
+ ARRAY SomeEmtpyArray;
+
+ SomeEmtryArray->Initialize();
+
+ ArgLex->Initialize(&SomeEmptyArray);
+
+
+
+ 2.- If we don't like some default, we change it:
+
+ ArgLex->PutSwitches("-/");
+ ArgLex->PutMetaCharacters("^");
+
+
+
+ 3.- Prepare the lexemizer for parsing. If we don't provide
+ a command line, it will take it from the environment.
+
+ ArgLex->PrepareToParse();
+
+
+
+ 4.- Define the arguments that our application will accept.
+ Initialize them with the pattern that they will match.
+ Put the argument in an ARRAY object. Note that the order
+ in which the arguments are in the array is important, since
+ that is the order in which they are matched.
+
+
+ ARRAY ArrayOfArg;
+ FLAG_ARGUMENT ArgRecursive; // Recursive flag
+ FLAG_ARGUMENT ArgVerbose; // Verbose flag
+
+ ArrayOfArg->Initialize();
+
+ ArgRecursive->Initialize("/R");
+ ArgVerbose->Initialize("/V");
+
+ ArrayOfArg->Put(&ArgRecursive);
+ ArrayOfArg->Put(&ArgVerbose);
+
+
+ 5.- Now let the lexemizer parse the arguments. If the parsing
+ returns TRUE, then all the command line was parsed correctly,
+ if it returns FALSE, then an error was found (e.g. invalid
+ argument):
+
+ if (!(ArgLex->DoParsing(&ArrayOfArg))) {
+
+ //
+ // Error, display usage
+ //
+ Usage();
+
+ }
+
+
+
+ 6.- Voila! We can now query our arguments for their value:
+
+
+ .
+ .
+ .
+ if (ArgRecursive->QueryFlag()) {
+ .
+ .
+ Do_recursive_stuff();
+ .
+ .
+
+
+
+ Warnings:
+
+ * The strings passed when setting options (such as switch
+ characters) have to remain in scope while the lexemizer is
+ being used, because the lexemizer keeps pointers to them.
+
+ * If after parsing the command line you want to change some
+ setting and parse the line again, you have to call the
+ PrepareToParse method after changing the setting and before
+ calling the DoParsing method. Note that in this case you
+ might want to use "fresh" argument objects, because most
+ arguments can only be set once.
+
+ * The method for querying the value of an argument is
+ argument-specific (no virtual method is provided).
+
+
+ * GLOMMING (mjb): This is something of a kludge I added to
+ allow xcopy to take switch arguments glommed together, as
+ in "/s/f/i/d" while not being confused by date arguments
+ such as "/d:8/24/95". This is handled similarly to the
+ "multiple switches"; only switches that are allowed to be
+ grouped may be glommed.
+
+ * NoSpcBetweenDstAndSwitch: This is a kludge to allow xcopy
+ to accept a destination path and a switch with no space
+ in between. The trick is to avoid being confused by date
+ arguments such as "/d:8/24/95".
+
+Revision History:
+
+
+--*/
+
+
+#include "array.hxx"
+#include "wstring.hxx"
+
+#if !defined( _AUTOCHECK_ )
+#include "timeinfo.hxx"
+#include "path.hxx"
+#endif
+
+
+//
+// Forward references
+//
+
+
+#if !defined (_ARGUMENT_LEXEMIZER_)
+
+#define _ARGUMENT_LEXEMIZER_
+
+DECLARE_CLASS( ARGUMENT_LEXEMIZER );
+DECLARE_CLASS( ARGUMENT );
+
+// Type of a pointer to the match function
+//
+typedef BOOLEAN (*PMATCHFUNCTION)(OUT PARGUMENT, OUT PARGUMENT_LEXEMIZER);
+
+class ARGUMENT_LEXEMIZER : public OBJECT {
+
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( ARGUMENT_LEXEMIZER );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~ARGUMENT_LEXEMIZER(
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PARRAY LexemeArray
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DoParsing (
+ IN PARRAY ArgumentArray
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTRING
+ GetLexemeAt (
+ IN ULONG Index
+ );
+
+ NONVIRTUAL
+ ULONG
+ IncrementConsumedCount (
+ IN ULONG HowMany DEFAULT 1
+ );
+
+ VOID
+ PutEndQuotes (
+ IN PCWSTRING QuoteChars
+ );
+
+ VOID
+ PutEndQuotes (
+ IN PCSTR QuoteChars
+ );
+
+ NONVIRTUAL
+ VOID
+ PutMetaChars (
+ IN PCSTR MetaChars
+ );
+
+ NONVIRTUAL
+ VOID
+ PutMetaChars (
+ IN PCWSTRING MetaChars
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ PutMultipleSwitch (
+ IN PCSTR MultipleSwitch
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ PutMultipleSwitch (
+ IN PCWSTRING MultipleSwitch
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ PutSeparators (
+ IN PCSTR Separators
+ );
+
+ NONVIRTUAL
+ VOID
+ PutSeparators (
+ IN PCWSTRING Separators
+ );
+
+ VOID
+ PutStartQuotes (
+ IN PCSTR QuoteChars
+ );
+
+ VOID
+ PutStartQuotes (
+ IN PCWSTRING QuoteChars
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ PutSwitches (
+ IN PCSTR Switches
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ PutSwitches (
+ IN PCWSTRING Switches
+ );
+
+ NONVIRTUAL
+ PCWSTRING
+ GetSwitches (
+ );
+
+ NONVIRTUAL
+ CHNUM
+ QueryCharPos (
+ IN ULONG LexemeNumber
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryConsumedCount (
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryLexemeCount (
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTRING
+ QueryInvalidArgument (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ PrepareToParse (
+ IN PWSTRING CommandLine DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ SetCaseSensitive (
+ BOOLEAN CaseSensitive
+ );
+
+ NONVIRTUAL
+ PCWSTRING
+ GetCmdLine(
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ SetAllowSwitchGlomming (
+ BOOLEAN AllowGlomming
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ SetNoSpcBetweenDstAndSwitch (
+ BOOLEAN NoSpcBetweenDstAndSwitch
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ PutCharPos (
+ IN ULONG Position,
+ IN CHNUM CharPos
+ );
+
+ PARRAY _parray; // Array of lexemes
+ PCHNUM _CharPos; // Character positions
+ ULONG _CharPosSize; // Size of _CharPos array
+ ULONG _ConsumedCount; // Lexemes consumed
+ ULONG _LexemeCount; // Total lexemes
+ DSTRING _WhiteSpace; // White space characters
+ DSTRING _SwitchChars; // Switch characters
+ DSTRING _Separators; // Separator characters
+ DSTRING _StartQuote; // Start of quote characters
+ DSTRING _SeparatorString; // All characters which cause separation
+ DSTRING _EndQuote; // End of quote characters
+ DSTRING _MultipleSwitches; // "Groupable" switches
+ DSTRING _MetaChars; // Meta-characters
+ BOOLEAN _CaseSensitive; // TRUE if case sensitive
+ BOOLEAN _AllowGlomming; // TRUE if switch glomming allowed
+ BOOLEAN _NoSpcBetweenDstAndSwitch; // TRUE if no space is required
+ // between tokens
+
+ WCHAR _Switch; // Switch character
+ DSTRING _CmdLine; // The entire command line
+
+};
+
+
+INLINE
+PCWSTRING
+ARGUMENT_LEXEMIZER::GetSwitches (
+ )
+
+/*++
+
+Routine Description:
+
+ Returns a ptr to a string containing the valid switch chars
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Returns string containing the valid switch chars
+
+--*/
+{
+ return &_SwitchChars;
+}
+
+
+INLINE
+ULONG
+ARGUMENT_LEXEMIZER::IncrementConsumedCount (
+ IN ULONG HowMany
+ )
+/*++
+
+Routine Description:
+
+ Increments count of Lexemes consumed
+
+Arguments:
+
+ HowMany - Supplies by how many to increment.
+
+Return Value:
+
+ New count
+
+--*/
+{
+ return (_ConsumedCount += HowMany);
+}
+
+
+INLINE
+VOID
+ARGUMENT_LEXEMIZER::PutEndQuotes (
+ IN PCSTR QuoteChars
+ )
+/*++
+
+Routine Description:
+
+ Initializes the ending quote chars
+
+Arguments:
+
+ QuoteChars - Supplies pointer to string of close quote chars
+
+Return Value:
+
+ none
+--*/
+{
+ DebugPtrAssert( QuoteChars );
+ _EndQuote.Initialize(QuoteChars);
+}
+
+
+INLINE
+VOID
+ARGUMENT_LEXEMIZER::PutEndQuotes (
+ IN PCWSTRING QuoteChars
+ )
+/*++
+
+Routine Description:
+
+ Initializes the ending quote chars
+
+Arguments:
+
+ QuoteChars - Supplies pointer to string of close quote chars
+
+Return Value:
+
+ none
+--*/
+{
+ DebugPtrAssert( QuoteChars );
+ _EndQuote.Initialize(QuoteChars);
+}
+
+
+INLINE
+VOID
+ARGUMENT_LEXEMIZER::PutStartQuotes (
+ IN PCSTR QuoteChars
+ )
+/*++
+
+Routine Description:
+
+ Initializes the starting quote chars
+
+Arguments:
+
+ QuoteChars - Supplies pointer to string of open quote chars
+
+Return Value:
+
+ none
+--*/
+{
+ DebugPtrAssert( QuoteChars );
+ _StartQuote.Initialize(QuoteChars);
+}
+
+
+INLINE
+VOID
+ARGUMENT_LEXEMIZER::PutStartQuotes (
+ IN PCWSTRING QuoteChars
+ )
+/*++
+
+Routine Description:
+
+ Initializes the starting quote chars
+
+Arguments:
+
+ QuoteChars - Supplies pointer to string of open quote chars
+
+Return Value:
+
+ none
+--*/
+{
+ DebugPtrAssert( QuoteChars );
+ _StartQuote.Initialize(QuoteChars);
+}
+
+
+INLINE
+ULONG
+ARGUMENT_LEXEMIZER::QueryConsumedCount (
+ )
+/*++
+
+Routine Description:
+
+ Returns number of lexemes consumed
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Number of lexemes consumed
+
+--*/
+{
+ return _ConsumedCount;
+}
+
+
+INLINE
+ULONG
+ARGUMENT_LEXEMIZER::QueryLexemeCount (
+ ) CONST
+/*++
+
+Routine Description:
+
+ Returns total number of lexemes
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Total number of lexemes
+
+--*/
+{
+ return _LexemeCount;
+}
+
+INLINE
+PCWSTRING
+ARGUMENT_LEXEMIZER::GetCmdLine(
+ ) CONST
+/*++
+
+Routine Description:
+
+ Returns the original commmand line.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The original command line.
+
+--*/
+{
+ return &_CmdLine;
+}
+
+
+#endif // _ARGUMENT_LEXEMIZER_
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ARGUMENT
+
+Abstract:
+
+ Base class for arguments.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+[Environment:]
+
+ optional-environment-info (e.g. kernel mode only...)
+
+Notes:
+
+
+
+Revision History:
+
+--*/
+
+#if !defined (_ARGUMENT_)
+
+#define _ARGUMENT_
+
+
+class ARGUMENT : public OBJECT {
+
+ public:
+
+ DECLARE_CONSTRUCTOR( ARGUMENT );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PSTR Pattern
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PWSTRING Pattern
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTRING
+ GetLexeme (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTRING
+ GetPattern (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsValueSet (
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetIfMatch (
+ OUT PARGUMENT_LEXEMIZER ArgumentLexemizer,
+ IN BOOLEAN CaseSensitive
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetValue (
+ IN PWSTRING Arg,
+ IN CHNUM chnIdx,
+ IN CHNUM chnEnd,
+ IN PARGUMENT_LEXEMIZER ArgumentLexemizer
+ );
+
+
+ protected:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ BOOLEAN _fValueSet; // TRUE when value set
+ PWSTRING _Lexeme; // Matched Lexeme
+ DSTRING _Pattern; // Pattern
+
+};
+
+#endif // _ARGUMENT
+
+
+
+
+
+
+
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ FLAG_ARGUMENT
+
+Abstract:
+
+ Argument class for flags and switches.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+Revision History:
+
+--*/
+
+#if !defined ( _FLAG_ARGUMENT_ )
+
+#define _FLAG_ARGUMENT_
+
+DECLARE_CLASS( FLAG_ARGUMENT );
+
+class FLAG_ARGUMENT : public ARGUMENT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( FLAG_ARGUMENT );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PSTR Pattern
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PWSTRING Pattern
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetValue (
+ IN PWSTRING Arg,
+ IN CHNUM chnIdx,
+ IN CHNUM chnEnd,
+ IN PARGUMENT_LEXEMIZER ArgumentLexemizer
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ QueryFlag (
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ BOOLEAN _flag; // TRUE if flag (switch) set
+
+};
+
+INLINE
+BOOLEAN
+FLAG_ARGUMENT::QueryFlag (
+ )
+/*++
+
+Routine Description:
+
+ Returns TRUE if flag set
+
+Arguments:
+
+ none
+
+Return Value:
+
+ TRUE if flag set. FALSE otherwise
+
+--*/
+{
+ return _flag;
+}
+
+#endif // _FLAG_ARGUMENT_
+
+
+
+
+
+
+
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ STRING_ARGUMENT
+
+Abstract:
+
+ Argument class for strings.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+Revision History:
+
+--*/
+
+#if !defined ( _STRING_ARGUMENT_ )
+
+#define _STRING_ARGUMENT_
+
+DECLARE_CLASS( STRING_ARGUMENT );
+
+class STRING_ARGUMENT : public ARGUMENT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( STRING_ARGUMENT );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ ~STRING_ARGUMENT(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PSTR Pattern
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PWSTRING Pattern
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ GetString (
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetValue (
+ IN PWSTRING Arg,
+ IN CHNUM chnIdx,
+ IN CHNUM chnEnd,
+ IN PARGUMENT_LEXEMIZER ArgumentLexemizer
+ );
+
+ protected:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+
+ PWSTRING _String; // Pointer to the string
+
+};
+
+INLINE
+PWSTRING
+STRING_ARGUMENT::GetString (
+ )
+/*++
+
+Routine Description:
+
+ Returns pointer to the string
+
+Arguments:
+
+ none
+
+Return Value:
+
+ pointer to the string
+
+--*/
+{
+ DebugAssert( _fValueSet );
+
+ return _String;
+}
+
+#endif // _STRING_ARGUMENT_
+
+
+
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ LONG_ARGUMENT
+
+Abstract:
+
+ Argument class for long integers.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+Revision History:
+
+--*/
+
+#if !defined ( _LONG_ARGUMENT_ )
+
+#define _LONG_ARGUMENT_
+
+DECLARE_CLASS( LONG_ARGUMENT );
+
+class LONG_ARGUMENT : public ARGUMENT {
+
+ public:
+
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( LONG_ARGUMENT );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PSTR Pattern
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PWSTRING Pattern
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetValue (
+ IN PWSTRING Arg,
+ IN CHNUM chnIdx,
+ IN CHNUM chnEnd,
+ IN PARGUMENT_LEXEMIZER ArgumentLexemizer
+ );
+
+ NONVIRTUAL
+ LONG
+ QueryLong (
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ LONG _value; // Long value
+
+};
+
+INLINE
+LONG
+LONG_ARGUMENT::QueryLong (
+ )
+/*++
+
+Routine Description:
+
+ Returns value of the long argument
+
+Arguments:
+
+ none
+
+Return Value:
+
+ value of the argument
+
+--*/
+{
+ DebugAssert( _fValueSet );
+
+ return _value;
+}
+
+#endif // _LONG_ARGUMENT_
+
+
+
+#if !defined( _AUTOCHECK_ )
+
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ PATH_ARGUMENT
+
+Abstract:
+
+ Argument class for paths.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+Revision History:
+
+--*/
+
+#if !defined( _PATH_ARGUMENT_ )
+
+#define _PATH_ARGUMENT_
+
+DECLARE_CLASS( PATH_ARGUMENT );
+
+class PATH_ARGUMENT : public ARGUMENT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( PATH_ARGUMENT );
+
+ ULIB_EXPORT
+ NONVIRTUAL
+ ~PATH_ARGUMENT (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PSTR Pattern,
+ IN BOOLEAN Canonicalize DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PWSTRING Pattern,
+ IN BOOLEAN Canonicalize DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ PPATH
+ GetPath (
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetValue (
+ IN PWSTRING Arg,
+ IN CHNUM chnIdx,
+ IN CHNUM chnEnd,
+ IN PARGUMENT_LEXEMIZER ArgumentLexemizer
+ );
+
+ protected:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+
+ PPATH _Path; // Pointer to the path
+ BOOLEAN _Canonicalize; // Canonicalization flag
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Destroy (
+ );
+
+};
+
+INLINE
+PPATH
+PATH_ARGUMENT::GetPath (
+ )
+/*++
+
+Routine Description:
+
+ Returns pointer to the path
+
+Arguments:
+
+ none
+
+Return Value:
+
+ pointer to the path
+
+--*/
+{
+ DebugAssert( _fValueSet );
+
+ return _Path;
+}
+
+#endif // _PATH_ARGUMENT_
+
+
+#endif // _AUTOCHECK_
+
+
+
+#if !defined( _AUTOCHECK_ )
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ MULTIPLE_PATH_ARGUMENT
+
+Abstract:
+
+ Provide for access to command line arguments that are file or path names.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+Environment:
+
+ user
+
+Revision History:
+
+
+--*/
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ MULTIPLE_PATH_ARGUMENT
+
+Abstract:
+
+ Hold multiple file names on command line.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+
+Revision History:
+
+--*/
+
+#if !defined ( _MULTIPLE_PATH_ARGUMENT_ )
+
+#define _MULTIPLE_PATH_ARGUMENT_
+
+DECLARE_CLASS( MULTIPLE_PATH_ARGUMENT );
+
+class MULTIPLE_PATH_ARGUMENT : public PATH_ARGUMENT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( MULTIPLE_PATH_ARGUMENT );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ ~MULTIPLE_PATH_ARGUMENT (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PSTR Pattern,
+ IN BOOLEAN Canonicalize DEFAULT FALSE,
+ IN BOOLEAN ExpandWildCards DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PWSTRING Pattern,
+ IN BOOLEAN Canonicalize DEFAULT FALSE,
+ IN BOOLEAN ExpandWildCards DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ PCWSTRING
+ GetLexemeThatFailed (
+ );
+
+ NONVIRTUAL
+ PARRAY
+ GetPathArray (
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryPathCount (
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetValue (
+ IN PWSTRING pwcArg,
+ IN CHNUM chnIdx,
+ IN CHNUM chnEnd,
+ IN PARGUMENT_LEXEMIZER ArgumentLexemizer
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ WildCardExpansionFailed (
+ );
+
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy (
+ );
+
+ PARRAY _PathArray;
+ ULONG _PathCount;
+ BOOLEAN _ExpandWildCards;
+ BOOLEAN _WildCardExpansionFailed;
+ DSTRING _LexemeThatFailed;
+};
+
+
+INLINE
+PCWSTRING
+MULTIPLE_PATH_ARGUMENT::GetLexemeThatFailed (
+ )
+/*++
+
+Routine Description:
+
+ Gets the lexeme that failed in case of a wildcard expansion failure
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Pointer to the lexeme that failed
+
+--*/
+{
+ return _WildCardExpansionFailed ? (PCWSTRING)&_LexemeThatFailed : NULL;
+}
+
+
+INLINE
+PARRAY
+MULTIPLE_PATH_ARGUMENT::GetPathArray (
+ )
+/*++
+
+Routine Description:
+
+ Returns pointer to the path array
+
+Arguments:
+
+ none
+
+Return Value:
+
+ pointer to the path array
+
+--*/
+{
+ return _PathArray;
+}
+
+INLINE
+ULONG
+MULTIPLE_PATH_ARGUMENT::QueryPathCount (
+ )
+/*++
+
+Routine Description:
+
+ Returns number of paths in the array
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Number of paths in the array
+
+--*/
+{
+ return _PathCount;
+}
+
+
+
+INLINE
+BOOLEAN
+MULTIPLE_PATH_ARGUMENT::WildCardExpansionFailed (
+ )
+/*++
+
+Routine Description:
+
+ Tells the caller if wildcard expansion failed
+
+Arguments:
+
+ none
+
+Return Value:
+
+ BOOLEAN - TRUE if wildcard expansion failed
+
+--*/
+{
+ return _WildCardExpansionFailed;
+}
+
+#endif // _MULTIPLE_PATH_ARGUMENT_
+
+
+#endif // _AUTOCHECK_
+
+
+
+#if !defined( _AUTOCHECK_ )
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ TIMEINFO_ARGUMENT
+
+Abstract:
+
+ Argument class for time information.
+
+Author:
+
+ Ramon Juan San Andres (ramonsa) May-15-1991
+
+Revision History:
+
+--*/
+
+#if !defined ( _TIMEINFO_ARGUMENT_ )
+
+#define _TIMEINFO_ARGUMENT_
+
+DECLARE_CLASS( TIMEINFO_ARGUMENT );
+
+class TIMEINFO_ARGUMENT : public ARGUMENT {
+
+ public:
+
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( TIMEINFO_ARGUMENT );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ ~TIMEINFO_ARGUMENT(
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PSTR Pattern
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PWSTRING Pattern
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetValue (
+ IN PWSTRING Arg,
+ IN CHNUM chnIdx,
+ IN CHNUM chnEnd,
+ IN PARGUMENT_LEXEMIZER ArgumentLexemizer
+ );
+
+ NONVIRTUAL
+ PTIMEINFO
+ GetTimeInfo (
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ PTIMEINFO _TimeInfo; // Time info.
+
+};
+
+INLINE
+PTIMEINFO
+TIMEINFO_ARGUMENT::GetTimeInfo (
+ )
+/*++
+
+Routine Description:
+
+ Returns pointer to the time information
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Pointer to time info.
+
+--*/
+{
+ DebugAssert( _fValueSet );
+
+ return _TimeInfo;
+}
+
+#endif // _TIMEINFO_ARGUMENT_
+
+
+
+#endif // _AUTOCHECK_
+
+
+
+
+#if !defined( _AUTOCHECK_ )
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ TIMEINFO_ARGUMENT
+
+Abstract:
+
+ Argument class for time information.
+
+Author:
+
+ Ramon Juan San Andres (ramonsa) May-15-1991
+
+Revision History:
+
+--*/
+
+#if !defined ( _REST_OF_LINE_ARGUMENT_ )
+
+#define _REST_OF_LINE_ARGUMENT_
+
+DECLARE_CLASS( REST_OF_LINE_ARGUMENT );
+
+class REST_OF_LINE_ARGUMENT : public ARGUMENT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( REST_OF_LINE_ARGUMENT );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetIfMatch(
+ IN OUT PARGUMENT_LEXEMIZER ArgumentLexemizer,
+ IN BOOLEAN CaseSensitive
+ );
+
+ NONVIRTUAL
+ PCWSTRING
+ GetRestOfLine(
+ ) CONST;
+
+ private:
+
+ DSTRING _RestOfLine;
+
+};
+
+
+INLINE
+PCWSTRING
+REST_OF_LINE_ARGUMENT::GetRestOfLine(
+ ) CONST
+/*++
+
+Routine Description:
+
+ Returns pointer to the macro argument.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ A pointer to the macro argument.
+
+--*/
+{
+ DebugAssert( _fValueSet );
+
+ return &_RestOfLine;
+}
+
+#endif // _REST_OF_LINE_ARGUMENT_
+
+
+
+#endif // _AUTOCHECK_
+
diff --git a/private/utils/ulib/inc/array.hxx b/private/utils/ulib/inc/array.hxx
new file mode 100644
index 000000000..82626b173
--- /dev/null
+++ b/private/utils/ulib/inc/array.hxx
@@ -0,0 +1,390 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ array.hxx
+
+Abstract:
+
+ This module contains the declaration for the ARRAY class.
+
+ ARRAY is a concrete implementation of a dynamic (i.e. growable) array
+ derived from the abstract class SORTABLE_CONTAINER.
+
+ ARRAY's support one 'writer' (i.e. one client poutting OBJECTs into
+ the ARRAY) and multiple readers via an ITERATOR. It is the client's
+ responsibility to synchronize multiple writers.
+
+ The ARRAY does not contain holes, i.e. all elements of the array (up
+ to QueryMemberCount() ) have objects.
+
+
+Author:
+
+ David J. Gilman (davegi) 31-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+
+--*/
+
+#if ! defined( _ARRAY_ )
+
+#define _ARRAY_
+
+#include "sortcnt.hxx"
+
+//
+// Forward references
+//
+DECLARE_CLASS( ARRAY );
+DECLARE_CLASS( ARRAY_ITERATOR );
+DECLARE_CLASS( SORTED_LIST );
+
+//
+// Pointer to array of POBJECTs
+//
+typedef POBJECT* PPOBJECT;
+
+//
+// Default values for an ARRAY object.
+//
+// - Capacity is the total number of elements that can be stored in an ARRAY
+// - CapacityIncrement is the number of elemnts that the ARRAY's Capacity
+// will be increased by when it's Capacity is exceeded
+//
+CONST ULONG DefaultCapacity = 50;
+CONST ULONG DefaultCapacityIncrement = 25;
+
+//
+// Invalid index within the array
+//
+CONST ULONG INVALID_INDEX = (ULONG)(-1);
+
+
+class ARRAY : public SORTABLE_CONTAINER {
+
+ friend ARRAY_ITERATOR;
+ friend SORTED_LIST;
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( ARRAY );
+
+ DECLARE_CAST_MEMBER_FUNCTION( ARRAY );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~ARRAY(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN ULONG Capacity DEFAULT DefaultCapacity,
+ IN ULONG CapacityIncrement DEFAULT DefaultCapacityIncrement
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DeleteAllMembers(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetAt(
+ IN ULONG Index
+ ) CONST;
+
+ VIRTUAL
+ ULONG
+ GetMemberIndex(
+ IN POBJECT Object
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ ULIB_EXPORT
+ Put(
+ IN OUT POBJECT Member
+ );
+
+ VIRTUAL
+ BOOLEAN
+ PutAt(
+ IN OUT POBJECT Member,
+ IN ULONG Index
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryCapacity (
+ ) CONST;
+
+ NONVIRTUAL
+ ULONG
+ QueryCapacityIncrement (
+ ) CONST;
+
+ VIRTUAL
+ ULIB_EXPORT
+ PITERATOR
+ QueryIterator(
+ ) CONST;
+
+ VIRTUAL
+ ULONG
+ QueryMemberCount(
+ ) CONST;
+
+ VIRTUAL
+ ULIB_EXPORT
+ POBJECT
+ Remove(
+ IN OUT PITERATOR Position
+ );
+
+ VIRTUAL
+ POBJECT
+ RemoveAt(
+ IN ULONG Index
+ );
+
+ NONVIRTUAL
+ ULONG
+ SetCapacity (
+ IN ULONG Capacity
+ );
+
+ NONVIRTUAL
+ VOID
+ SetCapacityIncrement (
+ IN ULONG CapacityIncrement
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Sort(
+ IN BOOLEAN Ascending DEFAULT TRUE
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Insert(
+ IN OUT POBJECT Member,
+ IN ULONG Index
+ );
+
+
+ protected:
+
+ STATIC
+ LONG
+ CompareAscDesc(
+ IN POBJECT Object1,
+ IN POBJECT Object2,
+ IN BOOLEAN Ascending DEFAULT TRUE
+ );
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ PPOBJECT
+ GetObjectArray (
+ );
+
+ private:
+
+ NONVIRTUAL
+ ULONG
+ SetArrayCapacity(
+ IN ULONG NumberOfElements
+ );
+
+ STATIC
+ int _CRTAPI1
+ CompareAscending (
+ IN const void * Object1,
+ IN const void * Object2
+ );
+
+ STATIC
+ int _CRTAPI1
+ CompareDescending (
+ IN const void * Object1,
+ IN const void * Object2
+ );
+
+ PPOBJECT _ObjectArray; // Array of pointers to OBJECTs
+ ULONG _PutIndex; // Put Index
+ ULONG _Capacity; // Capacity of the array
+ ULONG _CapacityIncrement; // Increment
+
+#if DBG==1
+ ULONG _IteratorCount; // Count of iterators
+#endif
+
+};
+
+
+INLINE
+ULONG
+ARRAY::QueryCapacity (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the current capacity (maximum number of members) of the ARRAY.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ULONG - Current capacity.
+
+
+--*/
+
+{
+ return( _Capacity );
+}
+
+
+
+INLINE
+ULONG
+ARRAY::QueryCapacityIncrement (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the current capacity increment (realloc amount) of the ARRAY.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ULONG - Current capacity increment.
+
+--*/
+
+{
+ return( _CapacityIncrement );
+}
+
+
+
+INLINE
+VOID
+ARRAY::SetCapacityIncrement (
+ IN ULONG CapacityIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ Set the capacity incement value.
+
+Arguments:
+
+ CapacityIncrement - Supplies the new value for the capacity increment.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ _CapacityIncrement = CapacityIncrement;
+}
+
+
+
+INLINE
+LONG
+ARRAY::CompareAscDesc(
+ IN POBJECT Object1,
+ IN POBJECT Object2,
+ IN BOOLEAN Ascending
+ )
+/*++
+
+Routine Description:
+
+ Compares two object accordint to an Ascending flag
+
+Arguments:
+
+ Object1 - Supplies first object
+ Object2 - Supplies second object
+ Ascending - Supplies ascending flag
+
+Return Value:
+
+ LONG - If Ascending:
+ <0 if Object1 is less that Object2
+ 0 if Object1 is equal to Object2
+ >0 if Object1 is greater than Object2
+
+ If !Ascending:
+ <0 if Object2 is less that Object1
+ 0 if Object2 is equal to Object1
+ >0 if Object2 is greater than Object1
+
+
+--*/
+{
+ return ( Ascending ? CompareAscending( &Object1, &Object2 ) :
+ CompareDescending( &Object1, &Object2) );
+}
+
+
+
+INLINE
+PPOBJECT
+ARRAY::GetObjectArray (
+ )
+/*++
+
+Routine Description:
+
+ Obtains pointer to the array of objects
+
+Arguments:
+
+ None
+
+Return Value:
+
+ PPOBJECT - Pointer to array of objects
+
+--*/
+
+{
+ return _ObjectArray;
+}
+
+#endif // _ARRAY_
+
diff --git a/private/utils/ulib/inc/arrayit.hxx b/private/utils/ulib/inc/arrayit.hxx
new file mode 100644
index 000000000..1d75de789
--- /dev/null
+++ b/private/utils/ulib/inc/arrayit.hxx
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ arrayit.hxx
+
+Abstract:
+
+ This module contains the declaration for the ARRAY_ITERATOR class.
+ ARRAY_ITERATOR is a concrete implementation derived from the abstarct
+ ITERATOR class. It is used to 'read' (iterate) over an ARRAY object.
+ It has no public constructor and therefore can only be queried from an
+ ARRAY object. It is the client's responsibility to detsroy
+ ARRAY_ITERATORs when they are done. ARRAY_ITERATORs maintain the currency
+ for reading an ARRAY in order.
+
+Author:
+
+ David J. Gilman (davegi) 29-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _ARRAY_ITERATOR_ )
+
+#define _ARRAY_ITERATOR_
+
+#include "iterator.hxx"
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( ARRAY );
+DECLARE_CLASS( ARRAY_ITERATOR );
+
+
+class ARRAY_ITERATOR : public ITERATOR {
+
+ friend ARRAY;
+
+ public:
+
+ VIRTUAL
+ ~ARRAY_ITERATOR(
+ );
+
+ VIRTUAL
+ VOID
+ Reset(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetCurrent(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetNext(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetPrevious(
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryCurrentIndex(
+ );
+
+ protected:
+
+ DECLARE_CAST_MEMBER_FUNCTION( ARRAY_ITERATOR );
+ DECLARE_CONSTRUCTOR( ARRAY_ITERATOR );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN OUT PARRAY Array
+ );
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ private:
+
+ PARRAY _Array; // Array
+ ULONG _CurrentIndex; // Current index
+
+};
+
+
+INLINE
+ULONG
+ARRAY_ITERATOR::QueryCurrentIndex(
+ )
+/*++
+
+Routine Description:
+
+ Obtains the current index
+
+Arguments:
+
+ None
+
+Return Value:
+
+ ULONG - The current index
+
+--*/
+
+{
+ return _CurrentIndex;
+}
+#endif // _ARRAY_ITERATOR_
diff --git a/private/utils/ulib/inc/basesys.hxx b/private/utils/ulib/inc/basesys.hxx
new file mode 100644
index 000000000..8d4409016
--- /dev/null
+++ b/private/utils/ulib/inc/basesys.hxx
@@ -0,0 +1,57 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ basesys.hxx
+
+Abstract:
+
+ BASE_SYSTEM is the a base class for SYSTEM. It is created so
+ encapsulate the methods on SYSTEM that are used for AUTOCHK.
+
+Author:
+
+ David J. Gilman (davegi) 13-Jan-1991
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if !defined( _BASE_SYSTEM_DEFN_ )
+
+#define _BASE_SYSTEM_DEFN_
+
+#include "message.hxx"
+
+
+class BASE_SYSTEM {
+
+ public:
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ QueryResourceString(
+ OUT PWSTRING ResourceString,
+ IN MSGID MsgId,
+ IN PCSTR Format ...
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ QueryResourceStringV(
+ OUT PWSTRING ResourceString,
+ IN MSGID MsgId,
+ IN PCSTR Format,
+ IN va_list VarPointer
+ );
+
+};
+
+
+#endif // _BASE_SYSTEM_DEFN_
diff --git a/private/utils/ulib/inc/bitvect.hxx b/private/utils/ulib/inc/bitvect.hxx
new file mode 100644
index 000000000..1b851740b
--- /dev/null
+++ b/private/utils/ulib/inc/bitvect.hxx
@@ -0,0 +1,447 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ bitvect.hxx
+
+Abstract:
+
+ This module contains the definition for the BITVECTOR class. BITVECTOR
+ is a concrete class which implements a bit array.
+
+Author:
+
+ David J. Gilman (davegi) 13-Jan-1991
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+ BITVECTOR is an implementation of a general purpose bit
+ vector. It is based around an abstract type called PT
+ (Primitive Type) to increase it's portability. BITVECTORs
+ can be created of arbitrary size. If required they will
+ allocate memory to maintain the bits or will use a memory
+ buffer supplied by the client. This allows the client to
+ superimpose a bit vector onto a predefined buffer (e.g. onto
+ a SECBUF).
+
+--*/
+#if ! defined ( _BITVECTOR_ )
+
+#define _BITVECTOR_
+
+DECLARE_CLASS( BITVECTOR );
+
+
+// extern ERRSTACK *perrstk; // pointer to error stack
+
+//
+// BITVECTOR allocation increment - Primitive Type
+//
+
+DEFINE_TYPE( ULONG, PT );
+
+//
+// BIT values
+//
+
+enum BIT {
+ SET = 1,
+ RESET = 0
+};
+
+//
+// Invalid bit count
+//
+
+extern CONST PT InvalidBitCount;
+
+class BITVECTOR : public OBJECT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( BITVECTOR );
+
+ DECLARE_CAST_MEMBER_FUNCTION( BITVECTOR );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ ~BITVECTOR (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PT Size DEFAULT 0,
+ IN BIT InitialValue DEFAULT RESET,
+ IN PPT Memory DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ PCPT
+ GetBuf (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsBitSet (
+ IN PT Index
+ ) CONST;
+
+ NONVIRTUAL
+ PT
+ QueryCountSet (
+ ) CONST;
+
+ NONVIRTUAL
+ PT
+ QuerySize (
+ ) CONST;
+
+ NONVIRTUAL
+ VOID
+ ResetAll (
+ );
+
+ NONVIRTUAL
+ VOID
+ ResetBit (
+ IN PT Index
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ ResetBit (
+ IN PT Index,
+ IN PT Count
+ );
+
+ NONVIRTUAL
+ VOID
+ SetAll (
+ );
+
+ NONVIRTUAL
+ VOID
+ SetBit (
+ IN PT Index
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ SetBit (
+ IN PT Index,
+ IN PT Count
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PT
+ SetSize (
+ IN PT Size,
+ IN BIT InitialValue DEFAULT RESET
+ );
+
+ NONVIRTUAL
+ VOID
+ ToggleBit (
+ IN PT Index,
+ IN PT Count DEFAULT 1
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PT
+ ComputeCountSet (
+ ) CONST;
+
+ NONVIRTUAL
+ VOID
+ Destroy (
+ );
+
+ VOID
+ NONVIRTUAL
+ InitAll (
+ IN PT InitialValue
+ );
+
+ // Note that these three member data items cannot
+ // be static because they are used in INLINE functions
+ // that are called from outside the DLL.
+
+ PT _BitsPerPT;
+ PT _IndexShiftCount;
+ PT _BitPositionMask;
+
+ STATIC
+ CONST
+ BYTE _BitsSetLookUp[ 256 ];
+
+ PPT _BitVector;
+ PT _PTCount;
+ BOOLEAN _FreeBitVector;
+
+};
+
+INLINE
+PCPT
+BITVECTOR::GetBuf (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Returns the underlying bit vector.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PCPT - Returns a pointer to the underlying bitvector.
+
+--*/
+
+{
+ return( _BitVector );
+}
+
+INLINE
+PT
+BITVECTOR::QuerySize (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Returns the number of bits in this BITVECTOR.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PT
+
+--*/
+
+{
+ return( _PTCount * _BitsPerPT );
+}
+
+INLINE
+VOID
+BITVECTOR::InitAll (
+ IN PT InitialValue
+ )
+
+/*++
+
+Routine Description:
+
+ Initialize each element in the internal bit vector to the
+ supplied bit pattern.
+
+Arguments:
+
+ InitialValue - Supplies the pattern for each element.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DebugAssert( _BitVector != NULL );
+
+ memset(( PVOID ) _BitVector,
+ ( int ) InitialValue, ( size_t ) ( sizeof( PT ) * _PTCount ));
+}
+
+INLINE
+VOID
+BITVECTOR::SetAll (
+ )
+
+/*++
+
+Routine Description:
+
+ Set (to one) all of the bits in this BITVECTOR.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ InitAll(( PT ) ~0 );
+}
+
+INLINE
+VOID
+BITVECTOR::ResetAll (
+ )
+
+/*++
+
+Routine Description:
+
+ Reset (to zero) all of the bits in this BITVECTOR.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ InitAll(( PT ) 0 );
+}
+
+INLINE
+BOOLEAN
+BITVECTOR::IsBitSet (
+ IN PT Index
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if the bit at the supplied index is set.
+
+Arguments:
+
+ Index - Supplies the index to the bit of interest.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if the bit of interest is set.
+
+--*/
+
+{
+ DebugAssert( _BitVector != NULL );
+ DebugAssert( Index < ( _PTCount * _BitsPerPT ));
+
+ return (_BitVector[Index >> _IndexShiftCount] &
+ (1 << (Index & _BitPositionMask))) ? TRUE : FALSE;
+}
+
+INLINE
+VOID
+BITVECTOR::SetBit (
+ IN PT Index
+ )
+
+/*++
+
+Routine Description:
+
+ Set the bit at the supplied index.
+
+Arguments:
+
+ Index - Supplies the index to the bit of interest.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DebugAssert( _BitVector != NULL );
+ DebugAssert( Index < ( _PTCount * _BitsPerPT ));
+
+ _BitVector[Index >> _IndexShiftCount] |=
+ (1 << (Index & _BitPositionMask));
+}
+
+INLINE
+VOID
+BITVECTOR::ResetBit (
+ IN PT Index
+ )
+
+/*++
+
+Routine Description:
+
+ Reset the bit at the supplied index.
+
+Arguments:
+
+ Index - Supplies the index to the bit of interest.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DebugAssert( _BitVector != NULL );
+ DebugAssert( Index < ( _PTCount * _BitsPerPT ));
+
+ _BitVector[Index >> _IndexShiftCount] &=
+ ~(1 << (Index & _BitPositionMask));
+}
+
+INLINE
+PT
+BITVECTOR::QueryCountSet (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine the number of bits set in this BITVECTOR.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PT - Returns the number of set bits.
+
+--*/
+{
+ return ComputeCountSet();
+}
+
+#endif // _BITVECTOR_
diff --git a/private/utils/ulib/inc/buffer.hxx b/private/utils/ulib/inc/buffer.hxx
new file mode 100644
index 000000000..7541b5d96
--- /dev/null
+++ b/private/utils/ulib/inc/buffer.hxx
@@ -0,0 +1,183 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ buffer.hxx
+
+Abstract:
+
+ This contains all buffer class definition.
+ No reallocing of buffers is done. A buffer must be big enough
+ to hold both buffer for a cat.
+
+Author:
+
+ Steve Rowe 27-Nov-90
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+
+
+Revision History:
+
+--*/
+
+//
+// This class is no longer supported.
+//
+
+#define _BUFFER_
+
+#if !defined (_BUFFER_)
+
+#define _BUFFER_
+
+#include "error.hxx"
+
+DECLARE_CLASS( BUFFER );
+
+
+class BUFFER : public OBJECT {
+
+ friend WSTRING;
+
+ public:
+
+ VIRTUAL
+ ~BUFFER (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ BuffCat (
+ IN PCBUFFER BufferToCat
+ );
+
+ NONVIRTUAL
+ PCVOID
+ GetBufferPtr (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ PutBuffer (
+ IN PCBUFFER BufferToCopy
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryBytesInBuffer (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ SetBuffer (
+ IN PVOID InitialBuffer,
+ IN ULONG SizeOfBuffer
+ );
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( BUFFER );
+
+ NONVIRTUAL
+ BOOLEAN
+ BufferCopyAt (
+ IN PCVOID BufferToCopy,
+ IN ULONG BytesToCopy,
+ IN ULONG StartingByte DEFAULT 0
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ DeleteAt (
+ IN ULONG cbToDelete,
+ IN ULONG oStartDelete
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ InsertAt (
+ IN PCVOID BufferToCopy,
+ IN ULONG cbToCopy,
+ IN ULONG oStartCopy
+ );
+
+ NONVIRTUAL
+ PVOID
+ ReAllocate (
+ IN ULONG NewCount
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ PVOID pBuffer; // pointer to the data byffer
+ ULONG cb; // count of bytes used
+ ULONG _BufSize; // count of bytes in buffer
+
+ STATIC
+ ULONG _ThresHold;
+};
+
+INLINE
+PCVOID
+BUFFER::GetBufferPtr (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Fetch pointer to internal buffer
+
+Arguments:
+
+ None
+
+Return Value:
+
+ PCVOID - pointer to internal buffer
+
+--*/
+
+{
+ return ( pBuffer );
+}
+
+INLINE
+ULONG
+BUFFER::QueryBytesInBuffer (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Fetch size in bytes of internal buffer
+
+Arguments:
+
+ None
+
+Return Value:
+
+ ULONG - size of internal buffer in bytes
+
+--*/
+
+{
+ return ( cb );
+}
+
+#endif // _BUFFER_
diff --git a/private/utils/ulib/inc/bufstrm.hxx b/private/utils/ulib/inc/bufstrm.hxx
new file mode 100644
index 000000000..f4e5d644e
--- /dev/null
+++ b/private/utils/ulib/inc/bufstrm.hxx
@@ -0,0 +1,217 @@
+ /*++
+
+ Copyright (c) 1991 Microsoft Corporation
+
+ Module Name:
+
+ bufstrm.hxx
+
+ Abstract:
+
+ This module contains the declaration for the BUFFER_STREAM class.
+ The BUFFER_STREAM is an abstract class derived from STREAM, that
+ provides a buffer for read operations in STREAM.
+ Buffer for read operations is needed in order to read
+ STRINGs from streams.
+
+ Buffer for write operation is not currently implemented. It should
+ be implemented if we notice that write operations are slow.
+
+
+ Author:
+
+ Jaime Sasson (jaimes) 12-Apr-1991
+
+ Environment:
+
+ ULIB, User Mode
+
+
+ --*/
+
+
+ #if !defined( _BUFFER_STREAM_ )
+
+ #define _BUFFER_STREAM_
+
+ #include "stream.hxx"
+ #include "wstring.hxx"
+
+ DECLARE_CLASS( STREAM );
+
+
+ class BUFFER_STREAM : public STREAM {
+
+ public:
+
+ VIRTUAL
+ ~BUFFER_STREAM(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ IsAtEnd(
+ ) CONST;
+
+ VIRTUAL
+ STREAMACCESS
+ QueryAccess(
+ ) CONST PURE;
+
+ VIRTUAL
+ VOID
+ SetStreamTypeANSI(
+ );
+
+ VIRTUAL
+ VOID
+ DetermineStreamType(
+ IN OUT PBYTE *Buffer,
+ IN ULONG BufferSize
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Read(
+ OUT PBYTE Buffer,
+ IN ULONG BytesToRead,
+ OUT PULONG BytesRead
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadChar(
+ OUT PWCHAR Char,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadMbString(
+ IN PSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN PSTR Delimiters,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadWString(
+ IN PWSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN PWSTR Delimiters,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadString(
+ OUT PWSTRING String,
+ IN PWSTRING Delimiters,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ );
+
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( BUFFER_STREAM );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN ULONG BufferSize
+ );
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ AdvanceBufferPointer(
+ IN ULONG NumberOfBytes
+ );
+
+ VIRTUAL
+ BOOLEAN
+ EndOfFile(
+ ) CONST PURE;
+
+ VIRTUAL
+ BOOLEAN
+ FillBuffer(
+ IN PBYTE Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG BytesRead
+ ) PURE;
+
+ NONVIRTUAL
+ ULONG
+ FlushBuffer(
+ );
+
+ VIRTUAL
+ PCBYTE
+ GetBuffer(
+ PULONG BytesInBuffer
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryBytesInBuffer(
+ ) CONST;
+
+ VIRTUAL
+ HANDLE
+ QueryHandle(
+ ) CONST PURE;
+
+
+
+
+ private:
+
+
+ PBYTE _Buffer;
+ ULONG _BufferSize;
+ PBYTE _CurrentByte;
+ ULONG _BytesInBuffer;
+ INT _BufferStreamType;
+ };
+
+
+
+ INLINE
+ ULONG
+ BUFFER_STREAM::QueryBytesInBuffer(
+ ) CONST
+
+ /*++
+
+ Routine Description:
+
+ Returns the number of bytes in the buffer.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ ULONG - Number of bytes in the buffer.
+
+
+ --*/
+
+
+ {
+ return( _BytesInBuffer );
+ }
+
+
+ #endif // _BUFFER_STREAM_
diff --git a/private/utils/ulib/inc/bytestrm.hxx b/private/utils/ulib/inc/bytestrm.hxx
new file mode 100644
index 000000000..91f117bad
--- /dev/null
+++ b/private/utils/ulib/inc/bytestrm.hxx
@@ -0,0 +1,169 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ bytestream.hxx
+
+Abstract:
+
+
+ This module contains the declarations for the BYTE_STREAM class.
+
+ BYTE_STREAM is a class which contains (not derives) a normal
+ ULIB stream and provided fast ReadByte operations. It is designed
+ for those utilities that have to read files one byte at a time.
+
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 28-Feb-1992
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+
+#if !defined( _BYTE_STREAM_ )
+
+#define _BYTE_STREAM_
+
+#include "stream.hxx"
+
+DECLARE_CLASS( BYTE_STREAM );
+
+
+#define DEFAULT_BUFFER_SIZE 256
+
+class BYTE_STREAM : public OBJECT {
+
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( BYTE_STREAM );
+
+ VOID
+ BYTE_STREAM::Construct (
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~BYTE_STREAM (
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PSTREAM Stream,
+ IN DWORD BufferSize DEFAULT DEFAULT_BUFFER_SIZE
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ IsAtEnd(
+ ) CONST;
+
+
+ NONVIRTUAL
+ BOOLEAN
+ ReadByte(
+ IN PBYTE Byte
+ );
+
+
+
+ private:
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ FillAndReadByte (
+ IN PBYTE Byte
+ );
+
+
+ PSTREAM _Stream;
+ PBYTE _Buffer;
+ PBYTE _NextByte;
+ DWORD _BufferSize;
+ DWORD _BytesInBuffer;
+
+};
+
+
+
+INLINE
+BOOLEAN
+BYTE_STREAM::IsAtEnd(
+ ) CONST
+/*++
+
+Routine Description:
+
+ Determines if we're at the end of the stream
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - TRUE if at end.
+
+--*/
+{
+ if ( _BytesInBuffer > 0 ) {
+ return FALSE;
+ } else {
+ return _Stream->IsAtEnd();
+ }
+}
+
+
+
+INLINE
+BOOLEAN
+BYTE_STREAM::ReadByte(
+ IN PBYTE Byte
+ )
+/*++
+
+
+Routine Description:
+
+ Reads next byte
+
+Arguments:
+
+ Byte - Supplies pointer to where to put the byte
+
+Return Value:
+
+ BOOLEAN - TRUE if byte read.
+
+--*/
+{
+ if ( _BytesInBuffer > 0 ) {
+
+ *Byte = *_NextByte++;
+ _BytesInBuffer--;
+
+ return TRUE;
+
+ } else {
+
+ return FillAndReadByte( Byte );
+
+ }
+}
+
+
+#endif // _BYTE_STREAM_
diff --git a/private/utils/ulib/inc/clasdesc.hxx b/private/utils/ulib/inc/clasdesc.hxx
new file mode 100644
index 000000000..05e3aabbd
--- /dev/null
+++ b/private/utils/ulib/inc/clasdesc.hxx
@@ -0,0 +1,183 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ clasdesc.hxx
+
+Abstract:
+
+ This module contains the declaration for the CLASS_DESCRIPTOR class.
+ A CLASS_DESCRIPTOR contains informatiom to help identify an object's
+ type at run-time. It is a concrete class which is associated with all
+ other concrete classes (i.e. there is one instance of a CLASS_DESCRIPTOR
+ for every concrete class in Ulib). The most important aspect of a
+ CLASS_DESCRIPTOR is that it supplies a guaranteed unique id for the class
+ that it decsribes.
+
+Author:
+
+ David J. Gilman (davegi) 26-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+--*/
+
+#if ! defined( _CLASS_DESCRIPTOR_ )
+
+#define _CLASS_DESCRIPTOR_
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( CLASS_DESCRIPTOR );
+
+
+#if DBG==1
+
+ //
+ // Define a CLASS_DESCRIPTOR in the file ulib.cxx. The name will be
+ // the same as the type name for the associated class.
+ //
+
+ #define DEFINE_CLASS_DESCRIPTOR( c ) \
+ ((( c##_cd = NEW CLASS_DESCRIPTOR ) != NULL ) && \
+ ((( PCLASS_DESCRIPTOR ) c##_cd )->Initialize(( PCCLASS_NAME ) #c )))
+
+ #define CLASS_DESCRIPTOR_INITIALIZE \
+ NONVIRTUAL \
+ ULIB_EXPORT \
+ BOOLEAN \
+ Initialize ( \
+ IN PCCLASS_NAME ClassName \
+ )
+
+ //
+ // For debugging purposes, CLASS_DESCRIPTOR stores the name of the class
+ // that it describes.
+ //
+ // NOTE - DebugGetClassName is declared for both CLASS_DESCRIPTOR and
+ // OBJECT. See the note at the end of this module.
+ //
+
+ //
+ // Maximum length for the name of a class
+ //
+
+ CONST _MaxClassNameLength = 20;
+
+ #define DECLARE_CD_DBG_DATA \
+ CLASS_NAME _ClassName[ _MaxClassNameLength ]
+
+ #define DECLARE_CD_DBG_FUNCTIONS \
+ NONVIRTUAL \
+ PCCLASS_NAME \
+ DebugGetClassName ( \
+ ) CONST
+
+ #define DEFINE_CD_INLINE_DBG_FUNCTIONS \
+ \
+ inline \
+ PCCLASS_NAME \
+ CLASS_DESCRIPTOR::DebugGetClassName ( \
+ ) CONST \
+ { \
+ return(( PCCLASS_NAME ) _ClassName );\
+ }
+
+ #define DbgGetClassName( pobj ) \
+ ( pobj )->DebugGetClassName( )
+#else // DBG == 0
+
+ #define DEFINE_CLASS_DESCRIPTOR( c ) \
+ ((( c##_cd = NEW CLASS_DESCRIPTOR ) != NULL ) && \
+ ((( PCLASS_DESCRIPTOR ) c##_cd )->Initialize( )))
+
+ #define CLASS_DESCRIPTOR_INITIALIZE \
+ NONVIRTUAL \
+ ULIB_EXPORT \
+ BOOLEAN \
+ Initialize ( \
+ )
+
+ #define DECLARE_CD_DBG_DATA \
+ static char d
+
+ #define DECLARE_CD_DBG_FUNCTIONS \
+ void f(void){}
+
+ #define DEFINE_CD_INLINE_DBG_FUNCTIONS \
+ inline void f(void){}
+
+ #define DbgGetClassName( pobj )
+
+#endif // DBG
+
+class CLASS_DESCRIPTOR {
+
+ friend
+ BOOLEAN
+ InitializeUlib(
+ IN HANDLE DllHandle,
+ IN ULONG Reason,
+ IN PVOID Reserved
+ );
+
+ public:
+
+ ULIB_EXPORT
+ CLASS_DESCRIPTOR(
+ );
+
+ CLASS_DESCRIPTOR_INITIALIZE;
+
+ NONVIRTUAL
+ CLASS_ID
+ QueryClassId (
+ ) CONST;
+
+ DECLARE_CD_DBG_FUNCTIONS;
+
+ private:
+
+ DECLARE_CD_DBG_DATA;
+
+ CLASS_ID _ClassID;
+};
+
+
+INLINE
+CLASS_ID
+CLASS_DESCRIPTOR::QueryClassId (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the CLASSID for the object described by this CLASS_DESCRIPTOR.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ CLASSID - The CLASSID as maintained by this CLASS_DESCRIPTOR.
+
+--*/
+
+{
+ return( _ClassID );
+}
+
+
+DEFINE_CD_INLINE_DBG_FUNCTIONS;
+
+#endif // CLASS_DESCRIPTOR
diff --git a/private/utils/ulib/inc/classes.xls b/private/utils/ulib/inc/classes.xls
new file mode 100644
index 000000000..a5be9db61
--- /dev/null
+++ b/private/utils/ulib/inc/classes.xls
Binary files differ
diff --git a/private/utils/ulib/inc/cmem.hxx b/private/utils/ulib/inc/cmem.hxx
new file mode 100644
index 000000000..a57cba24f
--- /dev/null
+++ b/private/utils/ulib/inc/cmem.hxx
@@ -0,0 +1,66 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ cmem.hxx
+
+Abstract:
+
+ The class CONT_MEM is an implementation of the class MEM which uses the
+ memory resources given to it on initialization. Successive calls
+ to Acquire will return successive portions of the memory given
+ to it on initialization.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 26-Nov-90
+
+--*/
+
+#if !defined( _CONT_MEM_DEFN_ )
+
+#define _CONT_MEM_DEFN_
+
+#include "mem.hxx"
+
+DECLARE_CLASS( CONT_MEM );
+
+
+class CONT_MEM : public MEM {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( CONT_MEM );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN PVOID Buffer,
+ IN ULONG Size
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ PVOID
+ Acquire(
+ IN ULONG Size,
+ IN ULONG AlignmentMask DEFAULT 0
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ PVOID _buf;
+ ULONG _size;
+
+};
+
+#endif // _CONT_MEM_DEFN_
diff --git a/private/utils/ulib/inc/comm.hxx b/private/utils/ulib/inc/comm.hxx
new file mode 100644
index 000000000..89d701b42
--- /dev/null
+++ b/private/utils/ulib/inc/comm.hxx
@@ -0,0 +1,564 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ COMM_DEVICE
+
+Abstract:
+
+ This module contains the definition for the COMM_DEVICE class.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 08-Jul-91
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+
+
+--*/
+
+#if !defined (_COMM_DEVICE_)
+
+#define _COMM_DEVICE_
+
+
+DECLARE_CLASS( FSN_FILE );
+DECLARE_CLASS( FILE_STREAM );
+DECLARE_CLASS( COMM_DEVICE );
+
+
+//
+// PARITY
+//
+enum PARITY {
+ COMM_PARITY_NONE = NOPARITY,
+ COMM_PARITY_EVEN = EVENPARITY,
+ COMM_PARITY_ODD = ODDPARITY,
+ COMM_PARITY_MARK = MARKPARITY,
+ COMM_PARITY_SPACE = SPACEPARITY
+};
+
+//
+// STOP BITS
+//
+enum STOPBITS {
+
+ COMM_STOPBITS_1 = ONESTOPBIT,
+ COMM_STOPBITS_15 = ONE5STOPBITS,
+ COMM_STOPBITS_2 = TWOSTOPBITS
+};
+
+//
+// DTR control
+//
+enum DTR_CONTROL {
+ DTR_ENABLE = DTR_CONTROL_ENABLE,
+ DTR_DISABLE = DTR_CONTROL_DISABLE,
+ DTR_HANDSHAKE = DTR_CONTROL_HANDSHAKE
+};
+
+//
+// RTS control
+//
+enum RTS_CONTROL {
+ RTS_ENABLE = RTS_CONTROL_ENABLE,
+ RTS_DISABLE = RTS_CONTROL_DISABLE,
+ RTS_HANDSHAKE = RTS_CONTROL_HANDSHAKE,
+ RTS_TOGGLE = RTS_CONTROL_TOGGLE
+};
+
+
+
+
+class COMM_DEVICE : public OBJECT {
+
+ public:
+
+ DECLARE_CAST_MEMBER_FUNCTION( COMM_DEVICE );
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( COMM_DEVICE );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~COMM_DEVICE(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PCPATH PortName,
+ OUT PBOOLEAN OpenError DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ CommitState (
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryBaudRate (
+ ) CONST;
+
+ NONVIRTUAL
+ ULONG
+ QueryDataBits (
+ ) CONST;
+
+ NONVIRTUAL
+ DTR_CONTROL
+ QueryDtrControl (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ QueryIdsr (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ QueryOcts (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ QueryOdsr (
+ ) CONST;
+
+ NONVIRTUAL
+ PARITY
+ QueryParity (
+ ) CONST;
+
+ NONVIRTUAL
+ RTS_CONTROL
+ QueryRtsControl (
+ ) CONST;
+
+ NONVIRTUAL
+ STOPBITS
+ QueryStopBits (
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ QueryTimeOut (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ QueryXon (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ ReadState (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetBaudRate (
+ IN ULONG BaudRate
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetDataBits (
+ IN ULONG DataBits
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetDtrControl (
+ IN DTR_CONTROL DtrControl
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetIdsr (
+ IN BOOLEAN Idsr
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetOcts (
+ IN BOOLEAN Octs
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetOdsr (
+ IN BOOLEAN Odsr
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetParity (
+ IN PARITY Parity
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetRtsControl (
+ IN RTS_CONTROL RtsControl
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetStopBits (
+ IN STOPBITS StopBits
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetTimeOut (
+ IN BOOLEAN TimeOut
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetXon (
+ IN BOOLEAN Xon
+ );
+
+ protected:
+
+
+ private:
+
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy (
+ );
+
+
+ HANDLE _Handle; // Handle to the port
+ DCB _Dcb; // DCB Structure.
+
+#if DBG==1
+
+ BOOLEAN _Initialized; // Object has been initialized
+
+#endif // DBG
+
+
+};
+
+INLINE
+ULONG
+COMM_DEVICE::QueryBaudRate (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries the baud rate
+
+Arguments:
+
+ none
+
+Return Value:
+
+ ULONG - The baud rate.
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return (ULONG)_Dcb.BaudRate;
+
+}
+
+INLINE
+ULONG
+COMM_DEVICE::QueryDataBits (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries the number of data bits
+
+Arguments:
+
+ none
+
+Return Value:
+
+ ULONG - The number of data bits
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return (ULONG)_Dcb.ByteSize;
+
+}
+
+INLINE
+DTR_CONTROL
+COMM_DEVICE::QueryDtrControl (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries the DTR control
+
+Arguments:
+
+ none
+
+Return Value:
+
+ DTR_CONTROL - The DTR control
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return (DTR_CONTROL)_Dcb.fDtrControl;
+
+}
+
+INLINE
+BOOLEAN
+COMM_DEVICE::QueryIdsr (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries whether DSR sensitivity is enabled or disabled
+
+Arguments:
+
+ none
+
+Return Value:
+
+ BOOLEAN - TRUE if DSR sensitivity enabled. FALSE otherwise.
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return ( _Dcb.fDsrSensitivity != 0 );
+
+}
+
+INLINE
+BOOLEAN
+COMM_DEVICE::QueryOcts (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries whether hanshaking using the CTS circuit is enabled or not.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ BOOLEAN - TRUE if handshaking enabled. FALSE otherwise.
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return ( _Dcb.fOutxCtsFlow != 0 );
+
+}
+
+INLINE
+BOOLEAN
+COMM_DEVICE::QueryOdsr (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries whether handshaking using the DSR circuit is enabled or not
+
+Arguments:
+
+ none
+
+Return Value:
+
+ BOOLEAN - TRUE if handshaking enabled. FALSE otherwise.
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return ( _Dcb.fOutxDsrFlow != 0 );
+
+}
+
+INLINE
+PARITY
+COMM_DEVICE::QueryParity (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries the parity
+
+Arguments:
+
+ none
+
+Return Value:
+
+ BYTE - The parity value.
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return (PARITY)_Dcb.Parity;
+
+}
+
+INLINE
+RTS_CONTROL
+COMM_DEVICE::QueryRtsControl (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries the RTS control
+
+Arguments:
+
+ none
+
+Return Value:
+
+ RTS_CONTROL - The RTS control
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return (RTS_CONTROL)_Dcb.fRtsControl;
+
+}
+
+INLINE
+STOPBITS
+COMM_DEVICE::QueryStopBits (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries the number of stop bits
+
+Arguments:
+
+ none
+
+Return Value:
+
+ BYTE - The number of stop bits
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return (STOPBITS)_Dcb.StopBits;
+}
+
+INLINE
+BOOLEAN
+COMM_DEVICE::QueryXon (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Queries whether XON/XOFF protocol is enabled or not.
+
+Arguments:
+
+ none
+
+Return Value:
+
+ BOOLEAN - TRUE if protocol enabled, FALSE otherwise
+
+--*/
+
+{
+
+ DebugAssert( _Initialized );
+
+ return ( _Dcb.fInX && _Dcb.fOutX );
+}
+
+
+
+
+#endif // _COMM_DEVICE_
diff --git a/private/utils/ulib/inc/contain.hxx b/private/utils/ulib/inc/contain.hxx
new file mode 100644
index 000000000..e588e8df3
--- /dev/null
+++ b/private/utils/ulib/inc/contain.hxx
@@ -0,0 +1,95 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ contain.hxx
+
+Abstract:
+
+ This module contains the definition for the CONTAINER class, the most
+ primitive, abstract class in the container sub-hierarchy. CONTAINERs
+ of all types are repositories for OBJECTs. CONTAINER is the most abstract
+ in that it makes no assumptions about the ordering of it's contents.
+
+Author:
+
+ David J. Gilman (davegi) 26-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _CONTAINER_ )
+
+#define _CONTAINER_
+
+DECLARE_CLASS( CONTAINER );
+
+
+class CONTAINER : public OBJECT {
+
+ public:
+
+ VIRTUAL
+ ~CONTAINER(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Put(
+ IN OUT POBJECT Member
+ ) PURE;
+
+ VIRTUAL
+ ULONG
+ QueryMemberCount(
+ ) CONST PURE;
+
+ VIRTUAL
+ BOOLEAN
+ DeleteAllMembers(
+ ) PURE;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsEmpty(
+ ) CONST;
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( CONTAINER );
+
+};
+
+
+INLINE
+BOOLEAN
+CONTAINER::IsEmpty(
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if the container is empty.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - TRUE if the container is empty.
+
+--*/
+
+{
+ return QueryMemberCount() == 0;
+}
+
+
+#endif // _CONTAINER_
diff --git a/private/utils/ulib/inc/cstring.h b/private/utils/ulib/inc/cstring.h
new file mode 100644
index 000000000..b401d2fd2
--- /dev/null
+++ b/private/utils/ulib/inc/cstring.h
@@ -0,0 +1,174 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ wstring.h
+
+Abstract:
+
+ This module contains the prototypes for the wide character
+ C-runtime support. Since there is no C-runtime support for
+ wide characters, the functions here are wrappers to the
+ single-byte counterparts
+
+Author:
+
+ Ramon San Andres (Ramonsa) 07-Jun-1991
+
+Revision History:
+
+--*/
+
+typedef char wchar;
+typedef WCHAR wchar_t;
+typedef size_t wsize_t;
+
+long watol( const wchar *);
+wchar * wcschr(const wchar *, int);
+wchar * wcslwr(wchar *);
+wchar * wcsrchr(const wchar *, int);
+wchar * wcsupr(wchar *);
+wsize_t wcscspn(const wchar *, const wchar *);
+wsize_t wcsspn(const wchar *, const wchar *);
+wchar * wcsstr(const wchar *, const wchar *);
+int wctomb( char *s, wchar_t wchar );
+int mbtowc(wchar_t *pwc, const char *s, size_t n);
+wchar_t towupper( wchar_t wc);
+
+INLINE
+long
+watol(
+ const wchar * p
+ )
+{
+ return atol( (char *)p );
+}
+
+
+INLINE
+wchar *
+wcschr (
+ const wchar * p,
+ int c
+ )
+{
+ return (wchar *)strchr( (char *)p, c);
+}
+
+
+INLINE
+wchar *
+wcslwr (
+ wchar * p
+ )
+{
+ return (wchar *)strlwr( (char *)p );
+}
+
+INLINE
+wchar *
+wcsrchr (
+ const wchar * p,
+ int c
+ )
+{
+ return (char *)strrchr( (char *)p, c);
+}
+
+INLINE
+wchar *
+wcsupr (
+ wchar * p
+ )
+{
+ return (char *)strupr( (char *)p );
+}
+
+
+INLINE
+wsize_t
+wcscspn (
+ const wchar *p1,
+ const wchar *p2
+ )
+{
+
+ return (wsize_t)strcspn( (char *)p1, (char *)p2);
+
+}
+
+INLINE
+wsize_t
+wcsspn (
+ const wchar *p1,
+ const wchar *p2
+ )
+{
+
+ return (wsize_t)strspn( (char *)p1, (char *)p2);
+
+}
+
+
+INLINE
+wchar *
+wcsstr (
+ const wchar *p1,
+ const wchar *p2
+ )
+{
+
+ return (wchar *)strstr( (char *)p1, (char *)p2);
+
+}
+
+
+INLINE
+int
+wctomb (
+ char *s,
+ wchar_t wchar
+ )
+{
+
+ if (s) {
+ *s = (char)wchar;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+INLINE
+int
+mbtowc (
+ wchar_t *pwc,
+ const char *s,
+ size_t n
+ )
+{
+ UNREFERENCED_PARAMETER( n );
+
+ if ( s && *s && (n > 0) ) {
+ *pwc = (wchar_t)(*s);
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+
+INLINE
+wchar_t
+towupper(
+ wchar_t wc
+ )
+{
+
+ return (wchar_t)toupper( (char)wc );
+
+}
diff --git a/private/utils/ulib/inc/dir.hxx b/private/utils/ulib/inc/dir.hxx
new file mode 100644
index 000000000..7c4ab3637
--- /dev/null
+++ b/private/utils/ulib/inc/dir.hxx
@@ -0,0 +1,150 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ dir.hxx
+
+Abstract:
+
+ This module contains the declaration for the FSN_DIRECTORY class.
+ FSN_DIRECTORY is derived from the abstract FSNODE class. It offers an
+ interface which supports the manipulation of DIRECTORIES. It's primary
+ purpose is to support the creation of lists of FSNODE (e.g. FILE and
+ DIRECTORY) objects that meet some criteria (see FSN_FILETER)and to
+ manipulate (e.g. copy, move) FSNODEs which are 'owned' by a FSN_DIRECTORY.
+
+Author:
+
+ David J. Gilman (davegi) 09-Jan-1991
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _FSN_DIRECTORY_ )
+
+#define _FSN_DIRECTORY_
+
+#include "fsnode.hxx"
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( FSN_DIRECTORY );
+DECLARE_CLASS( FSN_FILE );
+DECLARE_CLASS( FSN_FILTER );
+DECLARE_CLASS( FSNODE );
+DECLARE_CLASS( PATH );
+
+//
+// Type of the callback function for the Traverse method
+//
+typedef BOOLEAN (*CALLBACK_FUNCTION)( IN PVOID Object, IN OUT PFSNODE Node, IN PPATH DestinationPath);
+
+//
+// Type of the confirmation function for Copy method.
+//
+typedef BOOLEAN (*CONFIRM_COPY_FUNCTION)( IN PCFSNODE Source,
+ IN OUT PPATH DestinationPath );
+
+
+class FSN_DIRECTORY : public FSNODE {
+
+ friend class FSN_FILTER;
+ friend class SYSTEM;
+
+ public:
+
+ DECLARE_CAST_MEMBER_FUNCTION( FSN_DIRECTORY );
+
+ /*
+ NONVIRTUAL
+ PFSN_DIRECTORY
+ CreateDirectory (
+ IN PCPATH Path
+ ) CONST;
+ */
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PFSN_DIRECTORY
+ CreateDirectoryPath (
+ IN PCPATH Path
+ ) CONST;
+
+ NONVIRTUAL
+ PFSN_FILE
+ CreateFile (
+ IN PCPATH Path,
+ IN BOOLEAN OverWrite DEFAULT FALSE
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ Copy (
+ IN PFSN_FILTER FsnFilter,
+ IN PCFSN_DIRECTORY DestinationDir,
+ IN BOOLEAN Recurse DEFAULT FALSE,
+ IN BOOLEAN OverWrite DEFAULT FALSE
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DeleteDirectory (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ DeleteFsNode (
+ IN PCFSN_FILTER FsnFilter,
+ IN BOOLEAN Recurse DEFAULT FALSE
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsEmpty (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ Move (
+ IN PCFSN_FILTER FsnFilter,
+ IN PCSTR DestinationName DEFAULT NULL,
+ IN PCFSN_DIRECTORY DestinationDir DEFAULT NULL,
+ IN BOOLEAN Recurse DEFAULT FALSE,
+ IN BOOLEAN OverWrite DEFAULT FALSE
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PARRAY
+ QueryFsnodeArray (
+ IN PFSN_FILTER FsnFilter DEFAULT NULL
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Traverse (
+ IN PVOID Object,
+ IN PFSN_FILTER FsnFilter,
+ IN OUT PPATH DestinationPath,
+ IN CALLBACK_FUNCTION CallBackFunction
+ ) CONST;
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( FSN_DIRECTORY );
+
+ private:
+
+};
+
+#endif // _FSN_DIRECTORY_
diff --git a/private/utils/ulib/inc/error.hxx b/private/utils/ulib/inc/error.hxx
new file mode 100644
index 000000000..227eb1134
--- /dev/null
+++ b/private/utils/ulib/inc/error.hxx
@@ -0,0 +1,392 @@
+/*
+ Defining error code:
+*/
+
+
+#define ERROR_USER_DEFINED_BASE 0xFF00
+#define ERR_ERRSTK_STACK_OVERFLOW ERROR_USER_DEFINED_BASE + 1
+#define NEW_ALLOC_FAILED ERROR_USER_DEFINED_BASE + 2
+
+#define ERROR_NLS_STRING_BASE 0xFF10
+#define ERR_NLS_ALLOC_FAILED ERROR_NLS_STRING_BASE + 1
+#define ERR_NLS_INVALID_PSZ ERROR_NLS_STRING_BASE + 2
+#define ERR_NLS_INVALID_STRING ERROR_NLS_STRING_BASE + 3
+#define ERR_NLS_FIXED_SIZE_BUF ERROR_NLS_STRING_BASE + 4
+#define ERR_NLS_NOT_FOUND ERROR_NLS_STRING_BASE + 5
+#define ERR_NLS_BAD_DATE ERROR_NLS_STRING_BASE + 6
+#define ERR_NLS_BAD_TIME ERROR_NLS_STRING_BASE + 7
+#define ERR_BAD_SUBSTRING ERROR_NLS_STRING_BASE + 8
+
+#define ERROR_ARG_BASE 0xFF20
+#define ERR_UNKNOWN_ARG_STRING ERROR_ARG_BASE + 1
+#define ERR_INVALID_COMMAND_LINE ERROR_ARG_BASE + 2
+
+#define ERROR_ARRAYLIST_BASE 0xFF30
+#define ERR_REALLOC_SIZE_FAILED ERROR_ARRAYLIST_BASE + 1
+
+#define ERROR_STR_BUF_BASE 0xFF40
+#define ERR_FILE_TOO_LARGE ERROR_STR_BUF_BASE + 1
+#define ERR_MEMORY_UNAVAILABLE ERROR_STR_BUF_BASE + 2
+#define ERR_FILE_READ_ERROR ERROR_STR_BUF_BASE + 3
+#define ERR_NO_STRINGS_IN_BUFFER ERROR_STR_BUF_BASE + 4
+#define ERR_INVALID_FILE_NAME ERROR_STR_BUF_BASE + 4
+
+
+#define ERROR_MB_STRING_BASE 0xFF50
+#define ERR_COLLATE_FAILURE ERROR_MB_STRING_BASE + 1
+
+#define ERROR_VOLUME_BASE 0xFF60
+#define ERR_CANNOT_OPEN_VOL ERROR_VOLUME_BASE + 1
+#define ERR_CANNOT_GET_VOL ERROR_VOLUME_BASE + 2
+#define ERR_PARITION_TOOBIG ERROR_VOLUME_BASE + 3
+#define ERR_NO_S_SWITCH ERROR_VOLUME_BASE + 4
+#define ERR_INVALID_PARM ERROR_VOLUME_BASE + 5
+#define ERR_VOL_NOTOPEN ERROR_VOLUME_BASE + 6
+#define ERR_VOL_NOHELPERS ERROR_VOLUME_BASE + 7
+#define ERR_VOL_NETDRIVE ERROR_VOLUME_BASE + 8
+#define ERR_VOL_BUSYDRIVE ERROR_VOLUME_BASE + 9
+#define ERR_VOL_INVALIDLABEL ERROR_VOLUME_BASE + 0xA
+
+#define ERROR_FMT_BASE 0xFFFF0070
+#define ERR_FMT_NOTSUPPORTED ERROR_FMT_BASE + 1
+#define ERR_FMT_UNEXPECTEDERR ERROR_FMT_BASE + 2
+#define ERR_FMT_BADPARM ERROR_FMT_BASE + 3
+#define ERR_FMT_INCOMPATPARM ERROR_FMT_BASE + 4
+#define ERR_FMT_INCOMPATDISK ERROR_FMT_BASE + 5
+#define ERR_FMT_ONCEONLY ERROR_FMT_BASE + 6
+#define ERR_FMT_VOLTOOBIG ERROR_FMT_BASE + 7
+#define ERR_FMT_BADVOLID ERROR_FMT_BASE + 8
+#define ERR_FMT_EXECFAIL ERROR_FMT_BASE + 9
+#define ERR_FMT_BADCMMFUNC ERROR_FMT_BASE + 0xA
+#define ERR_FMT_INVALIDMEDIA ERROR_FMT_BASE + 0xB
+#define ERR_FMT_BADOS ERROR_FMT_BASE + 0xC
+#define ERR_FMT_GENERALFAIL ERROR_FMT_BASE + 0xD
+#define ERR_FMT_NOSPARM ERROR_FMT_BASE + 0xE
+#define ERR_FMT_INVALIDNAME ERROR_FMT_BASE + 0xF
+#define ERR_FMT_NOWRITEBOOT ERROR_FMT_BASE + 0x10
+#define ERR_FMT_BADLABEL ERROR_FMT_BASE + 0x11
+#define ERR_FMT_FATERR ERROR_FMT_BASE + 0x12
+#define ERR_FMT_DIRWRITE ERROR_FMT_BASE + 0x13
+#define ERR_FMT_DRIVELETTER ERROR_FMT_BASE + 0x14
+#define ERR_FMT_UNSUPP_PARMS ERROR_FMT_BASE + 0x15
+#define ERR_FMT_STOPIFDISK ERROR_FMT_BASE + 0x16
+#define ERR_FMT_NODRIVESPEC ERROR_FMT_BASE + 0x17
+
+#define ERROR_IOBUF_BASE 0xFF90
+#define ERR_ALLOC_FAILURE ERROR_IOBUF_BASE + 1
+#define ERR_REALLOC_FAILURE ERROR_IOBUF_BASE + 2
+#define ERR_BUFFER_OVERFLOW ERROR_IOBUF_BASE + 3
+#define ERR_BUFFER_NOT_LOCAL ERROR_IOBUF_BASE + 4
+
+#define ERROR_FS_MGR_BASE 0xff95
+#define ERROR_DRV_BASE 0xff96
+#define ERR_DRV_NOT_SET ERROR_DRV_BASE + 1
+#define ERR_DRV_INVALID_ARG ERROR_DRV_BASE + 2
+#define ERROR_FS_REF_BASE 0xff99
+#define ERROR_FS_REF_SETPROPERTY ERROR_FS_REF_BASE + 1
+#define ERROR_FILE_BASE 0xffa0
+#define ERROR_DIRECTORY_BASE 0xffb0
+#define ERROR_MSG_BASE 0xffc0
+
+#define ERROR_MBR_BASE 0xFFd0
+#define ERR_INVALID_PARITION ERROR_MBR_BASE + 1
+#define ERR_INVALID_SYSTEM_ID ERROR_MBR_BASE + 2
+
+#define ERROR_BPB_BASE 0xFFe0
+#define ERR_BPB_NOMEM ERROR_BPB_BASE + 1
+#define ERR_INVALID_DEVICE ERROR_BPB_BASE + 2
+#define ERR_NO_BPB ERROR_BPB_BASE + 3
+#define ERR_NO_MBR ERROR_BPB_BASE + 4
+
+#define ERROR_FAT_BASE 0xFFf0
+#define ERR_BAD_CLUS_NUM ERROR_FAT_BASE + 1
+
+#define ERROR_FATFMT_BASE 0xFFf5
+#define ERR_NOMULTITRACK ERROR_FATFMT_BASE + 1
+#define ERR_BADAREAS ERROR_FATFMT_BASE + 2
+
+#define ERROR_BMIND_BASE 0xFFFF0000
+#define ERR_BMIND_PARAMETER ERROR_BMIND_BASE + 1
+#define ERR_BMIND_INITIALIZATION ERROR_BMIND_BASE + 2
+
+#define ERROR_BITMAP_BASE 0xFFFF0010
+#define ERR_BM_PARAMETER ERROR_BITMAP_BASE + 1
+#define ERR_BM_FULL ERROR_BITMAP_BASE + 2
+
+#define ERROR_BADBLK_BASE 0xFFFF0020
+#define ERR_BB_PARAMETER ERROR_BADBLK_BASE + 1
+
+#define ERROR_HOTFIX_BASE 0xFFFF0030
+#define ERR_HF_PARAMETER ERROR_HOTFIX_BASE + 1
+
+#define ERROR_FNODE_BASE 0xFFFF0040
+#define ERR_FN_PARAMETER ERROR_FNODE_BASE + 1
+
+#define ERROR_SUPER_BASE 0xFFFF0050
+#define ERR_SB_PARAMETER ERROR_SUPER_BASE + 1
+
+#define ERROR_SPARE_BASE 0xFFFF0060
+#define ERR_SP_PARAMETER ERROR_SPARE_BASE + 1
+
+#define ERROR_HPFSVOL_BASE 0xFFFF0070
+#define ERR_HV_PARAMETER ERROR_HPFSVOL_BASE + 1
+#define ERR_HV_BAD_SA ERROR_HPFSVOL_BASE + 2
+
+#define ERROR_DIRMAP_BASE 0xFFFF0080
+#define ERR_DM_PARAMETER ERROR_DIRMAP_BASE + 1
+#define ERR_DM_FULL ERROR_DIRMAP_BASE + 2
+
+#define ERROR_DIRBLK_BASE 0xFFFF0090
+#define ERR_DB_PARAMETER ERROR_DIRBLK_BASE + 1
+
+#define ERROR_HP_SUPER_AREA_BASE 0xFFFF00A0
+#define ERR_HPSA_PARAMETER ERROR_HP_SUPER_AREA_BASE + 1
+#define ERR_HPSA_NOT_READ ERROR_HP_SUPER_AREA_BASE + 2
+#define ERR_HPSA_BAD_SA ERROR_HP_SUPER_AREA_BASE + 3
+
+#define ERROR_CHKDSK_BASE 0xFFFF00B0
+#define ERR_CHKDSK_NOTSUPPORTED ERROR_CHKDSK_BASE + 1
+#define ERR_CHKDSK_UNEXPECTEDERR ERROR_CHKDSK_BASE + 2
+#define ERR_CHKDSK_BADPARM ERROR_CHKDSK_BASE + 3
+#define ERR_CHKDSK_INCOMPATPARM ERROR_CHKDSK_BASE + 4
+#define ERR_CHKDSK_INCOMPATDISK ERROR_CHKDSK_BASE + 5
+#define ERR_CHKDSK_BADVOLID ERROR_CHKDSK_BASE + 6
+#define ERR_CHKDSK_EXECFAIL ERROR_CHKDSK_BASE + 7
+#define ERR_CHKDSK_BADCMMFUNC ERROR_CHKDSK_BASE + 8
+#define ERR_CHKDSK_INVALIDMEDIA ERROR_CHKDSK_BASE + 9
+#define ERR_CHKDSK_BADOS ERROR_CHKDSK_BASE + 0xA
+#define ERR_CHKDSK_GENERALFAIL ERROR_CHKDSK_BASE + 0xB
+#define ERR_CHKDSK_INVALIDNAME ERROR_CHKDSK_BASE + 0xC
+#define ERR_CHKDSK_NOWRITEBOOT ERROR_CHKDSK_BASE + 0xD
+#define ERR_CHKDSK_BADLABEL ERROR_CHKDSK_BASE + 0xE
+#define ERR_CHKDSK_FATERR ERROR_CHKDSK_BASE + 0xF
+#define ERR_CHKDSK_DIRWRITE ERROR_CHKDSK_BASE + 0x10
+#define ERR_CHKDSK_DRIVELETTER ERROR_CHKDSK_BASE + 0x11
+#define ERR_CHKDSK_UNSUPP_PARMS ERROR_CHKDSK_BASE + 0x12
+#define ERR_CHKDSK_NODRIVESPEC ERROR_CHKDSK_BASE + 0x13
+#define ERR_CHKDSK_INVALID_FSTYPE ERROR_CHKDSK_BASE + 0x14
+#define ERR_CHKDSK_NO_FIX_SECTOR0 ERROR_CHKDSK_BASE + 0x15
+
+#define ERR_NOT_INIT 0xFFFF00D0
+#define ERR_NOT_READ 0xFFFF00E0
+
+#define ERROR_MEM_BASE 0xFFFF00F0
+#define ERR_CMEM_NO_MEM ERROR_MEM_BASE + 1
+#define ERR_HMEM_NO_MEM ERROR_MEM_BASE + 2
+
+#define ERRSTK_DEFAULT_SIZE 20
+typedef ULONG ERRCODE; // errco
+
+
+#if !defined( ERRSTACK_DEFN )
+#define ERRSTACK_DEFN
+
+// this has to be defined in the .exe and has to use this name.
+
+class ERRSTACK;
+typedef ERRSTACK* PERRSTACK;
+
+extern ERRSTACK *perrstk;
+
+
+class ERRSTACK {
+
+ public:
+
+ void push (ERRCODE errIn, CLASS_ID idIn)
+ { (void)(errIn); (void)(idIn); (void)(this); };
+
+};
+
+
+#define PUSH_ERR( x ) perrstk->push( x, QueryClassId() );
+
+#endif // !defined ERRSTACK_DEFN
+
+
+
+
+
+
+
+#if 0 // BUGBUG davegi fix
+
+
+/***************************************************************************\
+CLASS: ERROR
+
+PURPOSE: Class to hold an error code.
+
+INTERFACE: ERROR constructs and init error with class id and error code
+ SetErr Sets the error code
+ QueryErr returns current error code
+ SetId Set id used to identify class that had error.
+ QueryClassId returns current class id
+ SetMsg Sets pointer to message object
+ QueryMsg Returns pointer to message object
+ SetIdErrMsg Sets err, id and message at same time
+
+NOTES: Any error that is to be passed up the stack should be put into
+ an error object and put in the ERRSTK object. All references
+ to ERRSTK are through the ulib defined global perrstk. All
+ users of ERRSTK should declare:
+
+ #include "error.hxx";
+ extern ERRSTK * perrstk;
+
+ The ERROR object contains the error code, the class id (see
+ object.hxx) and an optional pointer to a MESSAGE object.
+
+ Error codes are defined with error.hxx. These are the error codes
+ specific to the utility objects. All error codes generated from
+ outside of OS/2 need to be mapped to this set of error codes.
+ Specifically the C runtime error codes will have to be mapped
+ to an error code defined in error.hxx. An error code returned
+ from an OS/2 call is put directly into the ERROR object. An
+ error code from the C runtime has to be mapped to some error
+ code defined in error.hxx.
+
+ The class id is defined in object.hxx. Each class has a unique
+ class id. This can be found be using the QueryClassId method on any
+ object. If the error does not occur within an object then use
+ ID_NOT_AN_OBJECT. This is a generic class id defined for this
+ purpose. If a more specific location is needed and the error
+ is not in an object then define a new class id substracting
+ from ID_BASE as shown in object.hxx with the ID_NOT_AN_OBJECT
+ example.
+
+ The optional pointer to a MESSAGE object can be used latter
+ to process the ERROR and recover context specific information
+ about the ERROR. There will need to be a message id defined
+ for the error.
+
+HISTORY: 4-1-90 stever
+
+KEYWORDS: ERROR CLASS_ID
+
+SEEALSO: ERRSTK
+\***************************************************************************/
+#if !defined (ERROR_DEFN)
+
+#define ERROR_DEFN
+
+class MESSAGE;
+
+class ERROR : public OBJECT { // err
+
+ private:
+
+ ERRCODE err;
+ CLASS_ID id;
+// const MESSAGE * pmsg;
+
+ public:
+ ERROR ();
+// ERROR (ERRCODE errIn, CLASS_ID idIn, const MESSAGE *pmsgIn = (MESSAGE *)NULL);
+ ~ERROR ();
+ ERROR & operator= (ERROR & );
+ BOOL SetErr (ERRCODE errIn) {return(err = errIn);}
+ ERRCODE QueryErr () {return(err);}
+ BOOL SetId (CLASS_ID idIn) {return(id = idIn); }
+ CLASS_ID QueryClassId () {return(id); }
+// ERROR * PutIdErrMsg (CLASS_ID idIn, ERRCODE errIn, const MESSAGE * pmsgIn = (const MESSAGE *)NULL) {id = idIn; pmsg = pmsgIn; err = errIn; return(this); }
+// const MESSAGE * PutMsg (MESSAGE * pmsgIn) { return(pmsg = pmsgIn); }
+// const MESSAGE * GetMsg () { return(pmsg); }
+
+#if defined (DEBUG)
+ BOOL print ();
+#endif
+
+};
+
+#if defined( DEBUG_STOP_PUSHERR )
+
+#define PUSH_ERR( x ) DebugPrintAbort( "PUSH_ERR called" );
+
+#else
+
+#define PUSH_ERR( x ) (void)*perrstk->push( x, QueryClassId() );
+
+#endif // DEBUG
+
+#endif // ERROR_DEFN
+
+/***************************************************************************\
+CLASS: ERRSTACK
+
+PURPOSE: Hold a stack of error objects
+
+INTERFACE: ERRSTACK creates an array of error obj. pointers
+ ~ERRSTACK deletes array of errors. (calls ~ERROR on each)
+ push push an error object onto the stack. There are
+ two signatures one for pointer to error objectg
+ the other for error code, class id and message
+ pop pop the top error object off the stack
+ QueryCount Query number of errors on the stack
+ QueryTop Query Top index to stack.
+ QuerySize Query size in pointer of stack
+ ClearStack Clear all error from stack (deletes error objects)
+
+
+NOTES: Each exe should declare with global scope an object of type
+ ERRSTK. If you include error.hxx a pointer called perrstk will
+ be declared. perrstk = NEW ERRSTK should be done at the start
+ of the program. The default size for the error stack will be
+ ERRSTK_DEFAULT_SIZE. If the error stack cannot be constructed the
+ the program should abort.
+
+ One slot is always reserved in the stack to hold an overflow
+ error. If ERRSTK_DEFAULT_SIZE stack is allocated then the
+ actual size of the stack is ERRSTK_DEFAULT_SIZE + 1. The overflow
+ error will also occur at index 0. Index ERRSTK_DEFAULT_SIZE - 1
+ is the bottom of the stack. Unless an overflow has occured the
+ stack index will not go below 1. Note that QuerySize will
+ return the original size passed in plus 1. QueryCountError will
+ include a stack overflow error.
+
+ The ERROR object passed to the stack is copied before it is
+ pushed. The caller is responsible for deleting the object.
+
+HISTORY: 3-6-90 stever
+
+KEYWORDS: ERRSTK
+
+SEEALSO: ERROR CLASS_ID
+\***************************************************************************/
+
+#if !defined (ERRSTK_DEFN)
+
+#define ERRSTK_DEFN
+
+class ERRSTACK : public OBJECT { // errstk
+
+ public:
+
+ ERRSTACK (ULONG cpoInitIn = ERRSTK_DEFAULT_SIZE, ULONG cpoIncIn = 0);
+ ~ERRSTACK ();
+ ERROR * push (const ERROR * );
+ ERROR * push (ERRCODE errIn, CLASS_ID idIn);
+ ERROR * pop ();
+ ULONG QueryCount () { return(ipoCur); }
+ ULONG QueryTop () { return(ipoCur); }
+ ULONG QuerySize () { return(cpoMax); }
+ ULONG ClearStack ();
+
+#ifdef DEBUG
+ ULONG print ();
+#endif
+
+ private:
+
+ ERROR * AllocError();
+ ULONG ipoCur; // index to top of stack
+ ULONG cpoMax; // index to bottom of stack
+ ULONG cpoInc; // bytes to add for each realloc
+ ULONG cpoInit; // initial alloc. (used by ClearStack
+ ERROR ** papo; // pointer to stack bottom
+
+};
+
+#endif // ERRSTK_DEFN
+
+#endif // BUGBUG davegi
diff --git a/private/utils/ulib/inc/file.hxx b/private/utils/ulib/inc/file.hxx
new file mode 100644
index 000000000..3d1f7ac76
--- /dev/null
+++ b/private/utils/ulib/inc/file.hxx
@@ -0,0 +1,127 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ file.hxx
+
+Abstract:
+
+ This module contains the declaration for the FSN_FILE class. FSN_FILE
+ is derived from the abstract FSNODE class. It offers an interface which
+ supports manipulation of the external (i.e. non data) portion of files.
+
+Author:
+
+ David J. Gilman (davegi) 09-Jan-1991
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _FSN_FILE_ )
+
+#define _FSN_FILE_
+
+#include "fsnode.hxx"
+#include "filestrm.hxx"
+
+//
+// Error Codes from a copy
+//
+typedef enum _COPY_ERROR {
+ COPY_ERROR_ACCESS_DENIED = ERROR_ACCESS_DENIED,
+ COPY_ERROR_SHARE_VIOLATION = ERROR_SHARING_VIOLATION,
+ COPY_ERROR_NO_MEMORY = ERROR_NOT_ENOUGH_MEMORY,
+ COPY_ERROR_DISK_FULL = ERROR_DISK_FULL,
+ COPY_ERROR_INVALID_NAME = ERROR_INVALID_NAME
+} COPY_ERROR, *PCOPY_ERROR;
+
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( FSN_FILE );
+DECLARE_CLASS( FSN_FILTER );
+
+class FSN_FILE : public FSNODE {
+
+ friend FSN_FILTER;
+ friend SYSTEM;
+
+ public:
+
+ DECLARE_CAST_MEMBER_FUNCTION( FSN_FILE );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Copy (
+ IN OUT PPATH NewFile,
+ OUT PCOPY_ERROR ErrorCode DEFAULT NULL,
+ IN BOOLEAN OverwriteReadOnly DEFAULT FALSE,
+ IN BOOLEAN ResetReadOnly DEFAULT FALSE,
+ IN BOOLEAN Restartable DEFAULT FALSE,
+ IN LPPROGRESS_ROUTINE CallBack DEFAULT NULL,
+ IN VOID * Data DEFAULT NULL,
+ IN PBOOL Cancel DEFAULT NULL
+
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ DeleteFromDisk(
+ IN BOOLEAN Force DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ ULONG
+ QuerySize (
+ ) CONST;
+
+ ULIB_EXPORT
+ PFILE_STREAM
+ QueryStream (
+ IN STREAMACCESS Access
+ );
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( FSN_FILE );
+
+ private:
+
+};
+
+
+
+INLINE
+ULONG
+FSN_FILE::QuerySize (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the size of the file in bytes.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ULONG - returns the file size
+
+--*/
+
+{
+ return( _FileData.nFileSizeLow );
+}
+
+#endif // _FSN_FILE_
diff --git a/private/utils/ulib/inc/filestrm.hxx b/private/utils/ulib/inc/filestrm.hxx
new file mode 100644
index 000000000..581571670
--- /dev/null
+++ b/private/utils/ulib/inc/filestrm.hxx
@@ -0,0 +1,208 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ filestrm.hxx
+
+Abstract:
+
+ This module contains the declaration for the FILE_STREAM class.
+ The FILE_STREAM is an abstract class derived from BUFFER_STREAM,
+ that models a file as a stream of data.
+ A FILE_STREAM class has the concept of a pointer (file poiter),
+ and it provides some methods that allow operations on this pointer,
+ such as:
+
+ .move file pointer to a particular position;
+ .read/write byte in a particular position;
+ .query the position of the file pointer;
+
+ The only way that a client has to create a FILE_STREAM is through
+ QueryStream() (a method in FSN_FILE).
+ FILE_STREAM can be has a method for initialization with two different
+ signatures. In one case, a PFSN_FILE is passed as parameter. This
+ initialization is used by QueryStream().
+ The other signature allows that a HANDLE is passed as parameter.
+ This initialization is used by GetStandardStream() during the
+ initialization of ulib.
+
+
+
+Author:
+
+ Jaime Sasson (jaimes) 21-Mar-1991
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+
+#if !defined( _FILE_STREAM_ )
+
+#define _FILE_STREAM_
+
+#include "bufstrm.hxx"
+
+
+enum SEEKORIGIN {
+ STREAM_BEGINNING,
+ STREAM_CURRENT,
+ STREAM_END
+ };
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( FILE_STREAM );
+DECLARE_CLASS( FSN_FILE );
+
+
+class FILE_STREAM : public BUFFER_STREAM {
+
+ friend class FSN_FILE;
+ friend class COMM_DEVICE;
+ friend PSTREAM GetStandardStream( HANDLE, STREAMACCESS );
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CAST_MEMBER_FUNCTION( FILE_STREAM );
+
+ VIRTUAL
+ ~FILE_STREAM(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ MovePointerPosition(
+ IN LONG Position,
+ IN SEEKORIGIN Origin
+ );
+
+ VIRTUAL
+ STREAMACCESS
+ QueryAccess(
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ QueryPointerPosition(
+ OUT PULONG Position
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Read(
+ OUT PBYTE Buffer,
+ IN ULONG NumberOfBytesToRead,
+ OUT PULONG NumberOfBytesRead
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ ReadAt(
+ OUT PBYTE Buffer,
+ IN ULONG BytesToRead,
+ IN LONG Position,
+ IN SEEKORIGIN Origin,
+ OUT PULONG BytesRead
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Write(
+ IN PCBYTE Buffer,
+ IN ULONG BytesToWrite,
+ OUT PULONG BytesWritten
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ WriteAt(
+ OUT PBYTE Buffer,
+ IN ULONG BytesToWrite,
+ IN LONG Position,
+ IN SEEKORIGIN Origin,
+ OUT PULONG BytesWritten
+ );
+
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( FILE_STREAM );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ PCFSN_FILE File,
+ STREAMACCESS Access
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ HANDLE Handle,
+ STREAMACCESS Access
+ );
+
+ VIRTUAL
+ BOOLEAN
+ AdvanceBufferPointer(
+ IN ULONG NumberOfBytes
+ );
+
+ VIRTUAL
+ BOOLEAN
+ EndOfFile(
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ FillBuffer(
+ IN PBYTE Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG BytesRead
+ );
+
+ NONVIRTUAL
+ PCBYTE
+ GetBuffer(
+ PULONG BytesInBuffer
+ );
+
+ VIRTUAL
+ HANDLE
+ QueryHandle(
+ ) CONST;
+
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+
+ HANDLE _FileHandle;
+ HANDLE _FileMappingHandle;
+ STREAMACCESS _Access;
+ BOOLEAN _EndOfFile;
+ BOOLEAN _ShouldCloseHandle;
+ PBYTE _FileBaseAddress;
+ ULONG _FileSize;
+ PBYTE _CurrentByte;
+ BOOLEAN _EmptyFile;
+ BOOLEAN _MemoryMappedFile;
+};
+
+
+
+#endif // _FILE_STREAM_
diff --git a/private/utils/ulib/inc/filter.hxx b/private/utils/ulib/inc/filter.hxx
new file mode 100644
index 000000000..9519c475b
--- /dev/null
+++ b/private/utils/ulib/inc/filter.hxx
@@ -0,0 +1,274 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ filter.hxx
+
+Abstract:
+
+ This module contains the declaration for the FSN_FILTER class. FSN_FILTER
+ is a concrete class derived from OBJECT. It is used to maintain the state
+ information needed to determine if a file meets the criteria
+ pre-established in the FSN_FILTER.
+
+Author:
+
+ David J. Gilman (davegi) 04-Jan-1991
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+ Here is how the filter works:
+
+ 1.- You initialize the filter (no arguments). This sets the filter
+ to its default matching criteria, which is "everything matches".
+
+ 2.- You will usually want to set your desired matching criteria. There
+ are 3 parameters that you can set:
+
+ a.- The file name - here you specify a file name (possibly with
+ wild cards ).
+
+ b.- The time criteria - you have to use the SetTimeInfo() method
+ once for every type of time that you want to filter. For the
+ SetTimeInfo() method you have to specify:
+
+ - The time
+ - The type of time that you want to filter (e.g
+ modification time, creation time etc. ).
+ - The matching criteria, which is a combination of:
+
+ TIME_BEFORE - Match if file time before this time
+ TIME_AT - Match if file time is this time
+ TIME_AFTER - Match if file time after this time
+
+ for example, if you want files that have been modified on or
+ after a particular time, you do:
+
+ SetTimeInfo( Time, FSN_TIME_MODIFIED, (TIME_AT | TIME_AFTER ) );
+
+ c.- The attributes - here you can provide 3 masks, called the
+ "All" mask, the "Any" mask, and the "None" mask. The meaning of
+ these mask is:
+
+ ALL: In order to match, a file must contain all the attributes
+ specified in this mask set.
+
+ ANY: In order to match, a file must contain any of the attributes
+ specified in this mask set.
+
+ NONE: In order to match, a file must contain all the attributes
+ specified in this mask NOT set.
+
+ An attribute may be present in at most ONE of the masks. An
+ attribute may be present in none of the masks
+
+
+
+ Here are some examples of the queries that we might want and what
+ the masks should be set to. The attributes are represented by:
+
+ D (directory) H (hidden) S (system) A (archived)
+ R (read-only)
+
+
+ ALL ANY NONE
+ ----- ----- -----
+
+ All files (not directories) that are ---A- ----- DHS--
+ not hidden or system, and that are
+ archived (this is used by XCopy)
+
+ All directories (used by Tree) D---- ----- -----
+
+
+ All files that are read-only or ----- -H--R D----
+ hidden
+
+
+ All hidden files that are read-only -H--- --S-R D----
+ or system
+
+
+
+
+--*/
+
+#if ! defined( _FSN_FILTER_ )
+
+#define _FSN_FILTER_
+
+#include "fsnode.hxx"
+#include "wstring.hxx"
+#include "timeinfo.hxx"
+
+//
+// Forward reference
+//
+
+DECLARE_CLASS( FSN_FILTER );
+DECLARE_CLASS( FSN_DIRECTORY );
+
+#define TIME_BEFORE 1
+#define TIME_AT 2
+#define TIME_AFTER 4
+
+class FSN_FILTER : public OBJECT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( FSN_FILTER );
+
+ DECLARE_CAST_MEMBER_FUNCTION( FSN_FILTER );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~FSN_FILTER (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DoesNodeMatch (
+ IN PFSNODE Node
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ GetFileName (
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetFileName (
+ IN PCSTR FileName
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetFileName (
+ IN PCWSTRING FileName
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetAttributes (
+ IN FSN_ATTRIBUTE All DEFAULT (FSN_ATTRIBUTE)0,
+ IN FSN_ATTRIBUTE Any DEFAULT (FSN_ATTRIBUTE)0,
+ IN FSN_ATTRIBUTE None DEFAULT (FSN_ATTRIBUTE)0
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetTimeInfo (
+ IN PCTIMEINFO TimeInfo,
+ IN FSN_TIME TimeInfoType DEFAULT FSN_TIME_MODIFIED,
+ IN USHORT TimeInfoMatch DEFAULT TIME_AT
+ );
+
+ NONVIRTUAL
+ PFSNODE
+ QueryFilteredFsnode (
+ IN PCFSN_DIRECTORY ParentDirectory,
+ IN PWIN32_FIND_DATA FindData
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ FilterAttributes (
+ IN FSN_ATTRIBUTE Attributes
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ FilterFileName (
+ IN PCWSTRING FileName
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ FilterTimeInfo (
+ IN PFILETIME CreationTime,
+ IN PFILETIME LastAccessTime,
+ IN PFILETIME LastWriteTime
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ PatternMatch (
+ IN PCWSTRING FileName,
+ IN CHNUM FileNamePosition,
+ IN PCWSTRING FindName,
+ IN CHNUM FindNamePosition
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ TimeInfoMatch (
+ IN PTIMEINFO TimeInfo,
+ IN PFILETIME FileTime,
+ IN USHORT Criteria
+ );
+
+ FSN_ATTRIBUTE _AttributesAll;
+ FSN_ATTRIBUTE _AttributesAny;
+ FSN_ATTRIBUTE _AttributesNone;
+ BOOLEAN _AttributesSet;
+
+ DSTRING _FileName;
+ BOOLEAN _FileNameSet;
+
+ TIMEINFO _TimeInfo[3];
+ USHORT _TimeInfoMatch[3];
+ BOOLEAN _TimeInfoSet[3];
+};
+
+INLINE
+PWSTRING
+FSN_FILTER::GetFileName (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Gets a pointer to the filter's filename
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Pointer to the filter's filename
+
+--*/
+
+{
+ return &(((PFSN_FILTER) this)->_FileName);
+}
+
+#endif // _FSN_FILTER__
diff --git a/private/utils/ulib/inc/findleak.hxx b/private/utils/ulib/inc/findleak.hxx
new file mode 100644
index 000000000..34ed5010f
--- /dev/null
+++ b/private/utils/ulib/inc/findleak.hxx
@@ -0,0 +1,47 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ findleak.hxx
+
+Abstract:
+
+Author:
+
+ David J. Gilman (davegi) 02-Mar-1991
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _FINDLEAK_ )
+
+#define _FINDLEAK_
+
+DEFINE_CLASS_POINTER_AND_REFERENCE_TYPES( FINDLEAK );
+
+class FINDLEAK : public PROGRAM {
+
+ public:
+
+ DECLARE_CONSTRUCTOR( FINDLEAK );
+
+ VIRTUAL
+ BOOLEAN
+ Initialize (
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+};
+
+#endif // _FINDLEAK_
diff --git a/private/utils/ulib/inc/fsnode.hxx b/private/utils/ulib/inc/fsnode.hxx
new file mode 100644
index 000000000..fcca4f349
--- /dev/null
+++ b/private/utils/ulib/inc/fsnode.hxx
@@ -0,0 +1,1018 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ fsnode.hxx
+
+Abstract:
+
+ This module contains the declaration for the FSNODE class. FSNODE stands
+ for File System NODE and is an abstract class for all user visible
+ objects that exist in a file system (e.g. files, directories).
+
+Author:
+
+ David J. Gilman (davegi) 09-Jan-1991
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+ Do not confuse this class or it's derived classes with the IFS class
+ sub-hierarchy. FSNODE related classes are user visible classes. They
+ are not intended to be used for low level file system tasks such as
+ format or chkdsk. FSNODE classes are as file system independent as the
+ underlying system allows.
+
+--*/
+
+#if ! defined( _FSNODE_ )
+
+#define _FSNODE_
+
+#include "path.hxx"
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( ARRAY );
+DECLARE_CLASS( FSN_DIRECTORY );
+DECLARE_CLASS( FSNODE );
+DECLARE_CLASS( TIMEINFO );
+DECLARE_CLASS( WSTRING );
+
+
+//
+// Extend the set of system defined FILE_ATTRIBUTEs to include
+//
+// - all files (no directories)
+// - all file and directories
+//
+
+#define FILE_ATTRIBUTE_FILES ( FILE_ATTRIBUTE_ARCHIVE | \
+ FILE_ATTRIBUTE_HIDDEN | \
+ FILE_ATTRIBUTE_NORMAL | \
+ FILE_ATTRIBUTE_READONLY | \
+ FILE_ATTRIBUTE_COMPRESSED | \
+ FILE_ATTRIBUTE_SYSTEM )
+
+#define FILE_ATTRIBUTE_ALL ( FILE_ATTRIBUTE_FILES | \
+ FILE_ATTRIBUTE_DIRECTORY )
+
+typedef ULONG FSN_ATTRIBUTE;
+
+#define FSN_ATTRIBUTE_ARCHIVE FILE_ATTRIBUTE_ARCHIVE
+#define FSN_ATTRIBUTE_DIRECTORY FILE_ATTRIBUTE_DIRECTORY
+#define FSN_ATTRIBUTE_HIDDEN FILE_ATTRIBUTE_HIDDEN
+#define FSN_ATTRIBUTE_NORMAL FILE_ATTRIBUTE_NORMAL
+#define FSN_ATTRIBUTE_READONLY FILE_ATTRIBUTE_READONLY
+#define FSN_ATTRIBUTE_COMPRESSED FILE_ATTRIBUTE_COMPRESSED
+#define FSN_ATTRIBUTE_SYSTEM FILE_ATTRIBUTE_SYSTEM
+#define FSN_ATTRIBUTE_FILES FILE_ATTRIBUTE_FILES
+#define FSN_ATTRIBUTE_ALL FILE_ATTRIBUTE_ALL
+
+//
+// FSNODE time & date types
+//
+
+enum FSN_TIME {
+ FSN_TIME_MODIFIED = 0,
+ FSN_TIME_CREATED = 1,
+ FSN_TIME_ACCESSED = 2
+};
+
+class FSNODE : public OBJECT {
+
+ friend class FSN_FILTER;
+
+ public:
+
+ VIRTUAL
+ ~FSNODE (
+ );
+
+ NONVIRTUAL
+ PCPATH
+ GetPath (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsArchived (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsDirectory (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsHidden (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsNormal (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsReadOnly (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsSystem (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ MakeArchived (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ MakeHidden (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ MakeNormal (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ MakeReadOnly (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ MakeSystem (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ QueryBase (
+ ) CONST;
+
+ NONVIRTUAL
+ PWSTRING
+ QueryName (
+ ) CONST;
+
+ VIRTUAL
+ PFSN_DIRECTORY
+ QueryParentDirectory (
+ ) CONST;
+
+ VIRTUAL
+ PTIMEINFO
+ QueryTimeInfo (
+ IN FSN_TIME TimeInfoType DEFAULT FSN_TIME_MODIFIED
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ Rename(
+ IN PCPATH NewName
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ ResetArchivedAttribute (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ ResetHiddenAttribute (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ ResetReadOnlyAttribute (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ ResetSystemAttribute (
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetTimeInfo (
+ IN PCTIMEINFO TimeInfo,
+ IN FSN_TIME TimeInfoType DEFAULT FSN_TIME_MODIFIED
+ );
+
+ VIRTUAL
+ BOOLEAN
+ DeleteFromDisk(
+ IN BOOLEAN Force DEFAULT FALSE
+ );
+
+ VIRTUAL
+ BOOLEAN
+ UpdateFsNode(
+ );
+
+ NONVIRTUAL
+ FSN_ATTRIBUTE
+ QueryAttributes(
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ SetAttributes (
+ IN FSN_ATTRIBUTE Attributes,
+ OUT LPDWORD Win32Error DEFAULT NULL
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ UseAlternateName(
+ );
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( FSNODE );
+
+ VIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PCWSTR PathName,
+ IN PCFSN_DIRECTORY ParentDirectory,
+ IN PWIN32_FIND_DATA FileData
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Initialize (
+ IN PCWSTRING PathName,
+ IN PWIN32_FIND_DATA FileData
+ );
+
+ NONVIRTUAL
+ PFILETIME
+ GetCreationTime(
+ );
+
+ NONVIRTUAL
+ PFILETIME
+ GetLastAccessTime(
+ );
+
+ NONVIRTUAL
+ PFILETIME
+ GetLastWriteTime(
+ );
+
+ PATH _Path;
+ WIN32_FIND_DATAW _FileData;
+
+ private:
+
+};
+
+INLINE
+PCPATH
+FSNODE::GetPath (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the contained PATH object.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PCPATH - returns a constant pointer to the contained PATH object
+
+--*/
+
+{
+ return( &_Path );
+}
+
+INLINE
+PFILETIME
+FSNODE::GetCreationTime(
+ )
+
+
+/*++
+
+Routine Description:
+
+ Returns pointer to creation time.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PFILETIME - pointer to creation time
+
+--*/
+
+{
+ return( &_FileData.ftCreationTime );
+}
+
+INLINE
+PFILETIME
+FSNODE::GetLastAccessTime(
+ )
+
+
+/*++
+
+Routine Description:
+
+ Returns pointer to last access time.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PFILETIME - pointer to last access time
+
+--*/
+
+{
+ return( &_FileData.ftLastAccessTime );
+}
+
+INLINE
+PFILETIME
+FSNODE::GetLastWriteTime(
+ )
+
+
+/*++
+
+Routine Description:
+
+ Returns pointer to last write time.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PFILETIME - pointer to last write time
+
+--*/
+
+{
+ return( &_FileData.ftLastWriteTime );
+}
+
+INLINE
+BOOLEAN
+FSNODE::IsArchived (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if this FSNODE's archived attribute is set.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if this FSNODE's archived attribute is set.
+
+--*/
+
+{
+ return( ( _FileData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE ) != 0 );
+}
+
+INLINE
+BOOLEAN
+FSNODE::IsDirectory (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if this FSNODE's directory attribute is set.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if this FSNODE's directory attribute is set.
+
+--*/
+
+{
+ return( ( _FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) != 0 );
+}
+
+INLINE
+BOOLEAN
+FSNODE::IsHidden (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if this FSNODE's hidden attribute is set.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if this FSNODE's hidden attribute is set.
+
+--*/
+
+{
+ return( ( _FileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN ) != 0 );
+}
+
+INLINE
+BOOLEAN
+FSNODE::IsNormal (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if this FSNODE's normal attribute is set.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if this FSNODE's normal attribute is set.
+
+--*/
+
+{
+ return( ( _FileData.dwFileAttributes & FILE_ATTRIBUTE_NORMAL ) != 0 );
+}
+
+INLINE
+BOOLEAN
+FSNODE::IsReadOnly (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if this FSNODE's readonly attribute is set.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if this FSNODE's readonly attribute is set.
+
+--*/
+
+{
+ return( ( _FileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY ) != 0 );
+}
+
+INLINE
+BOOLEAN
+FSNODE::IsSystem (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if this FSNODE's system attribute is set.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if this FSNODE's system attribute is set.
+
+--*/
+
+{
+ return( ( _FileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM ) != 0 );
+}
+
+INLINE
+BOOLEAN
+FSNODE::MakeArchived (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' archived.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of setting the file's archived attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ _FileData.dwFileAttributes | FILE_ATTRIBUTE_ARCHIVE )) {
+
+ _FileData.dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
+ return( TRUE );
+ } else {
+
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+INLINE
+BOOLEAN
+FSNODE::MakeHidden (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' hidden.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of setting the file's hidden attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ _FileData.dwFileAttributes | FILE_ATTRIBUTE_HIDDEN )) {
+
+ _FileData.dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN;
+ return( TRUE );
+ } else {
+
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+INLINE
+BOOLEAN
+FSNODE::MakeNormal (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' normal.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of resetting all the file's resettable
+ attributes.
+
+Note:
+
+ Making a 'file' normal means resetting all but the
+ FILE_ATTRIBUTE_DIRECTORY attributes.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ FILE_ATTRIBUTE_NORMAL )) {
+
+ _FileData.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
+ return( TRUE );
+ } else {
+
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+INLINE
+BOOLEAN
+FSNODE::MakeReadOnly (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' read-only.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of setting the file's read-only attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ _FileData.dwFileAttributes | FILE_ATTRIBUTE_READONLY )) {
+
+ _FileData.dwFileAttributes |= FILE_ATTRIBUTE_READONLY;
+ return( TRUE );
+ } else {
+
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+INLINE
+BOOLEAN
+FSNODE::MakeSystem (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' a system file.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of setting the file's system attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ _FileData.dwFileAttributes | FILE_ATTRIBUTE_SYSTEM )) {
+
+ _FileData.dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM;
+ return( TRUE );
+ } else {
+
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+INLINE
+PWSTRING
+FSNODE::QueryBase (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the base name maintained by the contained PATH object.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PWSTRING - Returns a pointer to the base name.
+
+--*/
+
+{
+ return( ((PFSNODE) this)->_Path.QueryBase( ));
+}
+
+INLINE
+FSN_ATTRIBUTE
+FSNODE::QueryAttributes (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the node's attributes
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ FSN_ATTRIBUTE - The attributes
+
+--*/
+
+{
+ return( (FSN_ATTRIBUTE)_FileData.dwFileAttributes );
+}
+
+INLINE
+PWSTRING
+FSNODE::QueryName (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the name maintained by the contained PATH object.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PWSTRING - Returns a pointer to the name.
+
+--*/
+
+{
+ return( ((PFSNODE) this)->_Path.QueryName( ));
+}
+
+
+
+INLINE
+BOOLEAN
+FSNODE::ResetArchivedAttribute (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' non archived.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of resetting the file's archived attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ _FileData.dwFileAttributes & ~FILE_ATTRIBUTE_ARCHIVE )) {
+
+ _FileData.dwFileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE;
+ return( TRUE );
+ } else {
+
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+INLINE
+BOOLEAN
+FSNODE::ResetHiddenAttribute (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' non-hidden.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of resetting the file's hidden attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ _FileData.dwFileAttributes & ~FILE_ATTRIBUTE_HIDDEN )) {
+
+ _FileData.dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;
+ return( TRUE );
+ } else {
+
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+
+
+INLINE
+BOOLEAN
+FSNODE::ResetReadOnlyAttribute (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' non-read-only.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of resetting the file's read-only attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ _FileData.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY )) {
+
+ _FileData.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
+ return( TRUE );
+ } else {
+
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+INLINE
+BOOLEAN
+FSNODE::ResetSystemAttribute (
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Make the underlying 'file' a non-system file.
+
+Arguments:
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of setting the file's system attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ _FileData.dwFileAttributes & ~FILE_ATTRIBUTE_SYSTEM )) {
+
+ _FileData.dwFileAttributes &= ~FILE_ATTRIBUTE_SYSTEM;
+ return( TRUE );
+ } else {
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+
+INLINE
+BOOLEAN
+FSNODE::SetAttributes (
+ IN FSN_ATTRIBUTE Attributes,
+ OUT LPDWORD Win32Error
+ )
+
+/*++
+
+Routine Description:
+
+ Set the attributes of the underlying 'file'.
+ (This method was added to improve performance of attrib.exe).
+
+Arguments:
+
+ Attributes - New attributes for the file.
+
+ Win32Error - Optional parameter that will contain a Win32 error code
+ if the method is unable to change attribute.
+
+Return Value:
+
+ BOOLEAN - Returns the result of setting the file's system attribute.
+
+--*/
+
+{
+ if( SetFileAttributesW(( LPWSTR ) _FileData.cFileName,
+ (_FileData.dwFileAttributes & ~FILE_ATTRIBUTE_FILES) | Attributes )) {
+
+ _FileData.dwFileAttributes &= ~FILE_ATTRIBUTE_FILES;
+ _FileData.dwFileAttributes |= Attributes;
+ return( TRUE );
+ } else {
+ if( Win32Error != NULL ) {
+ *Win32Error = GetLastError();
+ }
+ return( FALSE );
+ }
+}
+
+
+
+
+
+#endif // _FSNODE_
diff --git a/private/utils/ulib/inc/hmem.hxx b/private/utils/ulib/inc/hmem.hxx
new file mode 100644
index 000000000..294bf617d
--- /dev/null
+++ b/private/utils/ulib/inc/hmem.hxx
@@ -0,0 +1,152 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ hmem.hxx
+
+Abstract:
+
+ The class HMEM is an implementation of the class MEM which uses the
+ memory resources of the heap.
+
+ After the first call to Acquire that succeeds, all successive calls
+ will return the same memory that was returned by the first call
+ provided that the size requested is within the bounds of the first call.
+ The common buffer which was created upon the first successful call to
+ Acquire will be available along with its size by calling GetBuf and
+ QuerySize.
+
+ Calling Destroy will put the object back in its initial state thus
+ invalidating any pointers to its memory and enabling future calls
+ to Acquire to succeed regardless of the size specicified.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 26-Nov-90
+
+--*/
+
+#if !defined(HMEM_DEFN)
+
+#define HMEM_DEFN
+
+#include "mem.hxx"
+
+DECLARE_CLASS( HMEM );
+
+
+class HMEM : public MEM {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( HMEM );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~HMEM(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ PVOID
+ Acquire(
+ IN ULONG Size,
+ IN ULONG AlignmentMask DEFAULT 0
+ );
+
+ NONVIRTUAL
+ PVOID
+ GetBuf(
+ ) CONST;
+
+ NONVIRTUAL
+ ULONG
+ QuerySize(
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Resize(
+ IN ULONG NewSize,
+ IN ULONG AlignmentMask DEFAULT 0
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy(
+ );
+
+ ULONG _size;
+ PVOID _real_buf;
+ PVOID _buf;
+
+};
+
+
+INLINE
+PVOID
+HMEM::GetBuf(
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns the memory that was previously 'Acquired'.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A pointer to the beginning of the memory buffer.
+
+--*/
+{
+ return _buf;
+}
+
+
+INLINE
+ULONG
+HMEM::QuerySize(
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns the size of the memory that was previously
+ 'Acquired'.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The size of the memory returned by 'GetBuf'.
+
+--*/
+{
+ return _size;
+}
+
+
+#endif // HMEM_DEFN
diff --git a/private/utils/ulib/inc/ifsentry.hxx b/private/utils/ulib/inc/ifsentry.hxx
new file mode 100644
index 000000000..14c57acd9
--- /dev/null
+++ b/private/utils/ulib/inc/ifsentry.hxx
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ifsentry.hxx
+
+Abstract:
+
+ Contains prototypes for entry points to the IFS
+ utility DLLs.
+
+
+Author:
+
+ Bill McJohn (billmc) 04-June-1991
+
+Environment:
+
+ User Mode
+
+--*/
+
+
+#if !defined ( _IFS_ENTRY_ )
+
+#define _IFS_ENTRY_
+
+#if defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ )
+#define FAR
+#define APIENTRY
+#endif // _AUTOCHECK_ || _SETUP_LOADER_
+
+typedef BOOLEAN(FAR APIENTRY * CHKDSK_FN)( PCWSTRING DriveName,
+ PMESSAGE Message,
+ BOOLEAN Fix,
+ BOOLEAN Verbose,
+ BOOLEAN,
+ BOOLEAN Recover,
+ PPATH,
+ BOOLEAN Extend,
+ BOOLEAN ResizeLogFile,
+ ULONG LogFileSize,
+ PULONG ExitStatus);
+
+typedef BOOLEAN(FAR APIENTRY * FORMAT_FN)( PCWSTRING,
+ PMESSAGE,
+ BOOLEAN,
+ MEDIA_TYPE,
+ PCWSTRING,
+ ULONG );
+
+
+typedef BOOLEAN(FAR APIENTRY * RECOVER_FN)( PPATH, PMESSAGE );
+
+typedef BOOLEAN (FAR APIENTRY * EXTEND_FN)(PCWSTRING, PMESSAGE, BOOLEAN Verify);
+
+//
+// Convert status code
+//
+typedef enum _CONVERT_STATUS {
+
+ CONVERT_STATUS_CONVERTED,
+ CONVERT_STATUS_INVALID_FILESYSTEM,
+ CONVERT_STATUS_CONVERSION_NOT_AVAILABLE,
+ CONVERT_STATUS_CANNOT_LOCK_DRIVE,
+ CONVERT_STATUS_ERROR,
+ CONVERT_STATUS_INSUFFICIENT_SPACE
+
+} CONVERT_STATUS, *PCONVERT_STATUS;
+
+
+typedef BOOLEAN(FAR APIENTRY * CONVERT_FN)( PCWSTRING,
+ PCWSTRING,
+ PMESSAGE,
+ BOOLEAN,
+ BOOLEAN,
+ PCONVERT_STATUS );
+
+typedef BOOLEAN (FAR APIENTRY * CHECKSPACE_FN)(
+ PCWSTRING,
+ PCWSTRING,
+ PMESSAGE,
+ BOOLEAN,
+ BOOLEAN,
+ BOOLEAN );
+
+typedef BOOLEAN(FAR APIENTRY * NAMETABLE_FN)( PCWSTRING,
+ PCWSTRING,
+ PMESSAGE );
+
+#endif // _IFS_ENTRY_
diff --git a/private/utils/ulib/inc/ifsserv.hxx b/private/utils/ulib/inc/ifsserv.hxx
new file mode 100644
index 000000000..7ae523505
--- /dev/null
+++ b/private/utils/ulib/inc/ifsserv.hxx
@@ -0,0 +1,109 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ifsentry.hxx
+
+Abstract:
+
+ Contains prototypes for entry points to the IFS
+ utility DLLs.
+
+
+Author:
+
+ Bill McJohn (billmc) 04-June-1991
+
+Environment:
+
+ User Mode
+
+--*/
+
+
+#if !defined ( _IFS_ENTRY_ )
+
+#define _IFS_ENTRY_
+
+#if defined( _AUTOCHECK_ ) && !defined( _SETUP_LOADER_ )
+#define FAR
+#define APIENTRY
+#endif // _AUTOCHECK_ || _SETUP_LOADER_
+
+extern "C"
+BOOLEAN
+FAR APIENTRY
+Chkdsk(
+ IN PCWSTRING NtDriveName,
+ IN OUT PMESSAGE Message,
+ IN BOOLEAN Fix,
+ IN BOOLEAN Verbose,
+ IN BOOLEAN OnlyIfDirty,
+ IN BOOLEAN Recover,
+ IN PPATH PathToCheck,
+ IN BOOLEAN Extend,
+ IN BOOLEAN ResizeLogFile,
+ IN ULONG LogFilesize,
+ OUT PULONG ExitStatus
+ );
+
+extern "C"
+BOOLEAN
+FAR APIENTRY
+Format(
+ IN PCWSTRING NtDriveName,
+ IN OUT PMESSAGE Message,
+ IN BOOLEAN Quick,
+ IN MEDIA_TYPE MediaType,
+ IN PCWSTRING LabelString,
+ IN ULONG ClusterSize
+ );
+
+extern "C"
+BOOLEAN
+FAR APIENTRY
+Recover(
+ IN PPATH RecFilePath,
+ IN OUT PMESSAGE Message
+ );
+
+extern "C"
+BOOLEAN
+FAR APIENTRY
+Extend(
+ IN PCWSTRING NtDriveName,
+ IN OUT PMESSAGE Message,
+ IN BOOLEAN Verify
+ );
+
+
+//
+// Convert status code
+//
+typedef enum _CONVERT_STATUS {
+
+ CONVERT_STATUS_CONVERTED,
+ CONVERT_STATUS_INVALID_FILESYSTEM,
+ CONVERT_STATUS_CONVERSION_NOT_AVAILABLE,
+ CONVERT_STATUS_CANNOT_LOCK_DRIVE,
+ CONVERT_STATUS_ERROR,
+ CONVERT_STATUS_INSUFFICIENT_SPACE
+
+} CONVERT_STATUS, *PCONVERT_STATUS;
+
+extern "C"
+BOOLEAN
+FAR APIENTRY
+Convert(
+ IN PCWSTRING NtDriveName,
+ IN PCWSTRING FsName,
+ IN OUT PMESSAGE Message,
+ IN BOOLEAN Verbose,
+ IN BOOLEAN Pause,
+ OUT PCONVERT_STATUS Status
+ );
+
+
+#endif // _IFS_ENTRY_
diff --git a/private/utils/ulib/inc/iterator.hxx b/private/utils/ulib/inc/iterator.hxx
new file mode 100644
index 000000000..3ea89ae8a
--- /dev/null
+++ b/private/utils/ulib/inc/iterator.hxx
@@ -0,0 +1,78 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ iterator.hxx
+
+Abstract:
+
+ This module contains the declaration for the abstract ITERATOR class.
+ ITERATORS are used to iterate over a CONTAINER allowing for multiple,
+ simultaneous readers. ITERATORs maintain the currency needed to perform
+ an iteration. This includes the current OBJECT in the CONTAINER and the
+ currency needed to get the next or previous OBJECT. ITERATORs also
+ provide the capability of wrapping when the end or begin of the container
+ is reached.
+
+Author:
+
+ David J. Gilman (davegi) 29-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _ITERATOR_ )
+
+#define _ITERATOR_
+
+DECLARE_CLASS( ITERATOR );
+
+
+class ITERATOR : public OBJECT {
+
+ public:
+
+ VIRTUAL
+ ~ITERATOR(
+ );
+
+ VIRTUAL
+ POBJECT
+ FindNext(
+ IN PCOBJECT Key
+ );
+
+ VIRTUAL
+ POBJECT
+ GetCurrent(
+ ) PURE;
+
+ VIRTUAL
+ POBJECT
+ GetNext(
+ ) PURE;
+
+ VIRTUAL
+ POBJECT
+ GetPrevious(
+ ) PURE;
+
+ VIRTUAL
+ VOID
+ Reset(
+ ) PURE;
+
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( ITERATOR );
+
+};
+
+
+#endif // _ITERATOR_
diff --git a/private/utils/ulib/inc/keyboard.hxx b/private/utils/ulib/inc/keyboard.hxx
new file mode 100644
index 000000000..f605b3198
--- /dev/null
+++ b/private/utils/ulib/inc/keyboard.hxx
@@ -0,0 +1,201 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ keyboard.hxx
+
+Abstract:
+
+ This module contains the declaration for the KEYBOARD class.
+ The KEYBOARD class is a derived from BUFFER_STREAM that provides
+ methods to access the keyboard as a stream of bytes with read-only
+ access.
+ It also provides some methods that set/reset the keyboard mode.
+
+
+Author:
+
+ Jaime Sasson (jaimes) 21-Mar-1991
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+
+#if !defined( _KEYBOARD_ )
+
+#define _KEYBOARD_
+
+#include "bufstrm.hxx"
+
+
+
+DECLARE_CLASS( KEYBOARD );
+
+class KEYBOARD : public BUFFER_STREAM {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( KEYBOARD );
+
+ ULIB_EXPORT
+ DECLARE_CAST_MEMBER_FUNCTION( KEYBOARD );
+
+
+ NONVIRTUAL
+ ~KEYBOARD (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN BOOLEAN LineMode DEFAULT TRUE,
+ IN BOOLEAN EchoMode DEFAULT TRUE
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ DisableBreakHandling (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ DisableEchoMode(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DisableLineMode(
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ EnableBreakHandling (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ EnableEchoMode(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ EnableLineMode(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ EndOfFile(
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ FillBuffer(
+ IN PBYTE Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG BytesRead
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Flush(
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ GotABreak (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ IsEchoModeEnabled(
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsKeyAvailable(
+ OUT PBOOLEAN Available
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsLineModeEnabled(
+ ) CONST;
+
+ VIRTUAL
+ STREAMACCESS
+ QueryAccess(
+ ) CONST;
+
+ NONVIRTUAL
+ ULONG
+ QueryDelay (
+ ) CONST;
+
+ VIRTUAL
+ HANDLE
+ QueryHandle(
+ ) CONST;
+
+ NONVIRTUAL
+ ULONG
+ QuerySpeed (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ SetDelay (
+ IN ULONG Delay
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ SetSpeed (
+ IN ULONG Speed
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ CONST
+ PBOOL
+ GetPFlagBreak (
+ VOID
+ ) CONST;
+
+ private:
+
+ HANDLE _KeyboardHandle;
+ ULONG _PreviousMode;
+ BOOLEAN _FlagCtrlZ;
+ STATIC BOOL _FlagBreak;
+
+ NONVIRTUAL
+ BOOLEAN
+ CheckForAsciiKey(
+ IN PINPUT_RECORD InputRecord,
+ IN ULONG NumberOfInputRecords
+ ) CONST;
+
+ STATIC
+ BOOL
+ BreakHandler (
+ IN ULONG CtrlType
+ );
+
+};
+
+#endif // _KEYBOARD_
diff --git a/private/utils/ulib/inc/list.hxx b/private/utils/ulib/inc/list.hxx
new file mode 100644
index 000000000..da5932343
--- /dev/null
+++ b/private/utils/ulib/inc/list.hxx
@@ -0,0 +1,115 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ list.hxx
+
+Abstract:
+
+ This class is an implementation of the SEQUENTIAL_CONTAINER
+ protocol. The specific implementation is that of a doubly
+ linked list.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 22-Oct-91
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if !defined( _LIST_DEFN_ )
+
+#define _LIST_DEFN_
+
+#include "seqcnt.hxx"
+#include "membmgr.hxx"
+
+
+struct OBJECT_LIST_NODE {
+ OBJECT_LIST_NODE* next;
+ OBJECT_LIST_NODE* prev;
+ POBJECT data;
+};
+
+DEFINE_POINTER_AND_REFERENCE_TYPES( OBJECT_LIST_NODE );
+
+DECLARE_CLASS( LIST );
+
+class LIST : public SEQUENTIAL_CONTAINER {
+
+ FRIEND class LIST_ITERATOR;
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( LIST );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~LIST(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ );
+
+ VIRTUAL
+ ULONG
+ QueryMemberCount(
+ ) CONST;
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Put(
+ IN OUT POBJECT Member
+ );
+
+ VIRTUAL
+ POBJECT
+ Remove(
+ IN OUT PITERATOR Position
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ PITERATOR
+ QueryIterator(
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Insert(
+ IN OUT POBJECT Member,
+ IN OUT PITERATOR Position
+ );
+
+ private:
+
+ POBJECT_LIST_NODE _head;
+ POBJECT_LIST_NODE _tail;
+ ULONG _count;
+ MEM_BLOCK_MGR _mem_block_mgr;
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy(
+ );
+
+};
+
+
+#endif // _LIST_DEFN_
diff --git a/private/utils/ulib/inc/listit.hxx b/private/utils/ulib/inc/listit.hxx
new file mode 100644
index 000000000..0dfbbac59
--- /dev/null
+++ b/private/utils/ulib/inc/listit.hxx
@@ -0,0 +1,118 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ listit.hxx
+
+Abstract:
+
+ This is an implementation of iterator for LIST.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 24-Oct-91
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _LIST_ITERATOR_ )
+
+#define _LIST_ITERATOR_
+
+#include "iterator.hxx"
+#include "list.hxx"
+
+DECLARE_CLASS( LIST_ITERATOR );
+
+class LIST_ITERATOR : public ITERATOR {
+
+ FRIEND class LIST;
+
+ public:
+
+ DECLARE_CONSTRUCTOR( LIST_ITERATOR );
+
+ DECLARE_CAST_MEMBER_FUNCTION( LIST_ITERATOR );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN PCLIST List
+ );
+
+ VIRTUAL
+ VOID
+ Reset(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetCurrent(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetNext(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetPrevious(
+ );
+
+ private:
+
+ POBJECT_LIST_NODE _current;
+ PCLIST _list;
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+};
+
+
+INLINE
+VOID
+LIST_ITERATOR::Construct(
+ )
+/*++
+
+Routine Description:
+
+ This routine resets LIST_ITERATOR.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ _current = NULL;
+ _list = NULL;
+}
+
+
+INLINE
+BOOLEAN
+LIST_ITERATOR::Initialize(
+ IN PCLIST List
+ )
+{
+ DebugAssert(List);
+ _list = List;
+ return TRUE;
+}
+
+
+#endif // _LIST_ITERATOR_
diff --git a/private/utils/ulib/inc/machine.hxx b/private/utils/ulib/inc/machine.hxx
new file mode 100644
index 000000000..9cfdb6f6b
--- /dev/null
+++ b/private/utils/ulib/inc/machine.hxx
@@ -0,0 +1,77 @@
+
+#if defined(JAPAN) && defined(_X86_)
+#if !defined(_MACHINE_DEFN_)
+
+#define _MACHINE_DEFN_
+
+extern "C" {
+ #include "windows.h"
+ #include "machine.h"
+}
+
+#if defined( _AUTOCHECK_ )
+
+extern "C"
+InitializeMachineId(
+ VOID
+);
+
+extern DWORD _dwMachineId;
+
+#define InitializeMachineData() InitializeMachineId();
+
+#define IsFMR_N() ( ISFUJITSUFMR( _dwMachineId ) )
+
+#define IsPC98_N() ( ISNECPC98( _dwMachineId ) )
+
+#define IsPCAT_N() ( ISMICROSOFT( _dwMachineId ) )
+
+#else
+
+DECLARE_CLASS( MACHINE );
+
+class MACHINE : public OBJECT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( MACHINE );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize( VOID );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsFMR( VOID );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsPC98( VOID );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsPCAT( VOID );
+
+ private:
+
+ STATIC DWORD _dwMachineId;
+};
+
+extern ULIB_EXPORT MACHINE MachinePlatform;
+
+#define InitializeMachineData() MachinePlatform.Initialize()
+
+#define IsFMR_N() MachinePlatform.IsFMR()
+
+#define IsPC98_N() MachinePlatform.IsPC98()
+
+#define IsPCAT_N() MachinePlatform.IsPCAT()
+
+#endif // defiend(_AUTOCHECK_)
+#endif // defined(JAPAN) && defiend(_X86_)
+#endif
diff --git a/private/utils/ulib/inc/mbstr.hxx b/private/utils/ulib/inc/mbstr.hxx
new file mode 100644
index 000000000..6b3c5ee14
--- /dev/null
+++ b/private/utils/ulib/inc/mbstr.hxx
@@ -0,0 +1,434 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ mbstr.hxx
+
+Abstract:
+
+ This module contains the definition 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:
+
+
+
+--*/
+
+#if ! defined( _MBSTR_ )
+
+#define _MBSTR_
+
+
+extern "C" {
+ #include <stdarg.h>
+ #include <string.h>
+ #include <memory.h>
+}
+
+DECLARE_CLASS( MBSTR );
+
+class MBSTR {
+
+ public:
+
+ STATIC
+ PVOID
+ Memcpy (
+ INOUT PVOID Src,
+ INOUT PVOID Dst,
+ IN DWORD Size
+ );
+
+ STATIC
+ PVOID
+ Memset (
+ INOUT PVOID Src,
+ IN BYTE Byte,
+ IN DWORD Size
+ );
+
+
+ STATIC
+ PSTR
+ Strcat (
+ INOUT PSTR String1,
+ IN PSTR String2
+ );
+
+ STATIC
+ PSTR
+ Strchr (
+ IN PSTR String,
+ IN CHAR Char
+ );
+
+
+ STATIC
+ INT
+ Strcmp (
+ IN PSTR String1,
+ IN PSTR String2
+ );
+
+
+#ifdef DBCS
+//fix kksuzuka: #931
+//enabling DBCS with stricmp
+ STATIC
+ ULIB_EXPORT
+ INT
+ Stricmp (
+ IN PSTR p1,
+ IN PSTR p2
+ );
+#else
+ STATIC
+ INT
+ Stricmp (
+ IN PSTR String1,
+ IN PSTR String2
+ );
+#endif
+
+
+ STATIC
+ ULIB_EXPORT
+ INT
+ Strcmps (
+ IN PSTR p1,
+ IN PSTR p2
+ );
+
+ STATIC
+ ULIB_EXPORT
+ INT
+ Strcmpis (
+ IN PSTR p1,
+ IN PSTR p2
+ );
+
+
+ STATIC
+ PSTR
+ Strcpy (
+ INOUT PSTR String1,
+ IN PSTR String2
+ );
+
+
+ STATIC
+ DWORD
+ Strcspn (
+ IN PSTR String1,
+ IN PSTR String2
+ );
+
+ STATIC
+ PSTR
+ Strdup (
+ IN PSTR String
+ );
+
+
+ STATIC
+ DWORD
+ Strlen (
+ IN PSTR String
+ );
+
+
+ STATIC
+ PSTR
+ Strlwr (
+ INOUT PSTR String
+ );
+
+ STATIC
+ PSTR
+ Strncat (
+ INOUT PSTR String1,
+ IN PSTR String2,
+ DWORD Size
+ );
+
+
+ STATIC
+ INT
+ Strncmp (
+ IN PSTR String1,
+ IN PSTR String2,
+ IN DWORD Size
+ );
+
+
+ STATIC
+ DWORD
+ Strspn (
+ IN PSTR String1,
+ IN PSTR String2
+ );
+
+
+#ifdef DBCS
+//fix kksuzuka: #926
+//enabling DBCS with strstr
+ STATIC
+ ULIB_EXPORT
+ PSTR
+ Strstr (
+ IN PSTR String1,
+ IN PSTR String2
+ );
+#else
+ STATIC
+ PSTR
+ Strstr (
+ IN PSTR String1,
+ IN PSTR String2
+ );
+#endif
+
+ STATIC
+ PSTR
+ Strupr (
+ INOUT PSTR String
+ );
+
+
+ STATIC
+ PSTR*
+ MakeLineArray (
+ INOUT PSTR* Buffer,
+ INOUT PDWORD BufferSize,
+ INOUT PDWORD NumberOfLines
+ );
+
+ STATIC
+ DWORD
+ Hash(
+ IN PSTR String,
+ IN DWORD Buckets DEFAULT 211,
+ IN DWORD BytesToSum DEFAULT (DWORD)-1
+ );
+
+
+ private:
+
+#ifdef DBCS
+ STATIC
+ INT
+ CheckSpace(
+ IN PSTR s
+ );
+#endif
+
+ STATIC
+ PSTR
+ SkipWhite(
+ IN PSTR p
+ );
+
+
+};
+
+
+INLINE
+PVOID
+MBSTR::Memcpy (
+ INOUT PVOID Src,
+ INOUT PVOID Dst,
+ IN DWORD Size
+ )
+{
+ return memcpy( Src, Dst, (size_t)Size );
+}
+
+
+INLINE
+PVOID
+MBSTR::Memset (
+ INOUT PVOID Src,
+ IN BYTE Byte,
+ IN DWORD Size
+ )
+{
+ return memset( Src, Byte, (size_t)Size );
+}
+
+
+
+INLINE
+PSTR
+MBSTR::Strcat (
+ INOUT PSTR String1,
+ IN PSTR String2
+ )
+{
+ return strcat( String1, String2 );
+}
+
+INLINE
+PSTR
+MBSTR::Strchr (
+ IN PSTR String,
+ IN CHAR Char
+ )
+{
+ return strchr( String, Char );
+}
+
+
+INLINE
+INT
+MBSTR::Strcmp (
+ IN PSTR String1,
+ IN PSTR String2
+ )
+{
+ return strcmp( String1, String2 );
+}
+
+
+#ifndef DBCS
+//fix kksuzuka: #931
+//enabling DBCS with stricmp
+INLINE
+INT
+MBSTR::Stricmp (
+ IN PSTR String1,
+ IN PSTR String2
+ )
+{
+ return _stricmp( String1, String2 );
+}
+#endif
+
+
+INLINE
+PSTR
+MBSTR::Strcpy (
+ INOUT PSTR String1,
+ IN PSTR String2
+ )
+{
+ return strcpy( String1, String2 );
+}
+
+
+INLINE
+DWORD
+MBSTR::Strcspn (
+ IN PSTR String1,
+ IN PSTR String2
+ )
+{
+ return strcspn( String1, String2 );
+}
+
+
+INLINE
+PSTR
+MBSTR::Strdup (
+ IN PSTR String
+ )
+{
+ return _strdup( String );
+}
+
+
+INLINE
+DWORD
+MBSTR::Strlen (
+ IN PSTR String
+ )
+{
+ return strlen( String );
+}
+
+
+INLINE
+PSTR
+MBSTR::Strlwr (
+ INOUT PSTR String
+ )
+{
+ return _strlwr( String );
+}
+
+
+INLINE
+PSTR
+MBSTR::Strncat (
+ INOUT PSTR String1,
+ IN PSTR String2,
+ DWORD Size
+ )
+{
+ return strncat( String1, String2, (unsigned int)Size );
+}
+
+
+INLINE
+INT
+MBSTR::Strncmp (
+ IN PSTR String1,
+ IN PSTR String2,
+ IN DWORD Size
+ )
+{
+ return strncmp( String1, String2, (size_t)Size );
+}
+
+
+INLINE
+DWORD
+MBSTR::Strspn (
+ IN PSTR String1,
+ IN PSTR String2
+ )
+{
+ return strspn( String1, String2 );
+}
+
+#ifndef DBCS
+//fix kksuzuka: #926
+//enabling DBCS with strstr
+INLINE
+PSTR
+MBSTR::Strstr (
+ IN PSTR String1,
+ IN PSTR String2
+ )
+{
+ return strstr( String1, String2 );
+}
+#endif
+
+
+INLINE
+PSTR
+MBSTR::Strupr (
+ INOUT PSTR String
+ )
+{
+ return _strupr( String );
+}
+
+
+
+
+
+#endif // _MBSTR_
diff --git a/private/utils/ulib/inc/mem.hxx b/private/utils/ulib/inc/mem.hxx
new file mode 100644
index 000000000..f0c316e77
--- /dev/null
+++ b/private/utils/ulib/inc/mem.hxx
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ mem.hxx
+
+Abstract:
+
+ The class MEM contains one pure virtual function named 'Acquire'.
+ The implementors and users of this class must follow some simple
+ constraints.
+
+ Acquire will return a pointer to Size bytes of memory or NULL.
+
+ A function taking a MEM as an argument should call Acquire at most one
+ time. It should not, for instance, cache a pointer to the MEM for
+ future calls to Acquire.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 26-Nov-90
+
+--*/
+
+#if !defined(MEM_DEFN)
+
+#define MEM_DEFN
+
+DECLARE_CLASS( MEM );
+
+class MEM : public OBJECT {
+
+ public:
+
+ VIRTUAL
+ PVOID
+ Acquire(
+ IN ULONG Size,
+ IN ULONG AlignmentMask DEFAULT 0
+ ) PURE;
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( MEM );
+
+};
+
+#endif // MEM_DEFN
diff --git a/private/utils/ulib/inc/membmgr.hxx b/private/utils/ulib/inc/membmgr.hxx
new file mode 100644
index 000000000..f3332048e
--- /dev/null
+++ b/private/utils/ulib/inc/membmgr.hxx
@@ -0,0 +1,258 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ membmgr.hxx
+
+Abstract:
+
+ This class offers two classes for the management of fixed
+ size blocks of memory. The first class STATIC_MEM_BLOCK_MGR
+ allows the user to allocate and free fixed size memory blocks
+ up to the specified limit that the class was initialized to.
+
+ The second class MEM_BLOCK_MGR offers a scheme for memory block
+ management that will grow as the clients needs increase.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 29-May-92
+
+--*/
+
+#if !defined(_MEM_BLOCK_MGR_DEFN_)
+
+#define _MEM_BLOCK_MGR_DEFN_
+
+
+#include "array.hxx"
+#include "bitvect.hxx"
+
+
+DECLARE_CLASS( STATIC_MEM_BLOCK_MGR );
+
+class STATIC_MEM_BLOCK_MGR : public OBJECT {
+
+ public:
+
+ DECLARE_CONSTRUCTOR( STATIC_MEM_BLOCK_MGR );
+
+ VIRTUAL
+ ~STATIC_MEM_BLOCK_MGR(
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN ULONG MemBlockSize,
+ IN ULONG NumBlocks DEFAULT 128
+ );
+
+ NONVIRTUAL
+ PVOID
+ Alloc(
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Free(
+ OUT PVOID MemBlock
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryBlockSize(
+ ) CONST;
+
+ NONVIRTUAL
+ ULONG
+ QueryNumBlocks(
+ ) CONST;
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy(
+ );
+
+ PCHAR _heap;
+ ULONG _num_blocks;
+ ULONG _block_size;
+ ULONG _num_allocated;
+ ULONG _next_alloc;
+ BITVECTOR _bitvector;
+
+};
+
+
+INLINE
+ULONG
+STATIC_MEM_BLOCK_MGR::QueryBlockSize(
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine return the number of bytes in a block returned
+ by this object.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The number of bytes per block.
+
+--*/
+{
+ return _block_size;
+}
+
+
+INLINE
+ULONG
+STATIC_MEM_BLOCK_MGR::QueryNumBlocks(
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine return the number of blocks contained
+ by this object.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The number of blocks.
+
+--*/
+{
+ return _num_blocks;
+}
+
+
+
+DECLARE_CLASS( MEM_BLOCK_MGR );
+
+class MEM_BLOCK_MGR : public OBJECT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( MEM_BLOCK_MGR );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~MEM_BLOCK_MGR(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN ULONG MemBlockSize,
+ IN ULONG InitialNumBlocks DEFAULT 128
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PVOID
+ Alloc(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Free(
+ OUT PVOID MemBlock
+ );
+
+ NONVIRTUAL
+ ULONG
+ QueryBlockSize(
+ ) CONST;
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy(
+ );
+
+ PSTATIC_MEM_BLOCK_MGR _static_mem_list[32];
+
+};
+
+
+INLINE
+ULONG
+MEM_BLOCK_MGR::QueryBlockSize(
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine return the number of bytes in a block returned
+ by this object.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The number of bytes per block.
+
+--*/
+{
+ return _static_mem_list[0] ? _static_mem_list[0]->QueryBlockSize() : 0;
+}
+
+
+INLINE
+PVOID
+operator new(
+ IN size_t Size,
+ IN PVOID Pointer
+ )
+/*++
+
+Routine Description:
+
+ This is an explicit placement version of the 'new' operator
+ which clients of these classes may wish to use in order to
+ call the constructor on their newly allocated objects.
+
+Arguments:
+
+ Size - Supplies the size of the buffer.
+ Pointer - Supplies a pointer to the buffer.
+
+Return Value:
+
+ This function returns the passed in pointer.
+
+--*/
+{
+ return Pointer;
+}
+
+
+#endif // _MEM_BLOCK_MGR_DEFN_
diff --git a/private/utils/ulib/inc/message.hxx b/private/utils/ulib/inc/message.hxx
new file mode 100644
index 000000000..2747fabcc
--- /dev/null
+++ b/private/utils/ulib/inc/message.hxx
@@ -0,0 +1,203 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ message.hxx
+
+Abstract:
+
+ The MESSAGE class provides a dummy implementation of a message displayer
+ class. Message displayers are meant to be used by applications to
+ relay information to the user. Many functions will require a 'MESSAGE'
+ parameter through which to relay their output.
+
+ This particular implementation of this concept will do nothing. It
+ will be used by users who do not wish to have any output from their
+ applications.
+
+ Additionally, this class serves as a base class to real implementations
+ of the virtual methods.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 1-Apr-91
+
+--*/
+
+
+#if !defined(MESSAGE_DEFN)
+
+#define MESSAGE_DEFN
+
+#include "wstring.hxx"
+
+extern "C" {
+ #include <stdarg.h>
+}
+
+enum MESSAGE_TYPE {
+ NORMAL_MESSAGE,
+ ERROR_MESSAGE,
+ PROGRESS_MESSAGE
+};
+
+//
+// Each message also has a visualization: text or GUI. The default is both
+//
+
+#define TEXT_MESSAGE 0x1
+#define GUI_MESSAGE 0x2
+#define NORMAL_VISUAL (TEXT_MESSAGE | GUI_MESSAGE)
+
+
+DECLARE_CLASS( MESSAGE );
+DECLARE_CLASS( HMEM );
+
+
+DEFINE_TYPE(ULONG, MSGID);
+
+
+class MESSAGE : public OBJECT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR(MESSAGE);
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~MESSAGE(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Set(
+ IN MSGID MsgId,
+ IN MESSAGE_TYPE MessageType DEFAULT NORMAL_MESSAGE,
+ IN ULONG MessageVisual DEFAULT NORMAL_VISUAL
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Display(
+ IN PCSTR Format ...
+ );
+
+ VIRTUAL
+ BOOLEAN
+ DisplayV(
+ IN PCSTR Format,
+ IN va_list VarPointer
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Display(
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsYesResponse(
+ IN BOOLEAN Default DEFAULT TRUE
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ QueryStringInput(
+ OUT PWSTRING String
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ WaitForUserSignal(
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ MSGID
+ SelectResponse(
+ IN ULONG NumberOfSelections ...
+ );
+
+ VIRTUAL
+ PMESSAGE
+ Dup(
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsLoggingEnabled(
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ VOID
+ SetLoggingEnabled(
+ IN BOOLEAN Enable DEFAULT TRUE
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ VOID
+ ResetLoggingIterator(
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ QueryNextLoggedMessage(
+ OUT PFSTRING MessageText
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ QueryPackedLog(
+ IN OUT PHMEM Mem,
+ OUT PULONG PackedDataLength
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetDotsOnly(
+ IN BOOLEAN DotsState
+ );
+};
+
+
+
+INLINE
+BOOLEAN
+MESSAGE::Display(
+ )
+/*++
+
+Routine Description:
+
+ This routine displays the message with no parameters.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ FALSE - Failure.
+ TRUE - Success.
+
+--*/
+{
+ return Display("");
+}
+
+
+
+#endif // MESSAGE_DEFN
diff --git a/private/utils/ulib/inc/newdelp.hxx b/private/utils/ulib/inc/newdelp.hxx
new file mode 100644
index 000000000..f12823d3c
--- /dev/null
+++ b/private/utils/ulib/inc/newdelp.hxx
@@ -0,0 +1,73 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ newdelp.hxx
+
+Abstract:
+
+ This module contains the private definitions used by Ulib's
+ implementation of the new and delete operators and the CRT's malloc,
+ calloc, realloc and free functions.
+
+Author:
+
+ David J. Gilman (davegi) 07-Dec-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+//
+// MEM_BLOCK header signature type and value.
+//
+
+DEFINE_TYPE( ULONG, MEM_BLOCKSIG );
+CONST MEM_BLOCKSIG Signature = 0xDEADDEAD;
+
+//
+// Maximum length of caller's file name.
+//
+
+CONST ULONG MaxFileLength = 20;
+
+//
+// Maximum size of call stack recorded.
+//
+
+CONST ULONG MaxCallStack = 20;
+
+//
+// MEM_BLOCK is the header attached to all allocated memory blocks.
+// Do not change the order of these fields without fixing the initialization
+// of the dummy MEM_BLOCK in newdel.cxx.
+//
+
+struct _MEM_BLOCK {
+ _MEM_BLOCK* pmemNext;
+ _MEM_BLOCK* pmemPrev;
+ MEM_BLOCKSIG memsig;
+ ULONG line;
+ ULONG size;
+ STR file[ MaxFileLength ];
+ DWORD call[ MaxCallStack ];
+};
+
+DEFINE_TYPE( struct _MEM_BLOCK, MEM_BLOCK );
+
+//
+// Returns the root of the stack frame list.
+//
+
+extern "C" {
+
+ VOID
+ DoStackTrace(
+ DWORD CallStack[]
+ );
+
+};
diff --git a/private/utils/ulib/inc/object.hxx b/private/utils/ulib/inc/object.hxx
new file mode 100644
index 000000000..81a37bbae
--- /dev/null
+++ b/private/utils/ulib/inc/object.hxx
@@ -0,0 +1,343 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ Object.hxx
+
+Abstract:
+
+ This module contains the class declaration for the OBJECT class,
+ the root of the Ulib hierarchy. OBJECT is a very important class as
+ it provides default (and sometimes NONVIRTUAL) implementations for
+ helping to identify and classify all other objects at run-time. This
+ capability allows CONTAINERs to manipulate OBJECTs rather than a given
+ derived class of objects. OBJECTs supply the most primitive support for
+ polymorphism within the library. Along with CLASS_DESCRIPTORs they supply
+ the ability to safely determine (Cast) if an OBJECT is of a given class
+ at run-time.
+
+Author:
+
+ David J. Gilman (davegi) 22-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _OBJECT_HXX_ )
+
+#define _OBJECT_HXX_
+
+#include "clasdesc.hxx"
+
+DECLARE_CLASS( OBJECT );
+
+#if DBG == 1
+
+ extern "C" {
+
+ #include <stdio.h>
+ };
+
+ #define DECLARE_OBJECT_DBG_FUNCTIONS \
+ \
+ VIRTUAL \
+ ULIB_EXPORT \
+ VOID \
+ DebugDump ( \
+ IN BOOLEAN Deep DEFAULT FALSE \
+ ) CONST; \
+ \
+ NONVIRTUAL \
+ PCCLASS_NAME \
+ DebugGetClassName ( \
+ ) CONST;
+
+ #define DEFINE_OBJECT_DBG_FUNCTIONS \
+ \
+ ULIB_EXPORT \
+ VOID \
+ OBJECT::DebugDump ( \
+ IN BOOLEAN Deep \
+ ) CONST \
+ { \
+ (void)(Deep); \
+ DebugPtrAssert( _ClassDescriptor ); \
+ } \
+ \
+ PCCLASS_NAME \
+ OBJECT::DebugGetClassName ( \
+ ) CONST \
+ { \
+ DebugPtrAssert( _ClassDescriptor ); \
+ return( _ClassDescriptor->DebugGetClassName( ));\
+ }
+
+
+ //
+ // Debug functions should never be invoked directly. Instead use the
+ // following Dbg macros. Inline functions are not used so that no space
+ // is used in the object when debugging is disabled.
+ //
+
+ #define DbgDump( pobj ) \
+ ( pobj )->DebugDump( FALSE );
+
+ #define DbgDumpAll( pobj ) \
+ ( pobj )->DebugDump( TRUE );
+
+ #define DbgDumpDeep( pobj, flag ) \
+ ( pobj )->DebugDump( flag );
+
+#else // DBG==0
+
+ #define DECLARE_OBJECT_DBG_FUNCTIONS
+
+ #define DEFINE_OBJECT_DBG_FUNCTIONS
+
+ #define DbgDump( pobj )
+
+ #define DbgDumpAll( pobj )
+
+ #define DbgDumpDeep( pobj, flag )
+
+#endif // DBG
+
+class OBJECT {
+
+ public:
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~OBJECT(
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ LONG
+ Compare(
+ IN PCOBJECT Object
+ ) CONST;
+
+ NONVIRTUAL
+ PCCLASS_DESCRIPTOR
+ GetClassDescriptor(
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsSameClass(
+ IN PCOBJECT Object
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsSameObject(
+ IN PCOBJECT Object
+ ) CONST;
+
+ NONVIRTUAL
+ CLASS_ID
+ QueryClassId(
+ ) CONST;
+
+ DECLARE_OBJECT_DBG_FUNCTIONS
+
+ protected:
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ OBJECT(
+ );
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ NONVIRTUAL
+ VOID
+ SetClassDescriptor(
+ IN PCCLASS_DESCRIPTOR ClassDescriptor
+ );
+
+ private:
+
+ PCCLASS_DESCRIPTOR _ClassDescriptor;
+
+};
+
+
+INLINE
+VOID
+OBJECT::Construct(
+ )
+{
+}
+
+
+INLINE
+CLASS_ID
+OBJECT::QueryClassId (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Return the CLASSID for this object.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ CLASSID - The CLASSID as maintained by the object's CLASS_DESCRIPTOR.
+
+Notes:
+
+ This function used to be at the end of clasdesac.hxx with th following
+ note:
+
+ This member functions is for OBJECT, not for CLASS_DESCRIPTOR. It is
+ defined here because it requires CLASS_DESCRIPTOR to be defined in
+ order to make it inline.
+
+--*/
+
+{
+ DebugPtrAssert( _ClassDescriptor );
+
+ return _ClassDescriptor->QueryClassId();
+}
+
+
+INLINE
+VOID
+OBJECT::SetClassDescriptor (
+ IN PCCLASS_DESCRIPTOR ClassDescriptor
+ )
+
+/*++
+
+Routine Description:
+
+ Set the CLASS_DESCRIPTOR for a derived class.
+
+Arguments:
+
+ ClassDescriptor - Supplies a pointer to the derived class'
+ CLASS_DECRIPTOR.
+
+Return Value:
+
+ None.
+
+Notes:
+
+ This function should only be called by the DEFINE_CONSTRUCTOR macro.
+
+--*/
+
+{
+ DebugPtrAssert( ClassDescriptor );
+ _ClassDescriptor = ClassDescriptor;
+}
+
+
+
+INLINE
+PCCLASS_DESCRIPTOR
+OBJECT::GetClassDescriptor (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Gain access to the object's CLASS_DESCRIPTOR.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PCCLASS_DESCRIPTOR - A pointer to the CLASS_DESCRIPTOR asscoicated with
+ this object.
+
+--*/
+
+{
+ DebugPtrAssert( _ClassDescriptor );
+
+ return( _ClassDescriptor );
+}
+
+
+INLINE
+BOOLEAN
+OBJECT::IsSameClass (
+ IN PCOBJECT Object
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if this object and the supplied object are of the same class
+ by checking their CLASS_IDs for equality.
+
+Arguments:
+
+ Object - Supplies the object to compare class types against.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if this object and the supplied object are of
+ the same class.
+
+--*/
+
+{
+ DebugPtrAssert( Object );
+
+ return (BOOLEAN) (QueryClassId() == Object->QueryClassId());
+}
+
+
+INLINE
+BOOLEAN
+OBJECT::IsSameObject (
+ IN PCOBJECT Object
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determine if this object and the supplied object are the same by checking
+ their CLASS_IDs and then their memory location.
+
+Arguments:
+
+ Object - Supplies the object to compare for equivalence.
+
+Return Value:
+
+ BOOLEAN - Returns TRUE if this object and the supplied object are
+ equivalent.
+
+--*/
+
+{
+ return (BOOLEAN) (this == Object);
+}
+
+
+#endif // OBJECT
diff --git a/private/utils/ulib/inc/path.hxx b/private/utils/ulib/inc/path.hxx
new file mode 100644
index 000000000..f950da038
--- /dev/null
+++ b/private/utils/ulib/inc/path.hxx
@@ -0,0 +1,508 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ path.hxx
+
+Abstract:
+
+ The PATH class provides an interface to the complete
+ Win32 name space. Complete means that it will correctly
+ handle long, drive or UNC based, blank embedded, mixed case
+ names. It should eliminate the need for everyone to code
+ statements such as "is the second char a ':'" or "search for
+ the first '\' from the end of the name". That is, access to and
+ manipulation of path and file names should be performed soley
+ through the PATH member functions. This will eliminate
+ the recoding of standard name manipulation code and ensure
+ complete support of Win32 functionality, such as codepage and
+ DBCS support.
+
+Author:
+
+ Steve Rowe 13-Dec-90
+
+Environment:
+
+ ULIB, user
+
+Notes:
+
+
+ To clarify terminology used here, the following describes a
+ canonicalized path (in butchered BNF/reg exp):
+
+ {Canon} ::= {Prefix}"\"{Name}
+ {Prefix} ::= {Device}{Dirs}
+ {Dirs} ::= {"\"{Component}}*
+ {Device} ::= {Drive}|{Machine}
+ {Drive} ::= {Letter}":"
+ {Machine} ::= "\\"{Char}+
+ {Letter} ::= valid drive letter [a-zA-Z]
+ {Char} ::= valid filename/directory char [~:\]
+ {Component} ::= {Char}+
+ {Name} ::= {Base - excluding "."} | { {Base}"."{Ext} }
+ {Base} ::= {Char}+
+ {Ext} ::= {Char - excluding "."}+
+
+ Legend:
+ -------
+ {x}* - 0 or more x
+ {x}+ - 1 or more x
+ "x" - just x (not the quotes)
+ {x}|{y} - x or y (not both or none)
+
+
+ Examples:
+ ---------
+ # Canon
+ --- -----
+ (1) x:\abc\def.ghi\jkl.mnop
+ (2) \\x\abc\def.ghi\jkl.mnop
+ (3) c:\config.sys
+
+ (1) (2) (3)
+
+ Prefix x:\abc\def.ghi \\x\abc\def.ghi c:
+ Device x: \\x c:
+ Dirs \abc \abc\def.ghi
+ Name jkl.mnop jkl.mnop config.sys
+ Base jkl jkl config
+ Ext mnop mnop sys
+
+ Component numbers are 0-based.
+
+
+--*/
+
+#if !defined( _PATH_)
+
+#define _PATH_
+
+#include "wstring.hxx"
+#include "array.hxx"
+
+//
+// Forward references & declarations
+//
+
+DECLARE_CLASS( PATH );
+
+
+
+//
+// PATHSTATE maintains the number of characters within each component that
+// makes up a PATH
+//
+struct _PATHSTATE {
+
+ //
+ // Prefix
+ //
+ CHNUM PrefixLen;
+ CHNUM DeviceLen;
+ CHNUM DirsLen;
+ CHNUM SeparatorLen;
+
+ //
+ // Name
+ //
+ CHNUM NameLen;
+ CHNUM BaseLen;
+ CHNUM ExtLen;
+
+};
+
+DEFINE_TYPE( struct _PATHSTATE, PATHSTATE );
+
+class PATH : public OBJECT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( PATH );
+
+ DECLARE_CAST_MEMBER_FUNCTION( PATH );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PCWSTR InitialPath,
+ IN BOOLEAN Canonicalize DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PCWSTRING InitialPath,
+ IN BOOLEAN Canonicalize DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN PCPATH InitialPath,
+ IN BOOLEAN Canonicalize DEFAULT FALSE
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~PATH (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ AppendBase (
+ IN PCWSTRING Base,
+ IN BOOLEAN Absolute DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ EndsWithDelimiter (
+ ) CONST;
+
+ NONVIRTUAL
+ PCWSTRING
+ GetPathString (
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ HasWildCard (
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsDrive (
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ IsRoot (
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ ModifyName (
+ IN PCWSTRING Pattern
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ QueryBase (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PARRAY
+ QueryComponentArray (
+ OUT PARRAY Array DEFAULT NULL
+ ) CONST;
+
+ NONVIRTUAL
+ PWSTRING
+ QueryDevice (
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ QueryDirs (
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ QueryDirsAndName (
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ QueryExt (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PPATH
+ QueryFullPath (
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTRING
+ QueryFullPathString (
+ ) CONST;
+
+ NONVIRTUAL
+ PWSTRING
+ QueryName (
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PPATH
+ QueryPath (
+ ) CONST;
+
+ NONVIRTUAL
+ PWSTRING
+ QueryPrefix (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTRING
+ QueryRoot (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PPATH
+ QueryWCExpansion(
+ IN PPATH BasePath
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ SetBase (
+ IN PCWSTRING NewBase
+ );
+
+ ULIB_EXPORT
+ BOOLEAN
+ SetDevice (
+ IN PCWSTRING NewDevice
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ SetExt (
+ IN PCWSTRING NewExt
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetName (
+ IN PCWSTRING NewName
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ SetPrefix (
+ IN PCWSTRING NewPrefix
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ TruncateBase (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ TruncateNameAtColon (
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ ExpandWildCards(
+ IN OUT PWSTRING pStr1,
+ IN OUT PWSTRING pStr2
+ );
+
+ BOOLEAN
+ Initialize (
+ );
+
+ NONVIRTUAL
+ CHNUM
+ QueryBaseStart (
+ ) CONST;
+
+ CHNUM
+ QueryDeviceLen(
+ IN PWSTRING pString
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ QueryDeviceStart (
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ QueryExtStart (
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ QueryNameStart (
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ QueryPrefixStart (
+ ) CONST;
+
+ NONVIRTUAL
+ VOID
+ SetPathState (
+ );
+
+
+
+#if DBG==1
+
+ ULONG _Signature;
+ BOOLEAN _Initialized;
+
+#endif
+ //
+ // path data
+ //
+ WCHAR _PathBuffer[MAX_PATH];
+ FSTRING _PathString;
+ PATHSTATE _PathState;
+
+};
+
+INLINE
+CHNUM
+PATH::QueryPrefixStart (
+ ) CONST
+
+{
+ return( 0 );
+}
+
+INLINE
+CHNUM
+PATH::QueryNameStart (
+ ) CONST
+
+{
+ //
+ // Increment past the '\'
+ //
+ return( QueryPrefixStart() + _PathState.PrefixLen + _PathState.SeparatorLen );
+}
+
+INLINE
+CHNUM
+PATH::QueryBaseStart (
+ ) CONST
+
+{
+ return( QueryNameStart() );
+}
+
+INLINE
+CHNUM
+PATH::QueryDeviceStart (
+ ) CONST
+
+{
+ return( 0 );
+}
+
+INLINE
+CHNUM
+PATH::QueryExtStart (
+ ) CONST
+{
+ return( QueryNameStart() + _PathState.BaseLen + 1 );
+}
+
+INLINE
+PCWSTRING
+PATH::GetPathString (
+ ) CONST
+
+{
+ return( &_PathString );
+}
+
+INLINE
+PWSTRING
+PATH::QueryBase (
+ )
+
+{
+ return( _PathState.BaseLen ? _PathString.QueryString( QueryBaseStart(), _PathState.BaseLen ) : NULL );
+}
+
+INLINE
+PWSTRING
+PATH::QueryDirs (
+ )
+
+{
+ return( _PathState.DirsLen ? _PathString.QueryString( QueryDeviceStart() + _PathState.DeviceLen, _PathState.DirsLen ) : NULL );
+}
+
+INLINE
+PWSTRING
+PATH::QueryDirsAndName (
+ )
+
+{
+ return( ( _PathState.DirsLen || _PathState.NameLen ) ? _PathString.QueryString( QueryDeviceStart() + _PathState.DeviceLen ) : NULL );
+}
+
+INLINE
+PWSTRING
+PATH::QueryDevice (
+ )
+
+{
+ return( _PathState.DeviceLen ? _PathString.QueryString( QueryDeviceStart(), _PathState.DeviceLen ) : NULL );
+}
+
+INLINE
+PWSTRING
+PATH::QueryExt (
+ )
+
+{
+ return( _PathState.ExtLen ? _PathString.QueryString( QueryExtStart(), _PathState.ExtLen ) : NULL );
+}
+
+INLINE
+PWSTRING
+PATH::QueryName (
+ ) CONST
+
+{
+ return( _PathState.NameLen ? _PathString.QueryString( QueryNameStart(), _PathState.NameLen ) : NULL );
+}
+
+INLINE
+PWSTRING
+PATH::QueryPrefix (
+ )
+
+{
+ return( _PathState.PrefixLen ? _PathString.QueryString( QueryPrefixStart(), _PathState.PrefixLen ) : NULL );
+}
+
+
+
+#endif // _PATH_
diff --git a/private/utils/ulib/inc/pipe.hxx b/private/utils/ulib/inc/pipe.hxx
new file mode 100644
index 000000000..aef3c917d
--- /dev/null
+++ b/private/utils/ulib/inc/pipe.hxx
@@ -0,0 +1,121 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pipe.hxx
+
+Abstract:
+
+ This module defines the PIPE object.
+
+Author:
+
+ Barry J. Gilhuly (W-Barry) June 27, 1991
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _PIPE_ )
+
+#define _PIPE_
+
+
+DECLARE_CLASS( PIPE_STREAM );
+DECLARE_CLASS( PIPE );
+DECLARE_CLASS( WSTRING );
+
+class PIPE : public OBJECT {
+
+ public:
+
+ DECLARE_CONSTRUCTOR( PIPE );
+
+ DECLARE_CAST_MEMBER_FUNCTION( PIPE );
+
+ BOOLEAN
+ Initialize(
+ IN LPSECURITY_ATTRIBUTES PipeAttributes DEFAULT NULL,
+ IN ULONG PipeSize DEFAULT 0,
+ IN PWSTRING PipeName DEFAULT NULL
+ );
+
+ PPIPE_STREAM
+ QueryReadStream(
+ );
+
+ PPIPE_STREAM
+ QueryWriteStream(
+ );
+
+ private:
+
+ PPIPE_STREAM
+ QueryPipeStream(
+ IN HANDLE hStream,
+ IN STREAMACCESS Access
+ );
+
+ VOID
+ Destroy(
+ );
+
+ BOOLEAN _fInitialized;
+ HANDLE _hReadPipe;
+ HANDLE _hWritePipe;
+
+};
+
+INLINE
+PPIPE_STREAM
+PIPE::QueryReadStream(
+ )
+/*++
+
+Routine Description:
+
+ Create a stream with read access to the PIPE.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A pointer to the created stream if success. Otherwise, it returns
+ NULL.
+
+--*/
+{
+ return( QueryPipeStream( _hReadPipe, READ_ACCESS ) );
+}
+
+INLINE
+PPIPE_STREAM
+PIPE::QueryWriteStream(
+ )
+/*++
+
+Routine Description:
+
+ Create a stream with write access to the PIPE.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A pointer to the created stream if success. Otherwise, it returns
+ NULL.
+
+--*/
+{
+ return( QueryPipeStream( _hWritePipe, WRITE_ACCESS ) );
+}
+
+#endif // _PIPE_
diff --git a/private/utils/ulib/inc/pipestrm.hxx b/private/utils/ulib/inc/pipestrm.hxx
new file mode 100644
index 000000000..28faf4ff5
--- /dev/null
+++ b/private/utils/ulib/inc/pipestrm.hxx
@@ -0,0 +1,112 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pipestr.hxx
+
+Abstract:
+
+ This module contains the declaration for the PIPE_STREAM class.
+ The PIPE_STREAM is a class derived from BUFFER_STREAM that provides
+ methods to read and write data to an anonymous pipe.
+ A PIPE_STREAM will have one of the following access: READ or WRITE.
+
+
+Author:
+
+ Jaime Sasson (jaimes) 18-Apr-1991
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+
+#if !defined( PIPE_STREAM_ )
+
+#define PIPE_STREAM_
+
+#include "bufstrm.hxx"
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( PIPE_STREAM );
+DECLARE_CLASS( WSTRING );
+
+
+class PIPE_STREAM : public BUFFER_STREAM {
+
+ public:
+
+ friend class PIPE;
+ friend PSTREAM GetStandardStream( HANDLE, STREAMACCESS );
+
+ DECLARE_CAST_MEMBER_FUNCTION( PIPE_STREAM );
+
+ VIRTUAL
+ ~PIPE_STREAM(
+ );
+
+ VIRTUAL
+ STREAMACCESS
+ QueryAccess(
+ ) CONST;
+
+
+ protected:
+
+
+ DECLARE_CONSTRUCTOR( PIPE_STREAM );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN HANDLE Handle,
+ IN STREAMACCESS Access
+ );
+
+ VIRTUAL
+ BOOLEAN
+ EndOfFile(
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ FillBuffer(
+ IN PBYTE Buffer,
+ IN ULONG BufferSize,
+ OUT PULONG BytesRead
+ );
+
+ VIRTUAL
+ HANDLE
+ QueryHandle(
+ ) CONST;
+
+#ifdef DBCS // v-junm - 10/15/93
+
+ VIRTUAL
+ BOOLEAN
+ CheckIfLeadByte(
+ IN PUCHAR text,
+ IN ULONG offset
+ );
+
+#endif
+
+
+ private:
+
+ HANDLE _PipeHandle;
+ STREAMACCESS _Access;
+ BOOLEAN _EndOfFile;
+};
+
+
+#endif // _PIPE_STREAM_
diff --git a/private/utils/ulib/inc/program.hxx b/private/utils/ulib/inc/program.hxx
new file mode 100644
index 000000000..7e675b6aa
--- /dev/null
+++ b/private/utils/ulib/inc/program.hxx
@@ -0,0 +1,146 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ program.hxx
+
+Abstract:
+
+Author:
+
+ David J. Gilman (davegi) 02-Mar-1991
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _PROGRAM_ )
+
+#define _PROGRAM_
+
+#include "rtmsg.h"
+#include "smsg.hxx"
+
+DECLARE_CLASS( PATH );
+DECLARE_CLASS( PROGRAM );
+
+class PROGRAM : public OBJECT {
+
+ public:
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN MSGID UsageMsg DEFAULT MSG_UTILS_HELP,
+ IN MSGID FatalMsg DEFAULT MSG_UTILS_ERROR_FATAL,
+ IN ULONG FatalLevel DEFAULT 1
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ ~PROGRAM (
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DisplayMessage (
+ IN MSGID Message,
+ IN MESSAGE_TYPE Type DEFAULT NORMAL_MESSAGE
+ ) CONST;
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DisplayMessage (
+ IN MSGID Message,
+ IN MESSAGE_TYPE Type,
+ IN PSTR Format,
+ IN ...
+ ) CONST;
+
+ VIRTUAL
+ ULIB_EXPORT
+ VOID
+ ExitProgram (
+ ULONG Level
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ VOID
+ Fatal (
+ ) CONST;
+
+ VIRTUAL
+ ULIB_EXPORT
+ VOID
+ Fatal (
+ IN ULONG ErrorLevel,
+ IN MSGID Message,
+ IN PSTR Format,
+ IN ...
+ ) CONST;
+
+ VIRTUAL
+ ULIB_EXPORT
+ PSTREAM
+ GetStandardInput (
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ PSTREAM
+ GetStandardOutput (
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ PSTREAM
+ GetStandardError (
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ VOID
+ Usage (
+ ) CONST;
+
+ STATIC
+ PPATH
+ QueryImagePath (
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ VOID
+ ValidateVersion (
+ IN MSGID InvalidVersionMsg DEFAULT MSG_UTILS_ERROR_INVALID_VERSION,
+ IN ULONG ErrorLevel DEFAULT 1
+ ) CONST;
+
+ protected:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( PROGRAM );
+
+ STREAM_MESSAGE _Message; // Message stream
+ PSTREAM _Standard_Input; // Standard input
+ PSTREAM _Standard_Output; // Standard output
+ PSTREAM _Standard_Error; // Standard error
+
+ private:
+
+ MSGID _UsageMsg; // Usage message id.
+ MSGID _FatalMsg; // Fatal message id.
+ ULONG _FatalLevel; // Fatal error level
+
+};
+
+
+#endif // _PROGRAM_
diff --git a/private/utils/ulib/inc/prtstrm.hxx b/private/utils/ulib/inc/prtstrm.hxx
new file mode 100644
index 000000000..0fa283218
--- /dev/null
+++ b/private/utils/ulib/inc/prtstrm.hxx
@@ -0,0 +1,143 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ prtstrm.hxx
+
+Abstract:
+
+ This module contains the declaration for the PRINT_STREAM class.
+ The PRINT_STREAM is a class derived from STREAM that provides
+ methods to write data to a print device.
+ A PRINT_STREAM has always WRITE_ACCESS.
+
+
+Author:
+
+ Jaime Sasson (jaimes) 18-Apr-1991
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+
+#if !defined( _PRINT_STREAM_ )
+
+#define _PRINT_STREAM_
+
+#include "stream.hxx"
+
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( PRINT_STREAM );
+DECLARE_CLASS( WSTRING );
+DECLARE_CLASS( PATH );
+
+
+class PRINT_STREAM : public STREAM {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( PRINT_STREAM );
+
+ DECLARE_CAST_MEMBER_FUNCTION( PRINT_STREAM );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~PRINT_STREAM(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN PCPATH DeviceName
+ );
+
+ VIRTUAL
+ BOOLEAN
+ IsAtEnd(
+ ) CONST;
+
+ VIRTUAL
+ STREAMACCESS
+ QueryAccess(
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ Read(
+ OUT PBYTE Buffer,
+ IN ULONG BytesToRead,
+ OUT PULONG BytesRead
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadChar(
+ OUT PWCHAR Char,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadMbString(
+ IN PSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN PSTR Delimiters,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadWString(
+ IN PWSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN PWSTR Delimiters,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadString(
+ OUT PWSTRING String,
+ IN PWSTRING Delimiters,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ );
+
+
+
+ protected:
+
+ VIRTUAL
+ HANDLE
+ QueryHandle(
+ ) CONST;
+
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ HANDLE _Handle;
+};
+
+
+
+#endif // _PRINT_STREAM_
diff --git a/private/utils/ulib/inc/screen.hxx b/private/utils/ulib/inc/screen.hxx
new file mode 100644
index 000000000..6c3c5ceb6
--- /dev/null
+++ b/private/utils/ulib/inc/screen.hxx
@@ -0,0 +1,484 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ screen.hxx
+
+Abstract:
+
+ This module contains the declaration for the SCREEN class.
+ The SCREEN class provides methods that models the stream
+ of bytes, with write access.
+ Read operations from a SCREEN are not allowed.
+ End of stream in a SCREEN object means that the cursor is
+ in the last column of the last row.
+
+
+Author:
+
+ Jaime Sasson (jaimes) 21-Mar-1991
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+
+#if !defined( _SCREEN_ )
+
+#define _SCREEN_
+
+#include "stream.hxx"
+
+
+enum SCROLL_DIRECTION {
+ SCROLL_UP,
+ SCROLL_DOWN,
+ SCROLL_LEFT,
+ SCROLL_RIGHT
+ };
+
+DECLARE_CLASS( SCREEN );
+
+
+class SCREEN : public STREAM {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( SCREEN );
+
+ ULIB_EXPORT
+ DECLARE_CAST_MEMBER_FUNCTION( SCREEN );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ ~SCREEN (
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN BOOLEAN CurrentActiveScreen,
+ IN USHORT NumberOfRows,
+ IN USHORT NumberOfColumns,
+ IN USHORT TextAttribute,
+ IN BOOLEAN ExpandAsciiControlSequence DEFAULT TRUE,
+ IN BOOLEAN WrapAtEndOfLine DEFAULT TRUE
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ ChangeScreenSize(
+ IN USHORT NumberOfRows,
+ IN USHORT NumberOfColumns,
+ OUT PBOOLEAN IsFullScreen DEFAULT NULL
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ ChangeTextAttribute(
+ IN USHORT Attribute
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ DisableAsciiControlSequence(
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ DisableWrapMode(
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ EnableAsciiControlSequence(
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ EnableWrapMode(
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ EraseLine(
+ IN USHORT LineNumber
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ EraseScreen(
+ );
+
+
+#ifdef DBCS
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ EraseScreenAndResetAttribute(
+ );
+#endif
+
+
+ NONVIRTUAL
+ BOOLEAN
+ EraseToEndOfLine(
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ FillRectangularRegionAttribute(
+ IN USHORT TopLeftRow,
+ IN USHORT TopLeftColumn,
+ IN USHORT BottomRightRow,
+ IN USHORT BottomRightColumn,
+ IN USHORT Attribute
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ FillRegionAttribute(
+ IN USHORT StartRow,
+ IN USHORT StartColumn,
+ IN USHORT EndRow,
+ IN USHORT EndColumn,
+ IN USHORT Attribute
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ FillRectangularRegionCharacter(
+ IN USHORT TopLeftRow,
+ IN USHORT TopLeftColumn,
+ IN USHORT BottomRightRow,
+ IN USHORT BottomRightColumn,
+ IN CHAR Character
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ FillRegionCharacter(
+ IN USHORT StartRow,
+ IN USHORT StartColumn,
+ IN USHORT EndRow,
+ IN USHORT EndColumn,
+ IN CHAR Character
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ IsAsciiControlSequenceEnabled(
+ ) CONST;
+
+
+ VIRTUAL
+ BOOLEAN
+ IsAtEnd(
+ ) CONST;
+
+
+ NONVIRTUAL
+ BOOLEAN
+ IsWrapModeEnabled(
+ ) CONST;
+
+
+ NONVIRTUAL
+ BOOLEAN
+ MoveCursorDown(
+ IN USHORT Rows
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ MoveCursorLeft(
+ IN USHORT Columns
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ MoveCursorRight(
+ IN USHORT Columns
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ MoveCursorTo(
+ IN USHORT Row,
+ IN USHORT Column
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ MoveCursorUp(
+ IN USHORT Rows
+ );
+
+
+ VIRTUAL
+ STREAMACCESS
+ QueryAccess(
+ ) CONST;
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ DWORD
+ QueryCodePage (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ QueryCursorPosition(
+ OUT PUSHORT Row,
+ OUT PUSHORT Column
+ );
+
+
+ VIRTUAL
+ HANDLE
+ QueryHandle(
+ ) CONST;
+
+
+ NONVIRTUAL
+ DWORD
+ QueryOutputCodePage (
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ QueryScreenSize(
+ OUT PUSHORT NumberOfRows,
+ OUT PUSHORT NumberOfColumns,
+ OUT PUSHORT WindowRows DEFAULT NULL,
+ OUT PUSHORT WindowColumns DEFAULT NULL
+ ) CONST;
+
+
+ VIRTUAL
+ BOOLEAN
+ Read(
+ OUT PBYTE Buffer,
+ IN ULONG BytesToRead,
+ OUT PULONG BytesRead
+ );
+
+
+ VIRTUAL
+ BOOLEAN
+ ReadChar(
+ OUT PWCHAR Char,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ );
+
+
+ VIRTUAL
+ BOOLEAN
+ ReadMbString(
+ IN PSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN PSTR Delimiters,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadWString(
+ IN PWSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN PWSTR Delimiters,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadString(
+ OUT PWSTRING String,
+ IN PWSTRING Delimiter,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ ScrollScreen(
+ USHORT Amount,
+ SCROLL_DIRECTION Direction
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetCodePage(
+ IN DWORD CodePage
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ SetCursorOff(
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ SetCursorOn(
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ SetCursorSize(
+ IN ULONG Size
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ SetOutputCodePage(
+ IN DWORD CodePage
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ SetScreenActive(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ WriteString(
+ IN PCWSTRING String,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ IN CHNUM Granularity DEFAULT 0
+ );
+
+ VIRTUAL
+ BOOLEAN
+ WriteChar(
+ IN WCHAR Char
+ );
+
+ private:
+
+ HANDLE _ScreenHandle;
+// USHORT _Rows;
+// USHORT _Columns;
+ USHORT _TextAttribute;
+ ULONG _ScreenMode;
+
+
+};
+
+
+INLINE
+BOOLEAN
+SCREEN::IsAsciiControlSequenceEnabled(
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determines if expansion of ASCII control sequences are currently
+ allowed.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - Indicates if ASCII control sequences are allowed.
+
+
+--*/
+
+
+{
+ if( ( _ScreenMode & ENABLE_PROCESSED_OUTPUT ) ) {
+ return( TRUE );
+ } else {
+ return( FALSE );
+ }
+}
+
+
+
+INLINE
+BOOLEAN
+SCREEN::IsWrapModeEnabled(
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Determines if twrap is allowed in the screen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ BOOLEAN - Indicates if the screen is in the wrap mode.
+
+
+--*/
+
+
+{
+ if( ( _ScreenMode & ENABLE_WRAP_AT_EOL_OUTPUT ) ) {
+ return( TRUE );
+ } else {
+ return( FALSE );
+ }
+}
+
+
+
+#endif // _SCREEN_
diff --git a/private/utils/ulib/inc/seqcnt.hxx b/private/utils/ulib/inc/seqcnt.hxx
new file mode 100644
index 000000000..352a86286
--- /dev/null
+++ b/private/utils/ulib/inc/seqcnt.hxx
@@ -0,0 +1,83 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ seqcnt.hxx
+
+Abstract:
+
+ This module contains the declaration for the SEQUENTIAL_CONTAINER class.
+ SEQUENTIAL_CONTAINER is a fairly primitive class which augments the
+ CONTAINER class by adding the capability that the objects stored in the
+ container have some sort of sequenced relationship. This means that
+ OBJECTs can be queried from SEQUENTIAL_CONTAINERs by the use of an
+ ITERATOR and that the concepts first, last, next and previous have
+ meaning.
+
+Author:
+
+ David J. Gilman (davegi) 29-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _SEQUENTIAL_CONTAINER_ )
+
+#define _SEQUENTIAL_CONTAINER_
+
+#include "contain.hxx"
+
+DECLARE_CLASS( SEQUENTIAL_CONTAINER );
+DECLARE_CLASS( ITERATOR );
+
+class SEQUENTIAL_CONTAINER : public CONTAINER {
+
+ FRIEND class ITERATOR;
+
+ public:
+
+ VIRTUAL
+ ~SEQUENTIAL_CONTAINER(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Put(
+ IN OUT POBJECT Member
+ ) PURE;
+
+ VIRTUAL
+ ULONG
+ QueryMemberCount(
+ ) CONST PURE;
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DeleteAllMembers(
+ );
+
+ VIRTUAL
+ PITERATOR
+ QueryIterator(
+ ) CONST PURE;
+
+ VIRTUAL
+ POBJECT
+ Remove(
+ IN OUT PITERATOR Position
+ ) PURE;
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( SEQUENTIAL_CONTAINER );
+
+};
+
+
+#endif // _SEQUENTIAL_CONTAINER_
diff --git a/private/utils/ulib/inc/smsg.hxx b/private/utils/ulib/inc/smsg.hxx
new file mode 100644
index 000000000..13581bbb4
--- /dev/null
+++ b/private/utils/ulib/inc/smsg.hxx
@@ -0,0 +1,173 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ smsg.hxx
+
+Abstract:
+
+ The STREAM_MESSAGE class offers a STREAM implementation of the
+ MESSAGE class. The messages are output to the STREAM to which
+ the object is initialized to.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 1-Apr-91
+
+--*/
+
+
+#if !defined(STREAM_MESSAGE_DEFN)
+
+#define STREAM_MESSAGE_DEFN
+
+#include "message.hxx"
+
+DECLARE_CLASS( STREAM_MESSAGE );
+DECLARE_CLASS( STREAM );
+
+class STREAM_MESSAGE : public MESSAGE {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( STREAM_MESSAGE );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~STREAM_MESSAGE(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN OUT PSTREAM OutputStream,
+ IN OUT PSTREAM InputStream,
+ IN OUT PSTREAM ErrorStream DEFAULT NULL
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Set(
+ IN MSGID MsgId,
+ IN MESSAGE_TYPE MessageType DEFAULT NORMAL_MESSAGE,
+ IN ULONG MessageVisual DEFAULT NORMAL_VISUAL
+ );
+
+ VIRTUAL
+ BOOLEAN
+ DisplayV(
+ IN PCSTR Format,
+ IN va_list VarPointer
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ IsYesResponse(
+ IN BOOLEAN Default DEFAULT TRUE
+ );
+
+ VIRTUAL
+ BOOLEAN
+ QueryStringInput(
+ OUT PWSTRING String
+ );
+
+ VIRTUAL
+ BOOLEAN
+ WaitForUserSignal(
+ );
+
+ VIRTUAL
+ MSGID
+ SelectResponse(
+ IN ULONG NumberOfSelections ...
+ );
+
+ NONVIRTUAL
+ VOID
+ SetInputCaseSensitivity(
+ IN BOOLEAN CaseSensitive
+ );
+
+ VIRTUAL
+ PMESSAGE
+ Dup(
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy(
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ ReadLine(
+ OUT PWSTRING String
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Flush(
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ DisplayString(
+ );
+
+ MSGID _msgid;
+ MESSAGE_TYPE _msgtype;
+ ULONG _msgvisual;
+ PSTREAM _out_stream;
+ PSTREAM _in_stream;
+ PSTREAM _err_stream;
+ BOOLEAN _case_sensitive;
+ BOOLEAN _copy_input;
+ DSTRING _display_string;
+
+};
+
+
+typedef STREAM_MESSAGE* PSTREAM_MESSAGE;
+
+
+INLINE
+VOID
+STREAM_MESSAGE::SetInputCaseSensitivity(
+ IN BOOLEAN CaseSensitive
+ )
+/*++
+
+Routine Description:
+
+ This routine sets whether or not to be case sensitive on input.
+ The class defaults this value to FALSE when it is initialized.
+
+Arguments:
+
+ CaseSensitive - Supplies whether or not to be case sensitive on input.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ _case_sensitive = CaseSensitive;
+}
+
+
+#endif // STREAM_MESSAGE_DEFN
diff --git a/private/utils/ulib/inc/sortcnt.hxx b/private/utils/ulib/inc/sortcnt.hxx
new file mode 100644
index 000000000..a4870e5a5
--- /dev/null
+++ b/private/utils/ulib/inc/sortcnt.hxx
@@ -0,0 +1,79 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ sortcnt.hxx
+
+Abstract:
+
+ This module contains the declaration for the SORTABLE_CONTAINER class.
+ SORTABLE_CONTAINER is an abstract classe that is derived from the abstract
+ class SEQUENTIAL_CONTAINER. It not only assumes a sequence but also
+ assumes that the sequence can be changed by sorting it's contents. That
+ is the contents have a relative order independent from how they were
+ placed in the container.
+
+Author:
+
+ David J. Gilman (davegi) 29-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _SORTABLE_CONTAINER_ )
+
+#define _SORTABLE_CONTAINER_
+
+#include "seqcnt.hxx"
+
+DECLARE_CLASS( SORTABLE_CONTAINER );
+
+class SORTABLE_CONTAINER : public SEQUENTIAL_CONTAINER {
+
+ public:
+
+ VIRTUAL
+ ~SORTABLE_CONTAINER(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Put(
+ IN OUT POBJECT Member
+ ) PURE;
+
+ VIRTUAL
+ ULONG
+ QueryMemberCount(
+ ) CONST PURE;
+
+ VIRTUAL
+ PITERATOR
+ QueryIterator(
+ ) CONST PURE;
+
+ VIRTUAL
+ POBJECT
+ Remove(
+ IN OUT PITERATOR Position
+ ) PURE;
+
+ VIRTUAL
+ BOOLEAN
+ Sort(
+ IN BOOLEAN Ascending DEFAULT TRUE
+ ) PURE;
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( SORTABLE_CONTAINER );
+
+};
+
+
+#endif // _SORTABLE_CONTAINER_
diff --git a/private/utils/ulib/inc/sortlist.hxx b/private/utils/ulib/inc/sortlist.hxx
new file mode 100644
index 000000000..a2ae1ecb0
--- /dev/null
+++ b/private/utils/ulib/inc/sortlist.hxx
@@ -0,0 +1,153 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ sortlist.hxx
+
+Abstract:
+
+ This module contains the declaration for the SORTED_LIST class.
+
+ SORTED_LIST is a concrete implementation of a SORTABLE_CONTAINER.
+ The elements in a SORTED_LIST are maintained in sorted order.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 29-Oct-1991
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _SORTED_LIST_ )
+
+#define _SORTED_LIST_
+
+#include "sortcnt.hxx"
+#include "array.hxx"
+
+DECLARE_CLASS( SORTED_LIST );
+
+class SORTED_LIST : public SORTABLE_CONTAINER {
+
+ friend class SORTED_LIST_ITERATOR;
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( SORTED_LIST );
+
+ DECLARE_CAST_MEMBER_FUNCTION( SORTED_LIST );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~SORTED_LIST (
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN BOOLEAN Ascending DEFAULT TRUE
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ IsAscending (
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ DeleteAllMembers(
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Put (
+ IN OUT POBJECT Member
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ PITERATOR
+ QueryIterator (
+ ) CONST;
+
+ VIRTUAL
+ ULIB_EXPORT
+ ULONG
+ QueryMemberCount (
+ ) CONST;
+
+ VIRTUAL
+ POBJECT
+ Remove (
+ IN OUT PITERATOR Position
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Sort(
+ IN BOOLEAN Ascending DEFAULT TRUE
+ );
+
+ protected:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ VIRTUAL
+ ULONG
+ Search(
+ IN PCOBJECT Key,
+ IN ULONG FirstIndex,
+ IN ULONG LastIndex
+ );
+
+
+ private:
+
+ ARRAY _Array; // Array
+ BOOLEAN _Ascending; // Ascending flag
+#if DBG==1
+ ULONG _IteratorCount; // Iterator Count
+#endif
+
+};
+
+
+INLINE
+BOOLEAN
+SORTED_LIST::IsAscending (
+ )
+/*++
+
+Routine Description:
+
+ Determines if the list is sorted in ascending order
+
+Arguments:
+
+ None
+
+Return Value:
+
+ BOOLEAN - TRUE if list is sorted in ascending order, FALSE otherwise
+
+--*/
+
+{
+ return _Ascending;
+}
+
+
+
+#endif // _SORTED_LIST_
diff --git a/private/utils/ulib/inc/sortlit.hxx b/private/utils/ulib/inc/sortlit.hxx
new file mode 100644
index 000000000..81acfbfae
--- /dev/null
+++ b/private/utils/ulib/inc/sortlit.hxx
@@ -0,0 +1,98 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ sortlit.hxx
+
+Abstract:
+
+ This module contains the declaration for the SORTED_LIST_ITERATOR class.
+ SORTED_LIST_ITERATOR is a concrete implementation of the ITERATOR class.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 29-Oct-1991
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+#if ! defined( _SORTED_LIST_ITERATOR_ )
+
+#define _SORTED_LIST_ITERATOR_
+
+#include "iterator.hxx"
+
+//
+// Forward references
+//
+DECLARE_CLASS( SORTED_LIST );
+DECLARE_CLASS( SORTED_LIST_ITERATOR );
+
+
+class SORTED_LIST_ITERATOR : public ITERATOR {
+
+ friend SORTED_LIST;
+
+ public:
+
+ VIRTUAL
+ ~SORTED_LIST_ITERATOR(
+ );
+
+ VIRTUAL
+ POBJECT
+ FindNext(
+ IN PCOBJECT Key
+ );
+
+ VIRTUAL
+ POBJECT
+ GetCurrent(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetNext(
+ );
+
+ VIRTUAL
+ POBJECT
+ GetPrevious(
+ );
+
+ VIRTUAL
+ VOID
+ Reset(
+ );
+
+ protected:
+
+ DECLARE_CAST_MEMBER_FUNCTION( SORTED_LIST_ITERATOR );
+ DECLARE_CONSTRUCTOR( SORTED_LIST_ITERATOR );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN OUT PSORTED_LIST List
+ );
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ private:
+
+ PSORTED_LIST _List; // Sorted List
+ ULONG _CurrentIndex; // Current index
+
+};
+
+
+#endif // _SORTED_LIST_ITERATOR_
diff --git a/private/utils/ulib/inc/spackmsg.hxx b/private/utils/ulib/inc/spackmsg.hxx
new file mode 100644
index 000000000..30888480f
--- /dev/null
+++ b/private/utils/ulib/inc/spackmsg.hxx
@@ -0,0 +1,64 @@
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ spackmsg.hxx
+
+Abstract:
+
+ Header file for the SP_AUTOCHECK_MESSAGE subclass.
+
+Author:
+
+ Lonny McMichael (lonnym) 09-Jun-94
+
+--*/
+
+#if !defined( _SP_AUTOCHECK_MESSAGE_DEFN_ )
+
+#define _SP_AUTOCHECK_MESSAGE_DEFN_
+
+#include "achkmsg.hxx"
+
+DECLARE_CLASS( SP_AUTOCHECK_MESSAGE );
+
+class SP_AUTOCHECK_MESSAGE : public AUTOCHECK_MESSAGE {
+
+ public:
+
+ DECLARE_CONSTRUCTOR( SP_AUTOCHECK_MESSAGE );
+
+ VIRTUAL
+ ~SP_AUTOCHECK_MESSAGE(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ DisplayV(
+ IN PCSTR Format,
+ IN va_list VarPointer
+ );
+
+ VIRTUAL
+ BOOLEAN
+ IsYesResponse(
+ IN BOOLEAN Default DEFAULT TRUE
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy(
+ );
+};
+
+
+#endif // _SP_AUTOCHECK_MESSAGE_DEFN_
diff --git a/private/utils/ulib/inc/stack.hxx b/private/utils/ulib/inc/stack.hxx
new file mode 100644
index 000000000..c5a2f4964
--- /dev/null
+++ b/private/utils/ulib/inc/stack.hxx
@@ -0,0 +1,233 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ stack.hxx
+
+Abstract:
+
+ This module contains the declaration for the concrete STACK class.
+ STACK is derived from the ORDERED_CONTAINER class. It implements a
+ standard FIFO stack data structure with the addition that it has a last
+ position which can be queried. STACKs are dynamic in that they will
+ grow rather than overflow.
+
+Author:
+
+ David J. Gilman (davegi) 11-Dec-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _STACK_ )
+
+#define _STACK_
+
+#include "seqcnt.hxx"
+
+//
+// Forward references
+//
+
+DECLARE_CLASS( ARRAY );
+DECLARE_CLASS( ITERATOR );
+DECLARE_CLASS( STACK );
+
+
+//
+// Default values for an ARRAY object.
+//
+
+CONST ULONG DefaultCapacity = 50;
+CONST ULONG DefaultCapacityIncrement = 25;
+
+class STACK : public SEQUENTIAL_CONTAINER {
+
+ public:
+
+ DECLARE_CONSTRUCTOR( STACK );
+
+ DECLARE_CAST_MEMBER_FUNCTION( STACK );
+
+ NONVIRTUAL
+ VOID
+ Clear (
+ );
+
+ VIRTUAL
+ PCOBJECT
+ GetFirst (
+ ) CONST PURE;
+
+ VIRTUAL
+ PCOBJECT
+ GetLast (
+ ) CONST PURE;
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ IN ULONG Capacity DEFAULT DefaultCapacity,
+ IN ULONG CapacityIncrement DEFAULT DefaultCapacityIncrement
+ );
+
+ NONVIRTUAL
+ PCOBJECT
+ Pop (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Push (
+ IN PCOBJECT Object
+ );
+
+ VIRTUAL
+ PCOBJECT
+ Put (
+ IN PCOBJECT Member
+ ) PURE;
+
+ VIRTUAL
+ PITERATOR
+ QueryIterator (
+ ) CONST PURE;
+
+ VIRTUAL
+ PCOBJECT
+ Remove (
+ IN PCOBJECT Member
+ ) PURE;
+
+ NONVIRTUAL
+ PCOBJECT
+ Top (
+ ) CONST;
+
+ private:
+
+ PARRAY _Stack;
+ ULONG _Top;
+};
+
+INLINE
+PCOBJECT
+STACK::GetFirst (
+ ) CONST
+
+{
+ return( Top( ));
+}
+
+INLINE
+PCOBJECT
+STACK::GetLast (
+ ) CONST
+
+{
+ DebugPtrAssert( _Stack );
+ if( _Stack != NULL ) {
+ return( _Stack->GetLast( ));
+ } else {
+ return( NULL );
+ }
+}
+
+INLINE
+VOID
+STACK::Clear (
+ )
+
+{
+ _Top = 0;
+}
+
+INLINE
+PCOBJECT
+STACK::Pop (
+ )
+
+{
+ DebugPtrAssert( _Stack );
+ if( ( _Stack != NULL ) && ( _Top != 0 )) {
+ return( _Stack->GetAt( _Top-- ));
+ } else {
+ return( NULL );
+ }
+}
+
+INLINE
+BOOLEAN
+STACK::Push (
+ IN PCOBJECT Object
+ )
+
+{
+ DebugPtrAssert( _Stack );
+ if( _Stack != NULL ) {
+ return( _Stack->PutAt( ++_Top ));
+ } else {
+ return( NULL );
+ }
+}
+
+INLINE
+PCOBJECT
+STACK::Put (
+ IN PCOBJECT Member
+ )
+
+{
+ DebugPtrAssert( Member );
+ return( Push( Member ));
+}
+
+INLINE
+PITERATOR
+STACK::QueryIterator (
+ ) CONST
+
+{
+ DebugPtrAssert( _Stack );
+ if( _Stack != NULL ) {
+ return( _Stack->QueryIterator( ));
+ } else {
+ return( NULL );
+ }
+}
+
+INLINE
+PCOBJECT
+STACK::Remove (
+ IN PCOBJECT Member
+ ) PURE
+
+{
+ DebugPtrAssert( Member ).IsEqual( Top( ));
+ if( ( Member != NULL ) && Member.IsEqual( Top( )) ) {
+ return( Pop( ));
+ } else {
+ retrun( NULL );
+ }
+}
+
+INLINE
+PCOBJECT
+STACK::Top (
+ ) CONST
+
+{
+ DebugPtrAssert( _Stack );
+ if( ( _Stack != NULL ) && ( _Top != 0 )) {
+ return( _Stack->GetAt( _Top ));
+ } else {
+ return( NULL );
+ }
+}
+
+#endif // _STACK_
diff --git a/private/utils/ulib/inc/stream.hxx b/private/utils/ulib/inc/stream.hxx
new file mode 100644
index 000000000..7f8326c08
--- /dev/null
+++ b/private/utils/ulib/inc/stream.hxx
@@ -0,0 +1,244 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ stream.hxx
+
+Abstract:
+
+ This module contains the declarations for the STREAM class.
+ STREAM is an abstract class used to model "devices" that
+ allow read or write operations, as a stream of data.
+ ("Device" here means anything that can supply or accept data
+ through read and write operations. Examples of "devices" are
+ keyboard, screen, file, pipes, etc.)
+ A STREAM object can have one of the following access: READ,
+ WRITE and READ_AND_WRITE.
+
+ The STREAM class provides methods to read data from the stream,
+ write data to the stream, check the stream access, and check if
+ the end of the stream has occurred.
+ (The occurrence of the end of stream means that all data in
+ a stream with READ or READ_AND_WRITE access was consumed, and no
+ more data can be obtained from the stream.)
+
+
+Author:
+
+ Jaime Sasson (jaimes) 21-Mar-1991
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+
+#if !defined( _STREAM_ )
+
+#define _STREAM_
+
+#include "wstring.hxx"
+#include "system.hxx"
+
+DECLARE_CLASS( STREAM );
+
+
+enum STREAMACCESS {
+ READ_ACCESS,
+ WRITE_ACCESS,
+ READ_AND_WRITE_ACCESS
+ };
+
+
+class STREAM : public OBJECT {
+
+
+ public:
+
+ friend BOOLEAN SYSTEM::PutStandardStream( DWORD, PSTREAM );
+
+ VIRTUAL
+ ~STREAM(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ IsAtEnd(
+ ) CONST PURE;
+
+ VIRTUAL
+ STREAMACCESS
+ QueryAccess(
+ ) CONST PURE;
+
+ VIRTUAL
+ BOOLEAN
+ Read(
+ OUT PBYTE Buffer,
+ IN ULONG BytesToRead,
+ OUT PULONG BytesRead
+ ) PURE;
+
+ NONVIRTUAL
+ BOOLEAN
+ ReadByte(
+ OUT PBYTE Data
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadChar(
+ OUT PWCHAR Char,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ ) PURE;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ ReadLine(
+ OUT PWSTRING String,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ ReadMbLine(
+ IN PSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadMbString(
+ IN PSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN PSTR Delimiters,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ ) PURE;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ ReadWLine(
+ IN PWSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ );
+
+ VIRTUAL
+ BOOLEAN
+ ReadWString(
+ IN PWSTR String,
+ IN DWORD BufferSize,
+ INOUT PDWORD StringSize,
+ IN PWSTR Delimiters,
+ IN BOOLEAN ExpandTabs DEFAULT FALSE,
+ IN DWORD TabExp DEFAULT 8
+ ) PURE;
+
+ VIRTUAL
+ BOOLEAN
+ ReadString(
+ OUT PWSTRING String,
+ IN PWSTRING Delimiters,
+ IN BOOLEAN Unicode DEFAULT FALSE
+ ) PURE;
+
+ VIRTUAL
+ BOOLEAN
+ Write(
+ IN PCBYTE Buffer,
+ IN ULONG BytesToWrite,
+ OUT PULONG BytesWritten
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ WriteByte(
+ IN BYTE Data
+ );
+
+ VIRTUAL
+ BOOLEAN
+ WriteChar(
+ IN WCHAR Char
+ );
+
+ VIRTUAL
+ BOOLEAN
+ WriteString(
+ IN PCWSTRING String,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ IN CHNUM Granularity DEFAULT 0
+ );
+
+ protected:
+
+
+ DECLARE_CONSTRUCTOR( STREAM );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ );
+
+ VIRTUAL
+ HANDLE
+ QueryHandle(
+ ) CONST PURE;
+
+
+ private:
+
+
+ DSTRING _Delimiter;
+ PSTR _MbDelimiter;
+ PWSTR _WDelimiter;
+};
+
+
+INLINE
+BOOLEAN
+STREAM::Initialize(
+ )
+
+/*++
+
+Routine Description:
+
+ Initializes an object of type STREAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE if the initialization succeeded, or FALSE otherwise.
+
+
+--*/
+
+
+{
+ _MbDelimiter = "\n";
+ _WDelimiter = L"\n";
+ return( _Delimiter.Initialize( "\n" ) );
+}
+
+
+#endif // _STREAM_
diff --git a/private/utils/ulib/inc/string.hxx b/private/utils/ulib/inc/string.hxx
new file mode 100644
index 000000000..28d479ee2
--- /dev/null
+++ b/private/utils/ulib/inc/string.hxx
@@ -0,0 +1,464 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ GENERIC_STRING
+
+Abstract:
+
+ This module contains the definition for the GENERIC_STRING class.
+
+Author:
+
+ Ramon J. San Andres (ramonsa) 03-May-91
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+ A GENERIC_STRING is the base class for all string classes. This
+ base class provides a basic wide-character interface.
+
+ A string is a finite, ordered sequence of wide characters. Note
+ that a GENERIC_STRING is NOT necessarily null-terminated.
+
+ Individual characters within a string are indexed by a number of
+ type CHNUM (CHaracter NUMber). This index is zero-based.
+
+ There are three special symbols that are widely used in the ULIB
+ strings world:
+
+ INVALID_CHAR This symbol represents an invalid wide character.
+
+ INVALID_CHNUM This symbol represents an invalid CHNUM index within
+ a GENERIC_STRING.
+
+ TO_END This symbol means "up to the end of the string", and
+ is used a lot as a default value in those methods
+ that accept a length argument.
+
+
+--*/
+
+
+//
+// This class is no longer supported.
+//
+
+#include "wstring.hxx"
+
+#define _GENERIC_STRING_
+
+#if !defined (_GENERIC_STRING_)
+
+#define _GENERIC_STRING_
+
+//
+// Comparison flags
+//
+#define COMPARE_IGNORECASE ( 1 )
+#define COMPARE_IGNOREDIACRITIC ( 2 )
+#define COMPARE_IGNORESYMBOLS ( 4 )
+
+
+//
+// The type of the index used to access individual characters within
+// a generic string.
+//
+DEFINE_TYPE( ULONG, CHNUM );
+
+//
+// Magic constants
+//
+#define INVALID_CHAR ((WCHAR)(-1))
+#define INVALID_CHNUM ((CHNUM)(-1))
+#define TO_END INVALID_CHNUM
+
+
+DECLARE_CLASS( GENERIC_STRING );
+
+
+class GENERIC_STRING : public OBJECT {
+
+ public:
+
+ DECLARE_CAST_MEMBER_FUNCTION( GENERIC_STRING );
+
+ VIRTUAL
+ ~GENERIC_STRING(
+ );
+
+ VIRTUAL
+ PBYTE
+ GetInternalBuffer (
+ IN CHNUM Position DEFAULT 0
+ ) CONST PURE;
+
+ VIRTUAL
+ BOOLEAN
+ IsChAt (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0
+ ) CONST PURE;
+
+ VIRTUAL
+ BOOLEAN
+ MakeNumber (
+ OUT PLONG Number,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST PURE;
+
+ VIRTUAL
+ ULONG
+ QueryByteCount (
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST PURE;
+
+ VIRTUAL
+ WCHAR
+ QueryChAt(
+ IN CHNUM Position DEFAULT 0
+ ) CONST PURE;
+
+ VIRTUAL
+ CHNUM
+ QueryChCount (
+ ) CONST PURE;
+
+ VIRTUAL
+ PGENERIC_STRING
+ QueryGenericString (
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST PURE;
+
+ VIRTUAL
+ PSTR
+ QuerySTR(
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ IN OUT PSTR Buffer DEFAULT NULL,
+ IN ULONG BufferSize DEFAULT 0
+ ) CONST PURE;
+
+ VIRTUAL
+ PWSTR
+ QueryWSTR (
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ IN OUT PWSTR Buffer DEFAULT NULL,
+ IN ULONG BufferSize DEFAULT 0,
+ IN BOOLEAN ForceNull DEFAULT TRUE
+ ) CONST PURE;
+
+ VIRTUAL
+ BOOLEAN
+ Replace (
+ IN PCGENERIC_STRING String2,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ IN CHNUM Position2 DEFAULT 0,
+ IN CHNUM Length2 DEFAULT TO_END
+ ) PURE;
+
+ VIRTUAL
+ BOOLEAN
+ SetChAt (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) PURE;
+
+ VIRTUAL
+ CHNUM
+ Strchr (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST PURE;
+
+ VIRTUAL
+ LONG
+ Strcmp (
+ IN PCGENERIC_STRING GenericString
+ ) CONST PURE;
+
+ VIRTUAL
+ CHNUM
+ Strcspn (
+ IN PCGENERIC_STRING GenericString,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST PURE;
+
+ VIRTUAL
+ LONG
+ Stricmp (
+ IN PCGENERIC_STRING GenericString
+ ) CONST PURE;
+
+ VIRTUAL
+ LONG
+ StringCompare (
+ IN CHNUM Position1,
+ IN CHNUM Length1 ,
+ IN PCGENERIC_STRING GenericString2,
+ IN CHNUM Position2,
+ IN CHNUM Length2,
+ IN USHORT CompareFlags DEFAULT COMPARE_IGNORECASE
+ ) CONST PURE;
+
+ VIRTUAL
+ CHNUM
+ StrLen (
+ ) CONST PURE;
+
+ VIRTUAL
+ CHNUM
+ Strrchr (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST PURE;
+
+ VIRTUAL
+ CHNUM
+ Strspn (
+ IN PCGENERIC_STRING GenericString,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST PURE;
+
+ VIRTUAL
+ CHNUM
+ Strstr (
+ IN PCGENERIC_STRING GenericString,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST PURE;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator == (
+ IN RCGENERIC_STRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator != (
+ IN RCGENERIC_STRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator < (
+ IN RCGENERIC_STRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator > (
+ IN RCGENERIC_STRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator <= (
+ IN RCGENERIC_STRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator >= (
+ IN RCGENERIC_STRING String
+ ) CONST;
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( GENERIC_STRING );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize (
+ );
+
+ private:
+
+ VOID
+ Construct (
+ );
+
+
+};
+
+INLINE
+BOOLEAN
+GENERIC_STRING::operator == (
+ IN RCGENERIC_STRING String
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Compares this string with another.
+
+Arguments:
+
+ String - Supplies a reference to the string to compare.
+
+Return Value:
+
+ TRUE - if String is equal to this string
+ FALSE - if not.
+
+--*/
+
+{
+ return (StringCompare( 0, QueryChCount(), (PCGENERIC_STRING)&String, 0, String.QueryChCount(), COMPARE_IGNORECASE ) == 0);
+}
+
+INLINE
+BOOLEAN
+GENERIC_STRING::operator != (
+ IN RCGENERIC_STRING String
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Compares this string with another.
+
+Arguments:
+
+ String - Supplies a reference to the string to compare.
+
+Return Value:
+
+ TRUE - if String is equal to this string
+ FALSE - if not.
+
+--*/
+
+{
+ return (StringCompare( 0, QueryChCount(), (PCGENERIC_STRING)&String, 0, String.QueryChCount(), COMPARE_IGNORECASE ) != 0);
+}
+
+INLINE
+BOOLEAN
+GENERIC_STRING::operator < (
+ IN RCGENERIC_STRING String
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Compares this string with another.
+
+Arguments:
+
+ String - Supplies a reference to the string to compare.
+
+Return Value:
+
+ TRUE - if String is less then this string
+ FALSE - if not.
+
+--*/
+
+{
+ return (StringCompare( 0, QueryChCount(), (PCGENERIC_STRING)&String, 0, String.QueryChCount(), COMPARE_IGNORECASE ) < 0);
+}
+
+INLINE
+BOOLEAN
+GENERIC_STRING::operator > (
+ IN RCGENERIC_STRING String
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Compares this string with another.
+
+Arguments:
+
+ String - Supplies a reference to the string to compare.
+
+Return Value:
+
+ TRUE - if String is greater then this string
+ FALSE - if not.
+
+--*/
+
+
+{
+ return (StringCompare( 0, QueryChCount(), (PCGENERIC_STRING)&String, 0, String.QueryChCount(), COMPARE_IGNORECASE ) > 0);
+}
+
+INLINE
+BOOLEAN
+GENERIC_STRING::operator <= (
+ IN RCGENERIC_STRING String
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Compares this string with another.
+
+Arguments:
+
+ String - Supplies a reference to the string to compare.
+
+Return Value:
+
+ TRUE - if String is less then or equal this string
+ FALSE - if not.
+
+--*/
+
+{
+ return (StringCompare( 0, QueryChCount(), (PCGENERIC_STRING)&String, 0, String.QueryChCount(), COMPARE_IGNORECASE ) <= 0);
+}
+
+INLINE
+NONVIRTUAL
+BOOLEAN
+GENERIC_STRING::operator >= (
+ IN RCGENERIC_STRING String
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Compares this string with another.
+
+Arguments:
+
+ String - Supplies a reference to the string to compare.
+
+Return Value:
+
+ TRUE - if String is greater then or equal this string
+ FALSE - if not.
+
+--*/
+
+{
+ return (StringCompare( 0, QueryChCount(), (PCGENERIC_STRING)&String, 0, String.QueryChCount(), COMPARE_IGNORECASE ) >= 0);
+}
+
+#endif // _GENERIC_STRING_
diff --git a/private/utils/ulib/inc/stringar.hxx b/private/utils/ulib/inc/stringar.hxx
new file mode 100644
index 000000000..dfae463e5
--- /dev/null
+++ b/private/utils/ulib/inc/stringar.hxx
@@ -0,0 +1,83 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ stringar.hxx
+
+Abstract:
+
+ This module contains the definitions for 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
+
+--*/
+
+#if ! defined( _STRING_ARRAY_ )
+
+#define _STRING_ARRAY_
+
+
+
+//
+// Default values for an STRING_ARRAY object.
+//
+// - Capacity is the total number of elemnts that can be stored in an STRING_ARRAY
+// - CapacityIncrement is the number of elemnts that the STRING_ARRAY's Capacity
+// will be increased by when it's Capacity is exceeded
+//
+
+CONST CHNUM DefaultPosition = 0;
+// CONST ULONG DefaultCapacity = 50;
+// CONST ULONG DefaultCapacityIncrement = 25;
+
+class STRING_ARRAY : public ARRAY {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( STRING_ARRAY );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize (
+ IN CHNUM Position DEFAULT DefaultPosition,
+ IN ULONG Capacity DEFAULT DefaultCapacity,
+ IN ULONG CapacityIncrement DEFAULT DefaultCapacityIncrement
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Sort(
+ IN BOOLEAN Ascending
+ );
+
+ private:
+
+ static
+ NONVIRTUAL
+ int _CRTAPI1
+ StringCompare(
+ IN const void * String1,
+ IN const void * String2
+ );
+
+ static CHNUM _Position;
+ static BOOLEAN _Ascending;
+};
+
+#endif // _STRING_ARRAY_
+
diff --git a/private/utils/ulib/inc/substrng.hxx b/private/utils/ulib/inc/substrng.hxx
new file mode 100644
index 000000000..c7faa0542
--- /dev/null
+++ b/private/utils/ulib/inc/substrng.hxx
@@ -0,0 +1,632 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ SUB_STRING
+
+Abstract:
+
+ This module contains the definition of the SUB_STRING class.
+
+Author:
+
+ Steve Rowe (stever)
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+ A substring is a subsequence of characters taken from a "base"
+ string. Substrings are useful in those cases in which we want
+ to operate on "chunks" of a given string (e.g. parsing), without
+ having to create separate strings for each one.
+
+ One must be careful when using substrings, though. Since
+ substrings depend on a base string, the base string must exist
+ during the life span of all its substrings. In other words,
+ the base string must not be deleted before having deleted all
+ the substrings obtained from it.
+
+ Note that GENERIC_STRINGs have no substring support. It is up to
+ the derived string classes to provide it.
+
+ Since substrings are just "windows" into a base string, any
+ modification of a substring will be reflected in the base
+ string (hence in all other substrings). This is why we have
+ two classes of substrings:
+
+ SUB_STRING allows only read operations. Note however that
+ one can modify the base string directly.
+
+ DYNAMIC_SUB_STRING is derived from the above, and it allows
+ write operations. Needless to say, you should
+ not use this class unless you're sure of what
+ you are doing.
+
+ Substring objects cannot be created and initialized directly by the
+ user, they must be obtained thru a base string class with substring
+ support.
+
+ Substrings pertaining to the same base string are chained together
+ in a doubly-linked queue. Since substrings have no knowledge of the
+ internals of their base string, the chain has a dummy element as its
+ head. In order to provide substring support, the base string must
+ follow these steps:
+
+
+ 1.- Before spawning any substring, the substring chain head must
+ be created and initialized using the InitializeChainHead() method.
+ Note that this substring is a dummy one, beknown only to the base
+ string.
+
+ 2.- Whenever spawning a new substring, it must be linked to the chain
+ using the InitializeChainNode() method. Any substring already in
+ the chain may be use as argument, but the obvious choice is the
+ chain head.
+
+ 3.- Each time that the size of the string changes, the Update() of the
+ chain head must be invoked.
+
+ 4.- Before destroying a base string, you have to make sure that all its
+ substrings have gone away. This means that the chain head must be
+ the only element of the chain. Use the HasLinks() method to
+ verify this.
+
+ 5.- Don't forget to destroy the chain head before destorying the base
+ string.
+
+
+--*/
+
+//
+// This class is no longer supported
+//
+
+#include "wstring.hxx"
+
+#define _SUB_STRING_
+
+#if !defined (_SUB_STRING_)
+
+#define _SUB_STRING_
+
+#include "string.hxx"
+
+DECLARE_CLASS( SUB_STRING );
+
+class SUB_STRING : public GENERIC_STRING {
+
+ friend SUB_STRING;
+
+ public:
+
+ DECLARE_CONSTRUCTOR( SUB_STRING );
+ DECLARE_CAST_MEMBER_FUNCTION( SUB_STRING );
+
+ VIRTUAL
+ ~SUB_STRING (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ HasLinks (
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ InitializeChainHead (
+ IN PGENERIC_STRING BaseString
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ InitializeChainNode (
+ IN OUT PSUB_STRING SubString,
+ IN CHNUM Position,
+ IN CHNUM Length
+ );
+
+ VIRTUAL
+ PBYTE
+ GetInternalBuffer (
+ IN CHNUM Position DEFAULT 0
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ IsChAt (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ MakeNumber (
+ OUT PLONG Number,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ VIRTUAL
+ ULONG
+ QueryByteCount (
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ VIRTUAL
+ WCHAR
+ QueryChAt(
+ IN CHNUM Position DEFAULT 0
+ ) CONST;
+
+ VIRTUAL
+ CHNUM
+ QueryChCount (
+ ) CONST;
+
+ VIRTUAL
+ PGENERIC_STRING
+ QueryGenericString (
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ VIRTUAL
+ PSTR
+ QuerySTR(
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ IN OUT PSTR Buffer DEFAULT NULL,
+ IN ULONG BufferSize DEFAULT 0
+ ) CONST;
+
+ VIRTUAL
+ PSUB_STRING
+ QuerySubString (
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ OUT PSUB_STRING SubString DEFAULT NULL
+ );
+
+ VIRTUAL
+ PWSTR
+ QueryWSTR (
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ IN OUT PWSTR Buffer DEFAULT NULL,
+ IN ULONG BufferSize DEFAULT 0,
+ IN BOOLEAN ForceNull DEFAULT TRUE
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ Replace (
+ IN PCGENERIC_STRING String2,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ IN CHNUM Position2 DEFAULT 0,
+ IN CHNUM Length2 DEFAULT TO_END
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetChAt (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ );
+
+ VIRTUAL
+ CHNUM
+ Strchr (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ VIRTUAL
+ LONG
+ Strcmp (
+ IN PCGENERIC_STRING GenericString
+ ) CONST;
+
+ VIRTUAL
+ CHNUM
+ Strcspn (
+ IN PCGENERIC_STRING GenericString,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ VIRTUAL
+ LONG
+ Stricmp (
+ IN PCGENERIC_STRING GenericString
+ ) CONST;
+
+ VIRTUAL
+ LONG
+ StringCompare (
+ IN CHNUM Position1,
+ IN CHNUM Length1,
+ IN PCGENERIC_STRING GenericString2,
+ IN CHNUM Position2,
+ IN CHNUM Length2,
+ IN USHORT CompareFlags DEFAULT COMPARE_IGNORECASE
+ ) CONST;
+
+
+ VIRTUAL
+ CHNUM
+ StrLen (
+ ) CONST;
+
+ VIRTUAL
+ CHNUM
+ Strrchr (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ VIRTUAL
+ CHNUM
+ Strspn (
+ IN PCGENERIC_STRING GenericString,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ VIRTUAL
+ CHNUM
+ Strstr (
+ IN PCGENERIC_STRING GenericString,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ Update (
+ IN CHNUM Length
+ );
+
+ protected:
+
+ NONVIRTUAL
+ PGENERIC_STRING
+ GetBaseString (
+ );
+
+ NONVIRTUAL
+ PSUB_STRING
+ GetNextInChain (
+ );
+
+ NONVIRTUAL
+ PSUB_STRING
+ GetPreviousInChain (
+ );
+
+ NONVIRTUAL
+ VOID
+ GetValidLength(
+ IN CHNUM Position,
+ IN OUT PCHNUM Length
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ QueryStartingPosition (
+ ) CONST;
+
+ NONVIRTUAL
+ VOID
+ SetChCount(
+ IN CHNUM NewCount
+ );
+
+ private:
+
+ NONVIRTUAL
+ VOID
+ Construct (
+ );
+
+ NONVIRTUAL
+ VOID
+ Destroy (
+ );
+
+ PGENERIC_STRING _BaseString; // base string to take substring
+ CHNUM _StartingPosition; // starting index within base
+ CHNUM _CountOfChars; // # of chars in substring
+
+ PSUB_STRING _Previous; // Previous in chain
+ PSUB_STRING _Next; // Next in chain
+
+#if DBG==1
+ ULONG _Signature;
+ BOOLEAN _Initialized;
+#endif
+
+};
+
+INLINE
+PGENERIC_STRING
+SUB_STRING::GetBaseString (
+ )
+
+/*++
+
+Routine Description:
+
+ Gets a pointer to the base string
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Pointer to the base string
+
+--*/
+
+{
+ DebugAssert( _Initialized );
+ return _BaseString;
+}
+
+INLINE
+PSUB_STRING
+SUB_STRING::GetNextInChain (
+ )
+
+/*++
+
+Routine Description:
+
+ Gets a pointer to next substring in the chain
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Pointer to substring
+
+--*/
+
+{
+ DebugAssert( _Initialized );
+ return _Next;
+}
+
+INLINE
+PSUB_STRING
+SUB_STRING::GetPreviousInChain (
+ )
+
+/*++
+
+Routine Description:
+
+ Gets a pointer to previous substring in the chain
+
+Arguments:
+
+ none
+
+Return Value:
+
+ Pointer to the previous substring
+
+--*/
+
+{
+ DebugAssert( _Initialized );
+ return _Previous;
+}
+
+INLINE
+VOID
+SUB_STRING::GetValidLength (
+ IN CHNUM Position,
+ IN OUT PCHNUM Length
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ If the length passed has the magic value TO_END, then it is
+ updated to be the from the passed position up to the end of the
+ substring.
+
+Arguments:
+
+ Position - Supplies a starting position within the substring
+ Length - Supplies a length
+
+Return Value:
+
+ none
+
+--*/
+
+{
+
+ DebugAssert(_Initialized );
+
+ DebugAssert( Position <= _CountOfChars );
+
+ if ( *Length == TO_END ) {
+ *Length = _CountOfChars - Position;
+ }
+
+ DebugAssert( Position + *Length <= _CountOfChars );
+}
+
+INLINE
+BOOLEAN
+SUB_STRING::HasLinks (
+ )
+
+/*++
+
+Routine Description:
+
+ Determines if the substring has forward and backward links
+
+Arguments:
+
+ none
+
+Return Value:
+
+ TRUE if the stubstring has forward or backward links
+ FALSE otherwise
+
+--*/
+
+{
+ DebugAssert( _Initialized );
+ return ( (GetNextInChain() != NULL ) || (GetPreviousInChain() != NULL ) );
+
+}
+
+INLINE
+CHNUM
+SUB_STRING::QueryStartingPosition (
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ Returns the starting character position within the base string.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The starting character position within the base string.
+
+--*/
+
+{
+ DebugAssert( _Initialized );
+ return _StartingPosition;
+}
+
+INLINE
+VOID
+SUB_STRING::SetChCount (
+ IN CHNUM NewCount
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the number of characters in the substring
+
+Arguments:
+
+ NewCount - Supplies the new count of characters
+
+Return Value:
+
+ none
+
+--*/
+
+{
+ DebugAssert( _Initialized );
+ _CountOfChars = NewCount;
+}
+
+
+
+#endif // _SUB_STRING_
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ DYNAMIC_SUB_STRING
+
+Abstract:
+
+ This module contains the definition of the DYNAMIC_SUB_STRING class.
+
+Author:
+
+ steve rowe stever 2/1/91
+
+Notes:
+
+ DYNAMIC_SUB_STRINGs can modify the base string (see notes for
+ SUB_STRING class).
+
+
+Revision History:
+
+--*/
+
+#define _DYNAMIC_SUB_STRING_
+
+#if !defined (_DYNAMIC_SUB_STRING_)
+
+#define _DYNAMIC_SUB_STRING_
+
+DECLARE_CLASS( DYNAMIC_SUB_STRING );
+
+class DYNAMIC_SUB_STRING : public SUB_STRING {
+
+ public:
+
+ DECLARE_CONSTRUCTOR( DYNAMIC_SUB_STRING );
+ DECLARE_CAST_MEMBER_FUNCTION( DYNAMIC_SUB_STRING );
+
+ NONVIRTUAL
+ BOOLEAN
+ Copy (
+ IN PCGENERIC_STRING GenericString
+ );
+
+ VIRTUAL
+ BOOLEAN
+ SetChAt (
+ IN WCHAR Char,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ );
+
+ NONVIRTUAL
+ CHNUM
+ Truncate (
+ IN CHNUM Position DEFAULT 0
+ );
+
+ private:
+
+ VOID
+ Construct (
+ );
+
+};
+
+
+#endif // _DYNAMIC_SUB_STRING_
diff --git a/private/utils/ulib/inc/system.hxx b/private/utils/ulib/inc/system.hxx
new file mode 100644
index 000000000..a204e07a1
--- /dev/null
+++ b/private/utils/ulib/inc/system.hxx
@@ -0,0 +1,253 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ system.hxx
+
+Abstract:
+
+ This module contains the definition for the SYSTEM class. The SYSTEM
+ class is an abstract class which offers an interface for communicating
+ with the underlying operating system.
+
+Author:
+
+ David J. Gilman (davegi) 13-Jan-1991
+
+Environment:
+
+ ULIB, User Mode
+
+Notes:
+
+
+
+--*/
+
+#if ! defined( _SYSTEM_ )
+
+#define _SYSTEM_
+
+DECLARE_CLASS( FSN_DIRECTORY );
+DECLARE_CLASS( FSN_FILE );
+DECLARE_CLASS( FSNODE );
+DECLARE_CLASS( WSTRING );
+DECLARE_CLASS( STREAM );
+DECLARE_CLASS( TIMEINFO );
+
+#include "message.hxx"
+#include "path.hxx"
+#include "basesys.hxx"
+
+extern "C" {
+ #include <stdarg.h>
+}
+
+
+
+enum DRIVE_TYPE {
+ UnknownDrive,
+ RemovableDrive,
+ FixedDrive,
+ RemoteDrive,
+ CdRomDrive,
+ RamDiskDrive
+};
+
+enum FILE_TYPE {
+ UnknownFile,
+ DiskFile,
+ CharFile,
+ PipeFile
+};
+
+struct _VOL_SERIAL_NUMBER {
+ ULONG HighOrder32Bits;
+ ULONG LowOrder32Bits;
+};
+
+DEFINE_TYPE( struct _VOL_SERIAL_NUMBER, VOL_SERIAL_NUMBER );
+
+class SYSTEM : public BASE_SYSTEM {
+
+ friend
+ BOOLEAN
+ InitializeUlib(
+ IN HANDLE DllHandle,
+ IN ULONG Reason,
+ IN PVOID Reserved
+ );
+
+ public:
+
+ STATIC
+ ULIB_EXPORT
+ PFSN_DIRECTORY
+ MakeDirectory (
+ IN PCPATH Path,
+ IN PCPATH TemplatePath OPTIONAL
+ );
+
+ STATIC
+ ULIB_EXPORT
+ PFSN_FILE
+ MakeFile (
+ IN PCPATH Path
+ );
+
+ STATIC
+ ULIB_EXPORT
+ PFSN_FILE
+ MakeTemporaryFile (
+ IN PCWSTRING PrefixString,
+ IN PCPATH Path DEFAULT NULL
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ RemoveNode (
+ IN PFSNODE *PointerToNode,
+ IN BOOLEAN Force DEFAULT FALSE
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ IsCorrectVersion (
+ );
+
+ STATIC
+ PPATH
+ QueryCurrentPath (
+ );
+
+ STATIC
+ ULIB_EXPORT
+ PFSN_DIRECTORY
+ QueryDirectory (
+ IN PCPATH Path,
+ IN BOOLEAN GetWhatYouCan DEFAULT FALSE
+ );
+
+ STATIC
+ ULIB_EXPORT
+ PWSTRING
+ QueryEnvironmentVariable (
+ IN PCWSTRING Variable
+ );
+
+
+ STATIC
+ ULIB_EXPORT
+ PPATH
+ QuerySystemDirectory (
+ );
+
+ STATIC
+ ULIB_EXPORT
+ PPATH
+ SearchPath(
+ PWSTRING pFileName,
+ PWSTRING pSearchPath DEFAULT NULL
+ );
+
+ STATIC
+ ULIB_EXPORT
+ PFSN_FILE
+ QueryFile (
+ IN PCPATH Path
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ QueryCurrentDosDriveName(
+ OUT PWSTRING DosDriveName
+ );
+
+ STATIC
+ ULIB_EXPORT
+ DRIVE_TYPE
+ QueryDriveType(
+ IN PCWSTRING DosDriveName
+ );
+
+ STATIC
+ ULIB_EXPORT
+ FILE_TYPE
+ QueryFileType(
+ IN PCWSTRING DosFileName
+ );
+
+ STATIC
+ ULIB_EXPORT
+ PWSTRING
+ QueryVolumeLabel(
+ IN PPATH Path,
+ OUT PVOL_SERIAL_NUMBER SerialNumber
+ );
+
+ STATIC
+ ULIB_EXPORT
+ FARPROC
+ QueryLibraryEntryPoint(
+ IN PCWSTRING LibraryName,
+ IN PCWSTRING EntryPointName,
+ OUT PHANDLE LibraryHandle
+ );
+
+ STATIC
+ ULIB_EXPORT
+ VOID
+ FreeLibraryHandle(
+ IN HANDLE LibraryHandle
+ );
+
+ STATIC
+ BOOLEAN
+ PutStandardStream(
+ IN DWORD StdHandle,
+ IN PSTREAM pStream
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ QueryLocalTimeFromUTime(
+ IN PCTIMEINFO UTimeInfo,
+ OUT PTIMEINFO LocalTimeInfo
+ );
+
+ STATIC
+ BOOLEAN
+ QueryUTimeFromLocalTime(
+ IN PCTIMEINFO LocalTimeInfo,
+ OUT PTIMEINFO UTimeInfo
+ );
+
+ STATIC
+ ULIB_EXPORT
+ BOOLEAN
+ QueryWindowsErrorMessage(
+ IN ULONG WindowsErrorCode,
+ OUT PWSTRING ErrorMessage
+ );
+
+};
+
+
+INLINE
+PPATH
+SYSTEM::QueryCurrentPath (
+ )
+
+{
+ DebugAssert( FALSE );
+ return( NEW PATH );
+}
+
+
+#endif // SYSTEM_DEFN
diff --git a/private/utils/ulib/inc/timeinfo.hxx b/private/utils/ulib/inc/timeinfo.hxx
new file mode 100644
index 000000000..e9bf783b2
--- /dev/null
+++ b/private/utils/ulib/inc/timeinfo.hxx
@@ -0,0 +1,631 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ time.hxx
+
+Abstract:
+
+ This module contains the declaration for the TIMEINFO class.
+ The data members of the TIMEINFO class contain the date and
+ time information represented as a FILETIME structure and a
+ SYSTEMTIME structure. These two representations of date and
+ time are always initialized independently of the way that the
+ TIMEINFO class is initialized (as a FILETIME or a SYSTEMTIME).
+
+Author:
+
+ Jaime Sasson (jaimes) 13-Mar-1991
+
+Environment:
+
+ ULIB, User Mode
+
+
+--*/
+
+
+#if !defined( _TIMEINFO_ )
+
+#define _TIMEINFO_
+
+#include "wstring.hxx"
+
+
+DECLARE_CLASS( TIMEINFO );
+
+
+class TIMEINFO : public OBJECT {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( TIMEINFO );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN PFILETIME FileTime
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN PSYSTEMTIME SystemTime
+ );
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ Initialize(
+ IN PCTIMEINFO TimeInfo
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ IN USHORT Year,
+ IN USHORT Month,
+ IN USHORT Day,
+ IN USHORT Hour,
+ IN USHORT Minute,
+ IN USHORT Second,
+ IN USHORT Milliseconds
+ );
+
+
+ NONVIRTUAL
+ SHORT
+ CompareTimeInfo(
+ IN PFILETIME FileTime
+ ) CONST;
+
+
+ NONVIRTUAL
+ SHORT
+ CompareTimeInfo(
+ IN PSYSTEMTIME SystemTime
+ ) CONST;
+
+
+ NONVIRTUAL
+ PFILETIME
+ GetFileTime(
+ ) CONST;
+
+
+ NONVIRTUAL
+ PSYSTEMTIME
+ GetSysTime(
+ ) CONST;
+
+
+ NONVIRTUAL
+ BOOLEAN
+ IsLeapYear(
+ USHORT Year DEFAULT 0
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryYear(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryMonth(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryDay(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryDayOfWeek(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryHour(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryMinute(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QuerySecond(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryMilliseconds(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryDayOffset(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryDaysInMonth(
+ ) CONST;
+
+
+ NONVIRTUAL
+ USHORT
+ QueryDaysInYear(
+ ) CONST;
+
+
+ NONVIRTUAL
+ BOOLEAN
+ SetDate(
+ USHORT Year,
+ USHORT Month,
+ USHORT Day
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ SetDate(
+ PCWSTRING Date
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ SetDateAndTime (
+ PCWSTRING DateAndTime
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ SetTime(
+ USHORT Hour DEFAULT 0,
+ USHORT Minute DEFAULT 0,
+ USHORT Second DEFAULT 0,
+ USHORT Millisecond DEFAULT 0
+ );
+
+
+ NONVIRTUAL
+ BOOLEAN
+ SetTime(
+ PCWSTRING Time
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ QueryTime(
+ OUT PWSTRING FormattedTimeString
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ QueryDate(
+ OUT PWSTRING FormattedDateString
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator== (
+ IN TIMEINFO TimeInfo
+ ) CONST;
+
+
+ NONVIRTUAL
+ BOOLEAN
+ operator!= (
+ IN TIMEINFO TimeInfo
+ ) CONST;
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ operator< (
+ IN TIMEINFO TimeInfo
+ ) CONST;
+
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ operator> (
+ IN TIMEINFO TimeInfo
+ ) CONST;
+
+
+ NONVIRTUAL
+ BOOLEAN
+ operator<= (
+ IN TIMEINFO TimeInfo
+ ) CONST;
+
+
+ NONVIRTUAL
+ BOOLEAN
+ operator>= (
+ IN TIMEINFO TimeInfo
+ ) CONST;
+
+
+ private:
+
+ VOID
+ Construct (
+ );
+
+ FILETIME _FileTime;
+ SYSTEMTIME _SystemTime;
+
+};
+
+
+
+INLINE
+BOOLEAN
+TIMEINFO::IsLeapYear(
+ USHORT Year
+ ) CONST
+
+/*++
+
+Routine Description:
+
+ This member function finds out if the year received as parameter
+ is a leap year.
+
+Arguments:
+
+ Year - Year to be verified. If the year specified is zero, then
+ the year stored in this class is verified.
+
+Return Value:
+
+ BOOLEAN - Indicates if it is a leap year (TRUE) or not (FALSE).
+
+
+--*/
+
+{
+ Year = ( Year == 0 )? (USHORT)_SystemTime.wYear : Year;
+ if( ( ( Year % 400 ) == 0 ) ||
+ ( ( Year % 100 ) != 0 ) && ( ( Year % 4 ) == 0 ) ) {
+ return( TRUE );
+ }
+ else {
+ return( FALSE );
+ }
+}
+
+
+
+INLINE
+USHORT
+TIMEINFO::QueryYear(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns the year stored in the data member of this class.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ USHORT - Number representing the year.
+
+
+--*/
+
+{
+ return( _SystemTime.wYear );
+}
+
+
+
+
+INLINE
+USHORT
+TIMEINFO::QueryMonth(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns the month stored in the data member of this class.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ USHORT - Number representing the month.
+
+
+--*/
+
+{
+ return( _SystemTime.wMonth );
+}
+
+
+
+
+INLINE
+USHORT
+TIMEINFO::QueryDay(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns the day stored in the data member of this class.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ USHORT - Number representing the day.
+
+
+--*/
+
+{
+ return( _SystemTime.wDay );
+}
+
+
+
+
+INLINE
+USHORT
+TIMEINFO::QueryDayOfWeek(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns the day of the week stored in the data member of this class.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ USHORT - Number representing the day of the week.
+
+
+--*/
+
+{
+ return( _SystemTime.wDayOfWeek );
+}
+
+
+
+
+INLINE
+USHORT
+TIMEINFO::QueryHour(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns the hour stored in the data member of this class.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ USHORT - Number representing the hour.
+
+
+--*/
+
+{
+ return( _SystemTime.wHour );
+}
+
+
+
+
+INLINE
+USHORT
+TIMEINFO::QueryMinute(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns the minutes stored in the data member of this class.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ USHORT - Number representing the minutes.
+
+
+--*/
+
+{
+ return( _SystemTime.wMinute );
+}
+
+
+
+
+INLINE
+USHORT
+TIMEINFO::QuerySecond(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns the seconds stored in the data member of this class.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ USHORT - Number representing the secondss.
+
+
+--*/
+
+{
+ return( _SystemTime.wSecond );
+}
+
+
+
+
+INLINE
+USHORT
+TIMEINFO::QueryMilliseconds(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns the number of milliseconds stored in the data member of
+ this class.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ USHORT - Number representing the millisecondss.
+
+
+--*/
+
+{
+ return( _SystemTime.wMilliseconds );
+}
+
+
+
+INLINE
+PFILETIME
+TIMEINFO::GetFileTime(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns a pointer to the data member that contains the file time.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PFILETIME - Pointer to FileTime.
+
+--*/
+
+{
+ return( ( PFILETIME )&_FileTime );
+}
+
+
+
+INLINE
+PSYSTEMTIME
+TIMEINFO::GetSysTime(
+ ) CONST
+
+
+/*++
+
+Routine Description:
+
+ Returns a pointer to the data member that contains the system time.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ PSYSTEMTIME - Pointer to SystemTime.
+
+--*/
+
+{
+ return( ( PSYSTEMTIME )&_SystemTime );
+}
+
+
+
+#endif // _TIMEINFO_
diff --git a/private/utils/ulib/inc/ulib.hxx b/private/utils/ulib/inc/ulib.hxx
new file mode 100644
index 000000000..97ce0ceae
--- /dev/null
+++ b/private/utils/ulib/inc/ulib.hxx
@@ -0,0 +1,152 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ Ulib.hxx
+
+Abstract:
+
+
+Author:
+
+ David J. Gilman (davegi) 22-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if !defined ( _ULIB_DEFINED_ )
+
+#define _ULIB_DEFINED_
+
+//
+// Autocheck implies no windows header files so this helps make up the
+// difference. Autocheck also has a special Debug switch, since
+// it allows printing to the debugger but does not execute any other
+// debug-only code.
+//
+
+#if defined( _AUTOCHECK_ )
+
+#define _NTAPI_ULIB_
+
+#if DBG
+#define _AUTOCHECK_DBG_
+#endif
+
+#undef DBG
+
+#define DBG 0
+
+#else
+
+ #ifndef _NTAPI_ULIB_
+ #define _NTAPI_ULIB_
+ #endif
+
+#endif // _AUTOCHECK_
+
+
+extern "C" {
+
+ #if defined( _NTAPI_ULIB_ )
+
+ #include <nt.h>
+ #include <ntrtl.h>
+ #include <nturtl.h>
+ #include <ntdddisk.h>
+
+ #endif // _NTAPI_ULIB_
+
+ #if !defined( _AUTOCHECK_ )
+
+ #include <windows.h>
+
+ #endif // _AUTOCHECK_
+}
+
+
+//
+// Function prototypes for Ulib non member functions (see ulib.cxx)
+//
+
+extern "C"
+BOOLEAN
+InitializeUlib(
+ IN HANDLE DllHandle,
+ IN ULONG Reason,
+ IN PVOID Reserved
+ );
+
+
+//
+// Intrinsic functions
+//
+#if DBG==0
+
+ #pragma intrinsic( memset, memcpy, memcmp )
+
+#endif
+
+//
+// Here's the scoop...ntdef.h defined NULL to be ( PVOID ) 0.
+// Cfront barfs on this if you try and assign NULL to any other pointer type.
+// This leaves two options (a) cast all NULL assignments or (b) define NULL
+// to be zero which is what C++ expects.
+//
+
+#if defined( NULL )
+
+ #undef NULL
+
+#endif
+#define NULL ( 0 )
+
+//
+// Make sure const is not defined.
+//
+#if defined( const )
+ #undef const
+#endif
+
+#include "ulibdef.hxx"
+#include "object.hxx"
+#include "clasdesc.hxx"
+
+//
+// External definitions for global objects (see ulib.cxx)
+//
+
+DECLARE_CLASS( PATH );
+
+#if !defined( _AUTOCHECK_ )
+
+ DECLARE_CLASS( STREAM );
+
+ //
+ // Standard streams
+ //
+ extern PSTREAM Standard_Input_Stream;
+ extern PSTREAM Standard_Output_Stream;
+ extern PSTREAM Standard_Error_Stream;
+
+#endif // _AUTOCHECK
+
+#if !defined( _AUTOCHECK_ )
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ HANDLE
+ FindFirstFile (
+ IN PCPATH Path,
+ OUT PWIN32_FIND_DATA FileFindData
+ );
+
+#endif // _AUTOCHECK
+
+
+#endif // _ULIB_DEFINED_
diff --git a/private/utils/ulib/inc/ulibcl.hxx b/private/utils/ulib/inc/ulibcl.hxx
new file mode 100644
index 000000000..ca882184e
--- /dev/null
+++ b/private/utils/ulib/inc/ulibcl.hxx
@@ -0,0 +1,40 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ulibcl.hxx
+
+Abstract:
+
+ This module contains declarations that the clients of
+ ULIB.DLL require.
+
+Author:
+
+ Bill McJohn (billmc) 17-May-1991
+
+Environment:
+
+ ULIB Clients, User Mode
+
+--*/
+
+#if ! defined( _ULIBCLIENTDEFN_ )
+
+#define _ULIBCLIENTDEFN_
+
+ULIB_EXPORT
+PSTREAM
+Get_Standard_Input_Stream();
+
+ULIB_EXPORT
+PSTREAM
+Get_Standard_Output_Stream();
+
+ULIB_EXPORT
+PSTREAM
+Get_Standard_Error_Stream();
+
+#endif
diff --git a/private/utils/ulib/inc/ulibdef.hxx b/private/utils/ulib/inc/ulibdef.hxx
new file mode 100644
index 000000000..84c104e8d
--- /dev/null
+++ b/private/utils/ulib/inc/ulibdef.hxx
@@ -0,0 +1,460 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ ulibdef.hxx
+
+Abstract:
+
+ This module contains primitive support for the ULIB class hierarchy
+ and it's clients. This support includes:
+
+ - type definitions
+ - manifest constants
+ - debugging support
+ - memory leakage support
+ - external references
+
+Author:
+
+ David J. Gilman (davegi) 19-Oct-1990
+
+Environment:
+
+ ULIB, User Mode
+
+--*/
+
+#if ! defined( _ULIBDEF_ )
+
+#define _ULIBDEF_
+
+extern "C" {
+ #include <stdlib.h>
+};
+
+// The ULIB_EXPORT macro marks functions that are to be
+// exported. The source files for ULIB.DLL will have _ULIB_MEMBER_
+// defined; clients will not.
+//
+#if defined ( _AUTOCHECK_ )
+#define ULIB_EXPORT
+#elif defined ( _ULIB_MEMBER_ )
+#define ULIB_EXPORT __declspec(dllexport)
+#else
+#define ULIB_EXPORT __declspec(dllimport)
+#endif
+
+
+
+#pragma warning(disable:4091) // Symbol not defined
+
+//
+// Macros for defining types:
+//
+// - pointers (Ptype)
+// - pointers to constants (PCtype)
+// - references (Rtype)
+// - references to constants (RCtype)
+//
+
+#define DEFINE_POINTER_TYPES( type ) \
+ typedef type* P##type; \
+ typedef const type* PC##type
+
+#define DEFINE_REFERENCE_TYPES( type ) \
+ typedef type& R##type; \
+ typedef const type& RC##type
+
+#define DEFINE_POINTER_AND_REFERENCE_TYPES( type ) \
+ DEFINE_POINTER_TYPES( type ); \
+ DEFINE_REFERENCE_TYPES( type )
+
+#define DEFINE_TYPE( basetype, newtype ) \
+ typedef basetype newtype; \
+ DEFINE_POINTER_AND_REFERENCE_TYPES( newtype )
+
+#define DECLARE_CLASS( c ) \
+ class c; \
+ DEFINE_POINTER_AND_REFERENCE_TYPES( c );\
+ extern PCCLASS_DESCRIPTOR c##_cd
+
+//
+// Primitive types.
+//
+
+DEFINE_TYPE( unsigned char, UCHAR );
+DEFINE_TYPE( unsigned short,USHORT );
+DEFINE_TYPE( unsigned long, ULONG );
+
+DEFINE_TYPE( char, CCHAR );
+DEFINE_TYPE( short, CSHORT );
+DEFINE_TYPE( ULONG, CLONG );
+
+DEFINE_TYPE( short, SSHORT );
+DEFINE_TYPE( long, SLONG );
+
+DEFINE_TYPE( UCHAR, BYTE );
+DEFINE_TYPE( char, STR );
+DEFINE_TYPE( UCHAR, BOOLEAN );
+DEFINE_TYPE( int, INT );
+DEFINE_TYPE( unsigned int, UINT );
+
+DEFINE_TYPE(USHORT, WCHAR );
+
+typedef WCHAR *LPWCH; // pwc
+typedef WCHAR *LPWSTR; // pwsz, 0x0000 terminated UNICODE strings only
+
+DEFINE_POINTER_AND_REFERENCE_TYPES( WCHAR );
+
+DEFINE_TYPE( WCHAR, WSTR );
+//DEFINE_TYPE( struct tagLC_ID, LC_ID );
+
+//
+// Augmented (beyond standard headers) VOID pointer types
+//
+
+DEFINE_POINTER_TYPES( VOID );
+
+//
+// Ulib specific, primitive types
+//
+
+DEFINE_TYPE( STR, CLASS_NAME );
+DEFINE_TYPE( ULONG, CLASS_ID );
+
+
+//
+// Member and non-member function/data modifiers
+//
+
+#define CONST const
+#define NONVIRTUAL
+#define PURE = 0
+#define STATIC static
+#define VIRTUAL virtual
+#define INLINE inline
+// #define INLINE // hack to build for mips
+#define FRIEND friend
+
+//
+// Argument modifiers
+//
+
+#define DEFAULT =
+#define IN
+#define OPTIONAL
+#define OUT
+#define INOUT
+
+#if !defined(max)
+ #define max(a,b) (((a) > (b)) ? (a) : (b) )
+#endif
+
+#if !defined(min)
+ #define min(a,b) (((a) < (b)) ? (a) : (b) )
+#endif
+
+#if DBG==1
+
+ #define REGISTER
+
+#else
+
+ #define REGISTER register
+
+#endif // DBG
+
+//
+// External constants
+//
+
+extern CONST CLASS_ID NIL_CLASS_ID;
+
+//
+// GetFileName returns the file name portion of the supplied path name.
+//
+
+extern "C" {
+ #include <string.h>
+};
+
+inline
+PCCHAR
+GetFileName (
+ IN PCCHAR PathName
+ )
+
+{
+ PCCHAR pch;
+
+ return((( pch = strrchr( PathName, '\\' )) != NULL ) ?
+ pch + 1 : PathName );
+}
+
+//
+// Cast (beProtocol) support
+//
+// If the ID of the passed object is equal to the ID in this class'
+// CLASS_DESCRIPTOR, then the object is of this type and the Cast succeeds
+// (i.e. returns Object) otherwise the Cast fails (i.e. returns NULL)
+//
+
+
+#define DECLARE_CAST_MEMBER_FUNCTION( type ) \
+ STATIC \
+ P##type \
+ Cast ( \
+ PCOBJECT Object \
+ )
+
+
+#define DEFINE_CAST_MEMBER_FUNCTION( type ) \
+ P##type \
+ type::Cast ( \
+ PCOBJECT Object \
+ ) \
+ { \
+ if( Object && ( Object->QueryClassId( ) == \
+ type##_cd->QueryClassId( ))) { \
+ return(( P##type ) Object ); \
+ } else { \
+ return NULL; \
+ } \
+ }
+
+#define DEFINE_EXPORTED_CAST_MEMBER_FUNCTION( type, export ) \
+ P##type \
+ export \
+ type::Cast ( \
+ PCOBJECT Object \
+ ) \
+ { \
+ if( Object && ( Object->QueryClassId( ) == \
+ type##_cd->QueryClassId( ))) { \
+ return(( P##type ) Object ); \
+ } else { \
+ return NULL; \
+ } \
+ }
+
+//
+// Constructor support
+//
+
+//
+// All classes have CLASS_DESCRIPTORS which are static and named
+// after the class appended with the suffix _cd. They are passed stored in
+// OBJECT and are set by the SetClassDescriptor function. The Construct
+// For debugging purposes the class' name is stored in the CLASS_DESCRIPTOR.
+// The Construct member function gas a no-op implementation in OBJECT and
+// could be overloaded as a private member in any derived class.
+//
+
+#define DECLARE_CONSTRUCTOR( c ) \
+ NONVIRTUAL \
+ c ( \
+ )
+
+#define DEFINE_CONSTRUCTOR( d, b ) \
+ PCCLASS_DESCRIPTOR d##_cd; \
+ d::d ( \
+ ) : b( ) \
+ { \
+ SetClassDescriptor( ##d##_cd ); \
+ Construct( ); \
+ }
+
+#define DEFINE_EXPORTED_CONSTRUCTOR( d, b, e ) \
+ PCCLASS_DESCRIPTOR d##_cd; \
+ e d::d ( \
+ ) : b( ) \
+ { \
+ SetClassDescriptor( ##d##_cd ); \
+ Construct( ); \
+ }
+
+
+
+//
+// Debug support.
+//
+// Use the Debug macros to invoke the following debugging functions.
+//
+// DebugAbort( str ) - Print a message and abort.
+// DebugAssert( exp ) - Assert that an expression is TRUE. Abort if FALSE.
+// DebugChkHeap( ) - Validate the heap. Abort if invalid.
+// DebugPrint( str ) - Print a string including location (file/line)
+// DebugPrintf( fmt, ... ) - Printf.
+//
+#if DBG==1
+
+#include <assert.h>
+
+#define DebugAbort( str ) \
+ DebugPrint( str ); \
+ ExitProcess( 99 )
+
+#define DebugAssert( exp ) \
+ assert( exp )
+
+#define DebugCheckHeap( )
+
+#define DebugPrint( str ) \
+ DebugPrintf( "%s in file: %s on line: %d.\n", \
+ str, \
+ __FILE__, \
+ __LINE__ )
+
+
+ULIB_EXPORT
+VOID
+DebugPrintf(
+ IN PCSTR Format,
+ IN ...
+ );
+
+#define DebugPtrAssert( ptr ) \
+ DebugAssert( ptr != NULL )
+
+//
+// UlibGlobalFlag is used to selectively enable debugging options at
+// run-time.
+//
+
+extern ULONG UlibGlobalFlag;
+
+#elif defined( _AUTOCHECK_DBG_ )
+
+// Autocheck uses the system's DbgPrint function.
+//
+#define DebugPrintf DbgPrint
+#define DebugPrint DbgPrint
+
+#define DebugAbort( str )
+
+#define DebugAssert( exp )
+
+#define DebugCheckHeap( )
+
+#define DebugPtrAssert( ptr )
+
+
+#else // DBG == 0 and _AUTOCHECK_DBG_ not defined.
+
+#define DebugAbort( str )
+
+#define DebugAssert( exp )
+
+#define DebugCheckHeap( )
+
+#define DebugPrint( str )
+
+#define DebugPtrAssert( ptr )
+
+inline
+VOID
+DebugPrintf(
+ IN PCSTR Format,
+ IN ...
+ )
+{
+}
+
+#endif // DBG
+
+//
+// DELETE macro that NULLifizes the pointer to the deleted object.
+//
+
+// Undo any previous definitions of DELETE.
+#undef DELETE
+
+// #define DELETE(x) FREE(x), x = NULL;
+
+#define DELETE( x ) \
+ delete x, x = NULL
+
+#define NEW new
+
+#define DumpStats
+
+#if defined( _AUTOCHECK_ )
+
+ #define MALLOC(bytes) (RtlAllocateHeap(RtlProcessHeap(), 0, bytes))
+
+ INLINE
+ PVOID
+ NtlibZeroAlloc(
+ ULONG Size
+ )
+ {
+ PVOID Result;
+
+ Result = MALLOC( Size );
+
+ if( Result != NULL ) {
+
+ memset( Result, 0, Size );
+ }
+
+ return Result;
+ }
+
+
+ #define CALLOC(nitems, size) (NtlibZeroAlloc(nitems*size))
+
+ ULIB_EXPORT PVOID UlibRealloc(PVOID, ULONG);
+
+ #define REALLOC(p,s) UlibRealloc(p,s)
+
+ #define FREE(x) ((x) ? (RtlFreeHeap(RtlProcessHeap(), 0, x), (x) = NULL) : 0)
+
+#else // _AUTOCHECK_ not defined
+
+ #if defined( _NTAPI_ULIB_ )
+
+ #define MALLOC(bytes) (RtlAllocateHeap(RtlProcessHeap(), 0, bytes))
+
+ #define CALLOC(nitems, size) \
+ (RtlAllocateHeap(RtlProcessHeap(), 0, nitems*size))
+
+ ULIB_EXPORT PVOID UlibRealloc(PVOID, ULONG);
+
+ #define REALLOC(p,s) UlibRealloc(p,s)
+
+ #define FREE(x) ((x) ? (RtlFreeHeap(RtlProcessHeap(), 0, x), (x) = NULL) : 0)
+
+ #else
+
+ #define MALLOC(bytes) ((PVOID) LocalAlloc(0, bytes))
+
+ #define CALLOC(nitems, size) ((PVOID) LocalAlloc(LMEM_ZEROINIT, nitems*size))
+
+ ULIB_EXPORT PVOID UlibRealloc(PVOID, ULONG);
+
+ #define REALLOC(x, size) ((PVOID) LocalReAlloc(x, size, LMEM_MOVEABLE))
+
+ #define FREE(x) ((x) ? (LocalFree(x), (x) = NULL) : 0)
+
+ #endif
+
+#endif // _AUTOCHECK
+
+#if !defined(_SETUP_LOADER_) && !defined(_AUTOCHECK_)
+
+__inline void * __cdecl operator new(size_t x)
+{
+ return(MALLOC(x));
+}
+
+__inline void __cdecl operator delete(void * x)
+{
+ FREE(x);
+}
+
+#endif
+
+#endif // _ULIBDEF_
diff --git a/private/utils/ulib/inc/winnls.old b/private/utils/ulib/inc/winnls.old
new file mode 100644
index 000000000..9ca9f7ddd
--- /dev/null
+++ b/private/utils/ulib/inc/winnls.old
@@ -0,0 +1,292 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ winnls.h
+
+Abstract:
+
+ This module defines the 32-Bit Windows NLS APIs.
+
+Author:
+
+ David J. Gilman (davegi) 22-Mar-1991
+
+Revision History:
+
+--*/
+
+#ifndef _WINNLS_
+#define _WINNLS_
+
+//
+// NLSAPI and wide character related types.
+//
+
+typedef char CHAR;
+typedef PDWORD LPWCHAR;
+typedef LPSTR LPCHAR;
+typedef DWORD HLCID;
+typedef DWORD HLOCALE;
+
+
+//
+// Length of locale strings.
+//
+
+#define MAX_LANG_LEN ( 128 )
+#define MAX_CTRY_LEN ( 128 )
+#define MAX_CP_LEN ( 128 )
+
+//
+// String based locale representation.
+//
+
+typedef struct tagLC_STRINGS {
+ CHAR szLanguage[MAX_LANG_LEN]; // language name
+ CHAR szCountry[MAX_CTRY_LEN]; // country name
+ CHAR szCodePage[MAX_CP_LEN]; // codepage name
+} LC_STRINGS, *LPLC_STRINGS, *PLC_STRINGS;
+
+//
+// Code based local representation.
+//
+
+typedef struct tagLC_ID {
+ WORD wLanguage; // language id
+ WORD wCountry; // country id
+ WORD wCodePage; // codepage id
+} LC_ID, *LPLC_ID, *PLC_ID;
+
+//
+// Locale information enumeration type.
+//
+
+#define LI_CPDATA ( 0 )
+#define LI_CTRYDATA ( 1 )
+#define LI_LANGDATA ( 2 )
+
+//
+// Locale information type.
+//
+
+#define LI_CPDATA ( 0 )
+#define LI_CTRYDATA ( 1 )
+#define LI_LANGDATA ( 2 )
+#define LI_LCMONETARY ( 3 )
+#define LI_LCNUMERIC ( 4 )
+#define LI_DATETIMEFMT ( 5 )
+#define LI_DATETIMESTR ( 6 )
+
+//
+// LC_ID and LC_STRINGS indicator.
+//
+
+#define QF_LCID ( 0 )
+#define QF_STRINGS ( 1 )
+
+//
+// Requested character type information.
+//
+#define CT_CTYPE1 ( 1 )
+#define CT_CTYPE2 ( 2 )
+
+//
+// Character type 1 (CT_CTYPE1) information
+//
+
+#define C1_ALPHA ( 0x100 )
+#define C1_CONTROLCHAR ( 0x020 )
+#define C1_DIACRITIC ( 0x200 )
+#define C1_DIGIT ( 0x004 )
+#define C1_LOWERCASE ( 0x002 )
+#define C1_PUNCTUATION ( 0x010 )
+#define C1_WHITESPACE ( 0x008 )
+#define C1_SYMBOL ( 0x400 )
+#define C1_UPPERCASE ( 0x001 )
+
+//
+// Extended character type 1 (CT_CTYPE1) information
+//
+
+#define C1_ALPHNUMERIC ( C1_ALPHA | C1_DIGIT )
+#define C1_GRAPHIC ( C1_PUNCTUATION | C1_ALPHNUMERIC )
+
+//
+// Character type 2 (CT_CTYPE2) information
+//
+
+#define C2_STRONGLEFTTORIGHT ( 0 )
+#define C2_STRONGRIGHTTOLEFT ( 1 )
+#define C2_WEAKLEFTTORIGHT ( 2 )
+#define C2_WEAKRIGHTTOLEFT ( 3 )
+#define C2_NEUTRAL ( 4 )
+#define C2_NUMERICCONTEXT ( 5 )
+#define C2_OPENPUNCTUATION ( 6 )
+#define C2_CLOSEPUNCTUATION ( 7 )
+
+//
+// Extended character type 2 (CT_CTYPE2) information
+//
+
+#define C2_UPSTREAM ( C2_CLOSEPUNCTUATION + 1 )
+#define C2_DOWNSTREAM ( C2_CLOSEPUNCTUATION + 2 )
+#define C2_IDEOGRAPHIC ( C2_CLOSEPUNCTUATION + 3 )
+#define C2_NONBREAKING ( C2_CLOSEPUNCTUATION + 4 )
+
+//
+// Comparison flags
+//
+
+#define CF_IGNORECASE ( 1 )
+#define CF_IGNOREDIACRITIC ( 2 )
+#define CF_IGNORESYMBOLS ( 4 )
+
+//
+// Map types and flags.
+//
+
+#define MAP_COLLATE ( 0 )
+#define MAP_CTYPE1 ( 1 )
+#define MAP_CTYPE2 ( 2 )
+#define MAP_UPPERCASE ( 3 )
+#define MAP_LOWERCASE ( 4 )
+#define MAP_UCTOMB ( 5 )
+#define MAP_MBTOUC ( 6 )
+#define MAP_SORTKEY ( 7 )
+
+//
+// Character traits.
+//
+
+#define STR_IGNORECASE ( 0 )
+#define STR_IGNOREDIACRITIC ( 1 )
+#define STR_IGNORESYMBOLS ( 2 )
+
+//
+// Low level NLSAPI routines.
+//
+
+HLCID
+BeginEnumLocale(
+ DWORD dwEnumType,
+ LPLC_ID lpLCID
+ );
+
+BOOL
+GetNextLocale(
+ HLCID hEnumHandle,
+ LPLC_ID lpLCID
+ );
+
+BOOL
+EndEnumLocale(
+ HLCID hEnumHandle
+ );
+
+DWORD
+GetLocaleInfo(
+ LPLC_ID lpLocale,
+ DWORD dwLCType,
+ LPVOID pvLCData,
+ DWORD cbBuf
+ );
+
+BOOL
+GetQualifiedLocale(
+ WORD wType,
+ LPVOID lpInput,
+ LPLC_ID lpOutID,
+ LPLC_STRINGS lpOutStr
+ );
+
+//
+// High level NLSAPI routines.
+//
+
+BOOL
+GetCharType(
+ HLOCALE hLocale,
+ WORD wInfoType,
+ WCHAR wcChar,
+ LPWORD lpCharType
+ );
+
+BOOL
+CloseLocale(
+ HLOCALE hLocale
+ );
+
+int
+CompareString(
+ HLOCALE hLocale,
+ DWORD dwCmpFlags,
+ LPWSTR lpwstrString1,
+ int nCount1,
+ LPWSTR lpwstrString2,
+ int nCount2
+ );
+
+int
+QueryMap(
+ HLOCALE hLocale,
+ WORD wMapType,
+ WORD wMapFlags,
+ WCHAR wcBeginMap,
+ WCHAR wcEndMap,
+ LPVOID pvOutMap,
+ DWORD dwOutSize
+ );
+
+int
+MapString(
+ HLOCALE hLocale,
+ DWORD dwMapFlags,
+ LPWSTR lpWCSrcStr,
+ int nWCSrc,
+ LPWSTR lpWCDestStr,
+ int nWCDest
+ );
+
+HLOCALE
+OpenLocale(
+ LPLC_ID lpLCID
+ );
+
+//
+// MBCS Support NLSAPI Routines
+//
+
+int
+WideCharToMultiByte(
+ WORD wCodePage,
+ LPWSTR lpWideCharStr,
+ int nWideChar,
+ LPSTR lpMultiByteStr,
+ int nChar,
+ LPCHAR lpDefaultChar
+ );
+
+int
+MultiByteToWideChar(
+ WORD wCodePage,
+ LPSTR lpMultiByteStr,
+ int nChar,
+ LPWSTR lpWideCharStr,
+ int nWideChar
+ );
+
+int
+MultiByteToMultiByte(
+ WORD wTranslations,
+ WORD wSrcCodePage,
+ LPSTR lpSrcString,
+ int nSrcChar,
+ WORD wDestCodePage,
+ LPSTR wDestString,
+ int nDestChar
+ );
+
+#endif // _WINNLS_
diff --git a/private/utils/ulib/inc/wstring.hxx b/private/utils/ulib/inc/wstring.hxx
new file mode 100644
index 000000000..d62283413
--- /dev/null
+++ b/private/utils/ulib/inc/wstring.hxx
@@ -0,0 +1,1250 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ wstring.hxx
+
+Abstract:
+
+ This module defines the new WSTRING hierarchy:
+
+ WSTRING
+ FSTRING
+ DSTRING
+
+ WSTRING provides all of the desired methods on a string.
+ FSTRING provides an implementation of a WSTRING with fixed
+ size, user provided buffer.
+ DSTRING provides an implementation of a WSTRING with a
+ dynamic heap based buffer.
+
+
+ WSTRING is an abstract classes who's methods depend on the
+ implementation of two pure virtual methods: 'Resize' and 'NewBuf'.
+ A derived class must make use of the protected 'PutString' methods
+ in order to supply WSTRING with its string buffer. Use of
+ 'PutString' is constrained as follows:
+
+ 1. Supplying just a PWSTR to 'PutString' implies that
+ the PWSTR is null-terminated.
+ 2. Supplying a PWSTR and length to 'PutString' implies that
+ the PWSTR points to a buffer of characters that is at
+ least one longer than the given length.
+
+
+ All implementations of 'Resize' and 'NewBuf' must:
+
+ 1. Allocate an extra character for the NULL.
+ 2. NULL-terminate the buffer allocated.
+ 3. Always succeed if size <= current buffer size.
+ 4. Always work as soon as the derived class is initialized (i.e.
+ WSTRING::Initialize method need not be called.).
+ 5. Supply the buffer to WSTRING via 'PutString'.
+
+ Additionally 'Resize' must:
+
+ 1. Preserve the contents of the current buffer.
+
+ All of the comparison operators supplied by WSTRING are
+ case insensitive.
+
+Author:
+
+ Norbert P. Kusters (norbertk) 6-Aug-92
+
+--*/
+
+#if !defined(_WSTRING_DEFN_)
+
+#define _WSTRING_DEFN_
+
+
+//
+// The type of the index used to access individual characters within
+// a generic string.
+//
+DEFINE_TYPE( ULONG, CHNUM );
+
+
+//
+// Magic constants
+//
+#define INVALID_CHAR ((WCHAR)(-1))
+#define INVALID_CHNUM ((CHNUM)(-1))
+#define TO_END INVALID_CHNUM
+
+
+DECLARE_CLASS( WSTRING );
+
+class WSTRING : public OBJECT {
+
+ public:
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN PCWSTRING InitialString,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN PCWSTR InitialString,
+ IN CHNUM StringLength DEFAULT TO_END
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN PCSTR InitialString,
+ IN CHNUM StringLength DEFAULT TO_END
+ );
+
+ NONVIRTUAL
+ BOOLEAN
+ Initialize(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Initialize(
+ IN LONG Number
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTRING
+ QueryString(
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ QueryNumber(
+ OUT PLONG Number,
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ QueryChCount(
+ ) CONST;
+
+
+#ifdef DBCS
+ NONVIRTUAL
+ ULIB_EXPORT
+ CHNUM
+ QueryByteCount(
+ ) CONST;
+#endif
+
+ NONVIRTUAL
+ CHNUM
+ SyncLength(
+ );
+
+ NONVIRTUAL
+ WCHAR
+ QueryChAt(
+ IN CHNUM Position
+ ) CONST;
+
+ NONVIRTUAL
+ WCHAR
+ SetChAt(
+ IN WCHAR Char,
+ IN CHNUM Position
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ VOID
+ DeleteChAt(
+ IN CHNUM Position,
+ IN CHNUM Length DEFAULT 1
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ InsertString(
+ IN CHNUM AtPosition,
+ IN PCWSTRING String,
+ IN CHNUM FromPosition DEFAULT 0,
+ IN CHNUM FromLength DEFAULT TO_END
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Replace(
+ IN CHNUM AtPosition,
+ IN CHNUM AtLength,
+ IN PCWSTRING String,
+ IN CHNUM FromPosition DEFAULT 0,
+ IN CHNUM FromLength DEFAULT TO_END
+ );
+
+ NONVIRTUAL
+ PCWSTR
+ GetWSTR(
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTR
+ QueryWSTR(
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ OUT PWSTR Buffer DEFAULT NULL,
+ IN CHNUM BufferLength DEFAULT 0,
+ IN BOOLEAN ForceNull DEFAULT TRUE
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PSTR
+ QuerySTR(
+ IN CHNUM Position DEFAULT 0,
+ IN CHNUM Length DEFAULT TO_END,
+ OUT PSTR Buffer DEFAULT NULL,
+ IN CHNUM BufferLength DEFAULT 0,
+ IN BOOLEAN ForceNull DEFAULT TRUE
+ ) CONST;
+
+ NONVIRTUAL
+ LONG
+ Strcmp(
+ IN PCWSTRING String
+ ) CONST;
+
+ STATIC
+ INT
+ Strcmp(
+ IN PWSTR String1,
+ IN PWSTR String2
+ ) ;
+
+ STATIC
+ INT
+ Stricmp(
+ IN PWSTR String1,
+ IN PWSTR String2
+ ) ;
+
+ NONVIRTUAL
+ LONG
+ Strcmp(
+ IN PCWSTRING String,
+ IN CHNUM LeftPosition
+ ) CONST;
+
+ NONVIRTUAL
+ LONG
+ Strcmp(
+ IN PCWSTRING String,
+ IN CHNUM LeftPosition,
+ IN CHNUM LeftLength,
+ IN CHNUM RightPosition DEFAULT 0,
+ IN CHNUM RightLength DEFAULT TO_END
+ ) CONST;
+
+ NONVIRTUAL
+ LONG
+ Stricmp(
+ IN PCWSTRING String
+ ) CONST;
+
+ NONVIRTUAL
+ LONG
+ Stricmp(
+ IN PCWSTRING String,
+ IN CHNUM LeftPosition
+ ) CONST;
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ LONG
+ Stricmp(
+ IN PCWSTRING String,
+ IN CHNUM LeftPosition,
+ IN CHNUM LeftLength,
+ IN CHNUM RightPosition DEFAULT 0,
+ IN CHNUM RightLength DEFAULT TO_END
+ ) CONST;
+
+ ULIB_EXPORT
+ STATIC
+ INT
+ Strcmps(
+ IN PWSTR p1,
+ IN PWSTR p2
+ );
+
+ ULIB_EXPORT
+ STATIC
+ INT
+ Strcmpis(
+ IN PWSTR p1,
+ IN PWSTR p2
+ );
+
+ STATIC
+ PWSTR
+ SkipWhite(
+ IN PWSTR p
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Strcat(
+ IN PCWSTRING String
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ Strupr(
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ Strupr(
+ IN CHNUM StartPosition,
+ IN CHNUM Length DEFAULT TO_END
+ );
+
+ NONVIRTUAL
+ PWSTRING
+ Strlwr(
+ );
+
+ NONVIRTUAL
+ ULIB_EXPORT
+ PWSTRING
+ Strlwr(
+ IN CHNUM StartPosition,
+ IN CHNUM Length DEFAULT TO_END
+ );
+
+ NONVIRTUAL
+ CHNUM
+ Strchr(
+ IN WCHAR Char,
+ IN CHNUM StartPosition DEFAULT 0
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ Strrchr(
+ IN WCHAR Char,
+ IN CHNUM StartPosition DEFAULT 0
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ Strstr(
+ IN PCWSTRING String
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ Strspn(
+ IN PCWSTRING String,
+ IN CHNUM StartPosition DEFAULT 0
+ ) CONST;
+
+ NONVIRTUAL
+ CHNUM
+ Strcspn(
+ IN PCWSTRING String,
+ IN CHNUM StartPosition DEFAULT 0
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator==(
+ IN RCWSTRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator!=(
+ IN RCWSTRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator<(
+ IN RCWSTRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator>(
+ IN RCWSTRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator<=(
+ IN RCWSTRING String
+ ) CONST;
+
+ NONVIRTUAL
+ BOOLEAN
+ operator>=(
+ IN RCWSTRING String
+ ) CONST;
+
+ VIRTUAL
+ BOOLEAN
+ Resize(
+ IN CHNUM NewStringLength
+ ) PURE;
+
+ VIRTUAL
+ BOOLEAN
+ NewBuf(
+ IN CHNUM NewStringLength
+ ) PURE;
+
+ NONVIRTUAL
+ CHNUM
+ Truncate(
+ IN CHNUM Position DEFAULT 0
+ );
+
+ STATIC
+ ULIB_EXPORT
+ VOID
+ SetAnsiConversions(
+ );
+
+ STATIC
+ ULIB_EXPORT
+ VOID
+ SetOemConversions(
+ );
+
+ STATIC
+ ULIB_EXPORT
+ VOID
+ SetConsoleConversions(
+ );
+
+#if defined DBCS
+ STATIC
+ ULIB_EXPORT
+ VOID
+ ResetConversions(
+ );
+#endif // DBCS
+
+ protected:
+
+ DECLARE_CONSTRUCTOR( WSTRING );
+
+ NONVIRTUAL
+ VOID
+ Construct(
+ );
+
+ NONVIRTUAL
+ VOID
+ PutString(
+ IN OUT PWSTR String
+ );
+
+ NONVIRTUAL
+ VOID
+ PutString(
+ IN OUT PWSTR String,
+ IN CHNUM Length
+ );
+
+ private:
+
+ STATIC BOOLEAN _UseAnsiConversions;
+ STATIC BOOLEAN _UseConsoleConversions;
+#if defined DBCS
+ STATIC BOOLEAN _UseAnsiConversionsPrev;
+ STATIC BOOLEAN _UseConsoleConversionsPrev;
+#endif // DBCS
+
+#if defined DBCS
+ STATIC
+ INT
+ CheckSpace(
+ IN PWSTR p
+ );
+#endif // DBCS
+
+ STATIC
+ BOOLEAN
+ ConvertOemToUnicodeN(
+ PWSTR UnicodeString,
+ ULONG MaxBytesInUnicodeString,
+ PULONG BytesInUnicodeString,
+ PCHAR OemString,
+ ULONG BytesInOemString
+ );
+
+ STATIC
+ BOOLEAN
+ ConvertUnicodeToOemN(
+ PCHAR OemString,
+ ULONG MaxBytesInOemString,
+ PULONG BytesInOemString,
+ PWSTR UnicodeString,
+ ULONG BytesInUnicodeString
+ );
+
+ PWSTR _s; // Beginning of string.
+ CHNUM _l; // Strlen of string.
+
+};
+
+
+INLINE
+VOID
+WSTRING::PutString(
+ IN OUT PWSTR String
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes this string with the given null
+ terminated buffer.
+
+Arguments:
+
+ String - Supplies the buffer to initialize the string with.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ _s = String;
+ _l = wcslen(_s);
+}
+
+
+INLINE
+VOID
+WSTRING::PutString(
+ IN OUT PWSTR String,
+ IN CHNUM Length
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes this string with the given buffer
+ and string length.
+
+Arguments:
+
+ String - Supplies the buffer to initialize the string with.
+ Length - Supplies the length of the string.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ _s = String;
+ _l = Length;
+ _s[_l] = 0;
+}
+
+
+INLINE
+BOOLEAN
+WSTRING::Initialize(
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes this string to an empty null-terminated
+ string.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ FALSE - Failure.
+ TRUE - Success.
+
+--*/
+{
+ return Resize(0);
+}
+
+
+INLINE
+CHNUM
+WSTRING::QueryChCount(
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns the number of characters in the string.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The number of characters in this string.
+
+--*/
+{
+ return _l;
+}
+
+
+INLINE
+CHNUM
+WSTRING::SyncLength(
+ )
+/*++
+
+Routine Description:
+
+ This routine recalculates the correct length of the string.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The recomputed length of the string.
+
+--*/
+{
+ return _l = wcslen(_s);
+}
+
+
+INLINE
+WCHAR
+WSTRING::QueryChAt(
+ IN CHNUM Position
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns the character at the given position.
+ The position is a zero-based index into the string.
+ The position must be in the range of the string.
+
+Arguments:
+
+ Position - Supplies an index into the string.
+
+Return Value:
+
+ The character at the given position.
+
+--*/
+{
+ return (Position < _l) ? _s[Position] : INVALID_CHAR;
+}
+
+
+INLINE
+WCHAR
+WSTRING::SetChAt(
+ IN WCHAR Char,
+ IN CHNUM Position
+ )
+/*++
+
+Routine Description:
+
+ This routine sets the given character at the given position in
+ the string.
+
+Arguments:
+
+ Char - Supplies the character to set into the string.
+ Position - Supplies the position at which to set the character.
+
+Return Value:
+
+ The character that was set.
+
+--*/
+{
+ DebugAssert(Position < _l);
+ return _s[Position] = Char;
+}
+
+
+INLINE
+PCWSTR
+WSTRING::GetWSTR(
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns this string internal buffer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A pointer to the strings buffer.
+
+--*/
+{
+ return _s;
+}
+
+
+INLINE
+LONG
+WSTRING::Strcmp(
+ IN PCWSTRING String
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine compares two strings.
+
+Arguments:
+
+ String - Supplies the string to compare to.
+
+Return Value:
+
+ < 0 - This string is less than the given string.
+ 0 - This string is equal to the given string.
+ > 0 - This string is greater than the given string.
+
+--*/
+{
+ return wcscoll(_s, String->_s);
+}
+
+
+INLINE
+INT
+WSTRING::Strcmp(
+ IN PWSTR String1,
+ IN PWSTR String2
+ )
+{
+ return wcscoll( String1, String2 );
+}
+
+INLINE
+INT
+WSTRING::Stricmp(
+ IN PWSTR String1,
+ IN PWSTR String2
+ )
+{
+ return _wcsicoll( String1, String2 );
+}
+
+INLINE
+LONG
+WSTRING::Strcmp(
+ IN PCWSTRING String,
+ IN CHNUM LeftPosition
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine compares two strings. It starts comparing the
+ current string at the given position.
+
+Arguments:
+
+ String - Supplies the string to compare to.
+ LeftPosition - Supplies the starting position to start comparison
+ on the current string.
+
+Return Value:
+
+ < 0 - This string is less than the given string.
+ 0 - This string is equal to the given string.
+ > 0 - This string is greater than the given string.
+
+--*/
+{
+ return wcscoll(_s + LeftPosition, String->_s);
+}
+
+
+INLINE
+LONG
+WSTRING::Stricmp(
+ IN PCWSTRING String
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine compares two strings insensitive of case.
+
+Arguments:
+
+ String - Supplies the string to compare to.
+
+Return Value:
+
+ < 0 - This string is less than the given string.
+ 0 - This string is equal to the given string.
+ > 0 - This string is greater than the given string.
+
+--*/
+{
+ return _wcsicoll(_s, String->_s);
+}
+
+
+INLINE
+LONG
+WSTRING::Stricmp(
+ IN PCWSTRING String,
+ IN CHNUM LeftPosition
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine compares two strings insensitive of case.
+
+Arguments:
+
+ String - Supplies the string to compare to.
+ LeftPosition - Supplies the position in this string to start
+ comparison.
+
+Return Value:
+
+ < 0 - This string is less than the given string.
+ 0 - This string is equal to the given string.
+ > 0 - This string is greater than the given string.
+
+--*/
+{
+ return _wcsicoll(_s + LeftPosition, String->_s);
+}
+
+
+INLINE
+PWSTRING
+WSTRING::Strupr(
+ )
+/*++
+
+Routine Description:
+
+ This routine uppercases this string.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ _wcsupr(_s);
+ return this;
+}
+
+
+INLINE
+PWSTRING
+WSTRING::Strlwr(
+ )
+/*++
+
+Routine Description:
+
+ This routine lowercases this string.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ _wcslwr(_s);
+ return this;
+}
+
+
+INLINE
+CHNUM
+WSTRING::Strchr(
+ IN WCHAR Char,
+ IN CHNUM StartPosition
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns the position of the first occurance of
+ the given character.
+
+Arguments:
+
+ Char - Supplies the character to find.
+
+Return Value:
+
+ The position of the given character or INVALID_CHNUM.
+
+--*/
+{
+ PWSTR p;
+
+ DebugAssert(StartPosition <= _l);
+ p = wcschr(_s + StartPosition, Char);
+ return p ? (p - _s) : INVALID_CHNUM;
+}
+
+
+INLINE
+CHNUM
+WSTRING::Strrchr(
+ IN WCHAR Char,
+ IN CHNUM StartPosition
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns the position of the last occurance of
+ the given character.
+
+Arguments:
+
+ Char - Supplies the character to find.
+
+Return Value:
+
+ The position of the given character or INVALID_CHNUM.
+
+--*/
+{
+ PWSTR p;
+
+ p = wcsrchr(_s + StartPosition, Char);
+ return p ? (p - _s) : INVALID_CHNUM;
+}
+
+
+INLINE
+CHNUM
+WSTRING::Strstr(
+ IN PCWSTRING String
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine finds the given string withing this string.
+
+Arguments:
+
+ String - Supplies the string to find.
+
+Return Value:
+
+ The position of the given string in this string or INVALID_CHNUM.
+
+--*/
+{
+ PWSTR p;
+
+ p = wcsstr(_s, String->_s);
+ return p ? (p - _s) : INVALID_CHNUM;
+}
+
+
+INLINE
+CHNUM
+WSTRING::Strspn(
+ IN PCWSTRING String,
+ IN CHNUM StartPosition
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns the position of the first character in this
+ string that does not belong to the set of characters in the given
+ string.
+
+Arguments:
+
+ String - Supplies the list of characters to search for.
+
+Return Value:
+
+ The position of the first character found that does not belong
+ to the given string.
+
+--*/
+{
+ CHNUM r;
+
+ DebugAssert(StartPosition <= _l);
+ r = wcsspn(_s + StartPosition, String->_s) + StartPosition;
+ return r < _l ? r : INVALID_CHNUM;
+}
+
+
+INLINE
+CHNUM
+WSTRING::Strcspn(
+ IN PCWSTRING String,
+ IN CHNUM StartPosition
+ ) CONST
+/*++
+
+Routine Description:
+
+ This routine returns the position of the first character in this
+ string that belongs to the set of characters in the given
+ string.
+
+Arguments:
+
+ String - Supplies the list of characters to search for.
+
+Return Value:
+
+ Returns the position of the first character in this string
+ belonging to the given string or INVALID_CHNUM.
+
+--*/
+{
+ CHNUM r;
+
+ DebugAssert(StartPosition <= _l);
+ r = wcscspn(_s + StartPosition, String->_s) + StartPosition;
+ return r < _l ? r : INVALID_CHNUM;
+}
+
+
+INLINE
+BOOLEAN
+WSTRING::operator==(
+ IN RCWSTRING String
+ ) CONST
+{
+ return Stricmp(&String) == 0;
+}
+
+
+INLINE
+BOOLEAN
+WSTRING::operator!=(
+ IN RCWSTRING String
+ ) CONST
+{
+ return Stricmp(&String) != 0;
+}
+
+
+INLINE
+BOOLEAN
+WSTRING::operator<(
+ IN RCWSTRING String
+ ) CONST
+{
+ return Stricmp(&String) < 0;
+}
+
+
+INLINE
+BOOLEAN
+WSTRING::operator>(
+ IN RCWSTRING String
+ ) CONST
+{
+ return Stricmp(&String) > 0;
+}
+
+
+INLINE
+BOOLEAN
+WSTRING::operator<=(
+ IN RCWSTRING String
+ ) CONST
+{
+ return Stricmp(&String) <= 0;
+}
+
+
+INLINE
+BOOLEAN
+WSTRING::operator>=(
+ IN RCWSTRING String
+ ) CONST
+{
+ return Stricmp(&String) >= 0;
+}
+
+
+INLINE
+CHNUM
+WSTRING::Truncate(
+ IN CHNUM Position
+ )
+{
+ DebugAssert(Position <= _l);
+ Resize(Position);
+ return _l;
+}
+
+
+DECLARE_CLASS( FSTRING );
+
+class FSTRING : public WSTRING {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( FSTRING );
+
+ NONVIRTUAL
+ PWSTRING
+ Initialize(
+ IN OUT PWSTR InitialString,
+ IN CHNUM BufferLength DEFAULT TO_END
+ );
+
+ VIRTUAL
+ ULIB_EXPORT
+ BOOLEAN
+ Resize(
+ IN CHNUM NewStringLength
+ );
+
+ VIRTUAL
+ BOOLEAN
+ NewBuf(
+ IN CHNUM NewStringLength
+ );
+
+ private:
+
+ CHNUM _buffer_length;
+
+};
+
+
+INLINE
+PWSTRING
+FSTRING::Initialize(
+ IN OUT PWSTR InitialString,
+ IN CHNUM BufferLength
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes this class with a null-terminated
+ unicode string. This routine does not make a copy of the string
+ but uses it as is.
+
+Arguments:
+
+ NullTerminatedString - Supplies a null-terminated unicode string.
+ BufferLength - Supplies the buffer length.
+
+Return Value:
+
+ A pointer to this class.
+
+--*/
+{
+ PutString(InitialString);
+ _buffer_length = ((BufferLength == TO_END) ?
+ (QueryChCount() + 1) : BufferLength);
+ return this;
+}
+
+
+DECLARE_CLASS( DSTRING );
+
+class DSTRING : public WSTRING {
+
+ public:
+
+ ULIB_EXPORT
+ DECLARE_CONSTRUCTOR( DSTRING );
+
+ VIRTUAL
+ ULIB_EXPORT
+ ~DSTRING(
+ );
+
+ VIRTUAL
+ BOOLEAN
+ Resize(
+ IN CHNUM NewStringLength
+ );
+
+ VIRTUAL
+ BOOLEAN
+ NewBuf(
+ IN CHNUM NewStringLength
+ );
+
+ private:
+
+ VOID
+ Construct(
+ );
+
+ PWSTR _buf; // String buffer.
+ CHNUM _length; // Number of characters in buffer.
+
+};
+
+
+#endif // _WSTRING_DEFN_
diff --git a/private/utils/ulib/memtrace/makefile b/private/utils/ulib/memtrace/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/utils/ulib/memtrace/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/memtrace/memtrace.c b/private/utils/ulib/memtrace/memtrace.c
new file mode 100644
index 000000000..3563c7752
--- /dev/null
+++ b/private/utils/ulib/memtrace/memtrace.c
@@ -0,0 +1,225 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ memtrace.c
+
+Abstract:
+
+ This function contains an extension to NTSD that allows tracing of
+ memory usage when ULIB objects are compiled with the MEMLEAK flag
+ defined.
+
+Author:
+
+ Barry Gilhuly (W-Barry) 25-July-91
+
+Revision History:
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <ntsdexts.h>
+
+#include <string.h>
+
+#include "memtrace.h"
+
+
+VOID
+DumpToFile( char *OutString, ... )
+{
+ DWORD bytes;
+
+ bytes = strlen( OutString );
+ WriteFile( hFile, OutString, bytes, &bytes, NULL );
+ return;
+}
+
+VOID
+MemTrace(
+ HANDLE hCurrentProcess,
+ HANDLE hCurrentThread,
+ DWORD dwCurrentPc,
+ PNTSD_EXTENSION_APIS lpExtensionApis,
+ LPSTR lpArgumentString
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called as an NTSD extension to format and dump
+ the current contents of the Mem list.
+
+Arguments:
+
+ hCurrentProcess - Supplies a handle to the current process (at the
+ time the extension was called).
+
+ hCurrentThread - Supplies a handle to the current thread (at the
+ time the extension was called).
+
+ CurrentPc - Supplies the current pc at the time the extension is
+ called.
+
+ lpExtensionApis - Supplies the address of the functions callable
+ by this extension.
+
+ lpArgumentString - Supplies the asciiz string that describes the
+ critical section to be dumped (e.g. ntdll!FastPebLock,
+ csrsrv!CsrProcessStructureLock...).
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ DWORD AddrMem;
+
+ BOOL b;
+ DWORD i;
+
+ PMEM_BLOCK MemListNext;
+ MEM_BLOCK MemObject;
+ CHAR Symbol[64];
+ CHAR Buffer[ 128 ];
+ DWORD Displacement;
+
+ PNTSD_OUTPUT_ROUTINE lpOutputRoutine;
+ PNTSD_OUTPUT_ROUTINE lpAlternateOutputRoutine;
+
+ PNTSD_GET_EXPRESSION lpGetExpressionRoutine;
+ PNTSD_GET_SYMBOL lpGetSymbolRoutine;
+
+ UNREFERENCED_PARAMETER(hCurrentThread);
+ UNREFERENCED_PARAMETER(dwCurrentPc);
+ UNREFERENCED_PARAMETER(lpArgumentString);
+
+ lpOutputRoutine = lpExtensionApis->lpOutputRoutine;
+ lpGetExpressionRoutine = lpExtensionApis->lpGetExpressionRoutine;
+ lpGetSymbolRoutine = lpExtensionApis->lpGetSymbolRoutine;
+
+ //
+ // Attempt to use the input string as a file name...
+ //
+ if( ( hFile = CreateFile( lpArgumentString,
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ 0
+ ) ) == (HANDLE)-1 ) {
+ //
+ // Unable to open the file - send all output to the screen.
+ //
+ lpAlternateOutputRoutine = lpExtensionApis->lpOutputRoutine;
+
+ } else {
+
+ lpAlternateOutputRoutine = DumpToFile;
+
+ }
+
+
+
+ //
+ // Get the address of the head of the memleak list...
+ //
+ AddrMem = (lpGetExpressionRoutine)("Ulib!pmemHead");
+ if ( !AddrMem ) {
+ (lpOutputRoutine)( "Unable to find the head of the Mem List!\n" );
+ if( hFile != (HANDLE)-1 ) {
+ CloseHandle( hFile );
+ }
+ return;
+ }
+ if( !ReadProcessMemory(
+ hCurrentProcess,
+ (LPVOID)AddrMem,
+ &MemListNext,
+ sizeof( PMEM_BLOCK ),
+ NULL
+ ) ) {
+ if( hFile != (HANDLE)-1 ) {
+ CloseHandle( hFile );
+ }
+ return;
+ }
+
+ //
+ // Traverse the list of Mem blocks stopping when the head hits the
+ // tail...At this point, the head of the list should be indicated
+ // by MemListHead and the tail by MemListTail. Since the first element
+ // in the list is a dummy entry, it can be skipped...
+ //
+ do {
+
+ if( !ReadProcessMemory(
+ hCurrentProcess,
+ (LPVOID)MemListNext,
+ &MemObject,
+ sizeof( MEM_BLOCK ),
+ NULL
+ ) ) {
+ return;
+ }
+
+ if( MemObject.memsig != Signature ) {
+
+ //
+ // This is an unrecognized memory block - die...
+ //
+ (lpOutputRoutine)( "Invalid block found!\n" );
+ return;
+ }
+
+ //
+ // Display the stored info - First the File, Line and Size of the
+ // memory block allocated. Then the stack trace...
+ //
+ sprintf( Buffer, "File: %s, Line: %ld, Size: %ld\n", MemObject.file,
+ MemObject.line, MemObject.size
+ );
+ ( lpAlternateOutputRoutine )( Buffer );
+
+ //
+ // This should dump the stack trace which was stored...
+ //
+ for( i = 0; ( i < MaxCallStack ) && ( MemObject.call[ i ] != 0 ); i++ ) {
+
+ (lpGetSymbolRoutine)( ( LPVOID )( MemObject.call[ i ] ),
+ Symbol,
+ &Displacement
+ );
+ sprintf( Buffer, "\t%s\n", Symbol );
+ ( lpAlternateOutputRoutine )( Buffer );
+
+ }
+ ( lpAlternateOutputRoutine )( "\n" );
+
+
+ } while( ( MemListNext = MemObject.pmemNext ) != NULL );
+
+
+
+ (lpOutputRoutine)( "\n...End of List...\n" );
+
+ if( hFile != (HANDLE)-1 ) {
+
+ ( lpAlternateOutputRoutine )( "\n...End of List...\n" );
+ CloseHandle( hFile );
+
+ }
+
+ return;
+}
diff --git a/private/utils/ulib/memtrace/memtrace.def b/private/utils/ulib/memtrace/memtrace.def
new file mode 100644
index 000000000..f5e529ac9
--- /dev/null
+++ b/private/utils/ulib/memtrace/memtrace.def
@@ -0,0 +1,6 @@
+NAME MEMTRACE
+
+DESCRIPTION 'Bonus NTSD Extensions'
+
+EXPORTS
+ MemTrace
diff --git a/private/utils/ulib/memtrace/memtrace.h b/private/utils/ulib/memtrace/memtrace.h
new file mode 100644
index 000000000..7d1138678
--- /dev/null
+++ b/private/utils/ulib/memtrace/memtrace.h
@@ -0,0 +1,65 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ memtrace.h
+
+Abstract:
+
+ This function contains an extension to NTSD that allows tracing of
+ memory usage when ULIB objects are compiled with the MEMLEAK flag
+ defined.
+
+Author:
+
+ Barry Gilhuly (W-Barry) 25-July-91
+
+Revision History:
+
+--*/
+
+//
+// The following was ripped off from ULIBDEF.HXX and NEWDELP.HXX
+//
+#define CONST const
+typedef ULONG MEM_BLOCKSIG;
+
+//
+// MEM_BLOCK header signature type and value.
+//
+CONST MEM_BLOCKSIG Signature = 0xDEADDEAD;
+
+//
+// Maximum length of caller's file name.
+//
+
+#define MaxFileLength 20
+
+//
+// Maximum size of call stack recorded.
+//
+
+#define MaxCallStack 20
+
+//
+// MEM_BLOCK is the header attached to all allocated memory blocks.
+// Do not change the order of these fields without fixing the initialization
+// of the dummy MEM_BLOCK in newdel.cxx.
+//
+
+typedef struct _MEM_BLOCK {
+ struct _MEM_BLOCK* pmemNext;
+ struct _MEM_BLOCK* pmemPrev;
+ MEM_BLOCKSIG memsig;
+ ULONG line;
+ ULONG size;
+ char file[ MaxFileLength ];
+ DWORD call[ MaxCallStack ];
+} MEM_BLOCK, *PMEM_BLOCK;
+
+//
+// File handle for data destination...
+//
+HANDLE hFile;
diff --git a/private/utils/ulib/memtrace/sources b/private/utils/ulib/memtrace/sources
new file mode 100644
index 000000000..e23cd09d8
--- /dev/null
+++ b/private/utils/ulib/memtrace/sources
@@ -0,0 +1,37 @@
+!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:
+
+ Mark Lucovsky (markl) 18-Sep-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntsd
+MINORCOMP=memtrace
+
+TARGETNAME=memtrace
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DYNLINK
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib
+
+INCLUDES=
+
+SOURCES= memtrace.c
+
+UMTYPE=console
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