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.

711 lines
14 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. main.c
  5. Abstract:
  6. <TODO: fill in abstract>
  7. Author:
  8. TODO: <full name> (<alias>) <date>
  9. Revision History:
  10. <full name> (<alias>) <date> <comments>
  11. --*/
  12. #include "pch.h"
  13. #include "wininet.h"
  14. #include <lm.h>
  15. HANDLE g_hHeap;
  16. HINSTANCE g_hInst;
  17. GROWLIST g_WindiffCmds = INIT_GROWLIST;
  18. BOOL WINAPI MigUtil_Entry (HINSTANCE, DWORD, PVOID);
  19. BOOL
  20. pCallEntryPoints (
  21. DWORD Reason
  22. )
  23. {
  24. switch (Reason) {
  25. case DLL_PROCESS_ATTACH:
  26. UtInitialize (NULL);
  27. break;
  28. case DLL_PROCESS_DETACH:
  29. UtTerminate ();
  30. break;
  31. }
  32. return TRUE;
  33. }
  34. BOOL
  35. Init (
  36. VOID
  37. )
  38. {
  39. g_hHeap = GetProcessHeap();
  40. g_hInst = GetModuleHandle (NULL);
  41. return pCallEntryPoints (DLL_PROCESS_ATTACH);
  42. }
  43. VOID
  44. Terminate (
  45. VOID
  46. )
  47. {
  48. pCallEntryPoints (DLL_PROCESS_DETACH);
  49. }
  50. VOID
  51. HelpAndExit (
  52. VOID
  53. )
  54. {
  55. //
  56. // This routine is called whenever command line args are wrong
  57. //
  58. fprintf (
  59. stderr,
  60. "Command Line Syntax:\n\n"
  61. //
  62. // TODO: Describe command line syntax(es), indent 2 spaces
  63. //
  64. " changes <changenumber>\n"
  65. "\nDescription:\n\n"
  66. //
  67. // TODO: Describe tool, indent 2 spaces
  68. //
  69. " changes.exe executes sd describe and windiff for a specific change.\n"
  70. "\nArguments:\n\n"
  71. //
  72. // TODO: Describe args, indent 2 spaces, say optional if necessary
  73. //
  74. " <changenumber> Specifies the Source Depot change number\n"
  75. );
  76. exit (1);
  77. }
  78. BOOL
  79. pGetNextLine (
  80. IN PCSTR Start,
  81. IN PCSTR Eof,
  82. OUT PCSTR *PrintableStart,
  83. OUT PCSTR *End,
  84. OUT PCSTR *NextLine
  85. )
  86. {
  87. PCSTR pos;
  88. pos = Start;
  89. *End = NULL;
  90. while (pos < Eof) {
  91. if (pos[0] != ' ' && pos[0] != '\t') {
  92. break;
  93. }
  94. pos++;
  95. }
  96. *PrintableStart = pos;
  97. while (pos < Eof) {
  98. if (pos[0] == '\r' || pos[0] == '\n') {
  99. break;
  100. }
  101. pos++;
  102. }
  103. *End = pos;
  104. if (pos < Eof && pos[0] == '\r') {
  105. pos++;
  106. }
  107. if (pos < Eof && pos[0] == '\n') {
  108. pos++;
  109. }
  110. *NextLine = pos;
  111. return Start != *NextLine;
  112. }
  113. PCSTR
  114. pFindNextCharAB (
  115. IN PCSTR Start,
  116. IN PCSTR End,
  117. IN CHAR FindChar
  118. )
  119. {
  120. if (!Start) {
  121. return NULL;
  122. }
  123. while (Start < End) {
  124. if (*Start == FindChar) {
  125. return Start;
  126. }
  127. Start++;
  128. }
  129. return NULL;
  130. }
  131. BOOL
  132. pParseViewLines (
  133. IN OUT PCSTR *FilePos,
  134. IN PCSTR Eof,
  135. IN PCSTR Root,
  136. IN PMAPSTRUCT Map
  137. )
  138. {
  139. UINT count = 0;
  140. PCSTR pos;
  141. PCSTR nextPos;
  142. PSTR prefix;
  143. PCSTR prefixEnd;
  144. PSTR subDir;
  145. PCSTR localPath;
  146. PCSTR clientPathStart;
  147. PCSTR clientPathEnd;
  148. PSTR p;
  149. PCSTR lineStart;
  150. PCSTR lineEnd;
  151. pos = *FilePos;
  152. while (pGetNextLine (pos, Eof, &lineStart, &lineEnd, &nextPos)) {
  153. if (pos == lineStart) {
  154. break;
  155. }
  156. //
  157. // Find depot prefix
  158. //
  159. prefixEnd = lineStart;
  160. for (;;) {
  161. prefixEnd = pFindNextCharAB (prefixEnd, lineEnd, '.');
  162. if (!prefixEnd) {
  163. break;
  164. }
  165. if (prefixEnd[1] == '.' && prefixEnd[2] == '.' &&
  166. isspace(prefixEnd[3]) &&
  167. prefixEnd[4] == '/' && prefixEnd[5] == '/'
  168. ) {
  169. break;
  170. }
  171. prefixEnd++;
  172. }
  173. if (!prefixEnd || prefixEnd == lineStart) {
  174. break;
  175. }
  176. //
  177. // Find client path
  178. //
  179. clientPathStart = pFindNextCharAB (prefixEnd + 6, lineEnd, '/');
  180. if (!clientPathStart) {
  181. break;
  182. }
  183. clientPathStart++;
  184. clientPathEnd = clientPathStart;
  185. for (;;) {
  186. clientPathEnd = pFindNextCharAB (clientPathEnd, lineEnd, '.');
  187. if (!clientPathEnd) {
  188. break;
  189. }
  190. if (clientPathEnd[1] == '.' && clientPathEnd[2] == '.' &&
  191. clientPathEnd + 3 == lineEnd
  192. ) {
  193. break;
  194. }
  195. clientPathEnd++;
  196. }
  197. if (!clientPathEnd) {
  198. break;
  199. }
  200. if (clientPathEnd > clientPathStart) {
  201. clientPathEnd--; // account for last slash
  202. }
  203. //
  204. // Clean the strings and add to mapping
  205. //
  206. prefix = AllocText (prefixEnd - lineStart);
  207. StringCopyAB (prefix, lineStart, prefixEnd);
  208. subDir = AllocText ((clientPathEnd - clientPathStart) + 1);
  209. if (clientPathEnd > clientPathStart) {
  210. StringCopyAB (subDir, clientPathStart, clientPathEnd);
  211. }
  212. p = strchr (subDir, '/');
  213. while (p) {
  214. *p++ = '\\';
  215. p = strchr (p, '/');
  216. }
  217. AppendWack (subDir);
  218. localPath = JoinPaths (Root, subDir);
  219. AddStringMappingPair (Map, prefix, localPath);
  220. FreeText (prefix);
  221. FreeText (subDir);
  222. FreePathString (localPath);
  223. count++;
  224. pos = nextPos;
  225. }
  226. *FilePos = pos;
  227. return count > 0;
  228. }
  229. BOOL
  230. pParseClientMapping (
  231. IN PCSTR SdClientOutput,
  232. IN PCSTR Eof,
  233. OUT PSTR RootPath,
  234. IN PMAPSTRUCT Map
  235. )
  236. {
  237. PCSTR lineStart;
  238. PCSTR lineEnd;
  239. PCSTR pos;
  240. PSTR dup;
  241. PCSTR root;
  242. BOOL viewFound = FALSE;
  243. //
  244. // Find Root: or View:
  245. //
  246. pos = SdClientOutput;
  247. *RootPath = 0;
  248. while (pGetNextLine (pos, Eof, &lineStart, &lineEnd, &pos)) {
  249. if (lineStart == lineEnd) {
  250. continue;
  251. }
  252. if (*lineStart == '#') {
  253. continue;
  254. }
  255. dup = AllocText (lineEnd - lineStart);
  256. StringCopyAB (dup, lineStart, lineEnd);
  257. if (StringIPrefix (dup, "Root:")) {
  258. root = dup + 5;
  259. while (isspace (*root)) {
  260. root++;
  261. }
  262. StringCopy (RootPath, root);
  263. } else if (StringIPrefix (dup, "View:")) {
  264. if (!(*RootPath)) {
  265. break;
  266. }
  267. viewFound = pParseViewLines (&pos, Eof, RootPath, Map);
  268. }
  269. FreeText (dup);
  270. dup = NULL;
  271. }
  272. FreeText (dup);
  273. return *RootPath && viewFound;
  274. }
  275. BOOL
  276. pParseChangeList (
  277. IN PCSTR SdDescribeOutput,
  278. IN PCSTR Eof,
  279. IN PMAPSTRUCT Map
  280. )
  281. {
  282. PCSTR lineStart;
  283. PCSTR lineEnd;
  284. PCSTR pos;
  285. PCSTR nextPos;
  286. PSTR dup;
  287. BOOL result = FALSE;
  288. PSTR p;
  289. UINT num;
  290. CHAR bigBuf[2048];
  291. PSTR change;
  292. CHAR cmdLine[2048];
  293. //
  294. // Find the line Affected files
  295. //
  296. pos = SdDescribeOutput;
  297. printf ("\n\n");
  298. while (pGetNextLine (pos, Eof, &lineStart, &lineEnd, &nextPos)) {
  299. if (lineEnd > lineStart &&
  300. StringMatchAB ("Affected files ...", lineStart, lineEnd)
  301. ) {
  302. result = TRUE;
  303. break;
  304. }
  305. dup = AllocText ((lineEnd - pos) + 1);
  306. if (lineEnd > pos) {
  307. StringCopyAB (dup, pos, lineEnd);
  308. }
  309. printf ("%s\n", dup);
  310. FreeText (dup);
  311. pos = nextPos;
  312. }
  313. if (result) {
  314. //
  315. // Files listed in output
  316. //
  317. while (pGetNextLine (pos, Eof, &lineStart, &lineEnd, &nextPos)) {
  318. pos = nextPos;
  319. if (lineStart[0] != '.') {
  320. continue;
  321. }
  322. lineStart += 4;
  323. if (lineStart > lineEnd) {
  324. continue;
  325. }
  326. //
  327. // Translate depot path into local path
  328. //
  329. StringCopyAB (bigBuf, lineStart, lineEnd);
  330. p = strrchr (bigBuf, '#');
  331. if (!p) {
  332. continue;
  333. }
  334. *p = 0;
  335. num = strtoul (p + 1, &change, 10);
  336. while (isspace (*change)) {
  337. change++;
  338. }
  339. MappingSearchAndReplace (Map, bigBuf, ARRAYSIZE(bigBuf));
  340. p = strchr (bigBuf, '/');
  341. while (p) {
  342. *p++ = '\\';
  343. p = strchr (p, '/');
  344. }
  345. if (StringIMatch (change, "edit") && num > 1) {
  346. wsprintf (cmdLine, "windiff.exe %s#%u %s#%u", bigBuf, num - 1, bigBuf, num);
  347. GlAppendString (&g_WindiffCmds, cmdLine);
  348. }
  349. printf ("%s: %s#%u\n", change, bigBuf, num);
  350. }
  351. }
  352. return GlGetSize (&g_WindiffCmds) > 0;
  353. }
  354. BOOL
  355. pLaunchSd (
  356. IN PSTR CmdLine,
  357. IN HANDLE TempFile,
  358. IN PCSTR Msg,
  359. OUT HANDLE *Mapping,
  360. OUT PCSTR *FileContent,
  361. OUT PCSTR *Eof
  362. )
  363. {
  364. STARTUPINFO si;
  365. PROCESS_INFORMATION pi;
  366. LONG rc;
  367. SetFilePointer (TempFile, 0, NULL, FILE_BEGIN);
  368. SetEndOfFile (TempFile);
  369. ZeroMemory (&si, sizeof (si));
  370. si.dwFlags = STARTF_USESTDHANDLES;
  371. si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
  372. if (!DuplicateHandle (
  373. GetCurrentProcess(),
  374. TempFile,
  375. GetCurrentProcess(),
  376. &si.hStdOutput,
  377. 0,
  378. TRUE,
  379. DUPLICATE_SAME_ACCESS
  380. )) {
  381. printf ("Can't dup temp file handle\n");
  382. return FALSE;
  383. }
  384. si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
  385. if (!CreateProcess (
  386. NULL,
  387. CmdLine,
  388. NULL,
  389. NULL,
  390. TRUE,
  391. 0,
  392. NULL,
  393. NULL,
  394. &si,
  395. &pi
  396. )) {
  397. printf ("Can't launch sd describe\n");
  398. CloseHandle (si.hStdOutput);
  399. return FALSE;
  400. }
  401. printf ("%s", Msg);
  402. rc = WaitForSingleObject (pi.hProcess, INFINITE);
  403. printf ("\n");
  404. CloseHandle (pi.hProcess);
  405. CloseHandle (pi.hThread);
  406. CloseHandle (si.hStdOutput);
  407. if (rc != WAIT_OBJECT_0) {
  408. return FALSE;
  409. }
  410. if (!GetFileSize (TempFile, NULL)) {
  411. return FALSE;
  412. }
  413. *Mapping = CreateFileMapping (TempFile, NULL, PAGE_READONLY, 0, 0, NULL);
  414. if (!(*Mapping)) {
  415. printf ("Can't map temp file into memory\n");
  416. return FALSE;
  417. }
  418. *FileContent = (PCSTR) MapViewOfFile (*Mapping, FILE_MAP_READ, 0, 0, 0);
  419. if (!*FileContent) {
  420. printf ("Can't map temp file data into memory\n");
  421. CloseHandle (*Mapping);
  422. return FALSE;
  423. }
  424. *Eof = *FileContent + GetFileSize (TempFile, NULL);
  425. return TRUE;
  426. }
  427. BOOL
  428. pLaunchWindiff (
  429. IN PCSTR CmdLine
  430. )
  431. {
  432. STARTUPINFO si;
  433. PROCESS_INFORMATION pi;
  434. LONG rc;
  435. PSTR writableCmdLine = DuplicateText (CmdLine);
  436. ZeroMemory (&si, sizeof (si));
  437. if (!CreateProcess (
  438. NULL,
  439. writableCmdLine,
  440. NULL,
  441. NULL,
  442. TRUE,
  443. 0,
  444. NULL,
  445. NULL,
  446. &si,
  447. &pi
  448. )) {
  449. FreeText (writableCmdLine);
  450. printf ("Can't launch %s\n", CmdLine);
  451. return FALSE;
  452. }
  453. FreeText (writableCmdLine);
  454. rc = WaitForSingleObject (pi.hProcess, INFINITE);
  455. CloseHandle (pi.hProcess);
  456. CloseHandle (pi.hThread);
  457. return TRUE;
  458. }
  459. INT
  460. __cdecl
  461. _tmain (
  462. INT argc,
  463. PCTSTR argv[]
  464. )
  465. {
  466. INT i;
  467. UINT change = 0;
  468. UINT u;
  469. UINT count;
  470. //
  471. // TODO: Parse command line here
  472. //
  473. for (i = 1 ; i < argc ; i++) {
  474. if (argv[i][0] == TEXT('/') || argv[i][0] == TEXT('-')) {
  475. HelpAndExit();
  476. } else {
  477. //
  478. // Parse other args that don't require / or -
  479. //
  480. if (change) {
  481. HelpAndExit();
  482. }
  483. change = _tcstoul (argv[i], NULL, 10);
  484. if (!change) {
  485. HelpAndExit();
  486. }
  487. }
  488. }
  489. if (!change) {
  490. HelpAndExit();
  491. }
  492. //
  493. // Begin processing
  494. //
  495. if (!Init()) {
  496. return 0;
  497. }
  498. //
  499. // TODO: Do work here
  500. //
  501. {
  502. TCHAR cmd[MAX_PATH];
  503. HANDLE tempFile;
  504. HANDLE mapping;
  505. PCSTR fileData;
  506. PCSTR endOfFile;
  507. BOOL runWinDiff = FALSE;
  508. CHAR root[MAX_PATH];
  509. PMAPSTRUCT map;
  510. tempFile = BfGetTempFile ();
  511. map = CreateStringMapping();
  512. if (!tempFile) {
  513. printf ("Can't create temp file\n");
  514. exit (1);
  515. }
  516. if (!pLaunchSd ("sd client -o", tempFile, "Getting client mapping...", &mapping, &fileData, &endOfFile)) {
  517. exit (1);
  518. }
  519. pParseClientMapping (fileData, endOfFile, root, map);
  520. wsprintf (cmd, TEXT("sd describe -s %u"), change);
  521. if (!pLaunchSd (cmd, tempFile, "Getting change list...", &mapping, &fileData, &endOfFile)) {
  522. exit (1);
  523. }
  524. runWinDiff = pParseChangeList (fileData, endOfFile, map);
  525. UnmapViewOfFile (fileData);
  526. CloseHandle (mapping);
  527. DestroyStringMapping (map);
  528. CloseHandle (tempFile);
  529. if (runWinDiff) {
  530. count = GlGetSize (&g_WindiffCmds);
  531. for (u = 0 ; u < count ; u++) {
  532. if (!pLaunchWindiff (GlGetString (&g_WindiffCmds, u))) {
  533. break;
  534. }
  535. }
  536. }
  537. GlFree (&g_WindiffCmds);
  538. }
  539. //
  540. // End of processing
  541. //
  542. Terminate();
  543. return 0;
  544. }