Text reformatting patch to clean up all the static strings.
[wine.git] / dlls / wininet / urlcache.c
blob337dbe5d4cd936c8e93ed180bbcc34e70843cd40
1 /*
2 * Wininet - Url Cache functions
4 * Copyright 2001,2002 CodeWeavers
5 * Copyright 2003 Robert Shearman
7 * Eric Kohl
8 * Aric Stewart
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #define COM_NO_WINDOWS_H
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winuser.h"
38 #include "wininet.h"
39 #include "winerror.h"
40 #include "internet.h"
41 #include "winreg.h"
42 #include "shlwapi.h"
43 #include "wingdi.h"
44 #include "shlobj.h"
46 #include "wine/unicode.h"
47 #include "wine/list.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
52 #define ENTRY_START_OFFSET 0x4000
53 #define DIR_LENGTH 8
54 #define BLOCKSIZE 128
55 #define HASHTABLE_SIZE 448
56 #define HASHTABLE_BLOCKSIZE 7
57 #define HASHTABLE_FREE 3
58 #define ALLOCATION_TABLE_OFFSET 0x250
59 #define ALLOCATION_TABLE_SIZE (0x1000 - ALLOCATION_TABLE_OFFSET)
60 #define HASHTABLE_NUM_ENTRIES (HASHTABLE_SIZE / HASHTABLE_BLOCKSIZE)
62 #define DWORD_SIG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
63 #define URL_SIGNATURE DWORD_SIG('U','R','L',' ')
64 #define REDR_SIGNATURE DWORD_SIG('R','E','D','R')
65 #define LEAK_SIGNATURE DWORD_SIG('L','E','A','K')
66 #define HASH_SIGNATURE DWORD_SIG('H','A','S','H')
68 #define DWORD_ALIGN(x) ( (DWORD)(((DWORD)(x)+sizeof(DWORD)-1)/sizeof(DWORD))*sizeof(DWORD) )
70 typedef struct _CACHEFILE_ENTRY
72 /* union
73 {*/
74 DWORD dwSignature; /* e.g. "URL " */
75 /* CHAR szSignature[4];
76 };*/
77 DWORD dwBlocksUsed; /* number of 128byte blocks used by this entry */
78 } CACHEFILE_ENTRY;
80 typedef struct _URL_CACHEFILE_ENTRY
82 CACHEFILE_ENTRY CacheFileEntry;
83 FILETIME LastModifiedTime;
84 FILETIME LastAccessTime;
85 WORD wExpiredDate; /* expire date in dos format */
86 WORD wExpiredTime; /* expire time in dos format */
87 DWORD dwUnknown1; /* usually zero */
88 DWORD dwSizeLow; /* see INTERNET_CACHE_ENTRY_INFO::dwSizeLow */
89 DWORD dwSizeHigh; /* see INTERNET_CACHE_ENTRY_INFO::dwSizeHigh */
90 DWORD dwUnknown2; /* usually zero */
91 DWORD dwExemptDelta; /* see INTERNET_CACHE_ENTRY_INFO::dwExemptDelta */
92 DWORD dwUnknown3; /* usually 0x60 */
93 DWORD dwOffsetUrl; /* usually 0x68 */
94 BYTE CacheDir; /* index of cache directory this url is stored in */
95 BYTE Unknown4; /* usually zero */
96 WORD wUnknown5; /* usually 0x1010 */
97 DWORD dwOffsetLocalName; /* offset of start of local filename from start of entry */
98 DWORD CacheEntryType; /* see INTERNET_CACHE_ENTRY_INFO::CacheEntryType */
99 DWORD dwOffsetHeaderInfo; /* offset of start of header info from start of entry */
100 DWORD dwHeaderInfoSize;
101 DWORD dwUnknown6; /* usually zero */
102 WORD wLastSyncDate; /* last sync date in dos format */
103 WORD wLastSyncTime; /* last sync time in dos format */
104 DWORD dwHitRate; /* see INTERNET_CACHE_ENTRY_INFO::dwHitRate */
105 DWORD dwUseCount; /* see INTERNET_CACHE_ENTRY_INFO::dwUseCount */
106 WORD wUnknownDate; /* usually same as wLastSyncDate */
107 WORD wUnknownTime; /* usually same as wLastSyncTime */
108 DWORD dwUnknown7; /* usually zero */
109 DWORD dwUnknown8; /* usually zero */
110 CHAR szSourceUrlName[1]; /* start of url */
111 /* packing to dword align start of next field */
112 /* CHAR szLocalFileName[]; (local file name exluding path) */
113 /* packing to dword align start of next field */
114 /* CHAR szHeaderInfo[]; (header info) */
115 } URL_CACHEFILE_ENTRY;
117 struct _HASH_ENTRY
119 DWORD dwHashKey;
120 DWORD dwOffsetEntry;
123 typedef struct _HASH_CACHEFILE_ENTRY
125 CACHEFILE_ENTRY CacheFileEntry;
126 DWORD dwAddressNext;
127 DWORD dwHashTableNumber;
128 struct _HASH_ENTRY HashTable[HASHTABLE_SIZE];
129 } HASH_CACHEFILE_ENTRY;
131 typedef struct _DIRECTORY_DATA
133 DWORD dwUnknown;
134 char filename[DIR_LENGTH];
135 } DIRECTORY_DATA;
137 typedef struct _URLCACHE_HEADER
139 char szSignature[28];
140 DWORD dwFileSize;
141 DWORD dwOffsetFirstHashTable;
142 DWORD dwIndexCapacityInBlocks;
143 DWORD dwBlocksInUse; /* is this right? */
144 DWORD dwUnknown1;
145 DWORD dwCacheLimitLow; /* disk space limit for cache */
146 DWORD dwCacheLimitHigh; /* disk space limit for cache */
147 DWORD dwUnknown4; /* current disk space usage for cache? */
148 DWORD dwUnknown5; /* current disk space usage for cache? */
149 DWORD dwUnknown6; /* possibly a flag? */
150 DWORD dwUnknown7;
151 BYTE DirectoryCount; /* number of directory_data's */
152 BYTE Unknown8[3]; /* just padding? */
153 DIRECTORY_DATA directory_data[1]; /* first directory entry */
154 } URLCACHE_HEADER, *LPURLCACHE_HEADER;
155 typedef const URLCACHE_HEADER *LPCURLCACHE_HEADER;
157 typedef struct _STREAM_HANDLE
159 HANDLE hFile;
160 CHAR lpszUrl[1];
161 } STREAM_HANDLE;
163 typedef struct _URLCACHECONTAINER
165 struct list entry; /* part of a list */
166 LPWSTR cache_prefix; /* string that has to be prefixed for this container to be used */
167 LPWSTR path; /* path to url container directory */
168 HANDLE hMapping; /* handle of file mapping */
169 DWORD file_size; /* size of file when mapping was opened */
170 HANDLE hMutex; /* hande of mutex */
171 } URLCACHECONTAINER;
174 /* List of all containers available */
175 static struct list UrlContainers = LIST_INIT(UrlContainers);
178 /***********************************************************************
179 * URLCache_PathToObjectName (Internal)
181 * Converts a path to a name suitable for use as a Win32 object name.
182 * Replaces '\\' characters in-place with the specified character
183 * (usually '_' or '!')
185 * RETURNS
186 * nothing
189 static void URLCache_PathToObjectName(LPWSTR lpszPath, WCHAR replace)
191 for (; *lpszPath; lpszPath++)
193 if (*lpszPath == '\\')
194 *lpszPath = replace;
198 /***********************************************************************
199 * URLCacheContainer_OpenIndex (Internal)
201 * Opens the index file and saves mapping handle in hCacheIndexMapping
203 * RETURNS
204 * TRUE if succeeded
205 * FALSE if failed
208 static BOOL URLCacheContainer_OpenIndex(URLCACHECONTAINER * pContainer)
210 HANDLE hFile;
211 WCHAR wszFilePath[MAX_PATH];
212 DWORD dwFileSize;
214 static const WCHAR wszIndex[] = {'i','n','d','e','x','.','d','a','t',0};
215 static const WCHAR wszMappingFormat[] = {'%','s','%','s','_','%','l','u',0};
217 if (pContainer->hMapping)
218 return TRUE;
220 strcpyW(wszFilePath, pContainer->path);
221 strcatW(wszFilePath, wszIndex);
223 hFile = CreateFileW(wszFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
224 if (hFile == INVALID_HANDLE_VALUE)
226 FIXME("need to create cache index file\n");
227 return FALSE;
230 dwFileSize = GetFileSize(hFile, NULL);
231 if (dwFileSize == INVALID_FILE_SIZE)
232 return FALSE;
234 if (dwFileSize == 0)
236 FIXME("need to create cache index file\n");
237 return FALSE;
240 wsprintfW(wszFilePath, wszMappingFormat, pContainer->path, wszIndex, dwFileSize);
241 URLCache_PathToObjectName(wszFilePath, '_');
242 pContainer->hMapping = OpenFileMappingW(FILE_MAP_WRITE, FALSE, wszFilePath);
243 if (!pContainer->hMapping)
244 pContainer->hMapping = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, 0, 0, wszFilePath);
245 CloseHandle(hFile);
246 if (!pContainer->hMapping)
248 ERR("Couldn't create file mapping (error is %ld)\n", GetLastError());
249 return FALSE;
252 return TRUE;
255 /***********************************************************************
256 * URLCacheContainer_CloseIndex (Internal)
258 * Closes the index
260 * RETURNS
261 * nothing
264 static void URLCacheContainer_CloseIndex(URLCACHECONTAINER * pContainer)
266 CloseHandle(pContainer->hMapping);
267 pContainer->hMapping = NULL;
270 static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix, LPCWSTR path, LPWSTR mutex_name)
272 URLCACHECONTAINER * pContainer = HeapAlloc(GetProcessHeap(), 0, sizeof(URLCACHECONTAINER));
273 int path_len = strlenW(path);
274 int cache_prefix_len = strlenW(cache_prefix);
276 if (!pContainer)
278 return FALSE;
281 pContainer->hMapping = NULL;
282 pContainer->file_size = 0;
284 pContainer->path = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (path_len + 1) * sizeof(WCHAR));
285 if (!pContainer->path)
287 HeapFree(GetProcessHeap(), 0, pContainer);
288 return FALSE;
291 memcpy(pContainer->path, path, (path_len + 1) * sizeof(WCHAR));
293 pContainer->cache_prefix = HeapAlloc(GetProcessHeap(), 0, (cache_prefix_len + 1) * sizeof(WCHAR));
294 if (!pContainer->cache_prefix)
296 HeapFree(GetProcessHeap(), 0, pContainer->path);
297 HeapFree(GetProcessHeap(), 0, pContainer);
298 return FALSE;
301 memcpy(pContainer->cache_prefix, cache_prefix, (cache_prefix_len + 1) * sizeof(WCHAR));
303 CharLowerW(mutex_name);
304 URLCache_PathToObjectName(mutex_name, '!');
306 if ((pContainer->hMutex = CreateMutexW(NULL, FALSE, mutex_name)) == NULL)
308 ERR("couldn't create mutex (error is %ld)\n", GetLastError());
309 HeapFree(GetProcessHeap(), 0, pContainer->path);
310 HeapFree(GetProcessHeap(), 0, pContainer);
311 return FALSE;
314 list_add_head(&UrlContainers, &pContainer->entry);
316 return TRUE;
319 static void URLCacheContainer_DeleteContainer(URLCACHECONTAINER * pContainer)
321 list_remove(&pContainer->entry);
323 URLCacheContainer_CloseIndex(pContainer);
324 CloseHandle(pContainer->hMutex);
325 HeapFree(GetProcessHeap(), 0, pContainer->path);
326 HeapFree(GetProcessHeap(), 0, pContainer->cache_prefix);
327 HeapFree(GetProcessHeap(), 0, pContainer);
330 void URLCacheContainers_CreateDefaults()
332 static const WCHAR UrlSuffix[] = {'C','o','n','t','e','n','t','.','I','E','5',0};
333 static const WCHAR UrlPrefix[] = {0};
334 static const WCHAR HistorySuffix[] = {'H','i','s','t','o','r','y','.','I','E','5',0};
335 static const WCHAR HistoryPrefix[] = {'V','i','s','i','t','e','d',':',0};
336 static const WCHAR CookieSuffix[] = {0};
337 static const WCHAR CookiePrefix[] = {'C','o','o','k','i','e',':',0};
338 static const struct
340 int nFolder; /* CSIDL_* constant */
341 const WCHAR * shpath_suffix; /* suffix on path returned by SHGetSpecialFolderPath */
342 const WCHAR * cache_prefix; /* prefix used to reference the container */
343 } DefaultContainerData[] =
345 { CSIDL_INTERNET_CACHE, UrlSuffix, UrlPrefix },
346 { CSIDL_HISTORY, HistorySuffix, HistoryPrefix },
347 { CSIDL_COOKIES, CookieSuffix, CookiePrefix },
349 DWORD i;
351 for (i = 0; i < sizeof(DefaultContainerData) / sizeof(DefaultContainerData[0]); i++)
353 WCHAR wszCachePath[MAX_PATH];
354 WCHAR wszMutexName[MAX_PATH];
355 int path_len, suffix_len;
357 if (FAILED(SHGetSpecialFolderPathW(NULL, wszCachePath, DefaultContainerData[i].nFolder, TRUE)))
359 ERR("Couldn't get path for default container %lu\n", i);
360 continue;
362 path_len = strlenW(wszCachePath);
363 suffix_len = strlenW(DefaultContainerData[i].shpath_suffix);
365 if (path_len + suffix_len + 2 > MAX_PATH)
367 ERR("Path too long\n");
368 continue;
371 wszCachePath[path_len] = '\\';
373 strcpyW(wszMutexName, wszCachePath);
375 if (suffix_len)
377 memcpy(wszCachePath + path_len + 1, DefaultContainerData[i].shpath_suffix, (suffix_len + 1) * sizeof(WCHAR));
378 wszCachePath[path_len + suffix_len + 1] = '\\';
379 wszCachePath[path_len + suffix_len + 2] = '\0';
382 URLCacheContainers_AddContainer(DefaultContainerData[i].cache_prefix, wszCachePath, wszMutexName);
386 void URLCacheContainers_DeleteAll()
388 while(!list_empty(&UrlContainers))
389 URLCacheContainer_DeleteContainer(
390 LIST_ENTRY(list_head(&UrlContainers), URLCACHECONTAINER, entry)
394 static BOOL URLCacheContainers_FindContainerW(LPCWSTR lpwszUrl, URLCACHECONTAINER ** ppContainer)
396 struct list * cursor;
398 TRACE("searching for prefix for URL: %s\n", debugstr_w(lpwszUrl));
400 LIST_FOR_EACH(cursor, &UrlContainers)
402 URLCACHECONTAINER * pContainer = LIST_ENTRY(cursor, URLCACHECONTAINER, entry);
403 int prefix_len = strlenW(pContainer->cache_prefix);
404 if (!strncmpW(pContainer->cache_prefix, lpwszUrl, prefix_len))
406 TRACE("found container with prefx %s for URL %s\n", debugstr_w(pContainer->cache_prefix), debugstr_w(lpwszUrl));
407 *ppContainer = pContainer;
408 return TRUE;
411 ERR("no container found\n");
412 SetLastError(ERROR_FILE_NOT_FOUND);
413 return FALSE;
416 static BOOL URLCacheContainers_FindContainerA(LPCSTR lpszUrl, URLCACHECONTAINER ** ppContainer)
418 BOOL ret;
419 LPWSTR lpwszUrl;
420 int url_len = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0);
421 if (url_len && (lpwszUrl = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(WCHAR))))
423 MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, lpwszUrl, url_len);
424 ret = URLCacheContainers_FindContainerW(lpwszUrl, ppContainer);
425 HeapFree(GetProcessHeap(), 0, lpwszUrl);
426 return ret;
428 return FALSE;
431 /***********************************************************************
432 * URLCacheContainer_LockIndex (Internal)
435 static LPURLCACHE_HEADER URLCacheContainer_LockIndex(URLCACHECONTAINER * pContainer)
437 BYTE index;
438 LPVOID pIndexData;
439 URLCACHE_HEADER * pHeader;
441 /* acquire mutex */
442 WaitForSingleObject(pContainer->hMutex, INFINITE);
444 pIndexData = MapViewOfFile(pContainer->hMapping, FILE_MAP_WRITE, 0, 0, 0);
446 if (!pIndexData)
448 ReleaseMutex(pContainer->hMutex);
449 ERR("Couldn't MapViewOfFile. Error: %ld\n", GetLastError());
450 return FALSE;
452 pHeader = (URLCACHE_HEADER *)pIndexData;
454 /* file has grown - we need to remap to prevent us getting
455 * access violations when we try and access beyond the end
456 * of the memory mapped file */
457 if (pHeader->dwFileSize != pContainer->file_size)
459 URLCacheContainer_CloseIndex(pContainer);
460 if (!URLCacheContainer_OpenIndex(pContainer))
462 ReleaseMutex(pContainer->hMutex);
463 return FALSE;
465 pIndexData = MapViewOfFile(pContainer->hMapping, FILE_MAP_WRITE, 0, 0, 0);
467 if (!pIndexData)
469 ReleaseMutex(pContainer->hMutex);
470 ERR("Couldn't MapViewOfFile. Error: %ld\n", GetLastError());
471 return FALSE;
473 pHeader = (URLCACHE_HEADER *)pIndexData;
476 TRACE("Signature: %s, file size: %ld bytes\n", pHeader->szSignature, pHeader->dwFileSize);
478 for (index = 0; index < pHeader->DirectoryCount; index++)
480 TRACE("Directory[%d] = \"%.8s\"\n", index, pHeader->directory_data[index].filename);
483 return pHeader;
486 /***********************************************************************
487 * URLCacheContainer_UnlockIndex (Internal)
490 static BOOL URLCacheContainer_UnlockIndex(URLCACHECONTAINER * pContainer, LPURLCACHE_HEADER pHeader)
492 /* release mutex */
493 ReleaseMutex(pContainer->hMutex);
494 return UnmapViewOfFile(pHeader);
498 #ifndef CHAR_BIT
499 #define CHAR_BIT (8 * sizeof(CHAR))
500 #endif
502 /***********************************************************************
503 * URLCache_Allocation_BlockIsFree (Internal)
505 * Is the specified block number free?
507 * RETURNS
508 * zero if free
509 * non-zero otherwise
512 static inline BYTE URLCache_Allocation_BlockIsFree(BYTE * AllocationTable, DWORD dwBlockNumber)
514 BYTE mask = 1 << (dwBlockNumber % CHAR_BIT);
515 return (AllocationTable[dwBlockNumber / CHAR_BIT] & mask) == 0;
518 /***********************************************************************
519 * URLCache_Allocation_BlockFree (Internal)
521 * Marks the specified block as free
523 * RETURNS
524 * nothing
527 static inline void URLCache_Allocation_BlockFree(BYTE * AllocationTable, DWORD dwBlockNumber)
529 BYTE mask = ~(1 << (dwBlockNumber % CHAR_BIT));
530 AllocationTable[dwBlockNumber / CHAR_BIT] &= mask;
533 /***********************************************************************
534 * URLCache_Allocation_BlockAllocate (Internal)
536 * Marks the specified block as allocated
538 * RETURNS
539 * nothing
542 static inline void URLCache_Allocation_BlockAllocate(BYTE * AllocationTable, DWORD dwBlockNumber)
544 BYTE mask = 1 << (dwBlockNumber % CHAR_BIT);
545 AllocationTable[dwBlockNumber / CHAR_BIT] |= mask;
548 /***********************************************************************
549 * URLCache_FindFirstFreeEntry (Internal)
551 * Finds and allocates the first block of free space big enough and
552 * sets ppEntry to point to it.
554 * RETURNS
555 * TRUE if it had enough space
556 * FALSE if it couldn't find enough space
559 static BOOL URLCache_FindFirstFreeEntry(URLCACHE_HEADER * pHeader, DWORD dwBlocksNeeded, CACHEFILE_ENTRY ** ppEntry)
561 LPBYTE AllocationTable = (LPBYTE)pHeader + ALLOCATION_TABLE_OFFSET;
562 DWORD dwBlockNumber;
563 DWORD dwFreeCounter;
564 for (dwBlockNumber = 0; dwBlockNumber < pHeader->dwIndexCapacityInBlocks; dwBlockNumber++)
566 for (dwFreeCounter = 0;
567 dwFreeCounter < dwBlocksNeeded &&
568 dwFreeCounter + dwBlockNumber < pHeader->dwIndexCapacityInBlocks &&
569 URLCache_Allocation_BlockIsFree(AllocationTable, dwBlockNumber + dwFreeCounter);
570 dwFreeCounter++)
571 TRACE("Found free block at no. %ld (0x%lx)\n", dwBlockNumber, ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
573 if (dwFreeCounter == dwBlocksNeeded)
575 DWORD index;
576 TRACE("Found free blocks starting at no. %ld (0x%lx)\n", dwBlockNumber, ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
577 for (index = 0; index < dwBlocksNeeded; index++)
578 URLCache_Allocation_BlockAllocate(AllocationTable, dwBlockNumber + index);
579 *ppEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
580 (*ppEntry)->dwBlocksUsed = dwBlocksNeeded;
581 return TRUE;
584 FIXME("Grow file\n");
585 return FALSE;
588 /***********************************************************************
589 * URLCache_DeleteEntry (Internal)
591 * Deletes the specified entry and frees the space allocated to it
593 * RETURNS
594 * TRUE if it succeeded
595 * FALSE if it failed
598 static BOOL URLCache_DeleteEntry(CACHEFILE_ENTRY * pEntry)
600 ZeroMemory(pEntry, pEntry->dwBlocksUsed * BLOCKSIZE);
601 return TRUE;
604 /***********************************************************************
605 * URLCache_LocalFileNameToPathW (Internal)
607 * Copies the full path to the specified buffer given the local file
608 * name and the index of the directory it is in. Always sets value in
609 * lpBufferSize to the required buffer size (in bytes).
611 * RETURNS
612 * TRUE if the buffer was big enough
613 * FALSE if the buffer was too small
616 static BOOL URLCache_LocalFileNameToPathW(
617 const URLCACHECONTAINER * pContainer,
618 LPCURLCACHE_HEADER pHeader,
619 LPCSTR szLocalFileName,
620 BYTE Directory,
621 LPWSTR wszPath,
622 LPLONG lpBufferSize)
624 LONG nRequired;
625 int path_len = strlenW(pContainer->path);
626 int file_name_len = MultiByteToWideChar(CP_ACP, 0, szLocalFileName, -1, NULL, 0);
627 if (Directory >= pHeader->DirectoryCount)
629 *lpBufferSize = 0;
630 return FALSE;
633 nRequired = (path_len + DIR_LENGTH + file_name_len + 1) * sizeof(WCHAR);
634 if (nRequired < *lpBufferSize)
636 int dir_len;
638 memcpy(wszPath, pContainer->path, path_len * sizeof(WCHAR));
639 dir_len = MultiByteToWideChar(CP_ACP, 0, pHeader->directory_data[Directory].filename, DIR_LENGTH, wszPath + path_len, DIR_LENGTH);
640 wszPath[dir_len + path_len] = '\\';
641 MultiByteToWideChar(CP_ACP, 0, szLocalFileName, -1, wszPath + dir_len + path_len + 1, file_name_len);
642 *lpBufferSize = nRequired;
643 return TRUE;
645 *lpBufferSize = nRequired;
646 return FALSE;
649 /***********************************************************************
650 * URLCache_LocalFileNameToPathA (Internal)
652 * Copies the full path to the specified buffer given the local file
653 * name and the index of the directory it is in. Always sets value in
654 * lpBufferSize to the required buffer size.
656 * RETURNS
657 * TRUE if the buffer was big enough
658 * FALSE if the buffer was too small
661 static BOOL URLCache_LocalFileNameToPathA(
662 const URLCACHECONTAINER * pContainer,
663 LPCURLCACHE_HEADER pHeader,
664 LPCSTR szLocalFileName,
665 BYTE Directory,
666 LPSTR szPath,
667 LPLONG lpBufferSize)
669 LONG nRequired;
670 int path_len = WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, NULL, 0, NULL, NULL);
671 int file_name_len = strlen(szLocalFileName);
672 int dir_len = DIR_LENGTH;
673 if (Directory >= pHeader->DirectoryCount)
675 *lpBufferSize = 0;
676 return FALSE;
679 nRequired = (path_len + dir_len + file_name_len + 1) * sizeof(WCHAR);
680 if (nRequired < *lpBufferSize)
682 WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, szPath, -1, NULL, NULL);
683 strncpy(szPath, pHeader->directory_data[Directory].filename, DIR_LENGTH);
684 szPath[dir_len + path_len] = '\\';
685 strcpy(szPath + dir_len + path_len + 1, szLocalFileName);
686 *lpBufferSize = nRequired;
687 return TRUE;
689 *lpBufferSize = nRequired;
690 return FALSE;
693 /***********************************************************************
694 * URLCache_CopyEntry (Internal)
696 * Copies an entry from the cache index file to the Win32 structure
698 * RETURNS
699 * TRUE if the buffer was big enough
700 * FALSE if the buffer was too small
703 static BOOL URLCache_CopyEntry(
704 URLCACHECONTAINER * pContainer,
705 LPCURLCACHE_HEADER pHeader,
706 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
707 LPDWORD lpdwBufferSize,
708 URL_CACHEFILE_ENTRY * pUrlEntry,
709 BOOL bUnicode)
711 int lenUrl;
712 DWORD dwRequiredSize = sizeof(*lpCacheEntryInfo);
714 if (*lpdwBufferSize >= dwRequiredSize)
716 lpCacheEntryInfo->lpHeaderInfo = NULL;
717 lpCacheEntryInfo->lpszFileExtension = NULL;
718 lpCacheEntryInfo->lpszLocalFileName = NULL;
719 lpCacheEntryInfo->lpszSourceUrlName = NULL;
720 lpCacheEntryInfo->CacheEntryType = pUrlEntry->CacheEntryType;
721 lpCacheEntryInfo->u.dwExemptDelta = pUrlEntry->dwExemptDelta;
722 lpCacheEntryInfo->dwHeaderInfoSize = pUrlEntry->dwHeaderInfoSize;
723 lpCacheEntryInfo->dwHitRate = pUrlEntry->dwHitRate;
724 lpCacheEntryInfo->dwSizeHigh = pUrlEntry->dwSizeHigh;
725 lpCacheEntryInfo->dwSizeLow = pUrlEntry->dwSizeLow;
726 lpCacheEntryInfo->dwStructSize = sizeof(*lpCacheEntryInfo);
727 lpCacheEntryInfo->dwUseCount = pUrlEntry->dwUseCount;
728 DosDateTimeToFileTime(pUrlEntry->wExpiredDate, pUrlEntry->wExpiredTime, &lpCacheEntryInfo->ExpireTime);
729 lpCacheEntryInfo->LastAccessTime.dwHighDateTime = pUrlEntry->LastAccessTime.dwHighDateTime;
730 lpCacheEntryInfo->LastAccessTime.dwLowDateTime = pUrlEntry->LastAccessTime.dwLowDateTime;
731 lpCacheEntryInfo->LastModifiedTime.dwHighDateTime = pUrlEntry->LastModifiedTime.dwHighDateTime;
732 lpCacheEntryInfo->LastModifiedTime.dwLowDateTime = pUrlEntry->LastModifiedTime.dwLowDateTime;
733 DosDateTimeToFileTime(pUrlEntry->wLastSyncDate, pUrlEntry->wLastSyncTime, &lpCacheEntryInfo->LastSyncTime);
736 if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
737 ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
738 dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
739 if (bUnicode)
740 lenUrl = MultiByteToWideChar(CP_ACP, 0, pUrlEntry->szSourceUrlName, -1, NULL, 0);
741 else
742 lenUrl = strlen(pUrlEntry->szSourceUrlName);
743 dwRequiredSize += lenUrl + 1;
745 /* FIXME: is source url optional? */
746 if (*lpdwBufferSize >= dwRequiredSize)
748 lpCacheEntryInfo->lpszSourceUrlName = (LPSTR)lpCacheEntryInfo + dwRequiredSize - lenUrl - 1;
749 if (bUnicode)
750 MultiByteToWideChar(CP_ACP, 0, pUrlEntry->szSourceUrlName, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenUrl + 1);
751 else
752 memcpy(lpCacheEntryInfo->lpszSourceUrlName, pUrlEntry->szSourceUrlName, (lenUrl + 1) * sizeof(CHAR));
755 if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
756 ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
757 dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
759 if (pUrlEntry->dwOffsetLocalName)
761 LONG nLocalFilePathSize;
762 LPSTR lpszLocalFileName;
763 lpszLocalFileName = (LPSTR)lpCacheEntryInfo + dwRequiredSize;
764 nLocalFilePathSize = *lpdwBufferSize - dwRequiredSize;
765 if ((bUnicode && URLCache_LocalFileNameToPathW(pContainer, pHeader, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetLocalName, pUrlEntry->CacheDir, (LPWSTR)lpszLocalFileName, &nLocalFilePathSize)) ||
766 URLCache_LocalFileNameToPathA(pContainer, pHeader, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetLocalName, pUrlEntry->CacheDir, lpszLocalFileName, &nLocalFilePathSize))
768 lpCacheEntryInfo->lpszLocalFileName = lpszLocalFileName;
770 dwRequiredSize += nLocalFilePathSize;
772 if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
773 ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
774 dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
776 dwRequiredSize += pUrlEntry->dwHeaderInfoSize + 1;
778 if (*lpdwBufferSize >= dwRequiredSize)
780 lpCacheEntryInfo->lpHeaderInfo = (LPBYTE)lpCacheEntryInfo + dwRequiredSize - pUrlEntry->dwHeaderInfoSize - 1;
781 memcpy(lpCacheEntryInfo->lpHeaderInfo, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo, pUrlEntry->dwHeaderInfoSize);
782 ((LPBYTE)lpCacheEntryInfo)[dwRequiredSize - 1] = '\0';
784 if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
785 ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
786 dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
788 if (dwRequiredSize > *lpdwBufferSize)
790 *lpdwBufferSize = dwRequiredSize;
791 SetLastError(ERROR_INSUFFICIENT_BUFFER);
792 return FALSE;
794 *lpdwBufferSize = dwRequiredSize;
795 return TRUE;
799 /***********************************************************************
800 * URLCache_SetEntryInfo (Internal)
802 * Helper for SetUrlCacheEntryInfo{A,W}. Sets fields in URL entry
803 * according the the flags set by dwFieldControl.
805 * RETURNS
806 * TRUE if the buffer was big enough
807 * FALSE if the buffer was too small
810 static BOOL URLCache_SetEntryInfo(URL_CACHEFILE_ENTRY * pUrlEntry, const INTERNET_CACHE_ENTRY_INFOW * lpCacheEntryInfo, DWORD dwFieldControl)
812 if (dwFieldControl & CACHE_ENTRY_ACCTIME_FC)
813 pUrlEntry->LastAccessTime = lpCacheEntryInfo->LastAccessTime;
814 if (dwFieldControl & CACHE_ENTRY_ATTRIBUTE_FC)
815 pUrlEntry->CacheEntryType = lpCacheEntryInfo->CacheEntryType;
816 if (dwFieldControl & CACHE_ENTRY_EXEMPT_DELTA_FC)
817 pUrlEntry->dwExemptDelta = lpCacheEntryInfo->u.dwExemptDelta;
818 if (dwFieldControl & CACHE_ENTRY_EXPTIME_FC)
819 FIXME("CACHE_ENTRY_EXPTIME_FC unimplemented\n");
820 if (dwFieldControl & CACHE_ENTRY_HEADERINFO_FC)
821 FIXME("CACHE_ENTRY_HEADERINFO_FC unimplemented\n");
822 if (dwFieldControl & CACHE_ENTRY_HITRATE_FC)
823 pUrlEntry->dwHitRate = lpCacheEntryInfo->dwHitRate;
824 if (dwFieldControl & CACHE_ENTRY_MODTIME_FC)
825 pUrlEntry->LastModifiedTime = lpCacheEntryInfo->LastModifiedTime;
826 if (dwFieldControl & CACHE_ENTRY_SYNCTIME_FC)
827 FileTimeToDosDateTime(&lpCacheEntryInfo->LastAccessTime, &pUrlEntry->wLastSyncDate, &pUrlEntry->wLastSyncTime);
829 return TRUE;
832 /***********************************************************************
833 * URLCache_HashKey (Internal)
835 * Returns the hash key for a given string
837 * RETURNS
838 * hash key for the string
841 static DWORD URLCache_HashKey(LPCSTR lpszKey)
843 /* NOTE: this uses the same lookup table as SHLWAPI.UrlHash{A,W}
844 * but the algorithm and result are not the same!
846 static const unsigned char lookupTable[256] =
848 0x01, 0x0E, 0x6E, 0x19, 0x61, 0xAE, 0x84, 0x77,
849 0x8A, 0xAA, 0x7D, 0x76, 0x1B, 0xE9, 0x8C, 0x33,
850 0x57, 0xC5, 0xB1, 0x6B, 0xEA, 0xA9, 0x38, 0x44,
851 0x1E, 0x07, 0xAD, 0x49, 0xBC, 0x28, 0x24, 0x41,
852 0x31, 0xD5, 0x68, 0xBE, 0x39, 0xD3, 0x94, 0xDF,
853 0x30, 0x73, 0x0F, 0x02, 0x43, 0xBA, 0xD2, 0x1C,
854 0x0C, 0xB5, 0x67, 0x46, 0x16, 0x3A, 0x4B, 0x4E,
855 0xB7, 0xA7, 0xEE, 0x9D, 0x7C, 0x93, 0xAC, 0x90,
856 0xB0, 0xA1, 0x8D, 0x56, 0x3C, 0x42, 0x80, 0x53,
857 0x9C, 0xF1, 0x4F, 0x2E, 0xA8, 0xC6, 0x29, 0xFE,
858 0xB2, 0x55, 0xFD, 0xED, 0xFA, 0x9A, 0x85, 0x58,
859 0x23, 0xCE, 0x5F, 0x74, 0xFC, 0xC0, 0x36, 0xDD,
860 0x66, 0xDA, 0xFF, 0xF0, 0x52, 0x6A, 0x9E, 0xC9,
861 0x3D, 0x03, 0x59, 0x09, 0x2A, 0x9B, 0x9F, 0x5D,
862 0xA6, 0x50, 0x32, 0x22, 0xAF, 0xC3, 0x64, 0x63,
863 0x1A, 0x96, 0x10, 0x91, 0x04, 0x21, 0x08, 0xBD,
864 0x79, 0x40, 0x4D, 0x48, 0xD0, 0xF5, 0x82, 0x7A,
865 0x8F, 0x37, 0x69, 0x86, 0x1D, 0xA4, 0xB9, 0xC2,
866 0xC1, 0xEF, 0x65, 0xF2, 0x05, 0xAB, 0x7E, 0x0B,
867 0x4A, 0x3B, 0x89, 0xE4, 0x6C, 0xBF, 0xE8, 0x8B,
868 0x06, 0x18, 0x51, 0x14, 0x7F, 0x11, 0x5B, 0x5C,
869 0xFB, 0x97, 0xE1, 0xCF, 0x15, 0x62, 0x71, 0x70,
870 0x54, 0xE2, 0x12, 0xD6, 0xC7, 0xBB, 0x0D, 0x20,
871 0x5E, 0xDC, 0xE0, 0xD4, 0xF7, 0xCC, 0xC4, 0x2B,
872 0xF9, 0xEC, 0x2D, 0xF4, 0x6F, 0xB6, 0x99, 0x88,
873 0x81, 0x5A, 0xD9, 0xCA, 0x13, 0xA5, 0xE7, 0x47,
874 0xE6, 0x8E, 0x60, 0xE3, 0x3E, 0xB3, 0xF6, 0x72,
875 0xA2, 0x35, 0xA0, 0xD7, 0xCD, 0xB4, 0x2F, 0x6D,
876 0x2C, 0x26, 0x1F, 0x95, 0x87, 0x00, 0xD8, 0x34,
877 0x3F, 0x17, 0x25, 0x45, 0x27, 0x75, 0x92, 0xB8,
878 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB, 0x0A,
879 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1
881 BYTE key[4];
882 DWORD i;
883 int subscript[sizeof(key) / sizeof(key[0])];
885 subscript[0] = *lpszKey;
886 subscript[1] = (char)(*lpszKey + 1);
887 subscript[2] = (char)(*lpszKey + 2);
888 subscript[3] = (char)(*lpszKey + 3);
890 for (i = 0; i < sizeof(key) / sizeof(key[0]); i++)
891 key[i] = lookupTable[i];
893 for (lpszKey++; *lpszKey && ((lpszKey[0] != '/') || (lpszKey[1] != 0)); lpszKey++)
895 for (i = 0; i < sizeof(key) / sizeof(key[0]); i++)
896 key[i] = lookupTable[*lpszKey ^ key[i]];
899 return *(DWORD *)key;
902 static inline HASH_CACHEFILE_ENTRY * URLCache_HashEntryFromOffset(LPCURLCACHE_HEADER pHeader, DWORD dwOffset)
904 return (HASH_CACHEFILE_ENTRY *)((LPBYTE)pHeader + dwOffset);
907 static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct _HASH_ENTRY ** ppHashEntry)
909 /* structure of hash table:
910 * 448 entries divided into 64 blocks
911 * each block therefore contains a chain of 7 key/offset pairs
912 * how position in table is calculated:
913 * 1. the url is hashed in helper function
914 * 2. the key % 64 * 8 is the offset
915 * 3. the key in the hash table is the hash key aligned to 64
917 * note:
918 * there can be multiple hash tables in the file and the offset to
919 * the next one is stored in the header of the hash table
921 DWORD key = URLCache_HashKey(lpszUrl);
922 DWORD offset = (key % HASHTABLE_NUM_ENTRIES) * sizeof(struct _HASH_ENTRY);
923 HASH_CACHEFILE_ENTRY * pHashEntry;
924 DWORD dwHashTableNumber = 0;
926 key = (DWORD)(key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES;
928 for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable);
929 ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize);
930 pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHashEntry->dwAddressNext))
932 int i;
933 if (pHashEntry->dwHashTableNumber != dwHashTableNumber++)
935 ERR("Error: not right hash table number (%ld) expected %ld\n", pHashEntry->dwHashTableNumber, dwHashTableNumber);
936 continue;
938 /* make sure that it is in fact a hash entry */
939 if (pHashEntry->CacheFileEntry.dwSignature != HASH_SIGNATURE)
941 ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->CacheFileEntry.dwSignature);
942 continue;
945 for (i = 0; i < HASHTABLE_BLOCKSIZE; i++)
947 struct _HASH_ENTRY * pHashElement = &pHashEntry->HashTable[offset + i];
948 if (key == (DWORD)(pHashElement->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES)
950 /* FIXME: we should make sure that this is the right element
951 * before returning and claiming that it is. We can do this
952 * by doing a simple compare between the URL we were given
953 * and the URL stored in the entry. However, this assumes
954 * we know the format of all the entries stored in the
955 * hash table */
956 *ppHashEntry = pHashElement;
957 return TRUE;
961 return FALSE;
964 /***********************************************************************
965 * URLCache_FindEntryInHash (Internal)
967 * Searches all the hash tables in the index for the given URL and
968 * returns the entry, if it was found, in ppEntry
970 * RETURNS
971 * TRUE if the entry was found
972 * FALSE if the entry could not be found
975 static BOOL URLCache_FindEntryInHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, CACHEFILE_ENTRY ** ppEntry)
977 struct _HASH_ENTRY * pHashEntry;
978 if (URLCache_FindHash(pHeader, lpszUrl, &pHashEntry))
980 *ppEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
981 return TRUE;
983 return FALSE;
986 /***********************************************************************
987 * URLCache_HashEntrySetUse (Internal)
989 * Searches all the hash tables in the index for the given URL and
990 * sets the use count (stored or'ed with key)
992 * RETURNS
993 * TRUE if the entry was found
994 * FALSE if the entry could not be found
997 static BOOL URLCache_HashEntrySetUse(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, DWORD dwUseCount)
999 struct _HASH_ENTRY * pHashEntry;
1000 if (URLCache_FindHash(pHeader, lpszUrl, &pHashEntry))
1002 pHashEntry->dwHashKey = dwUseCount | (DWORD)(pHashEntry->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES;
1003 return TRUE;
1005 return FALSE;
1008 /***********************************************************************
1009 * URLCache_DeleteEntryFromHash (Internal)
1011 * Searches all the hash tables in the index for the given URL and
1012 * then if found deletes the entry.
1014 * RETURNS
1015 * TRUE if the entry was found
1016 * FALSE if the entry could not be found
1019 static BOOL URLCache_DeleteEntryFromHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl)
1021 struct _HASH_ENTRY * pHashEntry;
1022 if (URLCache_FindHash(pHeader, lpszUrl, &pHashEntry))
1024 pHashEntry->dwHashKey = HASHTABLE_FREE;
1025 pHashEntry->dwOffsetEntry = HASHTABLE_FREE;
1026 return TRUE;
1028 return FALSE;
1031 /***********************************************************************
1032 * URLCache_AddEntryToHash (Internal)
1034 * Searches all the hash tables for a free slot based on the offset
1035 * generated from the hash key. If a free slot is found, the offset and
1036 * key are entered into the hash table.
1038 * RETURNS
1039 * TRUE if the entry was added
1040 * FALSE if the entry could not be added
1043 static BOOL URLCache_AddEntryToHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, DWORD dwOffsetEntry)
1045 /* see URLCache_FindEntryInHash for structure of hash tables */
1047 DWORD key = URLCache_HashKey(lpszUrl);
1048 DWORD offset = (key % HASHTABLE_NUM_ENTRIES) * sizeof(struct _HASH_ENTRY);
1049 HASH_CACHEFILE_ENTRY * pHashEntry;
1050 DWORD dwHashTableNumber = 0;
1052 key = (DWORD)(key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES;
1054 for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable);
1055 ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize);
1056 pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHashEntry->dwAddressNext))
1058 int i;
1059 if (pHashEntry->dwHashTableNumber != dwHashTableNumber++)
1061 ERR("not right hash table number (%ld) expected %ld\n", pHashEntry->dwHashTableNumber, dwHashTableNumber);
1062 break;
1064 /* make sure that it is in fact a hash entry */
1065 if (pHashEntry->CacheFileEntry.dwSignature != HASH_SIGNATURE)
1067 ERR("not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->CacheFileEntry.dwSignature);
1068 break;
1071 for (i = 0; i < HASHTABLE_BLOCKSIZE; i++)
1073 struct _HASH_ENTRY * pHashElement = &pHashEntry->HashTable[offset + i];
1074 if (pHashElement->dwHashKey == HASHTABLE_FREE) /* if the slot is free */
1076 pHashElement->dwHashKey = key;
1077 pHashElement->dwOffsetEntry = dwOffsetEntry;
1078 return TRUE;
1082 FIXME("need to create another hash table\n");
1083 return FALSE;
1086 /***********************************************************************
1087 * GetUrlCacheEntryInfoExA (WININET.@)
1090 BOOL WINAPI GetUrlCacheEntryInfoExA(
1091 LPCSTR lpszUrl,
1092 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1093 LPDWORD lpdwCacheEntryInfoBufSize,
1094 LPSTR lpszReserved,
1095 LPDWORD lpdwReserved,
1096 LPVOID lpReserved,
1097 DWORD dwFlags)
1099 TRACE("(%s, %p, %p, %p, %p, %p, %lx)\n",
1100 debugstr_a(lpszUrl),
1101 lpCacheEntryInfo,
1102 lpdwCacheEntryInfoBufSize,
1103 lpszReserved,
1104 lpdwReserved,
1105 lpReserved,
1106 dwFlags);
1108 if ((lpszReserved != NULL) ||
1109 (lpdwReserved != NULL) ||
1110 (lpReserved != NULL))
1112 ERR("Reserved value was not 0\n");
1113 SetLastError(ERROR_INVALID_PARAMETER);
1114 return FALSE;
1116 if (dwFlags != 0)
1117 FIXME("Undocumented flag(s): %lx\n", dwFlags);
1118 return GetUrlCacheEntryInfoA(lpszUrl, lpCacheEntryInfo, lpdwCacheEntryInfoBufSize);
1121 /***********************************************************************
1122 * GetUrlCacheEntryInfoA (WININET.@)
1125 BOOL WINAPI GetUrlCacheEntryInfoA(
1126 IN LPCSTR lpszUrlName,
1127 IN LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1128 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize
1131 LPURLCACHE_HEADER pHeader;
1132 CACHEFILE_ENTRY * pEntry;
1133 URL_CACHEFILE_ENTRY * pUrlEntry;
1134 URLCACHECONTAINER * pContainer;
1136 TRACE("(%s, %p, %p)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo, lpdwCacheEntryInfoBufferSize);
1138 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1139 return FALSE;
1141 if (!URLCacheContainer_OpenIndex(pContainer))
1142 return FALSE;
1144 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1145 return FALSE;
1147 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1149 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1150 WARN("entry %s not found!\n", debugstr_a(lpszUrlName));
1151 SetLastError(ERROR_FILE_NOT_FOUND);
1152 return FALSE;
1155 if (pEntry->dwSignature != URL_SIGNATURE)
1157 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1158 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1159 SetLastError(ERROR_FILE_NOT_FOUND);
1160 return FALSE;
1163 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1164 TRACE("Found URL: %s\n", debugstr_a(pUrlEntry->szSourceUrlName));
1165 if (pUrlEntry->dwOffsetHeaderInfo)
1166 TRACE("Header info: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo));
1168 if (!URLCache_CopyEntry(
1169 pContainer,
1170 pHeader,
1171 lpCacheEntryInfo,
1172 lpdwCacheEntryInfoBufferSize,
1173 pUrlEntry,
1174 FALSE /* ANSI */))
1176 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1177 return FALSE;
1179 TRACE("Local File Name: %s\n", debugstr_a(lpCacheEntryInfo->lpszLocalFileName));
1181 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1183 return TRUE;
1186 /***********************************************************************
1187 * GetUrlCacheEntryInfoW (WININET.@)
1190 BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl,
1191 LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
1192 LPDWORD lpdwCacheEntryInfoBufferSize)
1194 LPURLCACHE_HEADER pHeader;
1195 CACHEFILE_ENTRY * pEntry;
1196 URL_CACHEFILE_ENTRY * pUrlEntry;
1197 URLCACHECONTAINER * pContainer;
1198 LPSTR lpszUrlA;
1199 int url_len;
1201 TRACE("(%s, %p, %p)\n", debugstr_w(lpszUrl), lpCacheEntryInfo, lpdwCacheEntryInfoBufferSize);
1203 url_len = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
1204 lpszUrlA = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(CHAR));
1205 if (!lpszUrlA)
1207 SetLastError(ERROR_OUTOFMEMORY);
1208 return FALSE;
1210 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, lpszUrlA, url_len, NULL, NULL);
1212 if (!URLCacheContainers_FindContainerW(lpszUrl, &pContainer))
1214 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1215 return FALSE;
1218 if (!URLCacheContainer_OpenIndex(pContainer))
1220 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1221 return FALSE;
1224 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1226 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1227 return FALSE;
1230 if (!URLCache_FindEntryInHash(pHeader, lpszUrlA, &pEntry))
1232 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1233 WARN("entry %s not found!\n", debugstr_a(lpszUrlA));
1234 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1235 SetLastError(ERROR_FILE_NOT_FOUND);
1236 return FALSE;
1238 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1240 if (pEntry->dwSignature != URL_SIGNATURE)
1242 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1243 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1244 SetLastError(ERROR_FILE_NOT_FOUND);
1245 return FALSE;
1248 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1249 TRACE("Found URL: %s\n", debugstr_a(pUrlEntry->szSourceUrlName));
1250 TRACE("Header info: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo));
1252 if (!URLCache_CopyEntry(
1253 pContainer,
1254 pHeader,
1255 (LPINTERNET_CACHE_ENTRY_INFOA)lpCacheEntryInfo,
1256 lpdwCacheEntryInfoBufferSize,
1257 pUrlEntry,
1258 TRUE /* UNICODE */))
1260 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1261 return FALSE;
1263 TRACE("Local File Name: %s\n", debugstr_w(lpCacheEntryInfo->lpszLocalFileName));
1265 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1267 return TRUE;
1270 /***********************************************************************
1271 * GetUrlCacheEntryInfoExW (WININET.@)
1274 BOOL WINAPI GetUrlCacheEntryInfoExW(
1275 LPCWSTR lpszUrl,
1276 LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
1277 LPDWORD lpdwCacheEntryInfoBufSize,
1278 LPWSTR lpszReserved,
1279 LPDWORD lpdwReserved,
1280 LPVOID lpReserved,
1281 DWORD dwFlags)
1283 TRACE("(%s, %p, %p, %p, %p, %p, %lx)\n",
1284 debugstr_w(lpszUrl),
1285 lpCacheEntryInfo,
1286 lpdwCacheEntryInfoBufSize,
1287 lpszReserved,
1288 lpdwReserved,
1289 lpReserved,
1290 dwFlags);
1292 if ((lpszReserved != NULL) ||
1293 (lpdwReserved != NULL) ||
1294 (lpReserved != NULL))
1296 ERR("Reserved value was not 0\n");
1297 SetLastError(ERROR_INVALID_PARAMETER);
1298 return FALSE;
1300 if (dwFlags != 0)
1301 FIXME("Undocumented flag(s): %lx\n", dwFlags);
1302 return GetUrlCacheEntryInfoW(lpszUrl, lpCacheEntryInfo, lpdwCacheEntryInfoBufSize);
1305 /***********************************************************************
1306 * SetUrlCacheEntryInfoA (WININET.@)
1308 BOOL WINAPI SetUrlCacheEntryInfoA(
1309 LPCSTR lpszUrlName,
1310 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1311 DWORD dwFieldControl)
1313 LPURLCACHE_HEADER pHeader;
1314 CACHEFILE_ENTRY * pEntry;
1315 URLCACHECONTAINER * pContainer;
1317 TRACE("(%s, %p, 0x%08lx)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo, dwFieldControl);
1319 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1320 return FALSE;
1322 if (!URLCacheContainer_OpenIndex(pContainer))
1323 return FALSE;
1325 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1326 return FALSE;
1328 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1330 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1331 WARN("entry %s not found!\n", debugstr_a(lpszUrlName));
1332 SetLastError(ERROR_FILE_NOT_FOUND);
1333 return FALSE;
1336 if (pEntry->dwSignature != URL_SIGNATURE)
1338 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1339 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1340 SetLastError(ERROR_FILE_NOT_FOUND);
1341 return FALSE;
1344 URLCache_SetEntryInfo(
1345 (URL_CACHEFILE_ENTRY *)pEntry,
1346 (const INTERNET_CACHE_ENTRY_INFOW *)lpCacheEntryInfo,
1347 dwFieldControl);
1349 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1351 return TRUE;
1354 /***********************************************************************
1355 * SetUrlCacheEntryInfoW (WININET.@)
1357 BOOL WINAPI SetUrlCacheEntryInfoW(LPCWSTR lpszUrl, LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo, DWORD dwFieldControl)
1359 LPURLCACHE_HEADER pHeader;
1360 CACHEFILE_ENTRY * pEntry;
1361 URLCACHECONTAINER * pContainer;
1362 LPSTR lpszUrlA;
1363 int url_len;
1365 TRACE("(%s, %p, 0x%08lx)\n", debugstr_w(lpszUrl), lpCacheEntryInfo, dwFieldControl);
1367 url_len = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
1368 lpszUrlA = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(CHAR));
1369 if (!lpszUrlA)
1371 SetLastError(ERROR_OUTOFMEMORY);
1372 return FALSE;
1374 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, lpszUrlA, url_len, NULL, NULL);
1376 if (!URLCacheContainers_FindContainerW(lpszUrl, &pContainer))
1378 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1379 return FALSE;
1382 if (!URLCacheContainer_OpenIndex(pContainer))
1384 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1385 return FALSE;
1388 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1390 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1391 return FALSE;
1394 if (!URLCache_FindEntryInHash(pHeader, lpszUrlA, &pEntry))
1396 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1397 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1398 WARN("entry %s not found!\n", debugstr_a(lpszUrlA));
1399 SetLastError(ERROR_FILE_NOT_FOUND);
1400 return FALSE;
1402 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1404 if (pEntry->dwSignature != URL_SIGNATURE)
1406 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1407 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1408 SetLastError(ERROR_FILE_NOT_FOUND);
1409 return FALSE;
1412 URLCache_SetEntryInfo(
1413 (URL_CACHEFILE_ENTRY *)pEntry,
1414 lpCacheEntryInfo,
1415 dwFieldControl);
1417 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1419 return TRUE;
1422 /***********************************************************************
1423 * RetrieveUrlCacheEntryFileA (WININET.@)
1426 BOOL WINAPI RetrieveUrlCacheEntryFileA(
1427 IN LPCSTR lpszUrlName,
1428 OUT LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1429 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
1430 IN DWORD dwReserved
1433 LPURLCACHE_HEADER pHeader;
1434 CACHEFILE_ENTRY * pEntry;
1435 URL_CACHEFILE_ENTRY * pUrlEntry;
1436 URLCACHECONTAINER * pContainer;
1438 TRACE("(%s, %p, %p, 0x%08lx)\n",
1439 debugstr_a(lpszUrlName),
1440 lpCacheEntryInfo,
1441 lpdwCacheEntryInfoBufferSize,
1442 dwReserved);
1444 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1445 return FALSE;
1447 if (!URLCacheContainer_OpenIndex(pContainer))
1448 return FALSE;
1450 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1451 return FALSE;
1453 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1455 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1456 TRACE("entry %s not found!\n", lpszUrlName);
1457 SetLastError(ERROR_FILE_NOT_FOUND);
1458 return FALSE;
1461 if (pEntry->dwSignature != URL_SIGNATURE)
1463 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1464 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1465 SetLastError(ERROR_FILE_NOT_FOUND);
1466 return FALSE;
1469 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1470 TRACE("Found URL: %s\n", pUrlEntry->szSourceUrlName);
1471 TRACE("Header info: %s\n", (LPBYTE)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo);
1473 pUrlEntry->dwHitRate++;
1474 pUrlEntry->dwUseCount++;
1475 URLCache_HashEntrySetUse(pHeader, lpszUrlName, pUrlEntry->dwUseCount);
1477 if (!URLCache_CopyEntry(pContainer, pHeader, lpCacheEntryInfo, lpdwCacheEntryInfoBufferSize, pUrlEntry, FALSE))
1479 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1480 return FALSE;
1482 TRACE("Local File Name: %s\n", lpCacheEntryInfo->lpszLocalFileName);
1484 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1486 return TRUE;
1489 /***********************************************************************
1490 * RetrieveUrlCacheEntryFileW (WININET.@)
1493 BOOL WINAPI RetrieveUrlCacheEntryFileW(
1494 IN LPCWSTR lpszUrlName,
1495 OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
1496 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
1497 IN DWORD dwReserved
1500 TRACE("(%s, %p, %p, 0x%08lx)\n",
1501 debugstr_w(lpszUrlName),
1502 lpCacheEntryInfo,
1503 lpdwCacheEntryInfoBufferSize,
1504 dwReserved);
1506 return FALSE;
1509 /***********************************************************************
1510 * UnlockUrlCacheEntryFileA (WININET.@)
1513 BOOL WINAPI UnlockUrlCacheEntryFileA(
1514 IN LPCSTR lpszUrlName,
1515 IN DWORD dwReserved
1518 LPURLCACHE_HEADER pHeader;
1519 CACHEFILE_ENTRY * pEntry;
1520 URL_CACHEFILE_ENTRY * pUrlEntry;
1521 URLCACHECONTAINER * pContainer;
1523 TRACE("(%s, 0x%08lx)\n", debugstr_a(lpszUrlName), dwReserved);
1525 if (dwReserved)
1527 ERR("dwReserved != 0\n");
1528 SetLastError(ERROR_INVALID_PARAMETER);
1529 return FALSE;
1532 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1533 return FALSE;
1535 if (!URLCacheContainer_OpenIndex(pContainer))
1536 return FALSE;
1538 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1539 return FALSE;
1541 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1543 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1544 TRACE("entry %s not found!\n", lpszUrlName);
1545 SetLastError(ERROR_FILE_NOT_FOUND);
1546 return FALSE;
1549 if (pEntry->dwSignature != URL_SIGNATURE)
1551 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1552 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1553 SetLastError(ERROR_FILE_NOT_FOUND);
1554 return FALSE;
1557 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1559 if (pUrlEntry->dwUseCount == 0)
1561 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1562 return FALSE;
1564 pUrlEntry->dwUseCount--;
1565 URLCache_HashEntrySetUse(pHeader, lpszUrlName, pUrlEntry->dwUseCount);
1567 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1569 return TRUE;
1572 /***********************************************************************
1573 * UnlockUrlCacheEntryFileW (WININET.@)
1576 BOOL WINAPI UnlockUrlCacheEntryFileW( LPCWSTR lpszUrlName, DWORD dwReserved )
1578 FIXME("(%s, 0x%08lx)\n", debugstr_w(lpszUrlName), dwReserved);
1579 return TRUE;
1582 /***********************************************************************
1583 * CreateUrlCacheEntryA (WININET.@)
1586 BOOL WINAPI CreateUrlCacheEntryA(
1587 IN LPCSTR lpszUrlName,
1588 IN DWORD dwExpectedFileSize,
1589 IN LPCSTR lpszFileExtension,
1590 OUT LPSTR lpszFileName,
1591 IN DWORD dwReserved
1594 URLCACHECONTAINER * pContainer;
1595 LPURLCACHE_HEADER pHeader;
1596 CHAR szFile[MAX_PATH];
1597 CHAR szExtension[MAX_PATH];
1598 LPCSTR lpszUrlPart;
1599 LPCSTR lpszUrlEnd;
1600 LPCSTR lpszFileNameExtension;
1601 LPSTR lpszFileNameNoPath;
1602 int i;
1603 int countnoextension;
1604 BYTE CacheDir;
1605 LONG lBufferSize;
1606 BOOL bFound = FALSE;
1607 int count;
1609 TRACE("(%s, 0x%08lx, %s, %p, 0x%08lx)\n",
1610 debugstr_a(lpszUrlName),
1611 dwExpectedFileSize,
1612 debugstr_a(lpszFileExtension),
1613 lpszFileName,
1614 dwReserved);
1616 if (dwReserved)
1618 ERR("dwReserved != 0\n");
1619 SetLastError(ERROR_INVALID_PARAMETER);
1620 return FALSE;
1623 for (lpszUrlEnd = lpszUrlName; *lpszUrlEnd; lpszUrlEnd++)
1626 if (((lpszUrlEnd - lpszUrlName) > 1) && (*(lpszUrlEnd - 1) == '/'))
1627 lpszUrlEnd--;
1629 for (lpszUrlPart = lpszUrlEnd;
1630 (lpszUrlPart >= lpszUrlName);
1631 lpszUrlPart--)
1633 if ((*lpszUrlPart == '/') && ((lpszUrlEnd - lpszUrlPart) > 1))
1635 bFound = TRUE;
1636 lpszUrlPart++;
1637 break;
1640 if (!strcmp(lpszUrlPart, "www"))
1642 lpszUrlPart += strlen("www");
1645 count = lpszUrlEnd - lpszUrlPart;
1647 if (bFound && (count < MAX_PATH))
1649 memcpy(szFile, lpszUrlPart, count * sizeof(CHAR));
1650 szFile[count] = '\0';
1651 /* FIXME: get rid of illegal characters like \, / and : */
1653 else
1655 FIXME("need to generate a random filename\n");
1658 TRACE("File name: %s\n", szFile);
1660 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1661 return FALSE;
1663 if (!URLCacheContainer_OpenIndex(pContainer))
1664 return FALSE;
1666 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1667 return FALSE;
1669 CacheDir = (BYTE)(rand() % pHeader->DirectoryCount);
1671 lBufferSize = MAX_PATH * sizeof(CHAR);
1672 URLCache_LocalFileNameToPathA(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize);
1674 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1676 lpszFileNameNoPath = lpszFileName + lBufferSize / sizeof(CHAR) + DIR_LENGTH + 1;
1678 countnoextension = strlen(lpszFileNameNoPath);
1679 lpszFileNameExtension = PathFindExtensionA(lpszFileNameNoPath);
1680 if (lpszFileNameExtension)
1681 countnoextension -= strlen(lpszFileNameExtension);
1682 *szExtension = '\0';
1684 if (lpszFileExtension)
1686 szExtension[0] = '.';
1687 strcpy(szExtension+1, lpszFileExtension);
1690 for (i = 0; i < 255; i++)
1692 HANDLE hFile;
1693 strncpy(lpszFileNameNoPath, szFile, countnoextension);
1694 sprintf(lpszFileNameNoPath + countnoextension, "[%u]%s", i, szExtension);
1695 TRACE("Trying: %s\n", lpszFileName);
1696 hFile = CreateFileA(lpszFileName, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
1697 if (hFile != INVALID_HANDLE_VALUE)
1699 CloseHandle(hFile);
1700 return TRUE;
1704 return FALSE;
1707 /***********************************************************************
1708 * CreateUrlCacheEntryW (WININET.@)
1711 BOOL WINAPI CreateUrlCacheEntryW(
1712 IN LPCWSTR lpszUrlName,
1713 IN DWORD dwExpectedFileSize,
1714 IN LPCWSTR lpszFileExtension,
1715 OUT LPWSTR lpszFileName,
1716 IN DWORD dwReserved
1719 FIXME("(%s, 0x%08lx, %s, %p, 0x%08lx) stub\n",
1720 debugstr_w(lpszUrlName),
1721 dwExpectedFileSize,
1722 debugstr_w(lpszFileExtension),
1723 lpszFileName,
1724 dwReserved);
1726 return TRUE;
1729 /***********************************************************************
1730 * CommitUrlCacheEntryA (WININET.@)
1733 BOOL WINAPI CommitUrlCacheEntryA(
1734 IN LPCSTR lpszUrlName,
1735 IN LPCSTR lpszLocalFileName,
1736 IN FILETIME ExpireTime,
1737 IN FILETIME LastModifiedTime,
1738 IN DWORD CacheEntryType,
1739 IN LPBYTE lpHeaderInfo,
1740 IN DWORD dwHeaderSize,
1741 IN LPCSTR lpszFileExtension,
1742 IN LPCSTR dwReserved
1745 URLCACHECONTAINER * pContainer;
1746 LPURLCACHE_HEADER pHeader;
1747 CACHEFILE_ENTRY * pEntry;
1748 URL_CACHEFILE_ENTRY * pUrlEntry;
1749 DWORD dwBytesNeeded = sizeof(*pUrlEntry) - sizeof(pUrlEntry->szSourceUrlName);
1750 DWORD dwOffsetLocalFileName = 0;
1751 DWORD dwOffsetHeader = 0;
1752 DWORD dwFileSizeLow = 0;
1753 DWORD dwFileSizeHigh = 0;
1754 BYTE cDirectory = 0;
1756 TRACE("(%s, %s, ..., ..., %lx, %p, %ld, %s, %p)\n",
1757 debugstr_a(lpszUrlName),
1758 debugstr_a(lpszLocalFileName),
1759 CacheEntryType,
1760 lpHeaderInfo,
1761 dwHeaderSize,
1762 debugstr_a(lpszFileExtension),
1763 dwReserved);
1765 if (dwReserved)
1767 ERR("dwReserved != 0\n");
1768 SetLastError(ERROR_INVALID_PARAMETER);
1769 return FALSE;
1771 if (lpHeaderInfo == NULL)
1773 FIXME("lpHeaderInfo == NULL - will crash at the moment\n");
1776 if (lpszLocalFileName)
1778 HANDLE hFile;
1779 hFile = CreateFileA(lpszLocalFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
1780 if (hFile == INVALID_HANDLE_VALUE)
1782 ERR("couldn't open file %s (error is %ld)\n", debugstr_a(lpszLocalFileName), GetLastError());
1783 return FALSE;
1786 /* Get file size */
1787 dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh);
1788 if ((dwFileSizeLow == INVALID_FILE_SIZE) && (GetLastError() != NO_ERROR))
1790 ERR("couldn't get file size (error is %ld)\n", GetLastError());
1791 CloseHandle(hFile);
1792 return FALSE;
1795 CloseHandle(hFile);
1798 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1799 return FALSE;
1801 if (!URLCacheContainer_OpenIndex(pContainer))
1802 return FALSE;
1804 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1805 return FALSE;
1807 if (URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1809 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1810 FIXME("entry already in cache - don't know what to do!\n");
1812 * SetLastError(ERROR_FILE_NOT_FOUND);
1813 * return FALSE;
1815 return TRUE;
1818 if (lpszLocalFileName)
1820 BOOL bFound = FALSE;
1821 char szContainerPath[MAX_PATH];
1822 int container_path_len;
1823 container_path_len = WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, szContainerPath, sizeof(szContainerPath), NULL, NULL);
1824 if (!container_path_len)
1826 /* WideCharToMultiByte should have called SetLastError */
1827 return FALSE;
1830 if (strncmp(lpszLocalFileName, szContainerPath, container_path_len))
1832 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1833 ERR("path %s must begin with cache content path %s\n", debugstr_a(lpszLocalFileName), debugstr_a(szContainerPath));
1834 SetLastError(ERROR_INVALID_PARAMETER);
1835 return FALSE;
1838 /* skip container path prefix */
1839 lpszLocalFileName += container_path_len;
1841 for (cDirectory = 0; cDirectory < pHeader->DirectoryCount; cDirectory++)
1843 if (!strncmp(pHeader->directory_data[cDirectory].filename, lpszLocalFileName, DIR_LENGTH))
1845 bFound = TRUE;
1846 break;
1850 if (!bFound)
1852 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1853 ERR("cache directory not found in path %s\n", lpszLocalFileName);
1854 SetLastError(ERROR_INVALID_PARAMETER);
1855 return FALSE;
1858 lpszLocalFileName += (DIR_LENGTH + 1); /* "1234WXYZ\" */
1861 dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(lpszUrlName) + 1);
1862 if (lpszLocalFileName)
1864 dwOffsetLocalFileName = dwBytesNeeded;
1865 dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(lpszLocalFileName) + 1);
1867 if (lpHeaderInfo)
1869 dwOffsetHeader = dwBytesNeeded;
1870 dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + dwHeaderSize);
1873 /* round up to next block */
1874 if (dwBytesNeeded % BLOCKSIZE)
1876 dwBytesNeeded -= dwBytesNeeded % BLOCKSIZE;
1877 dwBytesNeeded += BLOCKSIZE;
1880 if (!URLCache_FindFirstFreeEntry(pHeader, dwBytesNeeded / BLOCKSIZE, &pEntry))
1882 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1883 ERR("no free entries\n");
1884 return FALSE;
1887 /* FindFirstFreeEntry fills in blocks used */
1888 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1889 pUrlEntry->CacheFileEntry.dwSignature = URL_SIGNATURE;
1890 pUrlEntry->CacheDir = cDirectory;
1891 pUrlEntry->CacheEntryType = CacheEntryType;
1892 pUrlEntry->dwHeaderInfoSize = dwHeaderSize;
1893 pUrlEntry->dwExemptDelta = 0;
1894 pUrlEntry->dwHitRate = 0;
1895 pUrlEntry->dwOffsetHeaderInfo = dwOffsetHeader;
1896 pUrlEntry->dwOffsetLocalName = dwOffsetLocalFileName;
1897 pUrlEntry->dwOffsetUrl = sizeof(*pUrlEntry) - sizeof(pUrlEntry->szSourceUrlName);
1898 pUrlEntry->dwSizeHigh = 0;
1899 pUrlEntry->dwSizeLow = dwFileSizeLow;
1900 pUrlEntry->dwSizeHigh = dwFileSizeHigh;
1901 pUrlEntry->dwUseCount = 0;
1902 GetSystemTimeAsFileTime(&pUrlEntry->LastAccessTime);
1903 pUrlEntry->LastModifiedTime = LastModifiedTime;
1904 FileTimeToDosDateTime(&pUrlEntry->LastAccessTime, &pUrlEntry->wLastSyncDate, &pUrlEntry->wLastSyncTime);
1905 FileTimeToDosDateTime(&ExpireTime, &pUrlEntry->wExpiredDate, &pUrlEntry->wExpiredTime);
1906 pUrlEntry->wUnknownDate = pUrlEntry->wLastSyncDate;
1907 pUrlEntry->wUnknownTime = pUrlEntry->wLastSyncTime;
1909 /*** Unknowns ***/
1910 pUrlEntry->dwUnknown1 = 0;
1911 pUrlEntry->dwUnknown2 = 0;
1912 pUrlEntry->dwUnknown3 = 0x60;
1913 pUrlEntry->Unknown4 = 0;
1914 pUrlEntry->wUnknown5 = 0x1010;
1915 pUrlEntry->dwUnknown6 = 0;
1916 pUrlEntry->dwUnknown7 = 0;
1917 pUrlEntry->dwUnknown8 = 0;
1919 strcpy(pUrlEntry->szSourceUrlName, lpszUrlName);
1920 if (dwOffsetLocalFileName)
1921 strcpy((LPSTR)((LPBYTE)pUrlEntry + dwOffsetLocalFileName), lpszLocalFileName);
1922 if (dwOffsetHeader)
1923 memcpy((LPSTR)((LPBYTE)pUrlEntry + dwOffsetHeader), lpHeaderInfo, dwHeaderSize);
1925 if (!URLCache_AddEntryToHash(pHeader, lpszUrlName, (DWORD)((LPBYTE)pUrlEntry - (LPBYTE)pHeader)))
1927 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1928 return FALSE;
1931 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1933 return TRUE;
1936 /***********************************************************************
1937 * CommitUrlCacheEntryW (WININET.@)
1940 BOOL WINAPI CommitUrlCacheEntryW(
1941 IN LPCWSTR lpszUrlName,
1942 IN LPCWSTR lpszLocalFileName,
1943 IN FILETIME ExpireTime,
1944 IN FILETIME LastModifiedTime,
1945 IN DWORD CacheEntryType,
1946 IN LPBYTE lpHeaderInfo,
1947 IN DWORD dwHeaderSize,
1948 IN LPCWSTR lpszFileExtension,
1949 IN LPCWSTR dwReserved
1952 FIXME("(%s, %s, ..., ..., %lx, %p, %ld, %s, %p) stub\n",
1953 debugstr_w(lpszUrlName),
1954 debugstr_w(lpszLocalFileName),
1955 CacheEntryType,
1956 lpHeaderInfo,
1957 dwHeaderSize,
1958 debugstr_w(lpszFileExtension),
1959 dwReserved);
1961 return TRUE;
1964 /***********************************************************************
1965 * ReadUrlCacheEntryStream (WININET.@)
1968 BOOL WINAPI ReadUrlCacheEntryStream(
1969 IN HANDLE hUrlCacheStream,
1970 IN DWORD dwLocation,
1971 IN OUT LPVOID lpBuffer,
1972 IN OUT LPDWORD lpdwLen,
1973 IN DWORD dwReserved
1976 /* Get handle to file from 'stream' */
1977 STREAM_HANDLE * pStream = (STREAM_HANDLE *)hUrlCacheStream;
1979 if (dwReserved != 0)
1981 ERR("dwReserved != 0\n");
1982 SetLastError(ERROR_INVALID_PARAMETER);
1983 return FALSE;
1986 if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->lpszUrl, INTERNET_MAX_URL_LENGTH))
1988 SetLastError(ERROR_INVALID_HANDLE);
1989 return FALSE;
1992 if (SetFilePointer(pStream->hFile, dwLocation, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
1993 return FALSE;
1994 return ReadFile(pStream->hFile, lpBuffer, *lpdwLen, lpdwLen, NULL);
1997 /***********************************************************************
1998 * RetrieveUrlCacheEntryStreamA (WININET.@)
2001 HANDLE WINAPI RetrieveUrlCacheEntryStreamA(
2002 IN LPCSTR lpszUrlName,
2003 OUT LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
2004 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
2005 IN BOOL fRandomRead,
2006 IN DWORD dwReserved
2009 /* NOTE: this is not the same as the way that the native
2010 * version allocates 'stream' handles. I did it this way
2011 * as it is much easier and no applications should depend
2012 * on this behaviour. (Native version appears to allocate
2013 * indices into a table)
2015 STREAM_HANDLE * pStream;
2016 HANDLE hFile;
2018 TRACE( "(%s, %p, %p, %x, 0x%08lx)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo,
2019 lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved );
2021 if (!RetrieveUrlCacheEntryFileA(lpszUrlName,
2022 lpCacheEntryInfo,
2023 lpdwCacheEntryInfoBufferSize,
2024 dwReserved))
2026 return NULL;
2029 hFile = CreateFileA(lpCacheEntryInfo->lpszLocalFileName,
2030 GENERIC_READ,
2031 FILE_SHARE_READ,
2032 NULL,
2033 OPEN_EXISTING,
2034 fRandomRead ? FILE_FLAG_RANDOM_ACCESS : 0,
2035 NULL);
2036 if (hFile == INVALID_HANDLE_VALUE)
2037 return FALSE;
2039 /* allocate handle storage space */
2040 pStream = (STREAM_HANDLE *)HeapAlloc(GetProcessHeap(), 0, sizeof(STREAM_HANDLE) + strlen(lpszUrlName) * sizeof(CHAR));
2041 if (!pStream)
2043 CloseHandle(hFile);
2044 SetLastError(ERROR_OUTOFMEMORY);
2045 return FALSE;
2048 pStream->hFile = hFile;
2049 strcpy(pStream->lpszUrl, lpszUrlName);
2050 return (HANDLE)pStream;
2053 /***********************************************************************
2054 * RetrieveUrlCacheEntryStreamW (WININET.@)
2057 HANDLE WINAPI RetrieveUrlCacheEntryStreamW(
2058 IN LPCWSTR lpszUrlName,
2059 OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
2060 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
2061 IN BOOL fRandomRead,
2062 IN DWORD dwReserved
2065 FIXME( "(%s, %p, %p, %x, 0x%08lx)\n", debugstr_w(lpszUrlName), lpCacheEntryInfo,
2066 lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved );
2067 return NULL;
2070 /***********************************************************************
2071 * UnlockUrlCacheEntryStream (WININET.@)
2074 BOOL WINAPI UnlockUrlCacheEntryStream(
2075 IN HANDLE hUrlCacheStream,
2076 IN DWORD dwReserved
2079 STREAM_HANDLE * pStream = (STREAM_HANDLE *)hUrlCacheStream;
2081 if (dwReserved != 0)
2083 ERR("dwReserved != 0\n");
2084 SetLastError(ERROR_INVALID_PARAMETER);
2085 return FALSE;
2088 if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->lpszUrl, INTERNET_MAX_URL_LENGTH))
2090 SetLastError(ERROR_INVALID_HANDLE);
2091 return FALSE;
2094 if (!UnlockUrlCacheEntryFileA(pStream->lpszUrl, 0))
2095 return FALSE;
2097 /* close file handle */
2098 CloseHandle(pStream->hFile);
2100 /* free allocated space */
2101 HeapFree(GetProcessHeap(), 0, pStream);
2103 return TRUE;
2107 /***********************************************************************
2108 * DeleteUrlCacheEntryA (WININET.@)
2111 BOOL WINAPI DeleteUrlCacheEntryA(LPCSTR lpszUrlName)
2113 URLCACHECONTAINER * pContainer;
2114 LPURLCACHE_HEADER pHeader;
2115 CACHEFILE_ENTRY * pEntry;
2116 DWORD dwStartBlock;
2117 DWORD dwBlock;
2118 BYTE * AllocationTable;
2120 TRACE("(%s)\n", debugstr_a(lpszUrlName));
2122 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
2123 return FALSE;
2125 if (!URLCacheContainer_OpenIndex(pContainer))
2126 return FALSE;
2128 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
2129 return FALSE;
2131 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
2133 URLCacheContainer_UnlockIndex(pContainer, pHeader);
2134 TRACE("entry %s not found!\n", lpszUrlName);
2135 SetLastError(ERROR_FILE_NOT_FOUND);
2136 return FALSE;
2139 AllocationTable = (LPBYTE)pHeader + ALLOCATION_TABLE_OFFSET;
2141 /* update allocation table */
2142 dwStartBlock = ((DWORD)pEntry - (DWORD)pHeader) / BLOCKSIZE;
2143 for (dwBlock = dwStartBlock; dwBlock < dwStartBlock + pEntry->dwBlocksUsed; dwBlock++)
2144 URLCache_Allocation_BlockFree(AllocationTable, dwBlock);
2146 URLCache_DeleteEntry(pEntry);
2148 URLCache_DeleteEntryFromHash(pHeader, lpszUrlName);
2150 URLCacheContainer_UnlockIndex(pContainer, pHeader);
2152 return TRUE;
2155 /***********************************************************************
2156 * DeleteUrlCacheEntryW (WININET.@)
2159 BOOL WINAPI DeleteUrlCacheEntryW(LPCWSTR lpszUrlName)
2161 FIXME("(%s) stub\n", debugstr_w(lpszUrlName));
2162 return TRUE;
2165 BOOL DeleteUrlCacheContainerA(DWORD d1, DWORD d2)
2167 FIXME("(0x%08lx, 0x%08lx) stub\n", d1, d2);
2168 return TRUE;
2171 BOOL DeleteUrlCacheContainerW(DWORD d1, DWORD d2)
2173 FIXME("(0x%08lx, 0x%08lx) stub\n", d1, d2);
2174 return TRUE;
2177 /***********************************************************************
2178 * CreateCacheContainerA (WININET.@)
2180 BOOL WINAPI CreateUrlCacheContainerA(DWORD d1, DWORD d2, DWORD d3, DWORD d4,
2181 DWORD d5, DWORD d6, DWORD d7, DWORD d8)
2183 FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx) stub\n",
2184 d1, d2, d3, d4, d5, d6, d7, d8);
2185 return TRUE;
2188 /***********************************************************************
2189 * CreateCacheContainerW (WININET.@)
2191 BOOL WINAPI CreateUrlCacheContainerW(DWORD d1, DWORD d2, DWORD d3, DWORD d4,
2192 DWORD d5, DWORD d6, DWORD d7, DWORD d8)
2194 FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx) stub\n",
2195 d1, d2, d3, d4, d5, d6, d7, d8);
2196 return TRUE;
2199 /***********************************************************************
2200 * FindCloseUrlCache (WININET.@)
2202 BOOL WINAPI FindCloseUrlCache(HANDLE hEnumHandle)
2204 FIXME("(%p) stub\n", hEnumHandle);
2205 return TRUE;
2208 /***********************************************************************
2209 * FindFirstUrlCacheContainerA (WININET.@)
2211 HANDLE WINAPI FindFirstUrlCacheContainerA( LPVOID p1, LPVOID p2, LPVOID p3, DWORD d1 )
2213 FIXME("(%p, %p, %p, 0x%08lx) stub\n", p1, p2, p3, d1 );
2214 return NULL;
2217 /***********************************************************************
2218 * FindFirstUrlCacheContainerW (WININET.@)
2220 HANDLE WINAPI FindFirstUrlCacheContainerW( LPVOID p1, LPVOID p2, LPVOID p3, DWORD d1 )
2222 FIXME("(%p, %p, %p, 0x%08lx) stub\n", p1, p2, p3, d1 );
2223 return NULL;
2226 /***********************************************************************
2227 * FindNextUrlCacheContainerA (WININET.@)
2229 BOOL WINAPI FindNextUrlCacheContainerA( HANDLE handle, LPVOID p1, LPVOID p2 )
2231 FIXME("(%p, %p, %p) stub\n", handle, p1, p2 );
2232 return FALSE;
2235 /***********************************************************************
2236 * FindNextUrlCacheContainerW (WININET.@)
2238 BOOL WINAPI FindNextUrlCacheContainerW( HANDLE handle, LPVOID p1, LPVOID p2 )
2240 FIXME("(%p, %p, %p) stub\n", handle, p1, p2 );
2241 return FALSE;
2244 HANDLE WINAPI FindFirstUrlCacheEntryExA(
2245 LPCSTR lpszUrlSearchPattern,
2246 DWORD dwFlags,
2247 DWORD dwFilter,
2248 GROUPID GroupId,
2249 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,
2250 LPDWORD lpdwFirstCacheEntryInfoBufferSize,
2251 LPVOID lpReserved,
2252 LPDWORD pcbReserved2,
2253 LPVOID lpReserved3
2256 FIXME("(%s, 0x%08lx, 0x%08lx, 0x%08lx%08lx, %p, %p, %p, %p, %p) stub\n", debugstr_a(lpszUrlSearchPattern),
2257 dwFlags, dwFilter, (ULONG)(GroupId >> 32), (ULONG)GroupId, lpFirstCacheEntryInfo,
2258 lpdwFirstCacheEntryInfoBufferSize, lpReserved, pcbReserved2,lpReserved3);
2259 SetLastError(ERROR_FILE_NOT_FOUND);
2260 return NULL;
2263 HANDLE WINAPI FindFirstUrlCacheEntryExW(
2264 LPCWSTR lpszUrlSearchPattern,
2265 DWORD dwFlags,
2266 DWORD dwFilter,
2267 GROUPID GroupId,
2268 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,
2269 LPDWORD lpdwFirstCacheEntryInfoBufferSize,
2270 LPVOID lpReserved,
2271 LPDWORD pcbReserved2,
2272 LPVOID lpReserved3
2275 FIXME("(%s, 0x%08lx, 0x%08lx, 0x%08lx%08lx, %p, %p, %p, %p, %p) stub\n", debugstr_w(lpszUrlSearchPattern),
2276 dwFlags, dwFilter, (ULONG)(GroupId >> 32), (ULONG)GroupId, lpFirstCacheEntryInfo,
2277 lpdwFirstCacheEntryInfoBufferSize, lpReserved, pcbReserved2,lpReserved3);
2278 SetLastError(ERROR_FILE_NOT_FOUND);
2279 return NULL;
2282 /***********************************************************************
2283 * FindFirstUrlCacheEntryA (WININET.@)
2286 INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern,
2287 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize)
2289 FIXME("(%s, %p, %p): stub\n", debugstr_a(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize);
2290 SetLastError(ERROR_FILE_NOT_FOUND);
2291 return 0;
2294 /***********************************************************************
2295 * FindFirstUrlCacheEntryW (WININET.@)
2298 INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern,
2299 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize)
2301 FIXME("(%s, %p, %p): stub\n", debugstr_w(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize);
2302 return 0;
2305 HANDLE WINAPI FindFirstUrlCacheGroup( DWORD dwFlags, DWORD dwFilter, LPVOID lpSearchCondition,
2306 DWORD dwSearchCondition, GROUPID* lpGroupId, LPVOID lpReserved )
2308 FIXME("(0x%08lx, 0x%08lx, %p, 0x%08lx, %p, %p) stub\n", dwFlags, dwFilter, lpSearchCondition,
2309 dwSearchCondition, lpGroupId, lpReserved);
2310 return NULL;
2313 BOOL WINAPI FindNextUrlCacheEntryA(
2314 HANDLE hEnumHandle,
2315 LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo,
2316 LPDWORD lpdwNextCacheEntryInfoBufferSize
2319 FIXME("(%p, %p, %p) stub\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize);
2320 return FALSE;
2323 BOOL WINAPI FindNextUrlCacheEntryW(
2324 HANDLE hEnumHandle,
2325 LPINTERNET_CACHE_ENTRY_INFOW lpNextCacheEntryInfo,
2326 LPDWORD lpdwNextCacheEntryInfoBufferSize
2329 FIXME("(%p, %p, %p) stub\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize);
2330 return FALSE;
2333 BOOL WINAPI FindNextUrlCacheEntryExA(
2334 HANDLE hEnumHandle,
2335 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,
2336 LPDWORD lpdwFirstCacheEntryInfoBufferSize,
2337 LPVOID lpReserved,
2338 LPDWORD pcbReserved2,
2339 LPVOID lpReserved3
2342 FIXME("(%p, %p, %p, %p, %p, %p) stub\n", hEnumHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize,
2343 lpReserved, pcbReserved2, lpReserved3);
2344 return FALSE;
2347 BOOL WINAPI FindNextUrlCacheEntryExW(
2348 HANDLE hEnumHandle,
2349 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,
2350 LPDWORD lpdwFirstCacheEntryInfoBufferSize,
2351 LPVOID lpReserved,
2352 LPDWORD pcbReserved2,
2353 LPVOID lpReserved3
2356 FIXME("(%p, %p, %p, %p, %p, %p) stub\n", hEnumHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize,
2357 lpReserved, pcbReserved2, lpReserved3);
2358 return FALSE;
2361 BOOL WINAPI FindNextUrlCacheGroup( HANDLE hFind, GROUPID* lpGroupId, LPVOID lpReserved )
2363 FIXME("(%p, %p, %p) stub\n", hFind, lpGroupId, lpReserved);
2364 return FALSE;
2367 /***********************************************************************
2368 * CreateUrlCacheGroup (WININET.@)
2371 INTERNETAPI GROUPID WINAPI CreateUrlCacheGroup(DWORD dwFlags, LPVOID lpReserved)
2373 FIXME("(0x%08lx, %p): stub\n", dwFlags, lpReserved);
2374 return FALSE;
2377 /***********************************************************************
2378 * DeleteUrlCacheGroup (WININET.@)
2381 BOOL WINAPI DeleteUrlCacheGroup(GROUPID GroupId, DWORD dwFlags, LPVOID lpReserved)
2383 FIXME("(0x%08lx%08lx, 0x%08lx, %p) stub\n",
2384 (ULONG)(GroupId >> 32), (ULONG)GroupId, dwFlags, lpReserved);
2385 return FALSE;
2388 /***********************************************************************
2389 * SetUrlCacheEntryGroupA (WININET.@)
2392 BOOL WINAPI SetUrlCacheEntryGroupA(LPCSTR lpszUrlName, DWORD dwFlags,
2393 GROUPID GroupId, LPBYTE pbGroupAttributes, DWORD cbGroupAttributes,
2394 LPVOID lpReserved)
2396 FIXME("(%s, 0x%08lx, 0x%08lx%08lx, %p, 0x%08lx, %p) stub\n",
2397 debugstr_a(lpszUrlName), dwFlags, (ULONG)(GroupId >> 32), (ULONG)GroupId,
2398 pbGroupAttributes, cbGroupAttributes, lpReserved);
2399 SetLastError(ERROR_FILE_NOT_FOUND);
2400 return FALSE;
2403 /***********************************************************************
2404 * SetUrlCacheEntryGroupW (WININET.@)
2407 BOOL WINAPI SetUrlCacheEntryGroupW(LPCWSTR lpszUrlName, DWORD dwFlags,
2408 GROUPID GroupId, LPBYTE pbGroupAttributes, DWORD cbGroupAttributes,
2409 LPVOID lpReserved)
2411 FIXME("(%s, 0x%08lx, 0x%08lx%08lx, %p, 0x%08lx, %p) stub\n",
2412 debugstr_w(lpszUrlName), dwFlags, (ULONG)(GroupId >> 32), (ULONG)GroupId,
2413 pbGroupAttributes, cbGroupAttributes, lpReserved);
2414 SetLastError(ERROR_FILE_NOT_FOUND);
2415 return FALSE;
2418 /***********************************************************************
2419 * GetUrlCacheConfigInfoW (WININET.@)
2421 BOOL WINAPI GetUrlCacheConfigInfoW(LPDWORD CacheInfo, LPDWORD size, DWORD bitmask)
2423 FIXME("(%p, %p, %lx)\n", CacheInfo, size, bitmask);
2424 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
2425 return FALSE;
2428 /***********************************************************************
2429 * GetUrlCacheConfigInfoA (WININET.@)
2431 * CacheInfo is some CACHE_CONFIG_INFO structure, with no MS info found by google
2433 BOOL WINAPI GetUrlCacheConfigInfoA(LPDWORD CacheInfo, LPDWORD size, DWORD bitmask)
2435 FIXME("(%p, %p, %lx)\n", CacheInfo, size, bitmask);
2436 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
2437 return FALSE;
2440 BOOL WINAPI GetUrlCacheGroupAttributeA( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
2441 LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo,
2442 LPDWORD lpdwGroupInfo, LPVOID lpReserved )
2444 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p, %p) stub\n",
2445 (ULONG)(gid >> 32), (ULONG)gid, dwFlags, dwAttributes, lpGroupInfo,
2446 lpdwGroupInfo, lpReserved);
2447 return FALSE;
2450 BOOL WINAPI GetUrlCacheGroupAttributeW( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
2451 LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,
2452 LPDWORD lpdwGroupInfo, LPVOID lpReserved )
2454 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p, %p) stub\n",
2455 (ULONG)(gid >> 32), (ULONG)gid, dwFlags, dwAttributes, lpGroupInfo,
2456 lpdwGroupInfo, lpReserved);
2457 return FALSE;
2460 BOOL WINAPI SetUrlCacheGroupAttributeA( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
2461 LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo, LPVOID lpReserved )
2463 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p) stub\n",
2464 (ULONG)(gid >> 32), (ULONG)gid, dwFlags, dwAttributes, lpGroupInfo, lpReserved);
2465 return TRUE;
2468 BOOL WINAPI SetUrlCacheGroupAttributeW( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
2469 LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo, LPVOID lpReserved )
2471 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p) stub\n",
2472 (ULONG)(gid >> 32), (ULONG)gid, dwFlags, dwAttributes, lpGroupInfo, lpReserved);
2473 return TRUE;
2476 BOOL WINAPI SetUrlCacheConfigInfoA( LPDWORD lpCacheConfigInfo, DWORD dwFieldControl )
2478 FIXME("(%p, 0x%08lx) stub\n", lpCacheConfigInfo, dwFieldControl);
2479 return TRUE;
2482 BOOL WINAPI SetUrlCacheConfigInfoW( LPDWORD lpCacheConfigInfo, DWORD dwFieldControl )
2484 FIXME("(%p, 0x%08lx) stub\n", lpCacheConfigInfo, dwFieldControl);
2485 return TRUE;
2488 /***********************************************************************
2489 * DeleteIE3Cache (WININET.@)
2491 * Deletes the files used by the IE3 URL caching system.
2493 * PARAMS
2494 * hWnd [I] A dummy window.
2495 * hInst [I] Instance of process calling the function.
2496 * lpszCmdLine [I] Options used by function.
2497 * nCmdShow [I] The nCmdShow value to use when showing windows created, if any.
2499 * RETURNS
2500 * nothing
2502 void WINAPI DeleteIE3Cache(HWND hWnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nCmdShow)
2504 FIXME("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_a(lpszCmdLine), nCmdShow);