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.

1953 lines
51 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. cachapiw.cxx
  5. Abstract:
  6. contains the UNICODE version of cache mangemant APIs.
  7. Author:
  8. Madan Appiah (madana) 12-Dec-1994
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. Ahsan Kabir (akabir) Dec-1997
  13. --*/
  14. #include <wininetp.h>
  15. #include <cache.hxx>
  16. #include <w95wraps.h>
  17. #define NUMBER_MEMBERS 4
  18. const BYTE bOffsetTable[NUMBER_MEMBERS] =
  19. {
  20. (BYTE)&(((LPINTERNET_CACHE_ENTRY_INFOW)NULL)->lpszSourceUrlName),
  21. (BYTE)&(((LPINTERNET_CACHE_ENTRY_INFOW)NULL)->lpszLocalFileName),
  22. (BYTE)&(((LPINTERNET_CACHE_ENTRY_INFOW)NULL)->lpHeaderInfo),
  23. (BYTE)&(((LPINTERNET_CACHE_ENTRY_INFOW)NULL)->lpszFileExtension)
  24. };
  25. DWORD
  26. TransformA2W(
  27. IN LPINTERNET_CACHE_ENTRY_INFOA pCEIA,
  28. IN DWORD cbCEIA,
  29. OUT LPINTERNET_CACHE_ENTRY_INFOW pCEIW,
  30. OUT LPDWORD pcbCEIW
  31. )
  32. {
  33. DWORD cbSize = sizeof(INTERNET_CACHE_ENTRY_INFOW);
  34. DWORD cc;
  35. if (!pCEIW || (*pcbCEIW<sizeof(INTERNET_CACHE_ENTRY_INFOW)))
  36. {
  37. *pcbCEIW = 0;
  38. cc = 0;
  39. }
  40. else
  41. {
  42. //
  43. // copy fixed portion.
  44. //
  45. memcpy((PBYTE)pCEIW, (PBYTE)pCEIA, sizeof(INTERNET_CACHE_ENTRY_INFOW) );
  46. pCEIW->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFOW);
  47. cc = (*pcbCEIW - sizeof(INTERNET_CACHE_ENTRY_INFOW))/sizeof(WCHAR);
  48. }
  49. // Destination for strings
  50. PWSTR pBuffer = (pCEIW ? (PWSTR)(pCEIW + 1) : NULL);
  51. // Convert strings
  52. for (int i=0; i < NUMBER_MEMBERS; i++)
  53. {
  54. PSTR *pBufferA = (PSTR*)((PBYTE)pCEIA + bOffsetTable[i]);
  55. if (*pBufferA)
  56. {
  57. DWORD dwTmp = MultiByteToWideChar(CP_ACP, 0, *pBufferA, -1, NULL, 0);
  58. if ((dwTmp<=cc) && pCEIW)
  59. {
  60. INET_ASSERT(pBuffer);
  61. PWSTR *pBufferW = (PWSTR*)((PBYTE)pCEIW + bOffsetTable[i]);
  62. *pBufferW = pBuffer;
  63. MultiByteToWideChar(CP_ACP, 0, *pBufferA, -1, *pBufferW, dwTmp);
  64. pBuffer += dwTmp;
  65. cc -= dwTmp;
  66. }
  67. cbSize += dwTmp*sizeof(WCHAR);
  68. }
  69. }
  70. DWORD dwErr = (*pcbCEIW>=cbSize) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
  71. *pcbCEIW = cbSize; // Tell how much space used/needed.
  72. return dwErr;
  73. }
  74. URLCACHEAPI
  75. BOOL
  76. WINAPI
  77. CreateUrlCacheEntryW(
  78. IN LPCWSTR lpszUrlName,
  79. IN DWORD dwExpectedFileSize,
  80. IN LPCWSTR lpszFileExtension,
  81. OUT LPWSTR lpszFileName,
  82. IN DWORD dwReserved
  83. )
  84. {
  85. ENTER_CACHE_API ((DBG_API, Bool, "CreateUrlCacheEntryW", "%wq, %wq, %d, %wq, %#x",
  86. lpszUrlName, lpszFileExtension, dwExpectedFileSize, lpszFileName, dwReserved));
  87. DWORD dwErr = ERROR_SUCCESS;
  88. BOOL fResult = FALSE, fStrNotSafe = FALSE;
  89. MEMORYPACKET mpUrlName, mpFileExtension, mpFileName;
  90. if (lpszUrlName)
  91. {
  92. ALLOC_MB(lpszUrlName,0,mpUrlName);
  93. if (!mpUrlName.psStr)
  94. {
  95. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  96. goto cleanup;
  97. }
  98. UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrlName, &fStrNotSafe);
  99. if (fStrNotSafe)
  100. {
  101. dwErr = ERROR_INVALID_PARAMETER;
  102. goto cleanup;
  103. }
  104. }
  105. if (lpszFileExtension)
  106. {
  107. ALLOC_MB(lpszFileExtension,0,mpFileExtension);
  108. if (!mpFileExtension.psStr)
  109. {
  110. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  111. goto cleanup;
  112. }
  113. UNICODE_TO_ANSI_CHECKED(lpszFileExtension,mpFileExtension, &fStrNotSafe);
  114. if (fStrNotSafe)
  115. {
  116. dwErr = ERROR_INVALID_PARAMETER;
  117. goto cleanup;
  118. }
  119. }
  120. ALLOC_MB(NULL, MAX_PATH, mpFileName);
  121. if (!mpFileName.psStr)
  122. {
  123. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  124. goto cleanup;
  125. }
  126. fResult = CreateUrlCacheEntryA(
  127. mpUrlName.psStr,
  128. dwExpectedFileSize,
  129. mpFileExtension.psStr,
  130. mpFileName.psStr,
  131. dwReserved);
  132. if (fResult)
  133. {
  134. MultiByteToWideChar(CP_ACP, 0, mpFileName.psStr, -1, lpszFileName, MAX_PATH);
  135. }
  136. cleanup:
  137. if (dwErr!=ERROR_SUCCESS)
  138. {
  139. SetLastError(dwErr);
  140. DEBUG_ERROR(API, dwErr);
  141. }
  142. DEBUG_LEAVE_API(fResult);
  143. return fResult;
  144. }
  145. URLCACHEAPI
  146. BOOL
  147. WINAPI
  148. CommitUrlCacheEntryW(
  149. IN LPCWSTR lpszUrlName,
  150. IN LPCWSTR lpszLocalFileName,
  151. IN FILETIME ExpireTime,
  152. IN FILETIME LastModifiedTime,
  153. IN DWORD CacheEntryType,
  154. IN LPWSTR lpszHeaderInfo,
  155. IN DWORD dwHeaders,
  156. IN LPCWSTR lpszFileExtension,
  157. IN LPCWSTR lpszOriginalUrl
  158. )
  159. {
  160. ENTER_CACHE_API ((DBG_API, Bool, "CommitUrlCacheEntryW",
  161. "%wq, %wq, <expires>, <last-mod>, %d, %wq, %d, %wq, %wq",
  162. lpszUrlName,
  163. lpszLocalFileName,
  164. CacheEntryType,
  165. lpszHeaderInfo,
  166. dwHeaders,
  167. lpszFileExtension,
  168. lpszOriginalUrl
  169. ));
  170. BOOL fResult = FALSE;
  171. BOOL fStrNotSafe = FALSE;
  172. DWORD dwErr = ERROR_SUCCESS;
  173. MEMORYPACKET mpUrlName, mpLocalFileName, mpFileExtension, mpHeaders, mpOriginalUrl;
  174. if( IsBadUrlW( lpszUrlName ) ||
  175. ( lpszLocalFileName ? IsBadStringPtrW( lpszLocalFileName, MAX_PATH ) : FALSE ) )
  176. {
  177. dwErr = ERROR_INVALID_PARAMETER;
  178. goto cleanup;
  179. }
  180. ALLOC_MB(lpszUrlName,0,mpUrlName);
  181. if (!mpUrlName.psStr)
  182. {
  183. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  184. goto cleanup;
  185. }
  186. UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrlName, &fStrNotSafe);
  187. if (fStrNotSafe)
  188. {
  189. dwErr = ERROR_INVALID_PARAMETER;
  190. goto cleanup;
  191. }
  192. if (lpszLocalFileName)
  193. {
  194. ALLOC_MB(lpszLocalFileName,0,mpLocalFileName);
  195. if (!mpLocalFileName.psStr)
  196. {
  197. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  198. goto cleanup;
  199. }
  200. UNICODE_TO_ANSI_CHECKED(lpszLocalFileName,mpLocalFileName, &fStrNotSafe);
  201. if (fStrNotSafe)
  202. {
  203. dwErr = ERROR_INVALID_PARAMETER;
  204. goto cleanup;
  205. }
  206. }
  207. if (lpszFileExtension)
  208. {
  209. ALLOC_MB(lpszFileExtension,0,mpFileExtension);
  210. if (!mpFileExtension.psStr)
  211. {
  212. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  213. goto cleanup;
  214. }
  215. UNICODE_TO_ANSI_CHECKED(lpszFileExtension,mpFileExtension, &fStrNotSafe);
  216. if (fStrNotSafe)
  217. {
  218. dwErr = ERROR_INVALID_PARAMETER;
  219. goto cleanup;
  220. }
  221. }
  222. if (lpszHeaderInfo)
  223. {
  224. ALLOC_MB(lpszHeaderInfo,0,mpHeaders);
  225. if (!mpHeaders.psStr)
  226. {
  227. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  228. goto cleanup;
  229. }
  230. UNICODE_TO_ANSI_CHECKED(lpszHeaderInfo,mpHeaders, &fStrNotSafe);
  231. if (fStrNotSafe)
  232. {
  233. dwErr = ERROR_INVALID_PARAMETER;
  234. goto cleanup;
  235. }
  236. }
  237. if (lpszOriginalUrl)
  238. {
  239. ALLOC_MB(lpszOriginalUrl,0,mpOriginalUrl);
  240. if (!mpOriginalUrl.psStr)
  241. {
  242. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  243. goto cleanup;
  244. }
  245. UNICODE_TO_ANSI_CHECKED(lpszOriginalUrl,mpOriginalUrl, &fStrNotSafe);
  246. if (fStrNotSafe)
  247. {
  248. dwErr = ERROR_INVALID_PARAMETER;
  249. goto cleanup;
  250. }
  251. }
  252. fResult = CommitUrlCacheEntryA(
  253. mpUrlName.psStr,
  254. mpLocalFileName.psStr,
  255. ExpireTime,
  256. LastModifiedTime,
  257. CacheEntryType,
  258. (LPBYTE)mpHeaders.psStr,
  259. mpHeaders.dwSize,
  260. mpFileExtension.psStr,
  261. mpOriginalUrl.psStr);
  262. cleanup:
  263. if (dwErr!=ERROR_SUCCESS)
  264. {
  265. SetLastError(dwErr);
  266. DEBUG_ERROR(API, dwErr);
  267. }
  268. DEBUG_LEAVE_API(fResult);
  269. return fResult;
  270. }
  271. BOOL
  272. RetrieveUrlCacheEntryWCore(
  273. IN LPCWSTR lpszUrlName,
  274. OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
  275. IN OUT LPDWORD lpcbCacheEntryInfo,
  276. IN DWORD dwReserved,
  277. IN DWORD dwLookupFlags,
  278. IN DWORD dwRetrievalFlags)
  279. {
  280. DWORD dwErr = ERROR_SUCCESS;
  281. BOOL fStrNotSafe = FALSE;
  282. MEMORYPACKET mpUrlName;
  283. LPINTERNET_CACHE_ENTRY_INFOA pCEIA = NULL;
  284. DWORD dwCEI = 0;
  285. if (!InitGlobals())
  286. {
  287. dwErr = ERROR_WINHTTP_INTERNAL_ERROR;
  288. goto cleanup;
  289. }
  290. if (!(lpszUrlName && lpcbCacheEntryInfo))
  291. {
  292. dwErr = ERROR_INVALID_PARAMETER;
  293. goto cleanup;
  294. }
  295. ALLOC_MB(lpszUrlName, 0, mpUrlName);
  296. if (!mpUrlName.psStr)
  297. {
  298. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  299. goto cleanup;
  300. }
  301. UNICODE_TO_ANSI_CHECKED(lpszUrlName, mpUrlName, &fStrNotSafe);
  302. if (fStrNotSafe)
  303. {
  304. dwErr = ERROR_INVALID_PARAMETER;
  305. goto cleanup;
  306. }
  307. dwErr = GlobalUrlContainers->RetrieveUrl(
  308. mpUrlName.psStr,
  309. &pCEIA,
  310. &dwCEI,
  311. dwLookupFlags,
  312. dwRetrievalFlags | RETRIEVE_WITH_ALLOCATION);
  313. if (dwErr==ERROR_SUCCESS)
  314. {
  315. dwErr = TransformA2W(
  316. pCEIA,
  317. dwCEI,
  318. lpCacheEntryInfo,
  319. lpcbCacheEntryInfo);
  320. if (dwErr!=ERROR_SUCCESS)
  321. {
  322. UnlockUrlCacheEntryFileW(lpszUrlName, 0);
  323. }
  324. }
  325. cleanup:
  326. if (pCEIA)
  327. {
  328. FREE_MEMORY(pCEIA);
  329. }
  330. if (dwErr!=ERROR_SUCCESS)
  331. {
  332. SetLastError(dwErr);
  333. DEBUG_ERROR(API, dwErr);
  334. }
  335. return (dwErr == ERROR_SUCCESS);
  336. }
  337. URLCACHEAPI
  338. BOOL
  339. WINAPI
  340. RetrieveUrlCacheEntryFileW(
  341. IN LPCWSTR lpszUrlName,
  342. OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
  343. IN OUT LPDWORD lpcbCacheEntryInfo,
  344. IN DWORD dwReserved
  345. )
  346. {
  347. ENTER_CACHE_API ((DBG_API, Bool, "RetrieveUrlCacheEntryFileW","%wq, %#x, %#x, %#x",
  348. lpszUrlName, lpCacheEntryInfo, lpcbCacheEntryInfo, dwReserved));
  349. BOOL fResult = RetrieveUrlCacheEntryWCore(
  350. lpszUrlName,
  351. lpCacheEntryInfo,
  352. lpcbCacheEntryInfo,
  353. dwReserved,
  354. LOOKUP_URL_CREATE,
  355. RETRIEVE_WITH_CHECKS);
  356. DEBUG_LEAVE_API(fResult);
  357. return fResult;
  358. }
  359. URLCACHEAPI
  360. HANDLE
  361. WINAPI
  362. RetrieveUrlCacheEntryStreamW(
  363. IN LPCWSTR lpszUrlName,
  364. OUT LPCACHE_ENTRY_INFOW lpCacheEntryInfo,
  365. IN OUT LPDWORD lpcbCacheEntryInfo,
  366. IN BOOL fRandomRead,
  367. IN DWORD dwReserved
  368. )
  369. {
  370. ENTER_CACHE_API ((DBG_API, Handle, "RetrieveUrlCacheEntryStreamW",
  371. "%wq, %#x, %#x, %d, %#x",
  372. lpszUrlName,
  373. lpCacheEntryInfo,
  374. lpcbCacheEntryInfo,
  375. fRandomRead,
  376. dwReserved
  377. ));
  378. BOOL fLocked = FALSE;
  379. HANDLE hInternet = NULL;
  380. HANDLE hFile = INVALID_HANDLE_VALUE;
  381. DWORD dwErr = ERROR_SUCCESS, dwFileSize;
  382. CACHE_STREAM_CONTEXT_HANDLE* pStream;
  383. if (!RetrieveUrlCacheEntryWCore(
  384. lpszUrlName,
  385. lpCacheEntryInfo,
  386. lpcbCacheEntryInfo,
  387. dwReserved,
  388. LOOKUP_URL_NOCREATE,
  389. RETRIEVE_WITHOUT_CHECKS))
  390. {
  391. goto cleanup;
  392. }
  393. fLocked = TRUE;
  394. // Allocate a stream handle.
  395. LOCK_CACHE();
  396. hInternet = HandleMgr.Alloc (sizeof(CACHE_STREAM_CONTEXT_HANDLE));
  397. if (hInternet)
  398. {
  399. pStream = (CACHE_STREAM_CONTEXT_HANDLE*) HandleMgr.Map (hInternet);
  400. INET_ASSERT (pStream);
  401. }
  402. UNLOCK_CACHE();
  403. if (!hInternet)
  404. {
  405. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  406. goto cleanup;
  407. }
  408. // Open the file.
  409. // Does CreateFileW exist on Win9x?
  410. hFile = CreateFileW
  411. (
  412. lpCacheEntryInfo->lpszLocalFileName,
  413. GENERIC_READ,
  414. FILE_SHARE_READ,
  415. NULL,
  416. OPEN_EXISTING,
  417. FILE_ATTRIBUTE_NORMAL |
  418. (fRandomRead ? FILE_FLAG_RANDOM_ACCESS : FILE_FLAG_SEQUENTIAL_SCAN),
  419. // improves file read (cache) performance?
  420. NULL
  421. );
  422. if( hFile == INVALID_HANDLE_VALUE )
  423. {
  424. dwErr = GetLastError();
  425. goto cleanup;
  426. }
  427. dwFileSize = GetFileSize(hFile, NULL);
  428. if (dwFileSize != lpCacheEntryInfo->dwSizeLow)
  429. {
  430. dwErr = (dwFileSize==0xFFFFFFFF) ? GetLastError() : ERROR_INVALID_DATA;
  431. goto cleanup;
  432. }
  433. pStream->FileHandle = hFile;
  434. // Copy URL name storage.
  435. {
  436. MEMORYPACKET mpUrl;
  437. ALLOC_MB(lpszUrlName,0,mpUrl);
  438. if (!mpUrl.psStr)
  439. {
  440. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  441. goto cleanup;
  442. }
  443. UNICODE_TO_ANSI(lpszUrlName,mpUrl);
  444. pStream->SourceUrlName = NewString(mpUrl.psStr);
  445. if( !pStream->SourceUrlName)
  446. {
  447. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  448. goto cleanup;
  449. }
  450. }
  451. cleanup:
  452. if (dwErr!=ERROR_SUCCESS)
  453. {
  454. if (hInternet)
  455. {
  456. HandleMgr.Free(hInternet);
  457. hInternet = NULL;
  458. }
  459. if (hFile)
  460. CloseHandle (hFile);
  461. if (fLocked)
  462. {
  463. UnlockUrlCacheEntryFileW(lpszUrlName, 0);
  464. }
  465. SetLastError (dwErr);
  466. DEBUG_ERROR(API, dwErr);
  467. }
  468. DEBUG_LEAVE_API(hInternet);
  469. return hInternet;
  470. }
  471. BOOL
  472. GetUrlCacheEntryWCore(
  473. IN LPCWSTR lpszUrl,
  474. OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
  475. IN OUT LPDWORD lpcbCacheEntryInfo,
  476. DWORD dwFlags,
  477. DWORD dwLookupFlags,
  478. BOOL fConvertHeaders)
  479. {
  480. BOOL fResult = FALSE;
  481. DWORD dwErr = ERROR_SUCCESS;
  482. BOOL fStrNotSafe = FALSE;
  483. MEMORYPACKET mpUrlName;
  484. LPINTERNET_CACHE_ENTRY_INFOA pCEIA = NULL;
  485. DWORD cbCEIA;
  486. if (!InitGlobals())
  487. {
  488. dwErr = ERROR_WINHTTP_INTERNAL_ERROR;
  489. goto cleanup;
  490. }
  491. if (IsBadUrlW(lpszUrl))
  492. {
  493. dwErr = ERROR_INVALID_PARAMETER;
  494. goto cleanup;
  495. }
  496. ALLOC_MB(lpszUrl,0,mpUrlName);
  497. if (!mpUrlName.psStr)
  498. {
  499. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  500. goto cleanup;
  501. }
  502. UNICODE_TO_ANSI_CHECKED(lpszUrl,mpUrlName, &fStrNotSafe);
  503. if (fStrNotSafe)
  504. {
  505. dwErr = ERROR_INVALID_PARAMETER;
  506. goto cleanup;
  507. }
  508. if (lpcbCacheEntryInfo)
  509. {
  510. dwErr = GlobalUrlContainers->GetUrlInfo(
  511. mpUrlName.psStr,
  512. &pCEIA,
  513. &cbCEIA,
  514. dwFlags,
  515. dwLookupFlags,
  516. RETRIEVE_WITH_ALLOCATION);
  517. // convert from ansi to unicode.
  518. if (dwErr==ERROR_SUCCESS)
  519. {
  520. dwErr = TransformA2W(pCEIA, cbCEIA, lpCacheEntryInfo, lpcbCacheEntryInfo);
  521. if (dwErr==ERROR_SUCCESS)
  522. {
  523. fResult = TRUE;
  524. }
  525. }
  526. }
  527. else
  528. {
  529. fResult = GetUrlCacheEntryInfoExA(
  530. mpUrlName.psStr,
  531. NULL,
  532. NULL,
  533. NULL,
  534. NULL,
  535. NULL,
  536. dwFlags);
  537. }
  538. cleanup:
  539. if (pCEIA)
  540. {
  541. FREE_MEMORY(pCEIA);
  542. }
  543. if (dwErr!=ERROR_SUCCESS)
  544. {
  545. SetLastError(dwErr);
  546. DEBUG_ERROR(API, dwErr);
  547. }
  548. return fResult;
  549. }
  550. URLCACHEAPI
  551. BOOL
  552. WINAPI
  553. GetUrlCacheEntryInfoW(
  554. IN LPCWSTR lpszUrlName,
  555. OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
  556. IN OUT LPDWORD lpcbCacheEntryInfo
  557. )
  558. {
  559. ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheEntryInfoW", "%wq, %#x, %#x",
  560. lpszUrlName, lpCacheEntryInfo, lpcbCacheEntryInfo));
  561. BOOL fResult = GetUrlCacheEntryWCore(
  562. lpszUrlName,
  563. lpCacheEntryInfo,
  564. lpcbCacheEntryInfo,
  565. 0,
  566. LOOKUP_URL_NOCREATE,
  567. TRUE);
  568. DEBUG_LEAVE_API(fResult);
  569. return fResult;
  570. }
  571. BOOLAPI
  572. GetUrlCacheEntryInfoExW(
  573. IN LPCWSTR lpszUrl,
  574. OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
  575. IN OUT LPDWORD lpcbCacheEntryInfo,
  576. OUT LPWSTR lpszRedirectUrl,
  577. IN OUT LPDWORD lpcbRedirectUrl,
  578. LPVOID lpReserved,
  579. DWORD dwFlags
  580. )
  581. {
  582. ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheEntryInfoExW",
  583. "%wq, %#x, %#x, %wq, %#x, %#x, %#x",
  584. lpszUrl, lpCacheEntryInfo, lpcbCacheEntryInfo, lpszRedirectUrl, lpcbRedirectUrl, lpReserved, dwFlags));
  585. DWORD dwErr = ERROR_SUCCESS;
  586. BOOL fResult = FALSE;
  587. if (lpszRedirectUrl
  588. || lpcbRedirectUrl
  589. || lpReserved
  590. )
  591. {
  592. INET_ASSERT (FALSE);
  593. dwErr = ERROR_INVALID_PARAMETER;
  594. goto cleanup;
  595. }
  596. fResult = GetUrlCacheEntryWCore(
  597. lpszUrl,
  598. lpCacheEntryInfo,
  599. lpcbCacheEntryInfo,
  600. dwFlags,
  601. LOOKUP_URL_TRANSLATE | (dwFlags & INTERNET_CACHE_FLAG_ALLOW_COLLISIONS),
  602. TRUE);
  603. cleanup:
  604. if (dwErr!=ERROR_SUCCESS)
  605. {
  606. SetLastError(dwErr);
  607. DEBUG_ERROR(API, dwErr);
  608. }
  609. DEBUG_LEAVE_API(fResult);
  610. return fResult;
  611. }
  612. URLCACHEAPI
  613. BOOL
  614. WINAPI
  615. SetUrlCacheEntryInfoW(
  616. IN LPCWSTR lpszUrlName,
  617. IN LPCACHE_ENTRY_INFOW lpCacheEntryInfo,
  618. IN DWORD dwFieldControl
  619. )
  620. {
  621. ENTER_CACHE_API ((DBG_API, Bool, "SetUrlCacheEntryInfoW", "%wq, %#x, %d",
  622. lpszUrlName, lpCacheEntryInfo, dwFieldControl));
  623. BOOL fResult = FALSE;
  624. BOOL fStrNotSafe = FALSE;
  625. DWORD dwErr = ERROR_SUCCESS;
  626. MEMORYPACKET mpUrlName;
  627. INTERNET_CACHE_ENTRY_INFOA CacheEntryInfoA;
  628. if (!lpszUrlName)
  629. {
  630. dwErr = ERROR_INVALID_PARAMETER;
  631. goto cleanup;
  632. }
  633. memcpy( &CacheEntryInfoA, lpCacheEntryInfo, sizeof(CacheEntryInfoA) );
  634. ALLOC_MB(lpszUrlName,0,mpUrlName);
  635. if (!mpUrlName.psStr)
  636. {
  637. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  638. goto cleanup;
  639. }
  640. UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrlName, &fStrNotSafe);
  641. if (fStrNotSafe)
  642. {
  643. dwErr = ERROR_INVALID_PARAMETER;
  644. goto cleanup;
  645. }
  646. fResult = SetUrlCacheEntryInfoA(
  647. mpUrlName.psStr,
  648. &CacheEntryInfoA,
  649. dwFieldControl );
  650. cleanup:
  651. if (dwErr!=ERROR_SUCCESS)
  652. {
  653. SetLastError(dwErr);
  654. DEBUG_ERROR(API, dwErr);
  655. }
  656. DEBUG_LEAVE_API(fResult);
  657. return fResult;
  658. }
  659. BOOL FindUrlCacheEntryWCore(
  660. IN OUT HANDLE *phFind,
  661. IN LPCWSTR lpszUrlSearchPattern,
  662. IN DWORD dwFlags,
  663. IN DWORD dwFilter,
  664. IN GROUPID GroupId,
  665. OUT LPINTERNET_CACHE_ENTRY_INFOW pEntryInfo,
  666. IN OUT LPDWORD pcbEntryInfo,
  667. IN BOOL fConvertHeaders
  668. )
  669. {
  670. DWORD dwErr = ERROR_SUCCESS;
  671. BOOL fStrNotSafe = FALSE;
  672. MEMORYPACKET mpSearchPattern;
  673. LPINTERNET_CACHE_ENTRY_INFOA pCEIA = NULL;
  674. DWORD cbCEIA;
  675. BOOL fFindFirst = *phFind==NULL;
  676. // DebugBreak();
  677. if (!InitGlobals())
  678. {
  679. dwErr = ERROR_WINHTTP_INTERNAL_ERROR;
  680. goto cleanup;
  681. }
  682. if (!pcbEntryInfo)
  683. {
  684. dwErr = ERROR_INVALID_PARAMETER;
  685. goto cleanup;
  686. }
  687. if (lpszUrlSearchPattern)
  688. {
  689. ALLOC_MB(lpszUrlSearchPattern, 0, mpSearchPattern);
  690. if (!mpSearchPattern.psStr)
  691. {
  692. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  693. goto cleanup;
  694. }
  695. UNICODE_TO_ANSI_CHECKED(lpszUrlSearchPattern, mpSearchPattern, &fStrNotSafe);
  696. if (fStrNotSafe)
  697. {
  698. dwErr = ERROR_INVALID_PARAMETER;
  699. goto cleanup;
  700. }
  701. }
  702. dwErr = GlobalUrlContainers->FindNextEntry(phFind,
  703. mpSearchPattern.psStr,
  704. &pCEIA,
  705. &cbCEIA,
  706. dwFilter,
  707. GroupId,
  708. dwFlags,
  709. RETRIEVE_WITH_ALLOCATION);
  710. // TransformA2W will convert from ansi to unicode. ERROR_SUCCESS always means that
  711. // the cache entry has been returned.
  712. if (dwErr==ERROR_SUCCESS)
  713. {
  714. dwErr = TransformA2W(pCEIA,
  715. cbCEIA,
  716. pEntryInfo,
  717. pcbEntryInfo);
  718. }
  719. cleanup:
  720. if (pCEIA)
  721. {
  722. FREE_MEMORY(pCEIA);
  723. }
  724. if (dwErr!=ERROR_SUCCESS)
  725. {
  726. if (fFindFirst && *phFind)
  727. {
  728. GlobalUrlContainers->FreeFindHandle(*phFind);
  729. *phFind = NULL;
  730. }
  731. SetLastError(dwErr);
  732. DEBUG_ERROR(API, dwErr);
  733. }
  734. return (dwErr==ERROR_SUCCESS) ;
  735. }
  736. URLCACHEAPI
  737. HANDLE
  738. WINAPI
  739. FindFirstUrlCacheEntryW(
  740. IN LPCWSTR lpszUrlSearchPattern,
  741. OUT LPCACHE_ENTRY_INFOW lpFirstCacheEntryInfo,
  742. IN OUT LPDWORD lpcbCacheEntryInfo
  743. )
  744. {
  745. ENTER_CACHE_API ((DBG_API, Bool, "FindFirstUrlCacheEntryW",
  746. "%wq, %#x, %#x",
  747. lpszUrlSearchPattern,
  748. lpFirstCacheEntryInfo,
  749. lpcbCacheEntryInfo
  750. ));
  751. HANDLE hInternet = FindFirstUrlCacheEntryExW(
  752. lpszUrlSearchPattern,
  753. FIND_FLAGS_OLD_SEMANTICS,
  754. URLCACHE_FIND_DEFAULT_FILTER,
  755. NULL,
  756. lpFirstCacheEntryInfo,
  757. lpcbCacheEntryInfo,
  758. NULL,
  759. NULL,
  760. NULL);
  761. DEBUG_LEAVE_API(hInternet);
  762. return hInternet;
  763. }
  764. URLCACHEAPI
  765. BOOL
  766. WINAPI
  767. FindNextUrlCacheEntryW(
  768. IN HANDLE hEnumHandle,
  769. OUT LPCACHE_ENTRY_INFOW pEntryInfo,
  770. IN OUT LPDWORD pcbEntryInfo
  771. )
  772. {
  773. ENTER_CACHE_API ((DBG_API, Bool, "FindNextUrlCacheEntryW",
  774. "%#x, %#x, %#x",
  775. hEnumHandle,
  776. pEntryInfo,
  777. pcbEntryInfo
  778. ));
  779. BOOL fResult = FindNextUrlCacheEntryExW(
  780. hEnumHandle,
  781. pEntryInfo,
  782. pcbEntryInfo,
  783. NULL,
  784. NULL,
  785. NULL);
  786. DEBUG_LEAVE_API(fResult);
  787. return fResult;
  788. }
  789. INTERNETAPI
  790. HANDLE
  791. WINAPI
  792. FindFirstUrlCacheEntryExW(
  793. IN LPCWSTR lpszUrlSearchPattern,
  794. IN DWORD dwFlags,
  795. IN DWORD dwFilter,
  796. IN GROUPID GroupId,
  797. OUT LPINTERNET_CACHE_ENTRY_INFOW pEntryInfo,
  798. IN OUT LPDWORD pcbEntryInfo,
  799. OUT LPVOID lpGroupAttributes, // must pass NULL
  800. IN OUT LPDWORD pcbGroupAttributes, // must pass NULL
  801. IN LPVOID lpReserved // must pass NULL
  802. )
  803. {
  804. ENTER_CACHE_API ((DBG_API, Bool, "FindFirstUrlCacheEntryExW",
  805. "%wq, %#x, %#x, %#x, %#x, %#x, %#x, %#x, %#x",
  806. lpszUrlSearchPattern,
  807. dwFlags,
  808. dwFilter,
  809. GroupId,
  810. pEntryInfo,
  811. pcbEntryInfo,
  812. lpGroupAttributes,
  813. pcbGroupAttributes,
  814. lpReserved
  815. ));
  816. HANDLE hInternet = NULL;
  817. FindUrlCacheEntryWCore(
  818. &hInternet,
  819. lpszUrlSearchPattern,
  820. dwFlags,
  821. dwFilter,
  822. GroupId,
  823. pEntryInfo,
  824. pcbEntryInfo,
  825. TRUE);
  826. DEBUG_LEAVE_API(hInternet);
  827. return hInternet;
  828. }
  829. BOOLAPI
  830. FindNextUrlCacheEntryExW(
  831. IN HANDLE hEnumHandle,
  832. OUT LPINTERNET_CACHE_ENTRY_INFOW pEntryInfo,
  833. IN OUT LPDWORD pcbEntryInfo,
  834. OUT LPVOID lpGroupAttributes, // must pass NULL
  835. IN OUT LPDWORD pcbGroupAttributes, // must pass NULL
  836. IN LPVOID lpReserved // must pass NULL
  837. )
  838. {
  839. ENTER_CACHE_API ((DBG_API, Bool, "FindNextUrlCacheEntryExW",
  840. "%#x, %#x, %#x, %#x, %#x, %#x",
  841. hEnumHandle,
  842. pEntryInfo,
  843. pcbEntryInfo,
  844. lpGroupAttributes,
  845. pcbGroupAttributes,
  846. lpReserved
  847. ));
  848. BOOL fResult = FALSE;
  849. DWORD dwErr = ERROR_SUCCESS;
  850. if (!hEnumHandle)
  851. {
  852. dwErr = ERROR_INVALID_PARAMETER;
  853. goto cleanup;
  854. }
  855. fResult = FindUrlCacheEntryWCore(
  856. &hEnumHandle,
  857. NULL,
  858. 0,
  859. 0,
  860. 0,
  861. pEntryInfo,
  862. pcbEntryInfo,
  863. TRUE);
  864. cleanup:
  865. if (dwErr!=ERROR_SUCCESS)
  866. {
  867. SetLastError(dwErr);
  868. DEBUG_ERROR(API, dwErr);
  869. }
  870. DEBUG_LEAVE_API(fResult);
  871. return fResult;
  872. }
  873. URLCACHEAPI
  874. BOOL
  875. WINAPI
  876. FreeUrlCacheSpaceW(
  877. IN LPCWSTR lpszCachePath,
  878. IN DWORD dwSize,
  879. IN DWORD dwReserved
  880. )
  881. {
  882. ENTER_CACHE_API ((DBG_API, Bool, "FreeUrlCacheSpaceW",
  883. "<path>,%d, %#x", dwSize, dwReserved));
  884. BOOL fResult = FALSE;
  885. DWORD dwErr = ERROR_SUCCESS;
  886. BOOL fStrNotSafe = FALSE;
  887. MEMORYPACKET mpCachePath;
  888. if (lpszCachePath)
  889. {
  890. ALLOC_MB(lpszCachePath,0,mpCachePath);
  891. if (!mpCachePath.psStr)
  892. {
  893. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  894. goto cleanup;
  895. }
  896. UNICODE_TO_ANSI_CHECKED(lpszCachePath,mpCachePath, &fStrNotSafe);
  897. if (fStrNotSafe)
  898. {
  899. dwErr = ERROR_INVALID_PARAMETER;
  900. goto cleanup;
  901. }
  902. }
  903. fResult = FreeUrlCacheSpaceA(
  904. mpCachePath.psStr,
  905. dwSize,
  906. dwReserved );
  907. cleanup:
  908. if (dwErr!=ERROR_SUCCESS)
  909. {
  910. SetLastError(dwErr);
  911. DEBUG_ERROR(API, dwErr);
  912. }
  913. DEBUG_LEAVE_API(fResult);
  914. return fResult;
  915. }
  916. URLCACHEAPI
  917. BOOL
  918. WINAPI
  919. UnlockUrlCacheEntryFileW(
  920. LPCWSTR lpszUrlName,
  921. IN DWORD dwReserved
  922. )
  923. /*++
  924. Routine Description:
  925. This API checks in the file that was check out as part of
  926. RetrieveUrlFile API.
  927. Arguments:
  928. lpszUrlName : name of the URL that is being retrieved.
  929. dwReserved : reserved for future use.
  930. Return Value:
  931. Windows Error code.
  932. --*/
  933. {
  934. ENTER_CACHE_API ((DBG_API, Bool, "UnlockUrlCacheEntryFileW",
  935. "%wq, %#x", lpszUrlName, dwReserved));
  936. BOOL fResult = FALSE;
  937. BOOL fStrNotSafe = FALSE;
  938. DWORD dwErr = ERROR_SUCCESS;
  939. MEMORYPACKET mpUrl;
  940. if (!lpszUrlName)
  941. {
  942. dwErr = ERROR_INVALID_PARAMETER;
  943. goto cleanup;
  944. }
  945. ALLOC_MB(lpszUrlName,0,mpUrl);
  946. if (!mpUrl.psStr)
  947. {
  948. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  949. goto cleanup;
  950. }
  951. UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrl, &fStrNotSafe);
  952. if (fStrNotSafe)
  953. {
  954. dwErr = ERROR_INVALID_PARAMETER;
  955. goto cleanup;
  956. }
  957. fResult = UnlockUrlCacheEntryFileA(mpUrl.psStr, dwReserved);
  958. cleanup:
  959. if (dwErr!=ERROR_SUCCESS)
  960. {
  961. SetLastError(dwErr);
  962. DEBUG_ERROR(API, dwErr);
  963. }
  964. DEBUG_LEAVE_API(fResult);
  965. return fResult;
  966. }
  967. URLCACHEAPI
  968. BOOL
  969. WINAPI
  970. DeleteUrlCacheEntryW(
  971. IN LPCWSTR lpszUrlName
  972. )
  973. {
  974. ENTER_CACHE_API ((DBG_API, Bool, "DeleteUrlCacheEntryW",
  975. "%wq", lpszUrlName));
  976. BOOL fResult = FALSE;
  977. BOOL fStrNotSafe = FALSE;
  978. DWORD dwErr = ERROR_SUCCESS;
  979. MEMORYPACKET mpUrl;
  980. if (!lpszUrlName)
  981. {
  982. dwErr = ERROR_INVALID_PARAMETER;
  983. goto cleanup;
  984. }
  985. ALLOC_MB(lpszUrlName,0,mpUrl);
  986. if (!mpUrl.psStr)
  987. {
  988. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  989. goto cleanup;
  990. }
  991. UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrl, &fStrNotSafe);
  992. if (fStrNotSafe)
  993. {
  994. dwErr = ERROR_INVALID_PARAMETER;
  995. goto cleanup;
  996. }
  997. fResult = DeleteUrlCacheEntryA(mpUrl.psStr);
  998. cleanup:
  999. if (dwErr!=ERROR_SUCCESS)
  1000. {
  1001. SetLastError(dwErr);
  1002. DEBUG_ERROR(API, dwErr);
  1003. }
  1004. DEBUG_LEAVE_API(fResult);
  1005. return fResult;
  1006. }
  1007. BOOLAPI
  1008. IsUrlCacheEntryExpiredW(
  1009. IN LPCWSTR lpszUrlName,
  1010. IN DWORD dwFlags,
  1011. IN OUT FILETIME* pftLastModifiedTime
  1012. )
  1013. {
  1014. ENTER_CACHE_API ((DBG_API, Bool, "UrlCacheEntryExpiredW",
  1015. "%wq, %#x", lpszUrlName, dwFlags));
  1016. BOOL fResult = FALSE;
  1017. BOOL fStrNotSafe = FALSE;
  1018. DWORD dwErr = ERROR_SUCCESS;
  1019. MEMORYPACKET mpUrl;
  1020. if (!lpszUrlName)
  1021. {
  1022. dwErr = ERROR_INVALID_PARAMETER;
  1023. goto cleanup;
  1024. }
  1025. ALLOC_MB(lpszUrlName,0,mpUrl);
  1026. if (!mpUrl.psStr)
  1027. {
  1028. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1029. goto cleanup;
  1030. }
  1031. UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrl, &fStrNotSafe);
  1032. if (fStrNotSafe)
  1033. {
  1034. dwErr = ERROR_INVALID_PARAMETER;
  1035. goto cleanup;
  1036. }
  1037. fResult = IsUrlCacheEntryExpiredA(
  1038. mpUrl.psStr,
  1039. dwFlags,
  1040. pftLastModifiedTime);
  1041. cleanup:
  1042. if (dwErr!=ERROR_SUCCESS)
  1043. {
  1044. SetLastError(dwErr);
  1045. DEBUG_ERROR(API, dwErr);
  1046. }
  1047. DEBUG_LEAVE_API(fResult);
  1048. return fResult;
  1049. }
  1050. BOOL CacheGroupInfoA2W(
  1051. IN LPINTERNET_CACHE_GROUP_INFOA lpAnsiGroupInfo,
  1052. IN DWORD dwAnsiGroupInfoSize,
  1053. OUT LPINTERNET_CACHE_GROUP_INFOW lpUnicodeGroupInfo,
  1054. IN OUT LPDWORD lpdwUnicodeGroupInfoSize
  1055. )
  1056. {
  1057. INET_ASSERT( lpUnicodeGroupInfo && lpAnsiGroupInfo);
  1058. lpUnicodeGroupInfo->dwGroupSize = sizeof(INTERNET_CACHE_GROUP_INFOW);
  1059. lpUnicodeGroupInfo->dwGroupFlags = lpAnsiGroupInfo->dwGroupFlags;
  1060. lpUnicodeGroupInfo->dwGroupType = lpAnsiGroupInfo->dwGroupType;
  1061. lpUnicodeGroupInfo->dwDiskUsage = lpAnsiGroupInfo->dwDiskUsage;
  1062. lpUnicodeGroupInfo->dwDiskQuota = lpAnsiGroupInfo->dwDiskQuota;
  1063. memcpy(lpUnicodeGroupInfo->dwOwnerStorage,
  1064. lpAnsiGroupInfo->dwOwnerStorage,
  1065. GROUP_OWNER_STORAGE_SIZE * sizeof(DWORD) );
  1066. BOOL fRet = MultiByteToWideChar(
  1067. CP_ACP,
  1068. MB_PRECOMPOSED,
  1069. lpAnsiGroupInfo->szGroupName,
  1070. -1, // null terminated ansi string.
  1071. lpUnicodeGroupInfo->szGroupName,
  1072. GROUPNAME_MAX_LENGTH
  1073. );
  1074. if( fRet )
  1075. {
  1076. *lpdwUnicodeGroupInfoSize = lpUnicodeGroupInfo->dwGroupSize;
  1077. }
  1078. else
  1079. {
  1080. *lpdwUnicodeGroupInfoSize = 0;
  1081. SetLastError(ERROR_INVALID_PARAMETER);
  1082. }
  1083. return fRet;
  1084. }
  1085. BOOL CacheGroupInfoW2A(
  1086. IN LPINTERNET_CACHE_GROUP_INFOW lpUnicodeGroupInfo,
  1087. IN DWORD dwUnicodeGroupInfoSize,
  1088. OUT LPINTERNET_CACHE_GROUP_INFOA lpAnsiGroupInfo,
  1089. IN OUT LPDWORD lpdwAnsiGroupInfoSize
  1090. )
  1091. {
  1092. INET_ASSERT( lpUnicodeGroupInfo && lpAnsiGroupInfo);
  1093. BOOL fStrNotSafe = FALSE;
  1094. lpAnsiGroupInfo->dwGroupSize = sizeof(INTERNET_CACHE_GROUP_INFOA);
  1095. lpAnsiGroupInfo->dwGroupFlags = lpUnicodeGroupInfo->dwGroupFlags;
  1096. lpAnsiGroupInfo->dwGroupType = lpUnicodeGroupInfo->dwGroupType;
  1097. lpAnsiGroupInfo->dwDiskUsage = lpUnicodeGroupInfo->dwDiskUsage;
  1098. lpAnsiGroupInfo->dwDiskQuota = lpUnicodeGroupInfo->dwDiskQuota;
  1099. memcpy( lpAnsiGroupInfo->dwOwnerStorage,
  1100. lpUnicodeGroupInfo->dwOwnerStorage,
  1101. GROUP_OWNER_STORAGE_SIZE * sizeof(DWORD) );
  1102. BOOL fRet = WideCharToMultiByte(
  1103. CP_ACP,
  1104. 0, // no flags.
  1105. lpUnicodeGroupInfo->szGroupName,
  1106. -1, // null terminated unicode string.
  1107. lpAnsiGroupInfo->szGroupName,
  1108. GROUPNAME_MAX_LENGTH,
  1109. NULL, // lpDefaultChar
  1110. &fStrNotSafe // lpUseDefaultChar
  1111. );
  1112. if (fStrNotSafe)
  1113. {
  1114. fRet = FALSE;
  1115. }
  1116. if( fRet )
  1117. {
  1118. *lpdwAnsiGroupInfoSize = lpAnsiGroupInfo->dwGroupSize;
  1119. }
  1120. else
  1121. {
  1122. *lpdwAnsiGroupInfoSize = 0;
  1123. }
  1124. return fRet;
  1125. }
  1126. URLCACHEAPI
  1127. BOOLAPI
  1128. SetUrlCacheEntryGroupW(
  1129. IN LPCWSTR lpszUrlName,
  1130. IN DWORD dwFlags,
  1131. IN GROUPID GroupId,
  1132. IN LPBYTE pbGroupAttributes, // must pass NULL
  1133. IN DWORD cbGroupAttributes, // must pass 0
  1134. IN LPVOID lpReserved // must pass NULL
  1135. )
  1136. {
  1137. ENTER_CACHE_API ((DBG_API, Bool, "SetUrlCacheEntryGroupW",
  1138. "%wq, %#x, %#x, %#x, %#x, %#x", lpszUrlName, dwFlags, GroupId, pbGroupAttributes, cbGroupAttributes, lpReserved));
  1139. BOOL fResult = FALSE;
  1140. BOOL fStrNotSafe = FALSE;
  1141. DWORD dwErr = ERROR_SUCCESS;
  1142. MEMORYPACKET mpUrl;
  1143. if (!lpszUrlName)
  1144. {
  1145. dwErr = ERROR_INVALID_PARAMETER;
  1146. goto cleanup;
  1147. }
  1148. ALLOC_MB(lpszUrlName,0,mpUrl);
  1149. if (!mpUrl.psStr)
  1150. {
  1151. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1152. goto cleanup;
  1153. }
  1154. UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrl, &fStrNotSafe);
  1155. if (fStrNotSafe)
  1156. {
  1157. dwErr = ERROR_INVALID_PARAMETER;
  1158. goto cleanup;
  1159. }
  1160. fResult = SetUrlCacheEntryGroupA(
  1161. mpUrl.psStr,
  1162. dwFlags,
  1163. GroupId,
  1164. pbGroupAttributes,
  1165. cbGroupAttributes,
  1166. lpReserved);
  1167. cleanup:
  1168. if (dwErr!=ERROR_SUCCESS)
  1169. {
  1170. SetLastError(dwErr);
  1171. DEBUG_ERROR(API, dwErr);
  1172. }
  1173. DEBUG_LEAVE_API(fResult);
  1174. return fResult;
  1175. }
  1176. URLCACHEAPI
  1177. BOOL
  1178. WINAPI
  1179. GetUrlCacheGroupAttributeW(
  1180. IN GROUPID gid,
  1181. IN DWORD dwFlags,
  1182. IN DWORD dwAttributes,
  1183. OUT LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,
  1184. IN OUT LPDWORD lpdwGroupInfo,
  1185. IN OUT LPVOID lpReserved
  1186. )
  1187. {
  1188. ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheGroupAttributeW",
  1189. "%d, %d, %d, %#x, %#x, %#x",
  1190. gid, dwFlags, dwAttributes, lpGroupInfo, lpdwGroupInfo, lpReserved ));
  1191. BOOL fResult = FALSE;
  1192. DWORD Error = ERROR_SUCCESS;
  1193. INTERNET_CACHE_GROUP_INFOA AnsiGroupInfo;
  1194. DWORD dwAnsiGroupInfoSize = sizeof(INTERNET_CACHE_GROUP_INFOA);
  1195. if( !lpGroupInfo || !lpdwGroupInfo )
  1196. {
  1197. Error = ERROR_INVALID_PARAMETER;
  1198. goto Cleanup;
  1199. }
  1200. if( *lpdwGroupInfo < sizeof(INTERNET_CACHE_GROUP_INFOW) )
  1201. {
  1202. Error = ERROR_INSUFFICIENT_BUFFER;
  1203. goto Cleanup;
  1204. }
  1205. if( IsBadWriteUrlInfo(lpGroupInfo, *lpdwGroupInfo) )
  1206. {
  1207. Error = ERROR_INVALID_PARAMETER;
  1208. goto Cleanup;
  1209. }
  1210. if( GetUrlCacheGroupAttributeA(
  1211. gid, dwFlags, dwAttributes,
  1212. &AnsiGroupInfo, &dwAnsiGroupInfoSize, lpReserved ) )
  1213. {
  1214. fResult = CacheGroupInfoA2W( &AnsiGroupInfo,
  1215. dwAnsiGroupInfoSize,
  1216. lpGroupInfo,
  1217. lpdwGroupInfo );
  1218. }
  1219. Cleanup:
  1220. if (Error!=ERROR_SUCCESS)
  1221. {
  1222. SetLastError(Error);
  1223. DEBUG_ERROR(API, Error);
  1224. }
  1225. DEBUG_LEAVE_API(fResult);
  1226. return fResult;
  1227. }
  1228. URLCACHEAPI
  1229. BOOL
  1230. WINAPI
  1231. SetUrlCacheGroupAttributeW(
  1232. IN GROUPID gid,
  1233. IN DWORD dwFlags,
  1234. IN DWORD dwAttributes,
  1235. IN LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,
  1236. IN OUT LPVOID lpReserved
  1237. )
  1238. {
  1239. ENTER_CACHE_API ((DBG_API, Bool, "SetUrlCacheGroupAttributeA",
  1240. "%#x, %d, %d, %#x, %#x",
  1241. gid, dwFlags, dwAttributes, lpGroupInfo, lpReserved));
  1242. BOOL fResult = FALSE;
  1243. DWORD Error = ERROR_SUCCESS;
  1244. INTERNET_CACHE_GROUP_INFOA AnsiGroupInfo;
  1245. DWORD dwAnsiGroupInfoSize = sizeof(INTERNET_CACHE_GROUP_INFOA);
  1246. if( IsBadReadPtr(lpGroupInfo, sizeof(INTERNET_CACHE_GROUP_INFOW) ) )
  1247. {
  1248. Error = ERROR_INVALID_PARAMETER;
  1249. }
  1250. else if( CacheGroupInfoW2A(
  1251. lpGroupInfo, sizeof(INTERNET_CACHE_GROUP_INFOW),
  1252. &AnsiGroupInfo, &dwAnsiGroupInfoSize ) )
  1253. {
  1254. fResult = SetUrlCacheGroupAttributeA(
  1255. gid, dwFlags, dwAttributes, &AnsiGroupInfo, lpReserved );
  1256. }
  1257. if (Error!=ERROR_SUCCESS)
  1258. {
  1259. SetLastError(Error);
  1260. DEBUG_ERROR(API, Error);
  1261. }
  1262. DEBUG_LEAVE_API(fResult);
  1263. return fResult;
  1264. }
  1265. // Convert all the ansi strings in a structure to unicode
  1266. /* How does this work?
  1267. Take this structure for example:
  1268. struct foo
  1269. {
  1270. DWORD dwA;
  1271. LPTSTR pszB;
  1272. DWORD dwC;
  1273. LPTSTR pszD;
  1274. };
  1275. where LPTSTR are embedded pointers
  1276. The memory layout is thus:
  1277. [DWORD][LPTSTR][DWORD][LPTSTR][embedded string pszB][embedded string pszD]
  1278. ^ ^
  1279. | |
  1280. |-struct beginning |-beginning of embedded strings
  1281. Assuming a 32-bit platform, we can construct pointers (relative to the struct beginning) to each element
  1282. in the structure. In this case,
  1283. { 0, sizeof(DWORD), sizeof(DWORD)+sizeof(LPTSTR), sizeof(DWORD)+sizeof(LPTSTR)+sizeof(DWORD) }
  1284. Let's say we're interested in strings only, and we know that these strings are embedded. We can create a byte table thus:
  1285. BYTE bFoo[] = { sizeof(DWORD), sizeof(DWORD)+sizeof(LPTSTR)+sizeof(DWORD) }
  1286. Alternatively:
  1287. BYTE bFoo[] =
  1288. {
  1289. (BYTE)&(((foo*)NULL)->pszB),
  1290. (BYTE)&(((foo*)NULL)->pszD)
  1291. };
  1292. This layout is the same for both Ansi and Unicode versions of a struct, UNLESS the struct contains for example
  1293. a TCHAR szWhat[256] (in which case, we can't use the bulk converter).
  1294. Pass BulkConverter the following parameters, to convert strings in one swoop.
  1295. pbSrc = casted pointer to the beginning of the ansi structure
  1296. pbDest = casted pointer to the beginning of the unicode structure
  1297. cbAvail = number of bytes available for embedded strings
  1298. wSkip = offset from the beginning of the structure, at which point embedded strings may be written
  1299. cElements = number of elements to convert from ansi to unicode
  1300. If BulkConverter succeeds, it'll return the number of bytes used.
  1301. If it fails, it will return the number of bytes needed to store all the unicode strings.
  1302. BUT HOW DOES THIS THING WORK?
  1303. Oh.
  1304. 1. Using the offset table, we figure out where the pointer to the string is in both the structures.
  1305. 2. Then using magic, we decided where to place the unicode string.
  1306. 3. Figure how much space we'll need to store the unicode string
  1307. 4. If that much is available, convert.
  1308. 5. Keep track, either way.
  1309. 6. Go to 1, if we have any other strings left.
  1310. */
  1311. LONG BulkConverter(PBYTE pbSrc, PBYTE pbDest, LONG cbAvail, WORD wSkip, CONST BYTE abTable[], WORD cElements)
  1312. {
  1313. PWSTR pBuffer = (PWSTR)(pbDest + wSkip);
  1314. PSTR *pBufferA;
  1315. PWSTR *pBufferW;
  1316. for (DWORD i=0; i < cElements; i++)
  1317. {
  1318. pBufferA = (PSTR*)((PBYTE)pbSrc + abTable[i]);
  1319. pBufferW = (PWSTR*)((PBYTE)pbDest + abTable[i]);
  1320. if (*pBufferA)
  1321. {
  1322. *pBufferW = pBuffer;
  1323. LONG dwTmp = MultiByteToWideChar(CP_ACP, 0, *pBufferA, -1,
  1324. *pBufferW, 0);
  1325. if (dwTmp<cbAvail)
  1326. {
  1327. MultiByteToWideChar(CP_ACP, 0, *pBufferA, -1,
  1328. *pBufferW, cbAvail);
  1329. pBuffer += dwTmp;
  1330. }
  1331. cbAvail -= dwTmp;
  1332. }
  1333. }
  1334. return cbAvail;
  1335. }
  1336. const BYTE bOffsetTableContainer[] =
  1337. {
  1338. (BYTE)&(((LPINTERNET_CACHE_CONTAINER_INFOW)NULL)->lpszName),
  1339. (BYTE)&(((LPINTERNET_CACHE_CONTAINER_INFOW)NULL)->lpszCachePrefix),
  1340. (BYTE)&(((LPINTERNET_CACHE_CONTAINER_INFOW)NULL)->lpszVolumeLabel),
  1341. (BYTE)&(((LPINTERNET_CACHE_CONTAINER_INFOW)NULL)->lpszVolumeTitle)
  1342. };
  1343. BOOL
  1344. TransformCacheContainerInfoToW(
  1345. IN BOOL fResult,
  1346. IN LPINTERNET_CACHE_CONTAINER_INFOA pCCIA,
  1347. IN DWORD cbCCIA,
  1348. OUT LPINTERNET_CACHE_CONTAINER_INFOW pCCIW,
  1349. OUT LPDWORD pcbCCIW
  1350. )
  1351. {
  1352. DWORD cbSize = *pcbCCIW;
  1353. if (fResult)
  1354. {
  1355. // If we have pointers, try to convert from
  1356. LONG cc = *pcbCCIW - sizeof(INTERNET_CACHE_CONTAINER_INFOW);
  1357. if (*pcbCCIW > sizeof(INTERNET_CACHE_CONTAINER_INFOW))
  1358. {
  1359. pCCIW->dwCacheVersion = pCCIA->dwCacheVersion;
  1360. }
  1361. cc /= sizeof(WCHAR);
  1362. // Convert strings
  1363. cc = BulkConverter((PBYTE)pCCIA,
  1364. (PBYTE)pCCIW,
  1365. cc,
  1366. sizeof(INTERNET_CACHE_CONTAINER_INFOW),
  1367. bOffsetTableContainer,
  1368. ARRAY_ELEMENTS(bOffsetTableContainer));
  1369. // Tell how much space was actually used.
  1370. *pcbCCIW -= cc*sizeof(WCHAR);
  1371. if (*pcbCCIW>cbSize)
  1372. {
  1373. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1374. fResult = FALSE;
  1375. }
  1376. }
  1377. else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
  1378. {
  1379. *pcbCCIW = (cbCCIA - sizeof(INTERNET_CACHE_CONTAINER_INFOA))*sizeof(WCHAR) + sizeof(INTERNET_CACHE_CONTAINER_INFOW);
  1380. }
  1381. return fResult;
  1382. }
  1383. #define USE_ORIGINAL_CODE
  1384. URLCACHEAPI
  1385. BOOL
  1386. WINAPI
  1387. CreateUrlCacheContainerW(
  1388. IN LPCWSTR Name,
  1389. IN LPCWSTR CachePrefix,
  1390. IN LPCWSTR CachePath,
  1391. IN DWORD KBCacheLimit,
  1392. IN DWORD dwContainerType,
  1393. IN DWORD dwOptions,
  1394. IN OUT LPVOID pvBuffer,
  1395. IN OUT LPDWORD cbBuffer)
  1396. {
  1397. ENTER_CACHE_API ((DBG_API, Bool, "CreateUrlCacheContainerW", "%wq, %wq, %wq, %d, %d, %d, %#x, %#x",
  1398. Name, CachePrefix, CachePath, KBCacheLimit, dwContainerType, dwOptions, pvBuffer, cbBuffer));
  1399. DWORD dwErr = ERROR_SUCCESS;
  1400. BOOL fResult = FALSE;
  1401. MEMORYPACKET mpName, mpCachePrefix, mpCachePath;
  1402. BOOL fStrNotSafe = FALSE;
  1403. #ifdef USE_ORIGINAL_CODE
  1404. if (Name)
  1405. {
  1406. ALLOC_MB(Name, 0, mpName);
  1407. if (!mpName.psStr)
  1408. {
  1409. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1410. goto cleanup;
  1411. }
  1412. UNICODE_TO_ANSI_CHECKED(Name, mpName, &fStrNotSafe);
  1413. if (fStrNotSafe)
  1414. {
  1415. dwErr = ERROR_INVALID_PARAMETER;
  1416. goto cleanup;
  1417. }
  1418. }
  1419. if (CachePrefix)
  1420. {
  1421. ALLOC_MB(CachePrefix, 0, mpCachePrefix);
  1422. if (!mpCachePrefix.psStr)
  1423. {
  1424. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1425. goto cleanup;
  1426. }
  1427. UNICODE_TO_ANSI_CHECKED(CachePrefix, mpCachePrefix, &fStrNotSafe);
  1428. if (fStrNotSafe)
  1429. {
  1430. dwErr = ERROR_INVALID_PARAMETER;
  1431. goto cleanup;
  1432. }
  1433. }
  1434. if (CachePath)
  1435. {
  1436. ALLOC_MB(CachePath,0,mpCachePath);
  1437. if (!mpCachePath.psStr)
  1438. {
  1439. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1440. goto cleanup;
  1441. }
  1442. UNICODE_TO_ANSI_CHECKED(CachePath,mpCachePath, &fStrNotSafe);
  1443. if (fStrNotSafe)
  1444. {
  1445. dwErr = ERROR_INVALID_PARAMETER;
  1446. goto cleanup;
  1447. }
  1448. }
  1449. #else
  1450. // Theoretically, the following fragment should be smaller than the above fragment.
  1451. // Although the retail obj shows a function that's about 100 bytes shorter, the
  1452. // actual dll doesn't show this gain. Until I figure this out, we won't use it.
  1453. DWORD c;
  1454. do
  1455. {
  1456. MEMORYPACKET* mp;
  1457. PCWSTR psz;
  1458. switch (c)
  1459. {
  1460. case 0:
  1461. psz = Name;
  1462. mp = &mpName;
  1463. break;
  1464. case 1:
  1465. psz = CachePrefix;
  1466. mp = &mpCachePrefix;
  1467. break;
  1468. case 2:
  1469. psz = CachePath;
  1470. mp = &mpCachePath;
  1471. break;
  1472. }
  1473. ALLOC_MB(psz, 0, (*mp));
  1474. if (!mp->psStr)
  1475. {
  1476. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1477. goto cleanup;
  1478. }
  1479. UNICODE_TO_ANSI_CHECKED(psz, (*mp), &fStrNotSafe);
  1480. if (fStrNotSafe)
  1481. {
  1482. dwErr = ERROR_INVALID_PARAMETER;
  1483. goto cleanup;
  1484. }
  1485. c++;
  1486. }
  1487. while (c<3);
  1488. #endif
  1489. fResult = CreateUrlCacheContainerA(
  1490. mpName.psStr,
  1491. mpCachePrefix.psStr,
  1492. mpCachePath.psStr,
  1493. KBCacheLimit,
  1494. dwContainerType,
  1495. dwOptions,
  1496. pvBuffer,
  1497. cbBuffer);
  1498. cleanup:
  1499. if (dwErr!=ERROR_SUCCESS)
  1500. {
  1501. SetLastError(dwErr);
  1502. DEBUG_ERROR(API, dwErr);
  1503. }
  1504. DEBUG_LEAVE_API(fResult);
  1505. return fResult;
  1506. }
  1507. URLCACHEAPI
  1508. BOOL
  1509. WINAPI
  1510. DeleteUrlCacheContainerW(
  1511. IN LPCWSTR Name,
  1512. IN DWORD dwOptions)
  1513. {
  1514. ENTER_CACHE_API ((DBG_API, Bool, "DeleteContainerW", "%wq, %#x", Name, dwOptions));
  1515. DWORD dwErr = ERROR_SUCCESS;
  1516. MEMORYPACKET mpName;
  1517. BOOL fResult = FALSE, fStrNotSafe = FALSE;
  1518. ALLOC_MB(Name, 0, mpName);
  1519. if (!mpName.psStr)
  1520. {
  1521. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1522. goto cleanup;
  1523. }
  1524. UNICODE_TO_ANSI_CHECKED(Name, mpName, &fStrNotSafe);
  1525. if (fStrNotSafe)
  1526. {
  1527. dwErr = ERROR_INVALID_PARAMETER;
  1528. goto cleanup;
  1529. }
  1530. fResult = DeleteUrlCacheContainerA(mpName.psStr, dwOptions);
  1531. cleanup:
  1532. if (dwErr!=ERROR_SUCCESS)
  1533. {
  1534. SetLastError(dwErr);
  1535. DEBUG_ERROR(API, dwErr);
  1536. }
  1537. DEBUG_LEAVE_API(fResult);
  1538. return fResult;
  1539. }
  1540. URLCACHEAPI
  1541. HANDLE
  1542. WINAPI
  1543. FindFirstUrlCacheContainerW(
  1544. IN OUT DWORD *pdwModified,
  1545. OUT LPINTERNET_CACHE_CONTAINER_INFOW lpContainerInfo,
  1546. IN OUT LPDWORD lpcbContainerInfo,
  1547. IN DWORD dwOptions
  1548. )
  1549. {
  1550. ENTER_CACHE_API ((DBG_API, Bool, "FindFirstContainerW",
  1551. "%#x, %#x, %#x, %#x",
  1552. pdwModified,
  1553. lpContainerInfo,
  1554. lpcbContainerInfo,
  1555. dwOptions
  1556. ));
  1557. DWORD dwErr = ERROR_SUCCESS;
  1558. MEMORYPACKET mpCacheInfo;
  1559. HANDLE hInternet = NULL;
  1560. if (!(lpcbContainerInfo && lpContainerInfo))
  1561. {
  1562. dwErr = ERROR_INVALID_PARAMETER;
  1563. goto cleanup;
  1564. }
  1565. mpCacheInfo.psStr = (PSTR)ALLOC_BYTES(*lpcbContainerInfo);
  1566. if (!mpCacheInfo.psStr)
  1567. {
  1568. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1569. goto cleanup;
  1570. }
  1571. mpCacheInfo.dwSize = mpCacheInfo.dwAlloc = *lpcbContainerInfo;
  1572. hInternet = FindFirstUrlCacheContainerA(pdwModified,
  1573. (LPINTERNET_CACHE_CONTAINER_INFOA)mpCacheInfo.psStr, &mpCacheInfo.dwSize, dwOptions);
  1574. // TransformCacheContainerInfoToW takes the return value and decides if any further actions need to be taken
  1575. // (eg. if successful, then try to convert from ansi to unicode; else if the ansi api failed, should we care?)
  1576. if (!TransformCacheContainerInfoToW(
  1577. hInternet ? TRUE : FALSE,
  1578. (LPINTERNET_CACHE_CONTAINER_INFOA)mpCacheInfo.psStr,
  1579. mpCacheInfo.dwSize,
  1580. lpContainerInfo,
  1581. lpcbContainerInfo))
  1582. {
  1583. if (hInternet)
  1584. {
  1585. FindCloseUrlCache(hInternet);
  1586. hInternet = NULL;
  1587. }
  1588. }
  1589. cleanup:
  1590. if (dwErr!=ERROR_SUCCESS)
  1591. {
  1592. SetLastError(dwErr);
  1593. DEBUG_ERROR(API, dwErr);
  1594. }
  1595. DEBUG_LEAVE_API(hInternet);
  1596. return hInternet;
  1597. }
  1598. URLCACHEAPI
  1599. BOOL
  1600. WINAPI
  1601. FindNextUrlCacheContainerW(
  1602. IN HANDLE hEnumHandle,
  1603. OUT LPINTERNET_CACHE_CONTAINER_INFOW lpContainerInfo,
  1604. IN OUT LPDWORD lpcbContainerInfo
  1605. )
  1606. {
  1607. ENTER_CACHE_API ((DBG_API, Bool, "FindNextContainerW",
  1608. "%#x, %#x, %#x",
  1609. hEnumHandle,
  1610. lpContainerInfo,
  1611. lpcbContainerInfo
  1612. ));
  1613. DWORD dwErr = ERROR_SUCCESS;
  1614. MEMORYPACKET mpCacheInfo;
  1615. BOOL fResult = FALSE;
  1616. if (!(lpcbContainerInfo && lpContainerInfo))
  1617. {
  1618. dwErr = ERROR_INVALID_PARAMETER;
  1619. goto cleanup;
  1620. }
  1621. mpCacheInfo.psStr = (PSTR)ALLOC_BYTES(*lpcbContainerInfo);
  1622. if (!mpCacheInfo.psStr)
  1623. {
  1624. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  1625. goto cleanup;
  1626. }
  1627. mpCacheInfo.dwSize = mpCacheInfo.dwAlloc = *lpcbContainerInfo;
  1628. fResult = FindNextUrlCacheContainerA(
  1629. hEnumHandle,
  1630. (LPINTERNET_CACHE_CONTAINER_INFOA)mpCacheInfo.psStr,
  1631. &mpCacheInfo.dwSize);
  1632. // TransformCacheContainerInfoToW takes the return value and decides if any further actions need to be taken
  1633. // (eg. if successful, then try to convert from ansi to unicode; else if the ansi api failed, should we care?)
  1634. fResult = TransformCacheContainerInfoToW(
  1635. fResult,
  1636. (LPINTERNET_CACHE_CONTAINER_INFOA)mpCacheInfo.psStr,
  1637. mpCacheInfo.dwSize,
  1638. lpContainerInfo,
  1639. lpcbContainerInfo);
  1640. cleanup:
  1641. if (dwErr!=ERROR_SUCCESS)
  1642. {
  1643. SetLastError(dwErr);
  1644. DEBUG_ERROR(API, dwErr);
  1645. }
  1646. DEBUG_LEAVE_API(fResult);
  1647. return fResult;
  1648. }
  1649. /* here's the struct referred to below
  1650. typedef struct _INTERNET_CACHE_CONFIG_INFOA {
  1651. DWORD dwStructSize;
  1652. DWORD dwContainer;
  1653. DWORD dwQuota;
  1654. DWORD dwReserved4;
  1655. BOOL fPerUser;
  1656. DWORD dwSyncMode;
  1657. DWORD dwNumCachePaths;
  1658. union
  1659. {
  1660. struct
  1661. {
  1662. CHAR CachePath[MAX_PATH];
  1663. DWORD dwCacheSize;
  1664. };
  1665. INTERNET_CACHE_CONFIG_PATH_ENTRYA CachePaths[ANYSIZE_ARRAY];
  1666. };
  1667. DWORD dwNormalUsage;
  1668. DWORD dwExemptUsage;
  1669. } INTERNET_CACHE_CONFIG_INFOA, * LPINTERNET_CACHE_CONFIG_INFOA;
  1670. */
  1671. #define ICCIA_FIXED_PORTION_SIZE ((sizeof(DWORD)*6)+sizeof(BOOL))
  1672. /*
  1673. URLCACHEAPI
  1674. BOOL
  1675. WINAPI
  1676. GetUrlCacheConfigInfoW(
  1677. OUT LPINTERNET_CACHE_CONFIG_INFOW pCacheConfigInfo,
  1678. IN OUT LPDWORD pcbCacheConfigInfo,
  1679. IN DWORD dwFieldControl
  1680. )
  1681. {
  1682. ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheConfigInfoW", "%#x, %#x, %#x",
  1683. pCacheConfigInfo, pcbCacheConfigInfo, dwFieldControl ));
  1684. INTERNET_CACHE_CONFIG_INFOA iccia;
  1685. iccia.dwContainer = pCacheConfigInfo->dwContainer;
  1686. iccia.dwStructSize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
  1687. DWORD dwSize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
  1688. BOOL fResult = GetUrlCacheConfigInfoA(&iccia, &dwSize, dwFieldControl);
  1689. if (fResult)
  1690. {
  1691. memcpy(pCacheConfigInfo, &iccia, ICCIA_FIXED_PORTION_SIZE);
  1692. // These are appended to the _end_ of the structure.
  1693. pCacheConfigInfo->dwNormalUsage = iccia.dwNormalUsage;
  1694. pCacheConfigInfo->dwExemptUsage = iccia.dwExemptUsage;
  1695. pCacheConfigInfo->dwStructSize = sizeof(INTERNET_CACHE_CONFIG_INFOW);
  1696. if (pCacheConfigInfo->dwContainer <= HISTORY)
  1697. {
  1698. MultiByteToWideChar(CP_ACP, 0, iccia.CachePath, -1, pCacheConfigInfo->CachePath, ARRAY_ELEMENTS(pCacheConfigInfo->CachePath));
  1699. }
  1700. }
  1701. DEBUG_LEAVE_API (fResult);
  1702. return fResult;
  1703. }
  1704. URLCACHEAPI
  1705. BOOL
  1706. WINAPI
  1707. SetUrlCacheConfigInfoW(
  1708. LPCACHE_CONFIG_INFOW lpConfigConfigInfo,
  1709. DWORD dwFieldControl
  1710. )
  1711. {
  1712. SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
  1713. return( FALSE );
  1714. }
  1715. */