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.

842 lines
16 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. srcsrv.cpp
  5. Abstract:
  6. This code obtaining version-controlled source.
  7. Author:
  8. patst
  9. --*/
  10. #include "pch.h"
  11. BOOL gInitialized = false;
  12. LIST_ENTRY gProcessList;
  13. DWORD gProcessListCount = 0;
  14. DWORD gOptions = 0;
  15. BOOL
  16. DllMain(
  17. IN PVOID hdll,
  18. IN ULONG reason,
  19. IN PCONTEXT context OPTIONAL
  20. )
  21. {
  22. switch (reason)
  23. {
  24. case DLL_PROCESS_ATTACH:
  25. break;
  26. case DLL_PROCESS_DETACH:
  27. break;
  28. }
  29. return true;
  30. }
  31. BOOL error(DWORD err)
  32. {
  33. SetLastError(err);
  34. return false;
  35. }
  36. PVOID MemAlloc(DWORD size)
  37. {
  38. PVOID rc;
  39. rc = LocalAlloc(LPTR, size);
  40. if (!rc)
  41. return rc;
  42. ZeroMemory(rc, size);
  43. return rc;
  44. }
  45. void MemFree(PVOID p)
  46. {
  47. if (p)
  48. LocalFree(p);
  49. }
  50. PPROCESS_ENTRY FindProcessEntry(HANDLE hp)
  51. {
  52. PLIST_ENTRY next;
  53. PPROCESS_ENTRY pe;
  54. DWORD count;
  55. next = gProcessList.Flink;
  56. if (!next)
  57. return NULL;
  58. for (count = 0; (PVOID)next != (PVOID)&gProcessList; count++)
  59. {
  60. assert(count < gProcessListCount);
  61. if (count >= gProcessListCount)
  62. return NULL;
  63. pe = CONTAINING_RECORD(next, PROCESS_ENTRY, ListEntry);
  64. next = pe->ListEntry.Flink;
  65. if (pe->hProcess == hp)
  66. return pe;
  67. }
  68. return NULL;
  69. }
  70. PPROCESS_ENTRY
  71. FindFirstProcessEntry(
  72. )
  73. {
  74. return CONTAINING_RECORD(gProcessList.Flink, PROCESS_ENTRY, ListEntry);
  75. }
  76. void
  77. SendDebugString(
  78. PPROCESS_ENTRY pe,
  79. LPSTR sz
  80. )
  81. {
  82. __try
  83. {
  84. if (!pe)
  85. pe = FindFirstProcessEntry();
  86. if (!pe || !pe->callback)
  87. return;
  88. pe->callback(SRCSRVACTION_TRACE, (DWORD64)sz, pe->context);
  89. } __except (EXCEPTION_EXECUTE_HANDLER) {
  90. }
  91. }
  92. #define dprint ((gOptions & SRCSRVOPT_DEBUG) == SRCSRVOPT_DEBUG)&&_dprint
  93. #define eprint ((gOptions & SRCSRVOPT_DEBUG) == SRCSRVOPT_DEBUG)&&_eprint
  94. #define pdprint ((gOptions & SRCSRVOPT_DEBUG) == SRCSRVOPT_DEBUG)&&_pdprint
  95. #define pdeprint ((gOptions & SRCSRVOPT_DEBUG) == SRCSRVOPT_DEBUG)&&_pdeprint
  96. bool
  97. _pdprint(
  98. PPROCESS_ENTRY pe,
  99. LPSTR format,
  100. ...
  101. )
  102. {
  103. static char buf[1000] = "SRCSRV: ";
  104. va_list args;
  105. va_start(args, format);
  106. _vsnprintf(buf+9, sizeof(buf)-9, format, args);
  107. va_end(args);
  108. SendDebugString(pe, buf);
  109. return true;
  110. }
  111. bool
  112. _peprint(
  113. PPROCESS_ENTRY pe,
  114. LPSTR format,
  115. ...
  116. )
  117. {
  118. static char buf[1000] = "";
  119. va_list args;
  120. va_start(args, format);
  121. _vsnprintf(buf, sizeof(buf), format, args);
  122. va_end(args);
  123. SendDebugString(pe, buf);
  124. return true;
  125. }
  126. bool
  127. _dprint(
  128. LPSTR format,
  129. ...
  130. )
  131. {
  132. static char buf[1000] = "SRCSRV: ";
  133. va_list args;
  134. va_start(args, format);
  135. _vsnprintf(buf+9, sizeof(buf)-9, format, args);
  136. va_end(args);
  137. SendDebugString(NULL, buf);
  138. return true;
  139. }
  140. bool
  141. _eprint(
  142. LPSTR format,
  143. ...
  144. )
  145. {
  146. static char buf[1000] = "";
  147. va_list args;
  148. va_start(args, format);
  149. _vsnprintf(buf, sizeof(buf), format, args);
  150. va_end(args);
  151. SendDebugString(NULL, buf);
  152. return true;
  153. }
  154. void FreeModuleEntry(PPROCESS_ENTRY pe, PMODULE_ENTRY me)
  155. {
  156. MemFree(me->stream);
  157. MemFree(me);
  158. }
  159. PMODULE_ENTRY
  160. FindModuleEntry(
  161. PPROCESS_ENTRY pe,
  162. DWORD64 base
  163. )
  164. {
  165. static PLIST_ENTRY next = NULL;
  166. PMODULE_ENTRY me;
  167. if (base == (DWORD64)-1)
  168. {
  169. if (!next)
  170. return NULL;
  171. if ((PVOID)next == (PVOID)&pe->ModuleList)
  172. {
  173. // Reset to NULL so the list can be re-walked
  174. next = NULL;
  175. return NULL;
  176. }
  177. me = CONTAINING_RECORD( next, MODULE_ENTRY, ListEntry );
  178. next = me->ListEntry.Flink;
  179. return me;
  180. }
  181. next = pe->ModuleList.Flink;
  182. if (!next)
  183. return NULL;
  184. while ((PVOID)next != (PVOID)&pe->ModuleList)
  185. {
  186. me = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
  187. next = me->ListEntry.Flink;
  188. if (base == me->base)
  189. return me;
  190. }
  191. return NULL;
  192. }
  193. char *
  194. dotranslate(
  195. PMODULE_ENTRY me,
  196. char *input,
  197. char *output,
  198. DWORD outsize
  199. )
  200. {
  201. int i;
  202. char key[MAX_PATH + 1];
  203. PVARIABLE var;
  204. int cbkey;
  205. char *s;
  206. char *p;
  207. assert(me && input && *input && output);
  208. *output = 0;
  209. for (i = 0, var = me->vars; i < me->cvars; i++, var++)
  210. {
  211. CopyStrArray(key, "${");
  212. CatStrArray(key, var->key);
  213. CatStrArray(key, "}");
  214. cbkey = strlen(var->key) + 3;
  215. for (s = input, p = strstr(s, key); p; s = p + cbkey, p = strstr(s, key))
  216. {
  217. CatNString(output, s, p - s, outsize);
  218. CatString(output, var->val, outsize);
  219. }
  220. }
  221. if (!*output)
  222. CopyString(output, input, outsize);
  223. return output;
  224. }
  225. #define translate(me, input, output) dotranslate(me, input, output, DIMA(output))
  226. PSDFILE
  227. find(
  228. PMODULE_ENTRY me,
  229. const char *file
  230. )
  231. {
  232. int i;
  233. PSDFILE sdf;
  234. for (i = 0, sdf = me->sdfiles; i < me->cfiles; i++, sdf++)
  235. {
  236. if (!_strcmpi(sdf->path, file))
  237. return sdf;
  238. }
  239. return NULL;
  240. }
  241. void
  242. DumpModuleEntries(
  243. PPROCESS_ENTRY pe
  244. )
  245. {
  246. static PLIST_ENTRY next = NULL;
  247. PMODULE_ENTRY me;
  248. PVARIABLE vars;
  249. PSDFILE sdfiles;
  250. char path[MAX_PATH + 1];
  251. char depot[MAX_PATH + 1];
  252. char loc[MAX_PATH + 1];
  253. next = pe->ModuleList.Flink;
  254. if (!next)
  255. return;
  256. while ((PVOID)next != (PVOID)&pe->ModuleList)
  257. {
  258. me = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
  259. dprint("%s 0x%x\n", me->name, me->base);
  260. dprint("variables:\n");
  261. for (vars = me->vars; vars->key; vars++)
  262. dprint("%s=%s\n", vars->key, vars->val);
  263. dprint("source depot files:\n");
  264. for (sdfiles = me->sdfiles; sdfiles->path; sdfiles++)
  265. {
  266. translate(me, sdfiles->path, path);
  267. translate(me, sdfiles->depot, depot);
  268. translate(me, sdfiles->loc, loc);
  269. dprint("%s %s %s\n", path, depot, loc);
  270. }
  271. eprint("\n");
  272. next = me->ListEntry.Flink;
  273. }
  274. }
  275. char *
  276. GetLine(
  277. char *sz
  278. )
  279. {
  280. for (;*sz; sz++)
  281. {
  282. if (*sz == '\n' || *sz == '\r')
  283. {
  284. *sz++ = 0;
  285. if (*sz == 10)
  286. sz++;
  287. return (*sz) ? sz : NULL;
  288. }
  289. }
  290. return NULL;
  291. }
  292. int
  293. SetBlock(
  294. char *sz
  295. )
  296. {
  297. static char *labels[blMax] =
  298. {
  299. "SRCSRV: end", // blNone
  300. "SRCSRV: variables", // blVars
  301. "SRCSRV: source files" // blSource
  302. };
  303. static int lens[blMax] =
  304. {
  305. sizeof("SRCSRV: end") / sizeof(char) -1 , // blNone
  306. sizeof("SRCSRV: variables") / sizeof(char) -1 , // blVars
  307. sizeof("SRCSRV: source files") / sizeof(char) -1 // blSource
  308. };
  309. int i;
  310. char *label;
  311. for (i = blNone; i < blMax; i++)
  312. {
  313. label = labels[i];
  314. if (!strncmp(sz, label, lens[i]))
  315. return i;
  316. }
  317. return blMax;
  318. }
  319. bool
  320. ParseVars(
  321. char *sz,
  322. PVARIABLE var
  323. )
  324. {
  325. char *p;
  326. p = (strchr(sz, '='));
  327. if (!p)
  328. return false;
  329. *p = 0;
  330. var->key = sz;
  331. var->val = p + 1;
  332. return true;
  333. }
  334. bool
  335. ParseSD(
  336. char *sz,
  337. PSDFILE sdfile
  338. )
  339. {
  340. char *p;
  341. char *g;
  342. sz += 4;
  343. p = (strchr(sz, '*'));
  344. if (!p)
  345. return false;
  346. *p++ = 0;
  347. g = (strchr(p, '*'));
  348. if (!g)
  349. return false;
  350. *g++ = 0;
  351. sdfile->path = sz;
  352. sdfile->depot = p;
  353. sdfile->loc = g;
  354. return true;
  355. }
  356. BOOL
  357. IndexStream(
  358. PMODULE_ENTRY me
  359. )
  360. {
  361. char *sz;
  362. char *next;
  363. int block;
  364. int lines;
  365. int bl;
  366. PVARIABLE vars;
  367. PSDFILE sdfiles;
  368. // count the lines
  369. for (sz = me->stream, lines = 0; *sz; sz++)
  370. {
  371. if (*sz == '\n')
  372. lines++;
  373. }
  374. if (!lines)
  375. return false;
  376. me->vars = (PVARIABLE)MemAlloc(lines * sizeof(VARIABLE));
  377. if (!me->vars)
  378. return error(ERROR_NOT_ENOUGH_MEMORY);
  379. me->sdfiles = (PSDFILE)MemAlloc(lines * sizeof(SDFILE));
  380. if (!me->sdfiles)
  381. return error(ERROR_NOT_ENOUGH_MEMORY);
  382. block = blNone;
  383. vars = me->vars;
  384. sdfiles = me->sdfiles;
  385. me->cfiles = 0;
  386. me->cvars = 0;
  387. for (sz = me->stream; sz; sz = next)
  388. {
  389. next = GetLine(sz);
  390. bl = SetBlock(sz);
  391. // dprint("%s\n", sz);
  392. if (bl != blMax)
  393. {
  394. block = bl;
  395. continue;
  396. }
  397. switch(block)
  398. {
  399. case blVars:
  400. if (ParseVars(sz, vars))
  401. {
  402. vars++;
  403. me->cvars++;
  404. }
  405. break;
  406. case blSource:
  407. if (ParseSD(sz, sdfiles))
  408. {
  409. sdfiles++;
  410. me->cfiles++;
  411. }
  412. break;
  413. }
  414. }
  415. #if 0
  416. DumpIndexes(me);
  417. #endif
  418. return true;
  419. }
  420. DWORD
  421. WINAPI
  422. SrcSrvSetOptions(
  423. DWORD opts
  424. )
  425. {
  426. DWORD rc = gOptions;
  427. gOptions = opts;
  428. return rc;
  429. }
  430. DWORD
  431. WINAPI
  432. SrcSrvGetOptions(
  433. )
  434. {
  435. return gOptions;
  436. }
  437. BOOL
  438. WINAPI
  439. SrcSrvInit(
  440. HANDLE hProcess,
  441. LPCSTR path
  442. )
  443. {
  444. PPROCESS_ENTRY pe;
  445. // test the path for copying files to...
  446. if (!path || !*path)
  447. return error(ERROR_INVALID_PARAMETER);
  448. if (!EnsurePathExists(path, NULL, 0, TRUE))
  449. return false;
  450. if (!gInitialized)
  451. {
  452. gInitialized = true;
  453. InitializeListHead(&gProcessList);
  454. }
  455. if (pe = FindProcessEntry(hProcess))
  456. {
  457. pe->cRefs++;
  458. return error(ERROR_INVALID_HANDLE);
  459. }
  460. pe = (PPROCESS_ENTRY)MemAlloc(sizeof(PROCESS_ENTRY));
  461. if (!pe)
  462. return error(ERROR_NOT_ENOUGH_MEMORY);
  463. pe->hProcess = hProcess;
  464. pe->cRefs = 1;
  465. CopyStrArray(pe->path, path);
  466. gProcessListCount++;
  467. InitializeListHead(&pe->ModuleList);
  468. InsertTailList(&gProcessList, &pe->ListEntry);
  469. return true;
  470. }
  471. BOOL
  472. WINAPI
  473. SrcSrvCleanup(
  474. HANDLE hProcess
  475. )
  476. {
  477. PPROCESS_ENTRY pe;
  478. PLIST_ENTRY next;
  479. PMODULE_ENTRY me;
  480. pe = FindProcessEntry(hProcess);
  481. if (!pe)
  482. return error(ERROR_INVALID_HANDLE);
  483. if (--pe->cRefs)
  484. return true;
  485. next = pe->ModuleList.Flink;
  486. if (next)
  487. {
  488. while (next != &pe->ModuleList)
  489. {
  490. me = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
  491. next = me->ListEntry.Flink;
  492. FreeModuleEntry(pe, me);
  493. }
  494. }
  495. RemoveEntryList(&pe->ListEntry);
  496. MemFree(pe);
  497. gProcessListCount--;
  498. return true;
  499. }
  500. BOOL
  501. WINAPI
  502. SrcSrvSetTargetPath(
  503. HANDLE hProcess,
  504. LPCSTR path
  505. )
  506. {
  507. PPROCESS_ENTRY pe;
  508. pe = FindProcessEntry(hProcess);
  509. if (!pe)
  510. return error(ERROR_INVALID_HANDLE);
  511. // test the path for copying files to...
  512. if (!path || !*path)
  513. return error(ERROR_INVALID_PARAMETER);
  514. if (!EnsurePathExists(path, NULL, 0, TRUE))
  515. return false;
  516. // store the new path
  517. CopyStrArray(pe->path, path);
  518. return true;
  519. }
  520. BOOL
  521. WINAPI
  522. SrcSrvLoadModule(
  523. HANDLE hProcess,
  524. LPCSTR name,
  525. DWORD64 base,
  526. PVOID stream,
  527. DWORD size
  528. )
  529. {
  530. PPROCESS_ENTRY pe;
  531. PMODULE_ENTRY me;
  532. if (!base || !name || !*name || !stream || !*(PCHAR)stream || !size)
  533. return error(ERROR_INVALID_PARAMETER);
  534. pe = FindProcessEntry(hProcess);
  535. if (!pe)
  536. return error(ERROR_INVALID_PARAMETER);
  537. me = FindModuleEntry(pe, base);
  538. if (me)
  539. SrcSrvUnloadModule(pe, base);
  540. me = (PMODULE_ENTRY)MemAlloc(sizeof(MODULE_ENTRY));
  541. if (!me)
  542. return error(ERROR_NOT_ENOUGH_MEMORY);
  543. me->base = base;
  544. CopyStrArray(me->name, name);
  545. me->stream = (char *)MemAlloc(size);
  546. if (!me->stream)
  547. {
  548. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  549. goto error;
  550. }
  551. memcpy(me->stream, stream, size);
  552. me->cbStream = size;
  553. dprint(me->stream);
  554. IndexStream(me);
  555. InsertTailList(&pe->ModuleList, &me->ListEntry);
  556. DumpModuleEntries(pe);
  557. return true;
  558. error:
  559. FreeModuleEntry(pe, me);
  560. return false;
  561. }
  562. BOOL
  563. WINAPI
  564. SrcSrvUnloadModule(
  565. HANDLE hProcess,
  566. DWORD64 base
  567. )
  568. {
  569. PPROCESS_ENTRY pe;
  570. PLIST_ENTRY next;
  571. PMODULE_ENTRY me;
  572. pe = FindProcessEntry(hProcess);
  573. if (!pe)
  574. return error(ERROR_INVALID_PARAMETER);
  575. next = pe->ModuleList.Flink;
  576. if (!next)
  577. return error(ERROR_MOD_NOT_FOUND);
  578. while (next != &pe->ModuleList)
  579. {
  580. me = CONTAINING_RECORD(next, MODULE_ENTRY, ListEntry);
  581. if (me->base == base)
  582. {
  583. RemoveEntryList(next);
  584. FreeModuleEntry(pe, me);
  585. return true;
  586. }
  587. next = me->ListEntry.Flink;
  588. }
  589. return error(ERROR_MOD_NOT_FOUND);
  590. }
  591. BOOL
  592. WINAPI
  593. SrcSrvRegisterCallback(
  594. HANDLE hProcess,
  595. PSRCSRVCALLBACKPROC callback,
  596. DWORD64 context
  597. )
  598. {
  599. PPROCESS_ENTRY pe;
  600. pe = FindProcessEntry(hProcess);
  601. if (!pe)
  602. return error(ERROR_INVALID_PARAMETER);
  603. pe->callback = callback;
  604. pe->context = context;
  605. return true;
  606. }
  607. BOOL
  608. WINAPI
  609. SrcSrvGetFile(
  610. HANDLE hProcess,
  611. DWORD64 base,
  612. LPCSTR filename,
  613. LPSTR target,
  614. DWORD trgsize
  615. )
  616. {
  617. PPROCESS_ENTRY pe;
  618. PMODULE_ENTRY me;
  619. PSDFILE sdf;
  620. char name[MAX_PATH + 1];
  621. char ext[MAX_PATH + 1];
  622. BOOL rc;
  623. char depot[MAX_PATH + 1];
  624. char loc[MAX_PATH + 1];
  625. char cmd[MAX_PATH * 2];
  626. STARTUPINFO si;
  627. PROCESS_INFORMATION pi;
  628. if (!base || !filename || !*filename || !target)
  629. return error(ERROR_INVALID_PARAMETER);
  630. *target = 0;
  631. pe = FindProcessEntry(hProcess);
  632. if (!pe)
  633. return error(ERROR_INVALID_HANDLE);
  634. me = FindModuleEntry(pe, base);
  635. if (!me)
  636. return error(ERROR_MOD_NOT_FOUND);
  637. // get the matching file entry
  638. sdf = find(me, filename);
  639. if (!sdf)
  640. return error(ERROR_FILE_NOT_FOUND);
  641. // build the target path and command line for source depot
  642. #if 0
  643. _splitpath(filename, NULL, NULL, name, ext);
  644. strcpy(target, pe->path); // SECURITY: Don't know size of target buffer.
  645. EnsureTrailingBackslash(target);
  646. strcat(target, name); // SECURITY: Don't know size of target buffer.
  647. strcat(target, ext); // SECURITY: Don't know size of target buffer.
  648. CreateTargetPath(pe, sdf, target);
  649. #else
  650. strcpy(target, pe->path); // SECURITY: Don't know size of target buffer.
  651. EnsureTrailingBackslash(target);
  652. _splitpath(filename, NULL, NULL, name, ext);
  653. strcat(target, name); // SECURITY: Don't know size of target buffer.
  654. if (*ext)
  655. strcat(target, ext); // SECURITY: Don't know size of target buffer.
  656. #endif
  657. PrintString(cmd,
  658. DIMA(cmd),
  659. "sd.exe -p %s print -o %s -q %s",
  660. translate(me, sdf->depot, depot),
  661. target,
  662. translate(me, sdf->loc, loc));
  663. // execute the source depot command
  664. ZeroMemory((void *)&si, sizeof(si));
  665. rc = CreateProcess(NULL,
  666. cmd,
  667. NULL,
  668. NULL,
  669. false,
  670. 0,
  671. NULL,
  672. pe->path,
  673. &si,
  674. &pi);
  675. if (!rc)
  676. *target = 0;
  677. return rc;
  678. }