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.

516 lines
14 KiB

  1. #include "stdinc.h"
  2. static const char File[] = __FILE__;
  3. #include "handle.h"
  4. #include "mystring.h"
  5. #include <functional>
  6. #include <set>
  7. #include "rpc.h"
  8. // std::binary_search lamely only returns a bool, not an iterator
  9. // it is a simple layer over std::lower_bound
  10. template<class Iterator_t, class T> inline
  11. Iterator_t BinarySearch(Iterator_t First, Iterator_t Last, const T& t)
  12. {
  13. Iterator_t Iterator = std::lower_bound(First, Last, t);
  14. if (Iterator != Last
  15. && !(t < *Iterator) // this is a way to check for equality actually
  16. )
  17. return Iterator;
  18. return Last;
  19. }
  20. //
  21. // This is just like remove_copy_if, but it is missing an exclamation point
  22. //
  23. template<class InputIterator_t, class OutputIterator_t, class Predicate_t> inline
  24. OutputIterator_t CopyIf(InputIterator_t First, InputIterator_t Last, OutputIterator_t Out, Predicate_t Predicate)
  25. {
  26. for (; First != Last; ++First)
  27. if (/*!*/Predicate(*First))
  28. *Out++ = *First;
  29. return (Out);
  30. }
  31. //
  32. // get msvcrt.dll wildcard processing on the command line
  33. //
  34. extern "C" { int _dowildcard = 1; }
  35. typedef std::vector<String_t> StringVector_t;
  36. typedef std::deque<String_t> StringDeque_t;
  37. typedef StringVector_t::iterator StringVectorIterator_t;
  38. typedef StringVector_t::const_iterator StringVectorConstIterator_t;
  39. typedef std::set<String_t> StringSet_t;
  40. typedef StringSet_t::iterator StringSetIterator_t;
  41. typedef StringSet_t::const_iterator StringSetConstIterator_t;
  42. template <typename T, size_t N>
  43. class FixedSizeArray_t : public std::vector<T>
  44. {
  45. public:
  46. ~FixedSizeArray_t() { }
  47. FixedSizeArray_t() { reserve(N); }
  48. };
  49. class FileSystemPath_t
  50. {
  51. public:
  52. void Realize(String_t & str);
  53. FileSystemPath_t * m_pParent;
  54. String_t m_str;
  55. };
  56. void FileSystemPath_t::Realize(String_t & str)
  57. {
  58. if (m_pParent != NULL)
  59. {
  60. m_pParent->RealizePath(str);
  61. str += L"\\";
  62. }
  63. str += m_str;
  64. }
  65. typedef std::deque<FileSystemPath_t> FileSystemPathsDeque_t;
  66. void IfFailedThrow(HRESULT hr)
  67. {
  68. if (SUCCEEDED(hr))
  69. return;
  70. throw hr;
  71. }
  72. void
  73. CollectFilePathsRecursivelyHelper(
  74. const String_t& directory,
  75. FileSystemPathsDeque_t& paths,
  76. WIN32_FIND_DATAW& wfd
  77. )
  78. {
  79. CFindFile FindFile;
  80. HRESULT hr;
  81. IfFailedThrow(hr = FindFile.HrCreate((directory + L"\\*).c_str(), &wfd));
  82. do
  83. {
  84. if (FusionpIsDotOrDotDot(wfd.cFileName))
  85. continue;
  86. if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  87. {
  88. }
  89. else
  90. {
  91. }
  92. } while (::FindNextFileW(FindFile, &wfd));
  93. }
  94. void
  95. CollectFilePathsRecursively(
  96. const String_t & directory,
  97. FileSystemPathsDeque_t & paths
  98. )
  99. {
  100. WIN32_FIND_DATAW wfd;
  101. CollectFilePathsRecursivelyHelper(directory, paths, wfd);
  102. }
  103. class DelayloadTool_t
  104. {
  105. private:
  106. typedef DelayloadTool_t This_t;
  107. DelayloadTool_t(const DelayloadTool_t&);
  108. void operator=(const DelayloadTool_t&);
  109. public:
  110. typedef String_t File_t;
  111. ~DelayloadTool_t() { }
  112. Print_t Print;
  113. DelayloadTool_t() :
  114. Argv0base_cstr(L"")
  115. {
  116. }
  117. static bool IsPathSeperator(wchar_t ch)
  118. {
  119. return (ch == '\\' || ch == '/');
  120. }
  121. static bool IsAbsolutePath(const String_t& s)
  122. {
  123. return (s.length() > 2
  124. && (s[1] == ':' || (IsPathSeperator(s[0] && IsPathSeperator(s[1])))));
  125. }
  126. //
  127. // This transform lets LoadLibrary's search be more like CreateFile's search.
  128. //
  129. static String_t PrependDotSlashToRelativePath(const String_t& Path)
  130. {
  131. if (!IsAbsolutePath(Path))
  132. return L".\\" + Path;
  133. else
  134. return Path;
  135. }
  136. String_t Argv0;
  137. String_t Argv0base;
  138. PCWSTR Argv0base_cstr;
  139. typedef std::vector<File_t> Files_t;
  140. typedef std::set<ResourceIdTuple_t> Tuples_t;
  141. Files_t Files;
  142. Tuples_t Tuples;
  143. bool ShouldPrint;
  144. };
  145. typedef String_t::const_iterator StringConstIterator_t;
  146. void DelayloadToolAssertFailed(const char* Expression, const char* File, unsigned long Line)
  147. {
  148. fprintf(stderr, "ASSERTION FAILURE: File %s, Line %lu, Expression %s\n", File, Line, Expression);
  149. abort();
  150. }
  151. void DelayloadToolInternalErrorCheckFailed(const char* Expression, const char* File, unsigned long Line)
  152. {
  153. fprintf(stderr, "INTERNAL ERROR: File %s, Line %lu, Expression %s\n", File, Line, Expression);
  154. abort();
  155. }
  156. String_t NumberToString(ULONG Number, PCWSTR Format = L"0x%lx")
  157. {
  158. // the size needed is really dependent on Format..
  159. WCHAR NumberAsString[BITS_OF(Number) + 5];
  160. _snwprintf(NumberAsString, NUMBER_OF(NumberAsString), Format, Number);
  161. NumberAsString[NUMBER_OF(NumberAsString) - 1] = 0;
  162. return NumberAsString;
  163. }
  164. String_t GetLastErrorString()
  165. {
  166. PWSTR s = NULL;
  167. DWORD Error = GetLastError();
  168. String_t ErrorString = NumberToString(Error, L"%lu");
  169. PWSTR FormatMessageAllocatedBuffer = NULL;
  170. if (!FormatMessageW(
  171. FORMAT_MESSAGE_ALLOCATE_BUFFER
  172. | FORMAT_MESSAGE_FROM_SYSTEM
  173. | FORMAT_MESSAGE_IGNORE_INSERTS,
  174. NULL,
  175. Error,
  176. 0,
  177. reinterpret_cast<PWSTR>(&FormatMessageAllocatedBuffer),
  178. 100,
  179. NULL
  180. )
  181. || FormatMessageAllocatedBuffer == NULL
  182. )
  183. {
  184. goto Exit;
  185. }
  186. if (FormatMessageAllocatedBuffer[0] == 0)
  187. {
  188. goto Exit;
  189. }
  190. //
  191. // Error messages often end with vertical whitespce, remove it.
  192. //
  193. s = FormatMessageAllocatedBuffer + StringLength(FormatMessageAllocatedBuffer) - 1;
  194. while (s != FormatMessageAllocatedBuffer && (*s == '\n' || *s == '\r'))
  195. *s-- = 0;
  196. ErrorString = ErrorString + L" (" + FormatMessageAllocatedBuffer + L")";
  197. Exit:
  198. LocalFree(FormatMessageAllocatedBuffer);
  199. return ErrorString;
  200. }
  201. bool GetFileSize(PCWSTR Path, __int64& Size)
  202. {
  203. CFindFile FindFile;
  204. WIN32_FIND_DATAW wfd;
  205. LARGE_INTEGER liSize;
  206. if (!FindFile.Win32Create(Path, &wfd))
  207. return false;
  208. liSize.HighPart = wfd.nFileSizeHigh;
  209. liSize.LowPart = wfd.nFileSizeLow;
  210. Size = liSize.QuadPart;
  211. return true;
  212. }
  213. String_t RemoveOptionChar(const String_t& s)
  214. {
  215. if (s.Length() != 0)
  216. {
  217. if (s[0] == '-')
  218. return s.substr(1);
  219. else if (s[0] == '/')
  220. return s.substr(1);
  221. else if (s[0] == ':') // hacky..
  222. return s.substr(1);
  223. else if (s[0] == '=') // hacky..
  224. return s.substr(1);
  225. }
  226. return s;
  227. }
  228. //
  229. // String_t has specialized find_first_not_of that uses integral positions,
  230. // and globally there is only find_first_of. Here we provide the expected
  231. // iterator-based find_first_not_of, based on the std::string code.
  232. //
  233. // Find the first occurence in [first1, last1) of an element in [first2, last).
  234. //
  235. // eg:
  236. // find_first_not_of("abc":"12;3", ":;");
  237. // ^
  238. // find_first_not_of(":12;3", ":;");
  239. // ^
  240. // find_first_not_of("3", ":;");
  241. // ^
  242. //
  243. template <typename Iterator>
  244. Iterator FindFirstNotOf(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
  245. {
  246. if (first2 == last2)
  247. return last1;
  248. for ( ; first1 != last1 ; ++first1)
  249. {
  250. if (std::find(first2, last2, *first1) == last2)
  251. {
  252. break;
  253. }
  254. }
  255. return first1;
  256. }
  257. //
  258. // consistent style..
  259. //
  260. template <typename Iterator>
  261. Iterator FindFirstOf(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
  262. {
  263. return std::find_first_of(first1, last1, first2, last2);
  264. }
  265. template <typename String_t>
  266. void SplitString(const String_t& String, const String_t& Delim, std::vector<String_t>& Fields)
  267. {
  268. String_t::const_iterator FieldBegin;
  269. String_t::const_iterator FieldEnd = String.begin();
  270. while ((FieldBegin = FindFirstNotOf(FieldEnd, String.end(), Delim.begin(), Delim.end())) != String.end())
  271. {
  272. FieldEnd = FindFirstOf(FieldBegin, String.end(), Delim.begin(), Delim.end());
  273. Fields.push_back(String_t(FieldBegin, FieldEnd));
  274. }
  275. }
  276. void __cdecl Error(const wchar_t* s, ...)
  277. {
  278. printf("%s\n", s);
  279. exit(EXIT_FAILURE);
  280. }
  281. int DelayloadTool_t::Main(const StringVector_t& args)
  282. {
  283. StringVectorConstIterator_t i;
  284. Operation_t Operation = NULL;
  285. for (i = args.begin() ; i != args.end() ; ++i)
  286. {
  287. String_t s;
  288. String_t t;
  289. bool PrintAll = false;
  290. bool PrintNone = false;
  291. bool PrintValue = true;
  292. bool PrintUnequal = false;
  293. s = *i;
  294. s = RemoveOptionChar(s);
  295. if (s == L"Sxid12Tool1")
  296. {
  297. StringVector_t restArgs(i + 1, args.end());
  298. return Sxid12Tool1(restArgs);
  299. }
  300. else if (GetFileAttributesW(s) != 0xFFFFFFFF)
  301. {
  302. goto FileLabel;
  303. }
  304. else if (s.Starts(t = L"Query"))
  305. {
  306. Operation = &This_t::Query;
  307. }
  308. else if (s.Starts(t = L"FindDuplicates"))
  309. {
  310. Operation = &This_t::FindDuplicates;
  311. }
  312. else if (s.Starts(t = L"Explode"))
  313. {
  314. Operation = &This_t::Explode;
  315. }
  316. else if (s.Starts(t = L"Diff"))
  317. {
  318. Operation = &This_t::FindDuplicates;
  319. Print.LeftOnly = true;
  320. Print.RightOnly = true;
  321. Print.Equal = true;
  322. Print.UnequalContents = true;
  323. Print.UnequalSize = true;
  324. }
  325. else if (s.Starts(t = L"Delete"))
  326. Operation = &This_t::Delete;
  327. else if (s.Starts(t = L"Dump"))
  328. Operation = &This_t::Dump;
  329. else if (s.Starts(t = L"FindAndDeleteDuplicates"))
  330. Operation = &This_t::FindAndDeleteDuplicates;
  331. else if (s.Starts(t = L"NoPrint"))
  332. {
  333. PrintValue = !PrintValue;
  334. goto PrintCommonLabel;
  335. }
  336. else if (s.Starts(t = L"Print"))
  337. {
  338. PrintCommonLabel:
  339. s = RemoveOptionChar(s.substr(t.Length()));
  340. bool* Member = NULL;
  341. if (s == (t = L"UnequalSize"))
  342. Member = &this->Print.UnequalSize;
  343. else if (s == (t = L"UnequalContents"))
  344. Member = &this->Print.UnequalContents;
  345. else if (s == (t = L"UnequalSize"))
  346. Member = &this->Print.UnequalSize;
  347. else if (s == (t = L"Keep"))
  348. Member = &this->Print.Keep;
  349. else if (s == (t = L"Delete"))
  350. Member = &this->Print.Delete;
  351. else if (s == (t = L"Success"))
  352. Member = &this->Print.Success;
  353. else if (s == (t = L"Unchanged"))
  354. Member = &this->Print.Unchanged;
  355. else if (s == (t = L"Equal"))
  356. Member = &this->Print.Equal;
  357. else if (s == (t = L"LeftOnly"))
  358. Member = &this->Print.LeftOnly;
  359. else if (s == (t = L"RightOnly"))
  360. Member = &this->Print.RightOnly;
  361. else if (s == L"All")
  362. {
  363. PrintAll = true;
  364. Print.SetAll(true);
  365. }
  366. else if (s == L"None")
  367. {
  368. PrintNone = true;
  369. Print.SetAll(false);
  370. }
  371. else if (s == L"Unequal")
  372. {
  373. PrintUnequal = true;
  374. this->Print.UnequalContents = true;
  375. this->Print.UnequalSize = true;
  376. }
  377. if (PrintAll || PrintNone || PrintUnequal)
  378. {
  379. // nothing
  380. }
  381. else if (Member == NULL)
  382. {
  383. printf("%ls : WARNING: unknown print option \"%ls\" ignored\n", Argv0base_cstr, static_cast<PCWSTR>(s));
  384. continue;
  385. }
  386. else
  387. {
  388. bool knownValue = true;
  389. s = RemoveOptionChar(s.substr(t.Length()));
  390. if (s != L"")
  391. {
  392. //
  393. // This doesn't work because of the equality comparisons above. They need
  394. // ignore whatever follows the colon.
  395. //
  396. if (s == L"No" || s == L"False")
  397. PrintValue = !PrintValue;
  398. else if (s == L"Yes" || s == L"True")
  399. {
  400. /* nothing */
  401. }
  402. else
  403. {
  404. knownValue = false;
  405. printf("%ls : WARNING: unknown print option \"%ls\" ignored\n", Argv0base_cstr, static_cast<PCWSTR>(s));
  406. continue;
  407. }
  408. }
  409. if (knownValue)
  410. *Member = PrintValue;
  411. }
  412. continue;
  413. }
  414. else if (s.Starts(t = L"File"))
  415. {
  416. FileLabel:
  417. s = RemoveOptionChar(s.substr(t.Length()));
  418. Files.push_back(s);
  419. continue;
  420. }
  421. else
  422. {
  423. Files.push_back(s);
  424. continue;
  425. }
  426. s = RemoveOptionChar(s.substr(t.Length()));
  427. SplitResourceTupleString(s, Tuples);
  428. }
  429. //std::sort(Tuples.begin(), Tuples.end());
  430. if (Operation == NULL)
  431. {
  432. printf("Usage...\n");
  433. return EXIT_FAILURE;
  434. }
  435. (this->*Operation)();
  436. return EXIT_SUCCESS;
  437. }
  438. extern "C"
  439. {
  440. void __cdecl mainCRTStartup(void);
  441. void __cdecl wmainCRTStartup(void);
  442. }
  443. int __cdecl main(int argc, char** argv)
  444. {
  445. wmainCRTStartup();
  446. return 0;
  447. }
  448. extern "C" int __cdecl wmain(int argc, wchar_t** argv)
  449. {
  450. DelayloadTool_t tool;
  451. StringVector_t args;
  452. args.reserve(argc);
  453. tool.Argv0 = argv[0];
  454. String_t::size_type p = tool.Argv0.find_last_of(L"\\/");
  455. if (p != tool.Argv0.npos)
  456. tool.Argv0base = tool.Argv0.substr(1 + p);
  457. else
  458. tool.Argv0base = tool.Argv0;
  459. p = tool.Argv0base.find_last_of(L".");
  460. if (p != tool.Argv0base.npos)
  461. tool.Argv0base = tool.Argv0base.substr(0, p);
  462. tool.Argv0base_cstr = tool.Argv0base.c_str();
  463. std::copy(argv + 1, argv + argc, std::back_inserter(args));
  464. int ret = tool.Main(args);
  465. return ret;
  466. }