Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

421 lines
12 KiB

#include "stdinc.h"
#include "win32file.h"
#include <stdlib.h>
bool bUseReplacementTags = false;
const wstring MsftCopyRightInfo = L"<!-- Copyright © 1981-2001 Microsoft Corporation -->\r\n";
const wstring xml_declar_prefix = L"<?xml ";
const wstring xml_declar_suffix = L"?>";
// Converts a wstring into an array of bytes to be written to the file with the given
// type of character set
CByteVector ConvertWstringToDestination(wstring str, FileContentType fct)
{
CByteVector byteOutput;
UINT CodePage = CP_UTF8;
if ((fct == FileContentsUnicode) || (fct == FileContentsUnicodeBigEndian))
{
for (wstring::const_iterator i = str.begin(); i != str.end(); i++)
{
unsigned short us = *i;
char *ch = (char*)&us;
if (fct == FileContentsUnicodeBigEndian)
us = (us >> 8) | (us << 8);
byteOutput.push_back(ch[0]);
byteOutput.push_back(ch[1]);
}
}
else if (fct == FileContentsUTF8)
{
if (fct == FileContentsUTF8) CodePage = CP_UTF8;
byteOutput.resize(WideCharToMultiByte(CodePage, 0, str.c_str(), str.size(), 0, 0, 0, 0));
WideCharToMultiByte(CodePage, 0, str.c_str(), str.size(), byteOutput, byteOutput.size(), 0, 0);
}
return byteOutput;
}
// Converts a unicode string to a wstring
wstring ConvertToWstring(const CByteVector &bytes, FileContentType fct)
{
wstring wsOutput;
vector<WCHAR> wchbuffer;
UINT CodePage = CP_ACP;
if (fct == FileContentsUnicode)
{
wsOutput.assign(bytes, bytes.size() / 2);
}
else
{
wchbuffer.resize(MultiByteToWideChar(CodePage, 0, bytes, bytes.size(), NULL, 0), L'\0');
MultiByteToWideChar(CodePage, 0, bytes, bytes.size(), &wchbuffer.front(), wchbuffer.size());
wsOutput.assign(&wchbuffer.front(), wchbuffer.size());
}
return wsOutput;
}
typedef std::pair<wstring,wstring> TagValue;
typedef vector<TagValue> Definitions;
// Reads in a foo=bar pair
//7
// fragile, could use some whitespace tweaking or maybe smarter use of
// the stream operators
wistream& operator>>(wistream& in, TagValue& defined) {
wstring fullline;
getline(in, fullline);
defined.first = fullline.substr(0, fullline.find_first_of('='));
defined.second = fullline.substr(fullline.find_first_of('=') + 1);
return in;
}
// Load the entire parameterization file
Definitions ReadParameterizationFile(wistream &stream)
{
Definitions rvalue;
TagValue tv;
while (!(stream >> tv).eof())
rvalue.push_back(tv);
return rvalue;
}
typedef std::pair<wstring::size_type, wstring::size_type> StringSubspan;
typedef std::pair<wstring, wstring> ReplacementCode;
typedef std::pair<StringSubspan, ReplacementCode> ReplacementChunklet;
//
// Converts "foo:bar" into <foo, bar>
ReplacementCode ExtractIntoPieces(const wstring& blob)
{
ReplacementCode rvalue;
wstring::size_type colonoffset;
colonoffset = blob.find(L':');
if (colonoffset == wstring::npos)
{
rvalue.first = blob;
rvalue.second = L"";
}
else
{
rvalue.first = blob.substr(0, colonoffset);
rvalue.second = blob.substr(colonoffset + 1);
}
return rvalue;
}
ReplacementChunklet*
FindNextReplacementPiece(
wstring& search,
const wstring& target
)
{
ReplacementChunklet* pChunky;
wstring::size_type startchunk, endchunk;
wstring subchunk;
wstring predicate = bUseReplacementTags ? L"$(" : L"";
wstring suffix = bUseReplacementTags ? L")" : L"";
wstring wsFindOpener = predicate + target;
startchunk = search.find(wsFindOpener);
if (startchunk == wstring::npos)
return NULL;
if (bUseReplacementTags)
{
endchunk = search.find(suffix, startchunk);
}
else
{
endchunk = startchunk + target.size();
}
if (endchunk == wstring::npos)
return NULL;
pChunky = new ReplacementChunklet;
pChunky->first.first = startchunk;
pChunky->first.second = endchunk + suffix.size();
// Tear apart into predicate and suffix
// minus $(and)
wstring topieces = search.substr(startchunk + predicate.size(), endchunk - (startchunk + predicate.size()));
pChunky->second = ExtractIntoPieces(topieces);
return pChunky;
}
//
// Right now, the only operation permitted is just a pass-through. Anything after the : is ignored.
//
wstring CleanReplacement(const ReplacementCode code, const wstring& intendedReplacement, const wstring& context)
{
wstring rvalue = intendedReplacement;
return rvalue;
}
#define STRIPCOMMENTS_SLASHSLASH 0x000001
#define STRIPCOMMENTS_SLASHSTAR 0x000002
#define STRIPCOMMENTS_SLASHSLASH_UNAWARE 0x000004
#define STRIPCOMMENTS_SLASHSTAR_UNAWARE 0x000008
template <typename strtype>
void StripComments(int flags, basic_string<strtype>& s)
/*
We generally want to be "aware" of both types so that we don't
strip nested comments. Consider the comments that follow.
*/
// /* slash star in slsh slash */
/* // slashslash
in slash star
*/
{
typedef basic_string<strtype> ourstring;
ourstring t;
ourstring::const_iterator i;
const ourstring::const_iterator j = s.end();
ourstring::const_iterator k;
bool closed = true;
t.reserve(s.size());
for (i = s.begin() ; closed && i != j && i + 1 != j;)
{
if (((flags & STRIPCOMMENTS_SLASHSTAR) || (flags & STRIPCOMMENTS_SLASHSTAR_UNAWARE) == 0) &&
(*i == '/') &&
(*(i + 1) == '*'))
{
closed = false;
for (k = i + 2 ; k != j && k + 1 != j && !(closed = (*k == '*' && *(k + 1) == '/')) ; ++k)
{
}
if (flags & STRIPCOMMENTS_SLASHSTAR)
// t.append(1, ' ');
;
else
t.append(i, k + 2);
i = k + 2;
}
else if (((flags & STRIPCOMMENTS_SLASHSLASH) || (flags & STRIPCOMMENTS_SLASHSLASH_UNAWARE) == 0) &&
(*i == '/') &&
(*(i + 1) == '/'))
{
closed = false;
for (k = i + 2 ; k != j && !(closed = (*k == '\r' || *k == '\n')) ; ++k)
{
}
for (; k != j && *k == '\r' || *k == '\n' ; ++k)
{
}
if (flags & STRIPCOMMENTS_SLASHSLASH)
t.append(1, '\n');
else
t.append(i, k);
i = k;
}
if (closed && i != j)
t.append(1, *i++);
}
if (closed)
{
for (; i != j ; ++i)
{
t.append(1, *i);
}
}
s = t;
}
void GetXMLDeclarationIfAny(wstring & wsXmlDecl, wstring & wsFile)
{
SIZE_T p=0, q =0;
p = wsFile.find(xml_declar_prefix, 0);
if (p == 0) // find from exact the beginning of the xmlfile
{
q = wsFile.find(xml_declar_suffix, xml_declar_prefix.length());
if ( q == -1) // manifest has a format error
throw new Win32File::ReadWriteError(true, ::GetLastError());
q += xml_declar_suffix.length();
// skip whitespace
while ((q < wsFile.size()) && (wsFile[q] == L' '))
q ++;
while ((q < wsFile.size()) && ((wsFile[q] == L'\n') || (wsFile[q] == L'\r')))
q ++;
wsXmlDecl.assign(wsFile, 0, q);
wsFile.erase(0, q);
}
return;
}
void ProcessFile(Win32File& inputFile, Win32File& outputFile, Definitions SubstList)
{
wstring wsNextLine;
wstring wsXmlDeclaration;
inputFile.snarfFullFile(wsNextLine);
//
// No comments from the peanut gallery, please. Code by Jay Krell to remove
// comments from strings here...
//
StripComments(STRIPCOMMENTS_SLASHSLASH | STRIPCOMMENTS_SLASHSTAR, wsNextLine);
// Go until we run out of $(...) to replace
for (Definitions::const_iterator ditem = SubstList.begin(); ditem != SubstList.end(); ditem++)
{
ReplacementChunklet* pNextChunk = NULL;
while ((pNextChunk = FindNextReplacementPiece(wsNextLine, ditem->first)) != NULL)
{
wstring cleaned = CleanReplacement(pNextChunk->second, ditem->second, wsNextLine);
wsNextLine.replace(pNextChunk->first.first, pNextChunk->first.second - pNextChunk->first.first, cleaned);
delete pNextChunk;
}
}
//
// Clean up everything
//
while (wsNextLine.size() && iswspace(*wsNextLine.begin()))
wsNextLine = wsNextLine.substr(1);
GetXMLDeclarationIfAny(wsXmlDeclaration, wsNextLine);
if (wsXmlDeclaration.length() != 0)
{
outputFile.writeLine(wsXmlDeclaration);
}
//
// include Microsoft Copyright information at the head of the manifest
//
outputFile.writeLine(MsftCopyRightInfo);
//
// write the output of replacement defines
//
outputFile.writeLine(wsNextLine);
}
// Converts a wstring to a string
string ConvertWstring(wstring input)
{
string s;
vector<CHAR> strbytes;
strbytes.resize(WideCharToMultiByte(CP_ACP, 0, input.c_str(), input.size(), NULL, 0, NULL, NULL));
WideCharToMultiByte(CP_ACP, 0, input.c_str(), input.size(), &strbytes.front(), strbytes.size(), NULL, NULL);
s.assign(&strbytes.front(), strbytes.size());
return s;
}
int __cdecl wmain(int argc, WCHAR** argv)
{
using namespace std;
vector<wstring> args;
wstring wsInputFile, wsOutputFile;
Definitions defines;
Win32File InputFile, OutputFile;
for (int i = 1; i < argc; i++)
args.push_back(wstring(argv[i]));
for (vector<wstring>::const_iterator ci = args.begin(); ci != args.end(); ci++)
{
if (*ci == wstring(L"-reptags")) {
bUseReplacementTags = true;
}
else if (*ci == wstring(L"-i")) {
wsInputFile = *++ci;
}
else if (*ci == wstring(L"-o")) {
wsOutputFile = *++ci;
}
else if (*ci == wstring(L"-s")) {
wifstream iis;
iis.open(ConvertWstring(*++ci).c_str());
if (!iis.is_open()) {
wcerr << L"Failed opening substitution file " << ci->data() << endl;
return 1;
}
Definitions temp = ReadParameterizationFile(iis);
for (Definitions::const_iterator it = temp.begin(); it != temp.end(); it++)
defines.push_back(*it);
}
else if (ci->substr(0, 2) == wstring(L"-D"))
{
// Commandline definitions are NOT appreciated, but they seem to be a necessary evil.
wstringstream wsstemp(ci->substr(2));
TagValue temptag;
wsstemp >> temptag;
defines.push_back(temptag);
}
}
try {
InputFile.openForRead(wsInputFile);
} catch (Win32File::OpeningError *e) {
wcerr << L"Failed opening the input file " << wsInputFile.c_str() << L": " << e->error << endl;
delete e;
return EXIT_FAILURE;
} catch (Win32File::ReadWriteError *e) {
wcerr << L"Failed sensing lead bytes of input file " << wsInputFile.c_str() << L": " << e->error << endl;
delete e;
return EXIT_FAILURE;
}
try {
OutputFile.openForWrite(wsOutputFile, InputFile.gettype());
} catch (Win32File::OpeningError *e) {
wcerr << L"Failed opening the output file " << wsOutputFile.c_str() << L": " << e->error << endl;
delete e;
return EXIT_FAILURE;
} catch (Win32File::ReadWriteError *e) {
wcerr << L"Failed writing lead bytes of output file " << wsOutputFile.c_str() << L": " << e->error << endl;
delete e;
return EXIT_FAILURE;
}
ProcessFile(InputFile, OutputFile, defines);
return EXIT_SUCCESS;
}