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.

989 lines
21 KiB

  1. #include "pch.h"
  2. #include "store.hpp"
  3. #define CF_COMPRESSED 0x1
  4. #define TLS // __declspec( thread )
  5. #if defined(_WIN64) && defined(_M_IA64)
  6. #pragma section(".base", long, read, write)
  7. extern "C"
  8. __declspec(allocate(".base"))
  9. extern
  10. IMAGE_DOS_HEADER __ImageBase;
  11. #else
  12. extern "C"
  13. extern
  14. IMAGE_DOS_HEADER __ImageBase;
  15. #endif
  16. HINSTANCE ghSymSrv = (HINSTANCE)&__ImageBase;
  17. UINT_PTR goptions = SSRVOPT_DWORD;
  18. DWORD gptype = SSRVOPT_DWORD;
  19. PSYMBOLSERVERCALLBACKPROC gcallback = NULL;
  20. ULONG64 gcontext = 0;
  21. HWND ghwndParent = (HWND)0;
  22. char gproxy[MAX_PATH + 1] = "";
  23. int gdbgout = -1;
  24. char gdstore[MAX_PATH + 1] = "";
  25. void
  26. PrepOutputString(
  27. char *in,
  28. char *out,
  29. int len
  30. )
  31. {
  32. int i;
  33. *out = 0;
  34. for (i = 0; *in && i < len; i++, in++, out++) {
  35. if (*in == '\b')
  36. break;
  37. *out = *in;
  38. }
  39. *out = 0;
  40. }
  41. VOID
  42. OutputDbgString(
  43. char *sz
  44. )
  45. {
  46. char sztxt[3000];
  47. PrepOutputString(sz, sztxt, 3000);
  48. if (*sztxt)
  49. OutputDebugString(sztxt);
  50. }
  51. __inline
  52. BOOL
  53. DoCallback(
  54. DWORD action,
  55. ULONG64 data
  56. )
  57. {
  58. return gcallback(action, data, gcontext);
  59. }
  60. BOOL
  61. PostEvent(
  62. PIMAGEHLP_CBA_EVENT evt
  63. )
  64. {
  65. BOOL fdbgout = false;
  66. if (!*evt->desc)
  67. return true;
  68. // write to debug terminal, if called for
  69. if (gdbgout == 1) {
  70. fdbgout = true;
  71. OutputDbgString(evt->desc);
  72. }
  73. // don't pass info-level messages, unless told to
  74. if ((evt->severity <= sevInfo) && !(goptions & SSRVOPT_TRACE))
  75. return true;
  76. // If there is no callback function, send to the debug terminal.
  77. if (!gcallback) {
  78. if (!fdbgout)
  79. OutputDbgString(evt->desc);
  80. return true;
  81. }
  82. // Otherwise call the callback function.
  83. return DoCallback(SSRVACTION_EVENT, (ULONG64)evt);
  84. }
  85. BOOL
  86. WINAPIV
  87. evtprint(
  88. DWORD severity,
  89. DWORD code,
  90. PVOID object,
  91. LPSTR format,
  92. ...
  93. )
  94. {
  95. static char buf[1000] = "";
  96. IMAGEHLP_CBA_EVENT evt;
  97. va_list args;
  98. va_start(args, format);
  99. wvsprintf(buf, format, args);
  100. va_end(args);
  101. if (!*buf)
  102. return true;
  103. evt.severity = severity;
  104. evt.code = code;
  105. evt.desc = buf;
  106. evt.object = object;
  107. return PostEvent(&evt);
  108. }
  109. int
  110. _eprint(
  111. LPSTR format,
  112. ...
  113. )
  114. {
  115. static char buf[1000] = "";
  116. va_list args;
  117. if (!format || !*format)
  118. return 1;
  119. if (!(goptions & SSRVOPT_TRACE) && gdbgout != 1)
  120. return 1;
  121. va_start(args, format);
  122. wvsprintf(buf, format, args);
  123. va_end(args);
  124. if (!evtprint(sevInfo, 0, NULL, buf))
  125. if (gcallback)
  126. gcallback(SSRVACTION_TRACE, (ULONG64)buf, gcontext);
  127. return 1;
  128. }
  129. DBGEPRINT geprint = _eprint;
  130. int
  131. _dprint(
  132. LPSTR format,
  133. ...
  134. )
  135. {
  136. static char buf[1000] = "SYMSRV: ";
  137. va_list args;
  138. if (!format || !*format)
  139. return 1;
  140. if (!(goptions & SSRVOPT_TRACE) && gdbgout != 1)
  141. return 1;
  142. va_start(args, format);
  143. wvsprintf(buf + 9, format, args);
  144. va_end(args);
  145. return _eprint(buf);
  146. }
  147. DBGPRINT gdprint = NULL; // _dprint;
  148. // this one is for calling from dload.cpp
  149. int
  150. __dprint(
  151. LPSTR sz
  152. )
  153. {
  154. static char buf[1000] = "SYMSRV: ";
  155. va_list args;
  156. if (!sz || !*sz)
  157. return 1;
  158. CopyStrArray(buf, "SYMSRV: ");
  159. CatStrArray(buf, sz);
  160. if (gcallback)
  161. gcallback(SSRVACTION_TRACE, (ULONG64)buf, gcontext);
  162. if (!gcallback || (gdbgout == 1))
  163. OutputDbgString(buf);
  164. return 1;
  165. }
  166. int
  167. _querycancel(
  168. )
  169. {
  170. BOOL rc;
  171. BOOL cancel = false;
  172. if (!gcallback)
  173. return false;
  174. rc = gcallback(SSRVACTION_QUERYCANCEL, (ULONG64)&cancel, gcontext);
  175. if (rc && cancel)
  176. return true;
  177. return false;
  178. }
  179. QUERYCANCEL gquerycancel = _querycancel;
  180. BOOL
  181. SetError(
  182. DWORD err
  183. )
  184. {
  185. SetLastError(err);
  186. return 0;
  187. }
  188. BOOL
  189. copy(
  190. IN PCSTR trgsite,
  191. IN PCSTR srcsite,
  192. IN PCSTR rpath,
  193. IN PCSTR file,
  194. OUT PSTR trg, // must be at least MAX_PATH elements
  195. IN DWORD flags
  196. )
  197. {
  198. BOOL rc;
  199. DWORD type = stUNC;
  200. CHAR epath[MAX_PATH + 1];
  201. CHAR srcbuf[MAX_PATH + 1];
  202. CHAR tsite[MAX_PATH + 1];
  203. CHAR ssite[MAX_PATH + 1];
  204. PSTR src;
  205. Store *store;
  206. DWORD ec;
  207. assert(trgsite && srcsite);
  208. // use the default downstream store, if specified
  209. CopyStrArray(tsite, (*trgsite) ? trgsite : gdstore);
  210. CopyStrArray(ssite, srcsite);
  211. // get the store type of the target store
  212. type = GetStoreType(tsite);
  213. switch (type) {
  214. case stUNC:
  215. break;
  216. case stHTTP:
  217. case stHTTPS:
  218. // Can't use http for the target.
  219. // If a source is specifed, then bail.
  220. if (*ssite)
  221. return SetError(ERROR_INVALID_PARAMETER);
  222. // Otherwise, just use the default downstream store for a target.
  223. CopyStrArray(ssite, tsite);
  224. CopyStrArray(tsite, gdstore);
  225. break;
  226. case stError:
  227. return SetError(ERROR_INVALID_PARAMETER);
  228. default:
  229. return SetError(ERROR_INVALID_NAME); }
  230. // MAYBE PUT A CHECK IN HERE FOR A CAB. LIKE IF THE DIRECTORY IS
  231. // ACTUALLY A COMPRESSED FILE AND RETURN stCAB.
  232. // generate full target path
  233. pathcpy(trg, tsite, rpath, MAX_PATH);
  234. pathcat(trg, file, MAX_PATH);
  235. // if file exists, return it
  236. ec = FileStatus(trg);
  237. if (!ec) {
  238. return true;
  239. } else if (ec == ERROR_NOT_READY) {
  240. dprint("%s - drive not ready\n", trg);
  241. return false;
  242. }
  243. if (ReadFilePtr(trg, MAX_PATH)) {
  244. ec = FileStatus(trg);
  245. if (ec == NO_ERROR)
  246. return true;
  247. dprint("%s - %s\n", trg, FormatStatus(ec));
  248. return false;
  249. }
  250. if (!*ssite) {
  251. ec = FileStatus(CompressedFileName(trg));
  252. if (ec != NO_ERROR) {
  253. // if there is no source to copy from, then error
  254. dprint("%s - file not found\n", trg);
  255. return SetError(ERROR_FILE_NOT_FOUND);
  256. }
  257. // There is a compressed file..
  258. // Expand it to the default store.
  259. CopyStrArray(ssite, tsite);
  260. CopyStrArray(tsite, gdstore);
  261. pathcpy(trg, tsite, rpath, MAX_PATH);
  262. pathcat(trg, file, MAX_PATH);
  263. ec = FileStatus(trg);
  264. if (ec == NO_ERROR)
  265. return true;
  266. }
  267. if (goptions & SSRVOPT_SECURE) {
  268. dprint("%s - file copy not allowed in secure mode\n", trg);
  269. return SetError(ERROR_ACCESS_DENIED);
  270. }
  271. if (!EnsurePathExists(trg, epath, DIMA(epath))) {
  272. dprint("%s - couldn't create target path\n", trg);
  273. return SetError(ERROR_PATH_NOT_FOUND);
  274. }
  275. store = GetStore(ssite);
  276. if (!store)
  277. return false;
  278. rc = store->init();
  279. if (!rc)
  280. return false;
  281. rc = store->copy(rpath, file, tsite);
  282. // test the results and set the return value
  283. if (rc && !FileStatus(trg))
  284. return true;
  285. UndoPath(trg, epath);
  286. return false;
  287. }
  288. BOOL
  289. ping(
  290. IN PCSTR trgsite,
  291. IN PCSTR srcsite,
  292. IN PCSTR rpath,
  293. IN PCSTR file,
  294. OUT PSTR trg,
  295. IN DWORD flags
  296. )
  297. {
  298. BOOL rc;
  299. DWORD type = stUNC;
  300. CHAR epath[_MAX_PATH];
  301. CHAR srcbuf[_MAX_PATH];
  302. PSTR src;
  303. Store *store;
  304. DWORD ec;
  305. store = GetStore(srcsite);
  306. if (!store)
  307. return false;
  308. rc = store->init();
  309. if (!rc)
  310. return false;
  311. rc = store->ping();
  312. return rc;
  313. }
  314. void
  315. CatStrDWORD(
  316. IN OUT PSTR sz,
  317. IN DWORD value,
  318. IN DWORD size
  319. )
  320. {
  321. CHAR buf[MAX_PATH + 256];
  322. assert(sz);
  323. if (!value)
  324. return;
  325. wsprintf(buf, "%s%x", sz, value); // SECURITY: This will take a 256 digit DWORD.
  326. CopyString(sz, buf, size);
  327. }
  328. void
  329. CatStrGUID(
  330. IN OUT PSTR sz,
  331. IN GUID *guid,
  332. IN DWORD size
  333. )
  334. {
  335. CHAR buf[MAX_PATH + 256];
  336. BYTE byte;
  337. int i;
  338. assert(sz);
  339. if (!guid)
  340. return;
  341. // append the first DWORD in the pointer
  342. wsprintf(buf, "%08X", guid->Data1);
  343. CatString(sz, buf, size);
  344. // this will catch the passing of a PDWORD and avoid
  345. // all the GUID parsing
  346. if (!guid->Data2 && !guid->Data3) {
  347. for (i = 0, byte = 0; i < 8; i++) {
  348. byte |= guid->Data4[i];
  349. if (byte)
  350. break;
  351. }
  352. if (!byte)
  353. return;
  354. }
  355. // go ahead and add the rest of the GUID
  356. wsprintf(buf, "%04X", guid->Data2);
  357. CatString(sz, buf, size);
  358. wsprintf(buf, "%04X", guid->Data3);
  359. CatString(sz, buf, size);
  360. wsprintf(buf, "%02X", guid->Data4[0]);
  361. CatString(sz, buf, size);
  362. wsprintf(buf, "%02X", guid->Data4[1]);
  363. CatString(sz, buf, size);
  364. wsprintf(buf, "%02X", guid->Data4[2]);
  365. CatString(sz, buf, size);
  366. wsprintf(buf, "%02X", guid->Data4[3]);
  367. CatString(sz, buf, size);
  368. wsprintf(buf, "%02X", guid->Data4[4]);
  369. CatString(sz, buf, size);
  370. wsprintf(buf, "%02X", guid->Data4[5]);
  371. CatString(sz, buf, size);
  372. wsprintf(buf, "%02X", guid->Data4[6]);
  373. CatString(sz, buf, size);
  374. wsprintf(buf, "%02X", guid->Data4[7]);
  375. CatString(sz, buf, size);
  376. }
  377. void
  378. CatStrOldGUID(
  379. IN OUT PSTR sz,
  380. IN GUID *guid,
  381. IN DWORD size
  382. )
  383. {
  384. CHAR buf[MAX_PATH + 256];
  385. BYTE byte;
  386. int i;
  387. assert(sz);
  388. if (!guid)
  389. return;
  390. // append the first DWORD in the pointer
  391. wsprintf(buf, "%8x", guid->Data1);
  392. CatString(sz, buf, size);
  393. // this will catch the passing of a PDWORD and avoid
  394. // all the GUID parsing
  395. if (!guid->Data2 && !guid->Data3) {
  396. for (i = 0, byte = 0; i < 8; i++) {
  397. byte |= guid->Data4[i];
  398. if (byte)
  399. break;
  400. }
  401. if (!byte)
  402. return;
  403. }
  404. // go ahead and add the rest of the GUID
  405. wsprintf(buf, "%4x", guid->Data2);
  406. CatString(sz, buf, size);
  407. wsprintf(buf, "%4x", guid->Data3);
  408. CatString(sz, buf, size);
  409. wsprintf(buf, "%2x", guid->Data4[0]);
  410. CatString(sz, buf, size);
  411. wsprintf(buf, "%2x", guid->Data4[1]);
  412. CatString(sz, buf, size);
  413. wsprintf(buf, "%2x", guid->Data4[2]);
  414. CatString(sz, buf, size);
  415. wsprintf(buf, "%2x", guid->Data4[3]);
  416. CatString(sz, buf, size);
  417. wsprintf(buf, "%2x", guid->Data4[4]);
  418. CatString(sz, buf, size);
  419. wsprintf(buf, "%2x", guid->Data4[5]);
  420. CatString(sz, buf, size);
  421. wsprintf(buf, "%2x", guid->Data4[6]);
  422. CatString(sz, buf, size);
  423. wsprintf(buf, "%2x", guid->Data4[7]);
  424. CatString(sz, buf, size);
  425. }
  426. void
  427. CatStrID(
  428. IN OUT PSTR sz,
  429. PVOID id,
  430. DWORD paramtype,
  431. DWORD size
  432. )
  433. {
  434. switch (paramtype)
  435. {
  436. case SSRVOPT_DWORD:
  437. CatStrDWORD(sz, PtrToUlong(id), size);
  438. break;
  439. case SSRVOPT_DWORDPTR:
  440. CatStrDWORD(sz, *(DWORD *)id, size);
  441. break;
  442. case SSRVOPT_GUIDPTR:
  443. CatStrGUID(sz, (GUID *)id, size);
  444. break;
  445. case SSRVOPT_OLDGUIDPTR:
  446. CatStrOldGUID(sz, (GUID *)id, size);
  447. break;
  448. default:
  449. break;
  450. }
  451. }
  452. // for Barb and Greg only. I'm going to get rid of these...
  453. void
  454. AppendHexStringWithDWORD(
  455. IN OUT PSTR sz,
  456. IN DWORD value
  457. )
  458. {
  459. return CatStrDWORD(sz, value, MAX_PATH);
  460. }
  461. void
  462. AppendHexStringWithGUID(
  463. IN OUT PSTR sz,
  464. IN GUID *guid
  465. )
  466. {
  467. return CatStrGUID(sz, guid, MAX_PATH);
  468. }
  469. void
  470. AppendHexStringWithOldGUID(
  471. IN OUT PSTR sz,
  472. IN GUID *guid
  473. )
  474. {
  475. return CatStrOldGUID(sz, guid, MAX_PATH);
  476. }
  477. void
  478. AppendHexStringWithID(
  479. IN OUT PSTR sz,
  480. PVOID id,
  481. DWORD paramtype
  482. )
  483. {
  484. return CatStrID(sz, id, paramtype, MAX_PATH);
  485. }
  486. /*
  487. * Given a string, find the next '*' and zero it
  488. * out to convert the current token into it's
  489. * own string. Return the address of the next character,
  490. * if there are any more strings to parse.
  491. */
  492. PSTR
  493. ExtractToken(
  494. PSTR in,
  495. PSTR out,
  496. size_t size
  497. )
  498. {
  499. PSTR p = in;
  500. *out = 0;
  501. if (!in || !*in)
  502. return NULL;
  503. for (;*p; p++) {
  504. if (*p == '*') {
  505. *p = 0;
  506. p++;
  507. break;
  508. }
  509. }
  510. CopyString(out, in, size);
  511. return (*p) ? p : NULL;
  512. }
  513. BOOL
  514. BuildRelativePath(
  515. OUT LPSTR rpath,
  516. IN LPCSTR filename,
  517. IN PVOID id, // first number in directory name
  518. IN DWORD val2, // second number in directory name
  519. IN DWORD val3, // third number in directory name
  520. IN DWORD size
  521. )
  522. {
  523. LPSTR p;
  524. assert(rpath);
  525. CopyString(rpath, filename, size);
  526. EnsureTrailingBackslash(rpath);
  527. CatStrID(rpath, id, gptype, size);
  528. CatStrDWORD(rpath, val2, size);
  529. CatStrDWORD(rpath, val3, size);
  530. for (p = rpath + strlen(rpath) - 1; p > rpath; p--) {
  531. if (*p == '\\') {
  532. dprint("Insufficient information querying for %s\n", filename);
  533. SetLastError(ERROR_MORE_DATA);
  534. return false;
  535. }
  536. if (*p != '0')
  537. return true;
  538. }
  539. return true;
  540. }
  541. BOOL
  542. SymbolServerClose()
  543. {
  544. return true;
  545. }
  546. BOOL
  547. TestParameters(
  548. IN PCSTR params, // server and cache path
  549. IN PCSTR filename, // name of file to search for
  550. IN PVOID id, // first number in directory name
  551. IN DWORD val2, // second number in directory name
  552. IN DWORD val3, // third number in directory name
  553. OUT PSTR path // return validated file path here
  554. )
  555. {
  556. __try {
  557. if (path)
  558. *path = 0;
  559. } __except(EXCEPTION_EXECUTE_HANDLER) {
  560. return SetError(ERROR_INVALID_PARAMETER);
  561. }
  562. if (!path || !params || !*params || !filename || !*filename || (!id && !val2 && !val3))
  563. return SetError(ERROR_INVALID_PARAMETER);
  564. if (strlen(filename) > 100) {
  565. dprint("%s - filename cannot exceed 100 characters\n", filename);
  566. return SetError(ERROR_INVALID_PARAMETER);
  567. }
  568. switch (gptype)
  569. {
  570. case SSRVOPT_GUIDPTR:
  571. case SSRVOPT_OLDGUIDPTR:
  572. // this test should AV if a valid GUID pointer wasn't passed in
  573. __try {
  574. GUID *guid = (GUID *)id;
  575. BYTE b;
  576. b = guid->Data4[8];
  577. } __except(EXCEPTION_EXECUTE_HANDLER) {
  578. return SetError(ERROR_INVALID_PARAMETER);
  579. }
  580. break;
  581. case SSRVOPT_DWORDPTR:
  582. // this test should AV if a valid DWORD pointer wasn't passed in
  583. __try {
  584. DWORD dword = *(DWORD *)id;
  585. } __except(EXCEPTION_EXECUTE_HANDLER) {
  586. return SetError(ERROR_INVALID_PARAMETER);
  587. }
  588. break;
  589. }
  590. return true;
  591. }
  592. BOOL
  593. SymbolServer(
  594. IN PCSTR params, // server and cache path
  595. IN PCSTR filename, // name of file to search for
  596. IN PVOID id, // first number in directory name
  597. IN DWORD val2, // second number in directory name
  598. IN DWORD val3, // third number in directory name
  599. OUT PSTR path // return validated file path here
  600. )
  601. {
  602. CHAR *p;
  603. CHAR tdir[MAX_PATH + 1] = "";
  604. CHAR sdir[MAX_PATH + 1] = "";
  605. CHAR sz[MAX_PATH * 2 + 3];
  606. CHAR rpath[MAX_PATH + 1];
  607. BOOL rc;
  608. if (!TestParameters(params, filename, id, val2, val3, path))
  609. return false;
  610. // test environment
  611. if (gdbgout == -1) {
  612. if (GetEnvironmentVariable("SYMSRV_DBGOUT", sz, MAX_PATH))
  613. gdbgout = 1;
  614. else
  615. gdbgout = 0;
  616. *sz = 0;
  617. }
  618. // parse parameters
  619. CopyStrArray(sz, params);
  620. p = ExtractToken(sz, tdir, DIMA(tdir)); // 1st path is where the symbol should be
  621. p = ExtractToken(p, sdir, DIMA(sdir)); // 2nd optional path is the server to copy from
  622. // build the relative path to the target symbol file
  623. if (!BuildRelativePath(rpath, filename, id, val2, val3, DIMA(rpath)))
  624. return false;
  625. // if no_copy option is set, just return the path to the target
  626. if (goptions & SSRVOPT_NOCOPY) {
  627. pathcpy(path, tdir, rpath, MAX_PATH);
  628. pathcat(path, filename, MAX_PATH);
  629. return true;
  630. }
  631. // copy from server to specified symbol path
  632. rc = copy(tdir, sdir, rpath, filename, path, 0);
  633. if (!rc)
  634. *path = 0;
  635. return rc;
  636. }
  637. BOOL
  638. SymbolServerSetOptions(
  639. UINT_PTR options,
  640. ULONG64 data
  641. )
  642. {
  643. DWORD ptype;
  644. // set the callback function
  645. if (options & SSRVOPT_CALLBACK) {
  646. if (data) {
  647. goptions |= SSRVOPT_CALLBACK;
  648. gcallback = (PSYMBOLSERVERCALLBACKPROC)data;
  649. } else {
  650. goptions &= ~SSRVOPT_CALLBACK;
  651. gcallback = NULL;
  652. }
  653. }
  654. // set the callback context
  655. if (options & SSRVOPT_SETCONTEXT)
  656. gcontext = data;
  657. // when this flags is set, trace output will be delivered
  658. if (options & SSRVOPT_TRACE) {
  659. if (data) {
  660. goptions |= SSRVOPT_TRACE;
  661. setdprint(_dprint);
  662. } else {
  663. goptions &= ~SSRVOPT_TRACE;
  664. setdprint(NULL);
  665. }
  666. }
  667. // set the parameter type for the first ID parameter
  668. if (options & SSRVOPT_PARAMTYPE) {
  669. switch(data) {
  670. case SSRVOPT_DWORD:
  671. case SSRVOPT_DWORDPTR:
  672. case SSRVOPT_GUIDPTR:
  673. case SSRVOPT_OLDGUIDPTR:
  674. goptions &= ~(SSRVOPT_DWORD | SSRVOPT_DWORDPTR | SSRVOPT_GUIDPTR | SSRVOPT_OLDGUIDPTR);
  675. goptions |= data;
  676. gptype = (DWORD)data;
  677. break;
  678. default:
  679. SetLastError(ERROR_INVALID_PARAMETER);
  680. return false;
  681. }
  682. }
  683. // set the parameter type for the first ID paramter - OLD SYNTAX
  684. // the if statements provide and order of precedence
  685. ptype = 0;
  686. if (options & SSRVOPT_DWORD)
  687. ptype = SSRVOPT_DWORD;
  688. if (options & SSRVOPT_DWORDPTR)
  689. ptype = SSRVOPT_DWORDPTR;
  690. if (options & SSRVOPT_GUIDPTR)
  691. ptype = SSRVOPT_GUIDPTR;
  692. if (options & SSRVOPT_OLDGUIDPTR)
  693. ptype = SSRVOPT_OLDGUIDPTR;
  694. if (ptype) {
  695. goptions &= ~(SSRVOPT_DWORD | SSRVOPT_DWORDPTR | SSRVOPT_GUIDPTR | SSRVOPT_OLDGUIDPTR);
  696. if (data) {
  697. goptions |= ptype;
  698. gptype = ptype;
  699. } else if (gptype == ptype) {
  700. // when turning off a type, reset it to DWORD
  701. goptions |= SSRVOPT_DWORD;
  702. gptype = SSRVOPT_DWORD;
  703. }
  704. }
  705. // if this flag is set, no GUI will be displayed
  706. if (options & SSRVOPT_UNATTENDED) {
  707. if (data)
  708. goptions |= SSRVOPT_UNATTENDED;
  709. else
  710. goptions &= ~SSRVOPT_UNATTENDED;
  711. }
  712. // when this is set, the existence of the returned file path is not checked
  713. if (options & SSRVOPT_NOCOPY) {
  714. if (data)
  715. goptions |= SSRVOPT_NOCOPY;
  716. else
  717. goptions &= ~SSRVOPT_NOCOPY;
  718. }
  719. // this window handle is used as a parent for dialog boxes
  720. if (options & SSRVOPT_PARENTWIN) {
  721. SetParentWindow((HWND)data);
  722. if (data)
  723. goptions |= SSRVOPT_PARENTWIN;
  724. else
  725. goptions &= ~SSRVOPT_PARENTWIN;
  726. }
  727. // when running in secure mode, we don't copy files to downstream stores
  728. if (options & SSRVOPT_SECURE) {
  729. if (data)
  730. goptions |= SSRVOPT_SECURE;
  731. else
  732. goptions &= ~SSRVOPT_SECURE;
  733. }
  734. // set http proxy
  735. if (options & SSRVOPT_PROXY) {
  736. if (data) {
  737. goptions |= SSRVOPT_PROXY;
  738. CopyStrArray(gproxy, (char *)data);
  739. setproxy(gproxy);
  740. } else {
  741. goptions &= ~SSRVOPT_PROXY;
  742. *gproxy = 0;
  743. setproxy(NULL);
  744. }
  745. }
  746. // set default downstream store
  747. if (options & SSRVOPT_DOWNSTREAM_STORE) {
  748. if (data) {
  749. goptions |= SSRVOPT_DOWNSTREAM_STORE;
  750. CopyStrArray(gdstore, (char *)data);
  751. setdstore(gdstore);
  752. } else {
  753. goptions &= ~SSRVOPT_DOWNSTREAM_STORE;
  754. *gdstore = 0;
  755. setdstore(NULL);
  756. }
  757. }
  758. SetStoreOptions(goptions);
  759. return true;
  760. }
  761. UINT_PTR
  762. SymbolServerGetOptions(
  763. )
  764. {
  765. return goptions;
  766. }
  767. BOOL
  768. SymbolServerPing(
  769. IN PCSTR params // server and cache path
  770. )
  771. {
  772. CHAR *p;
  773. CHAR sz[MAX_PATH * 2 + 3];
  774. CHAR tdir[MAX_PATH + 1] = "";
  775. CHAR sdir[MAX_PATH + 1] = "";
  776. CHAR rpath[MAX_PATH + 1];
  777. CHAR filename[MAX_PATH + 1];
  778. CHAR path[MAX_PATH + 1];
  779. if (!params || !*params)
  780. return SetError(ERROR_INVALID_PARAMETER);
  781. // parse parameters
  782. // parse parameters
  783. CopyStrArray(sz, params);
  784. p = ExtractToken(sz, tdir, DIMA(tdir)); // 1st path is where the symbol should be
  785. p = ExtractToken(p, sdir, DIMA(sdir)); // 2nd optional path is the server to copy from
  786. // copy from server to specified symbol path
  787. return ping(tdir, sdir, rpath, filename, path, 0);
  788. return true;
  789. }