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.

1137 lines
23 KiB

  1. /*
  2. * store.cpp
  3. */
  4. #define STORE_DOT_CPP
  5. #include "pch.h"
  6. #include "store.hpp"
  7. #define MAX_STORES 50
  8. #define CHUNK_SIZE 4096L
  9. static SRVTYPEINFO gtypeinfo[stError] =
  10. {
  11. {"http://", 0, 7}, // inetCopy, 7},
  12. {"https://", 0, 8}, // inetCopy, 8},
  13. {"", 0, 0} // fileCopy, 0}
  14. };
  15. static HINTERNET ghint = INVALID_HANDLE_VALUE;
  16. static HWND ghwnd = 0;
  17. static UINT_PTR gopts;
  18. static char *gproxy = NULL;
  19. static char *gdstore = NULL;
  20. static BOOL gcancel = false;
  21. void disperror(
  22. DWORD err,
  23. char *file
  24. )
  25. {
  26. if (!err || err == ERROR_REQUEST_ABORTED)
  27. return;
  28. if (err == ERROR_FILE_NOT_FOUND)
  29. dprint("%s - file not found\n", file);
  30. else
  31. dprint("%s\n %s\n", file, FormatStatus(err));
  32. }
  33. void
  34. dumpproxyinfo(
  35. VOID
  36. )
  37. {
  38. HINTERNET hint;
  39. INTERNET_PROXY_INFO *pi;
  40. DWORD size;
  41. BOOL rc;
  42. DWORD err;
  43. hint = (gproxy) ? ghint : NULL;
  44. size = 0;
  45. rc = InternetQueryOption(hint, INTERNET_OPTION_PROXY, NULL, &size);
  46. if (rc) {
  47. SetLastError(ERROR_INVALID_DATA);
  48. return;
  49. }
  50. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  51. return;
  52. pi = (INTERNET_PROXY_INFO *)LocalAlloc(LPTR, size);
  53. if (!pi)
  54. return;
  55. ZeroMemory(pi, size);
  56. rc = InternetQueryOption(hint, INTERNET_OPTION_PROXY, pi, &size);
  57. if (rc && pi->lpszProxy && *pi->lpszProxy)
  58. dprint("Using proxy server: %s\n", pi->lpszProxy);
  59. if (pi)
  60. LocalFree(pi);
  61. }
  62. DWORD
  63. fixerror(
  64. DWORD err
  65. )
  66. {
  67. if (err == ERROR_PATH_NOT_FOUND)
  68. return ERROR_FILE_NOT_FOUND;
  69. return err;
  70. }
  71. void
  72. setdprint(
  73. DBGPRINT fndprint
  74. )
  75. {
  76. gdprint = fndprint;
  77. }
  78. void
  79. setproxy(
  80. char *proxy
  81. )
  82. {
  83. gproxy = proxy;
  84. }
  85. void
  86. setdstore(
  87. char *dstore
  88. )
  89. {
  90. gdstore = dstore;
  91. }
  92. void
  93. SetParentWindow(
  94. HWND hwnd
  95. )
  96. {
  97. ghwnd = hwnd;
  98. }
  99. void
  100. SetStoreOptions(
  101. UINT_PTR opts
  102. )
  103. {
  104. gopts = opts;
  105. }
  106. DWORD
  107. GetStoreType(
  108. LPCSTR sz
  109. )
  110. {
  111. DWORD i;
  112. for (i = 0; i < stError; i++) {
  113. if (!_strnicmp(sz, gtypeinfo[i].tag, gtypeinfo[i].taglen)) {
  114. return i;
  115. }
  116. }
  117. return stError;
  118. }
  119. BOOL
  120. ParsePath(
  121. IN LPCSTR ipath,
  122. OUT LPSTR site,
  123. OUT LPSTR path,
  124. OUT LPSTR file,
  125. IN BOOL striptype
  126. )
  127. {
  128. char sz[_MAX_PATH + 1];
  129. char *c;
  130. char *p;
  131. DWORD type;
  132. assert(ipath && site && path);
  133. *site = 0;
  134. *path = 0;
  135. if (file)
  136. *file = 0;
  137. if (!CopyString(sz, ipath, _MAX_PATH))
  138. return false;
  139. ConvertBackslashes(sz);
  140. // get start of site string
  141. type = GetStoreType(sz);
  142. p = sz + gtypeinfo[type].taglen;
  143. // there has to be at least a site
  144. c = strchr(p, '/');
  145. if (!c) {
  146. strcpy(site, p); // SECURITy: ParsePath is a safe function.
  147. return true;
  148. }
  149. // copy site name
  150. *c = 0;
  151. strcpy(site, (striptype) ? p : sz); // SECURITy: ParsePath is a safe function.
  152. p = c + 1;
  153. // if no file parameter, include the file in the path parameter
  154. if (!file) {
  155. strcpy(path, p); // SECURITy: ParsePath is a safe function.
  156. return true;
  157. }
  158. // look for path in the middle
  159. for (c = p + strlen(p); p < c; c--) {
  160. if (*c == '/') {
  161. *c = 0;
  162. strcpy(path, p); // SECURITy: ParsePath is a safe function.
  163. p = c + 1;
  164. break;
  165. }
  166. }
  167. strcpy(file, p); // SECURITy: ParsePath is a safe function.
  168. return true;
  169. }
  170. static char
  171. ChangeLastChar(
  172. LPSTR sz,
  173. char newchar
  174. )
  175. {
  176. char c;
  177. DWORD len;
  178. len = strlen(sz) - 1;
  179. c = sz[len];
  180. sz[len] = newchar;
  181. return c;
  182. }
  183. static BOOL
  184. ReplaceFileName(
  185. LPSTR path,
  186. LPCSTR file,
  187. DWORD size
  188. )
  189. {
  190. char *p;
  191. assert(path && *path && file && *file);
  192. for (p = path + strlen(path) - 1; *p; p--) {
  193. if (*p == '\\' || *p == '/') {
  194. CopyString(++p, file, size - (ULONG)(ULONG_PTR)(p - path));
  195. return true;
  196. }
  197. }
  198. return false;
  199. }
  200. DWORD CALLBACK cbCopyProgress(
  201. LARGE_INTEGER TotalFileSize, // file size
  202. LARGE_INTEGER TotalBytesTransferred, // bytes transferred
  203. LARGE_INTEGER StreamSize, // bytes in stream
  204. LARGE_INTEGER StreamBytesTransferred, // bytes transferred for stream
  205. DWORD dwStreamNumber, // current stream
  206. DWORD dwCallbackReason, // callback reason
  207. HANDLE hSourceFile, // handle to source file
  208. HANDLE hDestinationFile, // handle to destination file
  209. LPVOID lpData // from CopyFileEx
  210. )
  211. {
  212. Store *store = (Store *)lpData;
  213. store->setsize(TotalFileSize.QuadPart);
  214. store->setbytes(TotalBytesTransferred.QuadPart);
  215. store->progress();
  216. if (querycancel()) {
  217. store->setbytes((LONGLONG)-1);
  218. store->progress();
  219. return PROGRESS_CANCEL;
  220. }
  221. return PROGRESS_CONTINUE;
  222. }
  223. BOOL
  224. ReadFilePtr(
  225. LPSTR path,
  226. DWORD size
  227. )
  228. {
  229. BOOL rc;
  230. HANDLE hptr;
  231. DWORD fsize;
  232. DWORD cb;
  233. LPSTR p;
  234. char ptrfile[MAX_PATH + 1];
  235. char file[MAX_PATH + 1];
  236. assert(path && *path);
  237. rc = false;
  238. // check for existance of file pointer
  239. if (!CopyString(ptrfile, path, _MAX_PATH))
  240. return false;
  241. if (!ReplaceFileName(ptrfile, "file.ptr", DIMA(ptrfile)))
  242. return false;
  243. if (FileStatus(ptrfile))
  244. return false;
  245. hptr = CreateFile(ptrfile,
  246. GENERIC_READ,
  247. FILE_SHARE_READ,
  248. NULL,
  249. OPEN_EXISTING,
  250. FILE_ATTRIBUTE_NORMAL,
  251. NULL);
  252. if (hptr == INVALID_HANDLE_VALUE)
  253. return false;
  254. // test validity of file pointer
  255. fsize = GetFileSize(hptr, NULL);
  256. if (!fsize || fsize > MAX_PATH)
  257. goto cleanup;
  258. // read it
  259. ZeroMemory(file, _MAX_PATH * sizeof(path[0]));
  260. if (!ReadFile(hptr, file, fsize, &cb, 0))
  261. goto cleanup;
  262. if (cb != fsize)
  263. goto cleanup;
  264. rc = true;
  265. // trim string down to the CR
  266. for (p = file; *p; p++) {
  267. if (*p == 10 || *p == 13)
  268. {
  269. *p = 0;
  270. break;
  271. }
  272. }
  273. CopyString(path, file, size);
  274. dprint("%s\n", ptrfile);
  275. cleanup:
  276. // done
  277. if (hptr)
  278. CloseHandle(hptr);
  279. return rc;
  280. }
  281. #ifdef USE_INERROR
  282. DWORD inerror(DWORD error)
  283. {
  284. char *detail = NULL;
  285. DWORD iErr;
  286. DWORD len = 0;
  287. static char message[256]="";
  288. if (error == ERROR_SUCCESS)
  289. return error;
  290. FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
  291. GetModuleHandle("wininet.dll"),
  292. error,
  293. 0,
  294. message,
  295. 256,
  296. NULL);
  297. EnsureTrailingCR(message);
  298. dprint("Internet error code: %d\n Message: %s\n", error, message);
  299. if (error != ERROR_INTERNET_EXTENDED_ERROR)
  300. return error;
  301. InternetGetLastResponseInfo(&iErr, NULL, &len);
  302. if (!len)
  303. return error;
  304. detail = (char *)LocalAlloc(LPTR, len + 1000);
  305. if (!detail)
  306. return error;
  307. if (!InternetGetLastResponseInfo(&iErr, (LPTSTR)detail, &len))
  308. return error;
  309. dprint(detail);
  310. LocalFree(detail);
  311. return error;
  312. }
  313. #endif
  314. Store *gstores[MAX_STORES];
  315. DWORD gcstores = 0;
  316. Store *
  317. FindStore(
  318. PCSTR name
  319. )
  320. {
  321. DWORD i;
  322. for (i = 0; i < gcstores; i++) {
  323. if (gstores[i] && !strcmp((gstores[i])->name(), name))
  324. return gstores[i];
  325. }
  326. return NULL;
  327. }
  328. Store *
  329. AddStore(
  330. PCSTR name
  331. )
  332. {
  333. DWORD type;
  334. Store *store;
  335. type = GetStoreType(name);
  336. switch (type) {
  337. case stUNC:
  338. store = new StoreUNC();
  339. break;
  340. case stHTTP:
  341. case stHTTPS:
  342. store = new StoreHTTP();
  343. break;
  344. case stError:
  345. default:
  346. SetLastError(ERROR_INVALID_PARAMETER);
  347. return NULL;
  348. }
  349. if (!store) {
  350. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  351. return NULL;
  352. }
  353. store->assign(name);
  354. if (gcstores >= MAX_STORES) {
  355. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  356. return false;
  357. }
  358. if (!gcstores)
  359. ZeroMemory(gstores, sizeof(gstores));
  360. gstores[gcstores] = store;
  361. gcstores++;
  362. return store;
  363. }
  364. Store *
  365. GetStore(
  366. PCSTR name
  367. )
  368. {
  369. Store *store;
  370. store = FindStore(name);
  371. if (!store)
  372. store = AddStore(name);
  373. return store;
  374. }
  375. BOOL
  376. DeleteStore(
  377. Store *store
  378. )
  379. {
  380. DWORD i;
  381. for (i = 0; i < gcstores; i++) {
  382. if (gstores[i] == store) {
  383. gstores[i] = NULL;
  384. delete store;
  385. return true;
  386. }
  387. }
  388. return false;
  389. }
  390. DWORD Store::assign(PCSTR name)
  391. {
  392. CopyStrArray(m_name, name);
  393. m_type = GetStoreType(name);
  394. m_flags = 0;
  395. return m_type;
  396. }
  397. char *Store::target()
  398. {
  399. return m_tpath;
  400. }
  401. BOOL Store::init()
  402. {
  403. if (m_flags & SF_DISABLED)
  404. return false;
  405. *m_tpath = 0;
  406. return true;
  407. }
  408. BOOL Store::ping()
  409. {
  410. return false;
  411. }
  412. BOOL Store::open(PCSTR rpath, PCSTR file)
  413. {
  414. CopyStrArray(m_rpath, rpath ? rpath : "");
  415. CopyStrArray(m_file, file ? file : "");
  416. return true;
  417. }
  418. VOID Store::close()
  419. {
  420. return;
  421. }
  422. BOOL Store::get(PCSTR trg)
  423. {
  424. pathcpy(m_tpath, trg, m_rpath, DIMA(m_tpath));
  425. pathcat(m_tpath, m_file, DIMA(m_tpath));
  426. EnsurePathExists(m_tpath, m_epath, DIMA(m_epath));
  427. return true;
  428. }
  429. BOOL Store::copy(PCSTR rpath, PCSTR file, PCSTR trg)
  430. {
  431. if (m_flags & SF_DISABLED)
  432. return false;
  433. return true;
  434. }
  435. BOOL Store::progress()
  436. {
  437. SYSTEMTIME st;
  438. if (!*m_file)
  439. return true;
  440. // Do not condense these print statements into single lines.
  441. // They are split up to work with dbghelp's backspace filtering.
  442. switch (m_bytes)
  443. {
  444. case (LONGLONG)-1:
  445. eprint("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
  446. eprint("cancelled \n");
  447. SetLastError(ERROR_REQUEST_ABORTED);
  448. break;
  449. case 0:
  450. dprint("%s from %s: %ld bytes - ", m_file, m_name, m_size);
  451. eprint("\b%12ld ", 0);
  452. break;
  453. default:
  454. GetSystemTime(&st);
  455. if (st.wSecond != m_tic)
  456. eprint("\b\b\b\b\b\b\b\b\b\b\b\b%12ld", m_bytes);
  457. m_tic = st.wSecond;
  458. break;
  459. }
  460. if (m_bytes && (m_bytes == m_size)) {
  461. eprint("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
  462. eprint("copied \n");
  463. }
  464. return true;
  465. }
  466. void Store::setsize(LONGLONG size)
  467. {
  468. m_size = size;
  469. }
  470. void Store::setbytes(LONGLONG bytes)
  471. {
  472. m_bytes = bytes;
  473. }
  474. BOOL StoreUNC::get(PCSTR trg)
  475. {
  476. BOOL rc;
  477. DWORD err;
  478. char c;
  479. pathcpy(m_spath, m_name, m_rpath, DIMA(m_spath));
  480. pathcat(m_spath, m_file, DIMA(m_spath));
  481. Store::get(trg);
  482. do {
  483. // try to copy the file, first
  484. if (gdprint)
  485. rc = CopyFileEx(m_spath, m_tpath, cbCopyProgress, this, &gcancel, COPY_FILE_FAIL_IF_EXISTS);
  486. else
  487. rc = CopyFile(m_spath, m_tpath, true);
  488. if (rc)
  489. return true;
  490. err = GetLastError();
  491. err = fixerror(err);
  492. if (err != ERROR_FILE_NOT_FOUND) {
  493. disperror(err, m_spath);
  494. return false;
  495. }
  496. // now try to uncompress the file
  497. c = ChangeLastChar(m_spath, '_');
  498. if (!FileStatus(m_spath)) {
  499. rc = UncompressFile(m_spath, m_tpath);
  500. if (!rc)
  501. disperror(GetLastError(), m_spath);
  502. return rc;
  503. }
  504. ChangeLastChar(m_spath, c);
  505. // try to read from a file pointer
  506. } while (ReadFilePtr(m_spath, DIMA(m_spath)));
  507. err = GetLastError();
  508. err = fixerror(err);
  509. disperror(err, m_spath);
  510. return false;
  511. }
  512. BOOL StoreUNC::copy(PCSTR rpath, PCSTR file, PCSTR trg)
  513. {
  514. if (!Store::copy(rpath, file, trg))
  515. return false;
  516. if (!open(rpath, file))
  517. return false;
  518. return get(trg);
  519. }
  520. BOOL StoreUNC::ping()
  521. {
  522. BOOL rc;
  523. CopyStrArray(m_spath, m_name);
  524. EnsureTrailingBackslash(m_spath);
  525. CatStrArray(m_spath, "pingme.txt");
  526. rc = (GetFileAttributes(m_spath) == 0xFFFFFFFF);
  527. if (!rc)
  528. m_flags |= SF_DISABLED;
  529. return rc;
  530. }
  531. BOOL StoreInet::init()
  532. {
  533. char sz[_MAX_PATH];
  534. static char uasz[_MAX_PATH] = "";
  535. // internet handle is null, then we know from previous
  536. // attempts that it can't be opened, so bail
  537. if (!ghint)
  538. return false;
  539. if (!*uasz) {
  540. CopyStrArray(uasz, "Microsoft-Symbol-Server/");
  541. CatStrArray(uasz, VER_PRODUCTVERSION_STR);
  542. }
  543. *m_spath = 0;
  544. *m_rpath = 0;
  545. *m_file = 0;
  546. ParsePath(m_name, m_site, sz, NULL, true);
  547. CopyStrArray(m_srpath, "/");
  548. CatStrArray(m_srpath, sz);
  549. if (ghint == INVALID_HANDLE_VALUE) {
  550. ghint = InternetOpen(uasz,
  551. (gproxy) ? INTERNET_OPEN_TYPE_PROXY : INTERNET_OPEN_TYPE_PRECONFIG,
  552. gproxy,
  553. NULL,
  554. 0);
  555. if (!ghint)
  556. return false;
  557. dumpproxyinfo();
  558. }
  559. if (m_hsite)
  560. return true;
  561. m_hsite = InternetConnect(ghint,
  562. m_site,
  563. m_port,
  564. NULL,
  565. NULL,
  566. m_service,
  567. 0,
  568. NULL);//m_context ? (DWORD_PTR)&m_context : NULL);
  569. if (!m_hsite)
  570. return false;
  571. return true;
  572. }
  573. BOOL StoreInet::open(PCSTR rpath, PCSTR file)
  574. {
  575. Store::open(rpath, file);
  576. CopyStrArray(m_spath, m_srpath);
  577. pathcat(m_spath, m_rpath, DIMA(m_spath));
  578. return true;
  579. }
  580. BOOL StoreInet::copy(PCSTR rpath, PCSTR file, PCSTR trg)
  581. {
  582. BOOL rc;
  583. DWORD err;
  584. char cfile[MAX_PATH + 1];
  585. char c;
  586. if (!Store::copy(rpath, file, trg))
  587. return false;
  588. if (m_flags & SF_INTERNET_DISABLED)
  589. return false;
  590. // open and copy the file
  591. if (open(rpath, file)) {
  592. rc = get(trg);
  593. close();
  594. return rc;
  595. }
  596. // if file wasn't found, look for a compressed version
  597. err = GetLastError();
  598. if (err != ERROR_FILE_NOT_FOUND)
  599. return false;
  600. CopyStrArray(cfile, file);
  601. c = ChangeLastChar(cfile, '_');
  602. if (!open(rpath, cfile)) {
  603. dprint("%s%s%s not found\n", gtypeinfo[m_type].tag, m_site, m_spath);
  604. return false;
  605. }
  606. rc = get(trg);
  607. close();
  608. if (!rc)
  609. return false;
  610. // if we found a compressed version, expand it
  611. CopyStrArray(cfile, m_tpath);
  612. ChangeLastChar(m_tpath, c);
  613. rc = UncompressFile(cfile, m_tpath);
  614. DeleteFile(cfile);
  615. if (!rc)
  616. DeleteFile(m_tpath);
  617. return rc;
  618. }
  619. BOOL StoreInet::ping()
  620. {
  621. return open("", "pingme.txt");
  622. }
  623. BOOL StoreHTTP::init()
  624. {
  625. BOOL rc;
  626. m_iflags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_KEEP_CONNECTION;
  627. m_service = INTERNET_SERVICE_HTTP;
  628. m_context = 0;
  629. if (m_type == stHTTPS) {
  630. m_port = INTERNET_DEFAULT_HTTPS_PORT;
  631. m_iflags |= INTERNET_FLAG_SECURE;
  632. } else {
  633. m_port = INTERNET_DEFAULT_HTTP_PORT;
  634. }
  635. *m_srpath = 0;
  636. return StoreInet::init();
  637. }
  638. BOOL StoreHTTP::open(PCSTR rpath, PCSTR file)
  639. {
  640. DWORD err = ERROR_NOT_FOUND;
  641. Store::open(rpath, file);
  642. CopyStrArray(m_spath, m_srpath);
  643. pathcat(m_spath, m_rpath, DIMA(m_spath));
  644. pathcat(m_spath, m_file, DIMA(m_spath));
  645. ConvertBackslashes(m_spath);
  646. close();
  647. m_hfile = HttpOpenRequest(m_hsite,
  648. "GET",
  649. m_spath,
  650. HTTP_VERSION,
  651. NULL,
  652. NULL,
  653. m_iflags,
  654. 0);
  655. if (!m_hfile)
  656. goto error;
  657. err = fileinfo();
  658. if (!err)
  659. return true;
  660. error:
  661. close();
  662. SetLastError(err);
  663. return false;
  664. }
  665. VOID StoreHTTP::close()
  666. {
  667. DWORD err;
  668. if (!m_hfile)
  669. return;
  670. // InternetCloseHandle resets last error to zero.
  671. // Preserve it and restore it afterwards.
  672. err = GetLastError();
  673. InternetCloseHandle(m_hfile);
  674. if (err)
  675. SetLastError(err);
  676. m_hfile = 0;
  677. }
  678. DWORD StoreHTTP::fileinfo()
  679. {
  680. BOOL rc;
  681. DWORD err;
  682. DWORD status;
  683. DWORD cbstatus;
  684. DWORD index;
  685. DWORD cbsize;
  686. #ifdef PROXYTEST
  687. dprint("FILE %s\n", m_spath);
  688. #endif
  689. do {
  690. err = request();
  691. if (err != ERROR_SUCCESS)
  692. return err;
  693. index = 0;
  694. m_size = 0;
  695. cbsize = sizeof(m_size);
  696. rc = HttpQueryInfo(m_hfile,
  697. HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
  698. &m_size,
  699. &cbsize,
  700. &index);
  701. if (!rc) {
  702. if (GetLastError())
  703. return err;
  704. return ERROR_INTERNET_EXTENDED_ERROR;
  705. }
  706. index = 0;
  707. cbstatus = sizeof(status);
  708. rc = HttpQueryInfo(m_hfile,
  709. HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
  710. &status,
  711. &cbstatus,
  712. &index);
  713. if (!rc) {
  714. if (GetLastError())
  715. return err;
  716. return ERROR_INTERNET_EXTENDED_ERROR;
  717. }
  718. switch (status)
  719. {
  720. case HTTP_STATUS_DENIED: // need a valid login?
  721. // dprint("status HTTP_STATUS_DENIED\n");
  722. err = prompt(m_hfile, ERROR_INTERNET_INCORRECT_PASSWORD);
  723. // user entered a password - try again
  724. if (err == ERROR_INTERNET_FORCE_RETRY)
  725. break;
  726. // user cancelled
  727. m_flags |= SF_DISABLED;
  728. return ERROR_NOT_READY;
  729. case HTTP_STATUS_PROXY_AUTH_REQ:
  730. // dprint("status HTTP_STATUS_PROXY_AUTH_REQ\n");
  731. err = prompt(m_hfile, err);
  732. // user entered a password - try again
  733. if (err == ERROR_INTERNET_FORCE_RETRY)
  734. break;
  735. // user cancelled
  736. m_flags |= SF_INTERNET_DISABLED;
  737. return ERROR_NOT_READY;
  738. case HTTP_STATUS_FORBIDDEN:
  739. // dprint("status HTTP_STATUS_FORBIDDEN\n");
  740. m_flags |= SF_DISABLED;
  741. return ERROR_ACCESS_DENIED;
  742. case HTTP_STATUS_NOT_FOUND:
  743. // dprint("status HTTP_STATUS_NOT_FOUND\n");
  744. return ERROR_FILE_NOT_FOUND;
  745. case HTTP_STATUS_OK:
  746. // dprint("status HTTP_STATUS_OK\n");
  747. return ERROR_SUCCESS;
  748. }
  749. } while (err == ERROR_INTERNET_FORCE_RETRY);
  750. return ERROR_INTERNET_EXTENDED_ERROR;
  751. }
  752. DWORD StoreHTTP::request()
  753. {
  754. DWORD err = ERROR_SUCCESS;
  755. while (!HttpSendRequest(m_hfile, NULL, 0, NULL, 0))
  756. {
  757. err = GetLastError();
  758. switch (err)
  759. {
  760. // These cases get input from the user in oder to try again.
  761. case ERROR_INTERNET_INCORRECT_PASSWORD:
  762. case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
  763. err = prompt(m_hfile, err);
  764. if (err != ERROR_SUCCESS && err != ERROR_INTERNET_FORCE_RETRY)
  765. {
  766. err = ERROR_ACCESS_DENIED;
  767. return err;
  768. }
  769. break;
  770. // These cases get input from the user in order to try again.
  771. // However, if the user bails, don't use this internet
  772. // connection again in this session.
  773. case ERROR_INTERNET_INVALID_CA:
  774. case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
  775. case ERROR_INTERNET_SEC_CERT_CN_INVALID:
  776. case ERROR_INTERNET_POST_IS_NON_SECURE:
  777. err = prompt(m_hfile, err);
  778. if (err != ERROR_SUCCESS && err != ERROR_INTERNET_FORCE_RETRY)
  779. {
  780. m_flags |= SF_DISABLED;
  781. err = ERROR_NOT_READY;
  782. return err;
  783. }
  784. break;
  785. // no go - give up the channel
  786. case ERROR_INTERNET_SECURITY_CHANNEL_ERROR:
  787. m_flags |= SF_DISABLED;
  788. err = ERROR_NOT_READY;
  789. return err;
  790. // Tell the user something went wrong and get out of here.
  791. case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
  792. default:
  793. prompt(m_hfile, err);
  794. return err;
  795. }
  796. }
  797. return err;
  798. }
  799. DWORD StoreHTTP::prompt(HINTERNET hreq, DWORD err)
  800. {
  801. if (gopts & SSRVOPT_UNATTENDED)
  802. return err;
  803. if (!ghwnd)
  804. ghwnd = GetDesktopWindow();
  805. if (!ghwnd)
  806. return err;
  807. err = InternetErrorDlg(ghwnd,
  808. hreq,
  809. err,
  810. FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
  811. FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
  812. FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
  813. NULL);
  814. return err;
  815. }
  816. BOOL StoreHTTP::get(PCSTR trg)
  817. {
  818. DWORD read;
  819. DWORD written;
  820. DWORD err = 0;
  821. BYTE *buf;
  822. BOOL rc = false;
  823. HANDLE hf = INVALID_HANDLE_VALUE;
  824. ULONG64 copied;
  825. buf = (BYTE *)LocalAlloc(LPTR, CHUNK_SIZE);
  826. if (!buf) {
  827. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  828. return false;
  829. }
  830. Store::get(trg);
  831. hf = CreateFile(m_tpath,
  832. GENERIC_WRITE,
  833. 0,
  834. NULL,
  835. CREATE_ALWAYS,
  836. FILE_ATTRIBUTE_NORMAL,
  837. NULL);
  838. if (hf == INVALID_HANDLE_VALUE)
  839. goto cleanup;
  840. m_bytes = 0;
  841. do
  842. {
  843. if (!progress())
  844. goto cleanup;
  845. rc = InternetReadFile(m_hfile,
  846. (LPVOID)buf,
  847. CHUNK_SIZE,
  848. &read);
  849. if (!rc || !read)
  850. break;
  851. rc = WriteFile(hf, (LPVOID)buf, read, &written, NULL);
  852. m_bytes += written;
  853. }
  854. while (rc);
  855. cleanup:
  856. // if there was an error, save it and set it later
  857. if (!err)
  858. err = GetLastError();
  859. disperror(err || GetLastError(), m_spath);
  860. // If target file is open, close it.
  861. if (hf != INVALID_HANDLE_VALUE)
  862. CloseHandle(hf);
  863. // free the memory
  864. LocalFree(buf);
  865. SetLastError(err);
  866. return err ? false : true;
  867. }
  868. BOOL StoreHTTP::progress()
  869. {
  870. Store::progress();
  871. if (!m_bytes || !querycancel())
  872. return true;
  873. setbytes((LONGLONG)-1);
  874. Store::progress();
  875. return false;
  876. }