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

  1. #include "stdinc.h"
  2. #include "win32file.h"
  3. #include <stdlib.h>
  4. bool bUseReplacementTags = false;
  5. const wstring MsftCopyRightInfo = L"<!-- Copyright � 1981-2001 Microsoft Corporation -->\r\n";
  6. const wstring xml_declar_prefix = L"<?xml ";
  7. const wstring xml_declar_suffix = L"?>";
  8. // Converts a wstring into an array of bytes to be written to the file with the given
  9. // type of character set
  10. CByteVector ConvertWstringToDestination(wstring str, FileContentType fct)
  11. {
  12. CByteVector byteOutput;
  13. UINT CodePage = CP_UTF8;
  14. if ((fct == FileContentsUnicode) || (fct == FileContentsUnicodeBigEndian))
  15. {
  16. for (wstring::const_iterator i = str.begin(); i != str.end(); i++)
  17. {
  18. unsigned short us = *i;
  19. char *ch = (char*)&us;
  20. if (fct == FileContentsUnicodeBigEndian)
  21. us = (us >> 8) | (us << 8);
  22. byteOutput.push_back(ch[0]);
  23. byteOutput.push_back(ch[1]);
  24. }
  25. }
  26. else if (fct == FileContentsUTF8)
  27. {
  28. if (fct == FileContentsUTF8) CodePage = CP_UTF8;
  29. byteOutput.resize(WideCharToMultiByte(CodePage, 0, str.c_str(), str.size(), 0, 0, 0, 0));
  30. WideCharToMultiByte(CodePage, 0, str.c_str(), str.size(), byteOutput, byteOutput.size(), 0, 0);
  31. }
  32. return byteOutput;
  33. }
  34. // Converts a unicode string to a wstring
  35. wstring ConvertToWstring(const CByteVector &bytes, FileContentType fct)
  36. {
  37. wstring wsOutput;
  38. vector<WCHAR> wchbuffer;
  39. UINT CodePage = CP_ACP;
  40. if (fct == FileContentsUnicode)
  41. {
  42. wsOutput.assign(bytes, bytes.size() / 2);
  43. }
  44. else
  45. {
  46. wchbuffer.resize(MultiByteToWideChar(CodePage, 0, bytes, bytes.size(), NULL, 0), L'\0');
  47. MultiByteToWideChar(CodePage, 0, bytes, bytes.size(), &wchbuffer.front(), wchbuffer.size());
  48. wsOutput.assign(&wchbuffer.front(), wchbuffer.size());
  49. }
  50. return wsOutput;
  51. }
  52. typedef std::pair<wstring,wstring> TagValue;
  53. typedef vector<TagValue> Definitions;
  54. // Reads in a foo=bar pair
  55. //7
  56. // fragile, could use some whitespace tweaking or maybe smarter use of
  57. // the stream operators
  58. wistream& operator>>(wistream& in, TagValue& defined) {
  59. wstring fullline;
  60. getline(in, fullline);
  61. defined.first = fullline.substr(0, fullline.find_first_of('='));
  62. defined.second = fullline.substr(fullline.find_first_of('=') + 1);
  63. return in;
  64. }
  65. // Load the entire parameterization file
  66. Definitions ReadParameterizationFile(wistream &stream)
  67. {
  68. Definitions rvalue;
  69. TagValue tv;
  70. while (!(stream >> tv).eof())
  71. rvalue.push_back(tv);
  72. return rvalue;
  73. }
  74. typedef std::pair<wstring::size_type, wstring::size_type> StringSubspan;
  75. typedef std::pair<wstring, wstring> ReplacementCode;
  76. typedef std::pair<StringSubspan, ReplacementCode> ReplacementChunklet;
  77. //
  78. // Converts "foo:bar" into <foo, bar>
  79. ReplacementCode ExtractIntoPieces(const wstring& blob)
  80. {
  81. ReplacementCode rvalue;
  82. wstring::size_type colonoffset;
  83. colonoffset = blob.find(L':');
  84. if (colonoffset == wstring::npos)
  85. {
  86. rvalue.first = blob;
  87. rvalue.second = L"";
  88. }
  89. else
  90. {
  91. rvalue.first = blob.substr(0, colonoffset);
  92. rvalue.second = blob.substr(colonoffset + 1);
  93. }
  94. return rvalue;
  95. }
  96. ReplacementChunklet*
  97. FindNextReplacementPiece(
  98. wstring& search,
  99. const wstring& target
  100. )
  101. {
  102. ReplacementChunklet* pChunky;
  103. wstring::size_type startchunk, endchunk;
  104. wstring subchunk;
  105. wstring predicate = bUseReplacementTags ? L"$(" : L"";
  106. wstring suffix = bUseReplacementTags ? L")" : L"";
  107. wstring wsFindOpener = predicate + target;
  108. startchunk = search.find(wsFindOpener);
  109. if (startchunk == wstring::npos)
  110. return NULL;
  111. if (bUseReplacementTags)
  112. {
  113. endchunk = search.find(suffix, startchunk);
  114. }
  115. else
  116. {
  117. endchunk = startchunk + target.size();
  118. }
  119. if (endchunk == wstring::npos)
  120. return NULL;
  121. pChunky = new ReplacementChunklet;
  122. pChunky->first.first = startchunk;
  123. pChunky->first.second = endchunk + suffix.size();
  124. // Tear apart into predicate and suffix
  125. // minus $(and)
  126. wstring topieces = search.substr(startchunk + predicate.size(), endchunk - (startchunk + predicate.size()));
  127. pChunky->second = ExtractIntoPieces(topieces);
  128. return pChunky;
  129. }
  130. //
  131. // Right now, the only operation permitted is just a pass-through. Anything after the : is ignored.
  132. //
  133. wstring CleanReplacement(const ReplacementCode code, const wstring& intendedReplacement, const wstring& context)
  134. {
  135. wstring rvalue = intendedReplacement;
  136. return rvalue;
  137. }
  138. #define STRIPCOMMENTS_SLASHSLASH 0x000001
  139. #define STRIPCOMMENTS_SLASHSTAR 0x000002
  140. #define STRIPCOMMENTS_SLASHSLASH_UNAWARE 0x000004
  141. #define STRIPCOMMENTS_SLASHSTAR_UNAWARE 0x000008
  142. template <typename strtype>
  143. void StripComments(int flags, basic_string<strtype>& s)
  144. /*
  145. We generally want to be "aware" of both types so that we don't
  146. strip nested comments. Consider the comments that follow.
  147. */
  148. // /* slash star in slsh slash */
  149. /* // slashslash
  150. in slash star
  151. */
  152. {
  153. typedef basic_string<strtype> ourstring;
  154. ourstring t;
  155. ourstring::const_iterator i;
  156. const ourstring::const_iterator j = s.end();
  157. ourstring::const_iterator k;
  158. bool closed = true;
  159. t.reserve(s.size());
  160. for (i = s.begin() ; closed && i != j && i + 1 != j;)
  161. {
  162. if (((flags & STRIPCOMMENTS_SLASHSTAR) || (flags & STRIPCOMMENTS_SLASHSTAR_UNAWARE) == 0) &&
  163. (*i == '/') &&
  164. (*(i + 1) == '*'))
  165. {
  166. closed = false;
  167. for (k = i + 2 ; k != j && k + 1 != j && !(closed = (*k == '*' && *(k + 1) == '/')) ; ++k)
  168. {
  169. }
  170. if (flags & STRIPCOMMENTS_SLASHSTAR)
  171. // t.append(1, ' ');
  172. ;
  173. else
  174. t.append(i, k + 2);
  175. i = k + 2;
  176. }
  177. else if (((flags & STRIPCOMMENTS_SLASHSLASH) || (flags & STRIPCOMMENTS_SLASHSLASH_UNAWARE) == 0) &&
  178. (*i == '/') &&
  179. (*(i + 1) == '/'))
  180. {
  181. closed = false;
  182. for (k = i + 2 ; k != j && !(closed = (*k == '\r' || *k == '\n')) ; ++k)
  183. {
  184. }
  185. for (; k != j && *k == '\r' || *k == '\n' ; ++k)
  186. {
  187. }
  188. if (flags & STRIPCOMMENTS_SLASHSLASH)
  189. t.append(1, '\n');
  190. else
  191. t.append(i, k);
  192. i = k;
  193. }
  194. if (closed && i != j)
  195. t.append(1, *i++);
  196. }
  197. if (closed)
  198. {
  199. for (; i != j ; ++i)
  200. {
  201. t.append(1, *i);
  202. }
  203. }
  204. s = t;
  205. }
  206. void GetXMLDeclarationIfAny(wstring & wsXmlDecl, wstring & wsFile)
  207. {
  208. SIZE_T p=0, q =0;
  209. p = wsFile.find(xml_declar_prefix, 0);
  210. if (p == 0) // find from exact the beginning of the xmlfile
  211. {
  212. q = wsFile.find(xml_declar_suffix, xml_declar_prefix.length());
  213. if ( q == -1) // manifest has a format error
  214. throw new Win32File::ReadWriteError(true, ::GetLastError());
  215. q += xml_declar_suffix.length();
  216. // skip whitespace
  217. while ((q < wsFile.size()) && (wsFile[q] == L' '))
  218. q ++;
  219. while ((q < wsFile.size()) && ((wsFile[q] == L'\n') || (wsFile[q] == L'\r')))
  220. q ++;
  221. wsXmlDecl.assign(wsFile, 0, q);
  222. wsFile.erase(0, q);
  223. }
  224. return;
  225. }
  226. void ProcessFile(Win32File& inputFile, Win32File& outputFile, Definitions SubstList)
  227. {
  228. wstring wsNextLine;
  229. wstring wsXmlDeclaration;
  230. inputFile.snarfFullFile(wsNextLine);
  231. //
  232. // No comments from the peanut gallery, please. Code by Jay Krell to remove
  233. // comments from strings here...
  234. //
  235. StripComments(STRIPCOMMENTS_SLASHSLASH | STRIPCOMMENTS_SLASHSTAR, wsNextLine);
  236. // Go until we run out of $(...) to replace
  237. for (Definitions::const_iterator ditem = SubstList.begin(); ditem != SubstList.end(); ditem++)
  238. {
  239. ReplacementChunklet* pNextChunk = NULL;
  240. while ((pNextChunk = FindNextReplacementPiece(wsNextLine, ditem->first)) != NULL)
  241. {
  242. wstring cleaned = CleanReplacement(pNextChunk->second, ditem->second, wsNextLine);
  243. wsNextLine.replace(pNextChunk->first.first, pNextChunk->first.second - pNextChunk->first.first, cleaned);
  244. delete pNextChunk;
  245. }
  246. }
  247. //
  248. // Clean up everything
  249. //
  250. while (wsNextLine.size() && iswspace(*wsNextLine.begin()))
  251. wsNextLine = wsNextLine.substr(1);
  252. GetXMLDeclarationIfAny(wsXmlDeclaration, wsNextLine);
  253. if (wsXmlDeclaration.length() != 0)
  254. {
  255. outputFile.writeLine(wsXmlDeclaration);
  256. }
  257. //
  258. // include Microsoft Copyright information at the head of the manifest
  259. //
  260. outputFile.writeLine(MsftCopyRightInfo);
  261. //
  262. // write the output of replacement defines
  263. //
  264. outputFile.writeLine(wsNextLine);
  265. }
  266. // Converts a wstring to a string
  267. string ConvertWstring(wstring input)
  268. {
  269. string s;
  270. vector<CHAR> strbytes;
  271. strbytes.resize(WideCharToMultiByte(CP_ACP, 0, input.c_str(), input.size(), NULL, 0, NULL, NULL));
  272. WideCharToMultiByte(CP_ACP, 0, input.c_str(), input.size(), &strbytes.front(), strbytes.size(), NULL, NULL);
  273. s.assign(&strbytes.front(), strbytes.size());
  274. return s;
  275. }
  276. int __cdecl wmain(int argc, WCHAR** argv)
  277. {
  278. using namespace std;
  279. vector<wstring> args;
  280. wstring wsInputFile, wsOutputFile;
  281. Definitions defines;
  282. Win32File InputFile, OutputFile;
  283. for (int i = 1; i < argc; i++)
  284. args.push_back(wstring(argv[i]));
  285. for (vector<wstring>::const_iterator ci = args.begin(); ci != args.end(); ci++)
  286. {
  287. if (*ci == wstring(L"-reptags")) {
  288. bUseReplacementTags = true;
  289. }
  290. else if (*ci == wstring(L"-i")) {
  291. wsInputFile = *++ci;
  292. }
  293. else if (*ci == wstring(L"-o")) {
  294. wsOutputFile = *++ci;
  295. }
  296. else if (*ci == wstring(L"-s")) {
  297. wifstream iis;
  298. iis.open(ConvertWstring(*++ci).c_str());
  299. if (!iis.is_open()) {
  300. wcerr << L"Failed opening substitution file " << ci->data() << endl;
  301. return 1;
  302. }
  303. Definitions temp = ReadParameterizationFile(iis);
  304. for (Definitions::const_iterator it = temp.begin(); it != temp.end(); it++)
  305. defines.push_back(*it);
  306. }
  307. else if (ci->substr(0, 2) == wstring(L"-D"))
  308. {
  309. // Commandline definitions are NOT appreciated, but they seem to be a necessary evil.
  310. wstringstream wsstemp(ci->substr(2));
  311. TagValue temptag;
  312. wsstemp >> temptag;
  313. defines.push_back(temptag);
  314. }
  315. }
  316. try {
  317. InputFile.openForRead(wsInputFile);
  318. } catch (Win32File::OpeningError *e) {
  319. wcerr << L"Failed opening the input file " << wsInputFile.c_str() << L": " << e->error << endl;
  320. delete e;
  321. return EXIT_FAILURE;
  322. } catch (Win32File::ReadWriteError *e) {
  323. wcerr << L"Failed sensing lead bytes of input file " << wsInputFile.c_str() << L": " << e->error << endl;
  324. delete e;
  325. return EXIT_FAILURE;
  326. }
  327. try {
  328. OutputFile.openForWrite(wsOutputFile, InputFile.gettype());
  329. } catch (Win32File::OpeningError *e) {
  330. wcerr << L"Failed opening the output file " << wsOutputFile.c_str() << L": " << e->error << endl;
  331. delete e;
  332. return EXIT_FAILURE;
  333. } catch (Win32File::ReadWriteError *e) {
  334. wcerr << L"Failed writing lead bytes of output file " << wsOutputFile.c_str() << L": " << e->error << endl;
  335. delete e;
  336. return EXIT_FAILURE;
  337. }
  338. ProcessFile(InputFile, OutputFile, defines);
  339. return EXIT_SUCCESS;
  340. }