Moved the UsePrimary config parameter to the x11drv section, renamed
[wine/testsucceed.git] / dlls / wininet / urlcache.c
blob07de5cc3361ccd803219d749a31591ee7e712d29
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 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
38 #include "windef.h"
39 #include "winbase.h"
40 #include "winuser.h"
41 #include "wininet.h"
42 #include "winerror.h"
43 #include "internet.h"
44 #include "winreg.h"
45 #include "shlwapi.h"
46 #include "wingdi.h"
47 #include "shlobj.h"
49 #include "wine/unicode.h"
50 #include "wine/list.h"
51 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
55 #define ENTRY_START_OFFSET 0x4000
56 #define DIR_LENGTH 8
57 #define BLOCKSIZE 128
58 #define HASHTABLE_SIZE 448
59 #define HASHTABLE_BLOCKSIZE 7
60 #define HASHTABLE_FREE 3
61 #define ALLOCATION_TABLE_OFFSET 0x250
62 #define ALLOCATION_TABLE_SIZE (0x1000 - ALLOCATION_TABLE_OFFSET)
63 #define HASHTABLE_NUM_ENTRIES (HASHTABLE_SIZE / HASHTABLE_BLOCKSIZE)
65 #define DWORD_SIG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
66 #define URL_SIGNATURE DWORD_SIG('U','R','L',' ')
67 #define REDR_SIGNATURE DWORD_SIG('R','E','D','R')
68 #define LEAK_SIGNATURE DWORD_SIG('L','E','A','K')
69 #define HASH_SIGNATURE DWORD_SIG('H','A','S','H')
71 #define DWORD_ALIGN(x) ( (DWORD)(((DWORD)(x)+sizeof(DWORD)-1)/sizeof(DWORD))*sizeof(DWORD) )
73 typedef struct _CACHEFILE_ENTRY
75 /* union
76 {*/
77 DWORD dwSignature; /* e.g. "URL " */
78 /* CHAR szSignature[4];
79 };*/
80 DWORD dwBlocksUsed; /* number of 128byte blocks used by this entry */
81 } CACHEFILE_ENTRY;
83 typedef struct _URL_CACHEFILE_ENTRY
85 CACHEFILE_ENTRY CacheFileEntry;
86 FILETIME LastModifiedTime;
87 FILETIME LastAccessTime;
88 WORD wExpiredDate; /* expire date in dos format */
89 WORD wExpiredTime; /* expire time in dos format */
90 DWORD dwUnknown1; /* usually zero */
91 DWORD dwSizeLow; /* see INTERNET_CACHE_ENTRY_INFO::dwSizeLow */
92 DWORD dwSizeHigh; /* see INTERNET_CACHE_ENTRY_INFO::dwSizeHigh */
93 DWORD dwUnknown2; /* usually zero */
94 DWORD dwExemptDelta; /* see INTERNET_CACHE_ENTRY_INFO::dwExemptDelta */
95 DWORD dwUnknown3; /* usually 0x60 */
96 DWORD dwOffsetUrl; /* usually 0x68 */
97 BYTE CacheDir; /* index of cache directory this url is stored in */
98 BYTE Unknown4; /* usually zero */
99 WORD wUnknown5; /* usually 0x1010 */
100 DWORD dwOffsetLocalName; /* offset of start of local filename from start of entry */
101 DWORD CacheEntryType; /* see INTERNET_CACHE_ENTRY_INFO::CacheEntryType */
102 DWORD dwOffsetHeaderInfo; /* offset of start of header info from start of entry */
103 DWORD dwHeaderInfoSize;
104 DWORD dwUnknown6; /* usually zero */
105 WORD wLastSyncDate; /* last sync date in dos format */
106 WORD wLastSyncTime; /* last sync time in dos format */
107 DWORD dwHitRate; /* see INTERNET_CACHE_ENTRY_INFO::dwHitRate */
108 DWORD dwUseCount; /* see INTERNET_CACHE_ENTRY_INFO::dwUseCount */
109 WORD wUnknownDate; /* usually same as wLastSyncDate */
110 WORD wUnknownTime; /* usually same as wLastSyncTime */
111 DWORD dwUnknown7; /* usually zero */
112 DWORD dwUnknown8; /* usually zero */
113 CHAR szSourceUrlName[1]; /* start of url */
114 /* packing to dword align start of next field */
115 /* CHAR szLocalFileName[]; (local file name exluding path) */
116 /* packing to dword align start of next field */
117 /* CHAR szHeaderInfo[]; (header info) */
118 } URL_CACHEFILE_ENTRY;
120 struct _HASH_ENTRY
122 DWORD dwHashKey;
123 DWORD dwOffsetEntry;
126 typedef struct _HASH_CACHEFILE_ENTRY
128 CACHEFILE_ENTRY CacheFileEntry;
129 DWORD dwAddressNext;
130 DWORD dwHashTableNumber;
131 struct _HASH_ENTRY HashTable[HASHTABLE_SIZE];
132 } HASH_CACHEFILE_ENTRY;
134 typedef struct _DIRECTORY_DATA
136 DWORD dwUnknown;
137 char filename[DIR_LENGTH];
138 } DIRECTORY_DATA;
140 typedef struct _URLCACHE_HEADER
142 char szSignature[28];
143 DWORD dwFileSize;
144 DWORD dwOffsetFirstHashTable;
145 DWORD dwIndexCapacityInBlocks;
146 DWORD dwBlocksInUse; /* is this right? */
147 DWORD dwUnknown1;
148 DWORD dwCacheLimitLow; /* disk space limit for cache */
149 DWORD dwCacheLimitHigh; /* disk space limit for cache */
150 DWORD dwUnknown4; /* current disk space usage for cache? */
151 DWORD dwUnknown5; /* current disk space usage for cache? */
152 DWORD dwUnknown6; /* possibly a flag? */
153 DWORD dwUnknown7;
154 BYTE DirectoryCount; /* number of directory_data's */
155 BYTE Unknown8[3]; /* just padding? */
156 DIRECTORY_DATA directory_data[1]; /* first directory entry */
157 } URLCACHE_HEADER, *LPURLCACHE_HEADER;
158 typedef const URLCACHE_HEADER *LPCURLCACHE_HEADER;
160 typedef struct _STREAM_HANDLE
162 HANDLE hFile;
163 CHAR lpszUrl[1];
164 } STREAM_HANDLE;
166 typedef struct _URLCACHECONTAINER
168 struct list entry; /* part of a list */
169 LPWSTR cache_prefix; /* string that has to be prefixed for this container to be used */
170 LPWSTR path; /* path to url container directory */
171 HANDLE hMapping; /* handle of file mapping */
172 DWORD file_size; /* size of file when mapping was opened */
173 HANDLE hMutex; /* hande of mutex */
174 } URLCACHECONTAINER;
177 /* List of all containers available */
178 static struct list UrlContainers = LIST_INIT(UrlContainers);
181 /***********************************************************************
182 * URLCache_PathToObjectName (Internal)
184 * Converts a path to a name suitable for use as a Win32 object name.
185 * Replaces '\\' characters in-place with the specified character
186 * (usually '_' or '!')
188 * RETURNS
189 * nothing
192 static void URLCache_PathToObjectName(LPWSTR lpszPath, WCHAR replace)
194 for (; *lpszPath; lpszPath++)
196 if (*lpszPath == '\\')
197 *lpszPath = replace;
201 /***********************************************************************
202 * URLCacheContainer_OpenIndex (Internal)
204 * Opens the index file and saves mapping handle in hCacheIndexMapping
206 * RETURNS
207 * TRUE if succeeded
208 * FALSE if failed
211 static BOOL URLCacheContainer_OpenIndex(URLCACHECONTAINER * pContainer)
213 HANDLE hFile;
214 WCHAR wszFilePath[MAX_PATH];
215 DWORD dwFileSize;
217 static const WCHAR wszIndex[] = {'i','n','d','e','x','.','d','a','t',0};
218 static const WCHAR wszMappingFormat[] = {'%','s','%','s','_','%','l','u',0};
220 if (pContainer->hMapping)
221 return TRUE;
223 strcpyW(wszFilePath, pContainer->path);
224 strcatW(wszFilePath, wszIndex);
226 hFile = CreateFileW(wszFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
227 if (hFile == INVALID_HANDLE_VALUE)
229 FIXME("need to create cache index file\n");
230 return FALSE;
233 dwFileSize = GetFileSize(hFile, NULL);
234 if (dwFileSize == INVALID_FILE_SIZE)
235 return FALSE;
237 if (dwFileSize == 0)
239 FIXME("need to create cache index file\n");
240 return FALSE;
243 wsprintfW(wszFilePath, wszMappingFormat, pContainer->path, wszIndex, dwFileSize);
244 URLCache_PathToObjectName(wszFilePath, '_');
245 pContainer->hMapping = OpenFileMappingW(FILE_MAP_WRITE, FALSE, wszFilePath);
246 if (!pContainer->hMapping)
247 pContainer->hMapping = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, 0, 0, wszFilePath);
248 CloseHandle(hFile);
249 if (!pContainer->hMapping)
251 ERR("Couldn't create file mapping (error is %ld)\n", GetLastError());
252 return FALSE;
255 return TRUE;
258 /***********************************************************************
259 * URLCacheContainer_CloseIndex (Internal)
261 * Closes the index
263 * RETURNS
264 * nothing
267 static void URLCacheContainer_CloseIndex(URLCACHECONTAINER * pContainer)
269 CloseHandle(pContainer->hMapping);
270 pContainer->hMapping = NULL;
273 static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix, LPCWSTR path, LPWSTR mutex_name)
275 URLCACHECONTAINER * pContainer = HeapAlloc(GetProcessHeap(), 0, sizeof(URLCACHECONTAINER));
276 int path_len = strlenW(path);
277 int cache_prefix_len = strlenW(cache_prefix);
279 if (!pContainer)
281 return FALSE;
284 pContainer->hMapping = NULL;
285 pContainer->file_size = 0;
287 pContainer->path = HeapAlloc(GetProcessHeap(), 0, (path_len + 1) * sizeof(WCHAR));
288 if (!pContainer->path)
290 HeapFree(GetProcessHeap(), 0, pContainer);
291 return FALSE;
294 memcpy(pContainer->path, path, (path_len + 1) * sizeof(WCHAR));
296 pContainer->cache_prefix = HeapAlloc(GetProcessHeap(), 0, (cache_prefix_len + 1) * sizeof(WCHAR));
297 if (!pContainer->cache_prefix)
299 HeapFree(GetProcessHeap(), 0, pContainer->path);
300 HeapFree(GetProcessHeap(), 0, pContainer);
301 return FALSE;
304 memcpy(pContainer->cache_prefix, cache_prefix, (cache_prefix_len + 1) * sizeof(WCHAR));
306 CharLowerW(mutex_name);
307 URLCache_PathToObjectName(mutex_name, '!');
309 if ((pContainer->hMutex = CreateMutexW(NULL, FALSE, mutex_name)) == NULL)
311 ERR("couldn't create mutex (error is %ld)\n", GetLastError());
312 HeapFree(GetProcessHeap(), 0, pContainer->path);
313 HeapFree(GetProcessHeap(), 0, pContainer);
314 return FALSE;
317 list_add_head(&UrlContainers, &pContainer->entry);
319 return TRUE;
322 static void URLCacheContainer_DeleteContainer(URLCACHECONTAINER * pContainer)
324 list_remove(&pContainer->entry);
326 URLCacheContainer_CloseIndex(pContainer);
327 CloseHandle(pContainer->hMutex);
328 HeapFree(GetProcessHeap(), 0, pContainer->path);
329 HeapFree(GetProcessHeap(), 0, pContainer->cache_prefix);
330 HeapFree(GetProcessHeap(), 0, pContainer);
333 void URLCacheContainers_CreateDefaults()
335 static const WCHAR UrlSuffix[] = {'C','o','n','t','e','n','t','.','I','E','5',0};
336 static const WCHAR UrlPrefix[] = {0};
337 static const WCHAR HistorySuffix[] = {'H','i','s','t','o','r','y','.','I','E','5',0};
338 static const WCHAR HistoryPrefix[] = {'V','i','s','i','t','e','d',':',0};
339 static const WCHAR CookieSuffix[] = {0};
340 static const WCHAR CookiePrefix[] = {'C','o','o','k','i','e',':',0};
341 static const struct
343 int nFolder; /* CSIDL_* constant */
344 const WCHAR * shpath_suffix; /* suffix on path returned by SHGetSpecialFolderPath */
345 const WCHAR * cache_prefix; /* prefix used to reference the container */
346 } DefaultContainerData[] =
348 { CSIDL_INTERNET_CACHE, UrlSuffix, UrlPrefix },
349 { CSIDL_HISTORY, HistorySuffix, HistoryPrefix },
350 { CSIDL_COOKIES, CookieSuffix, CookiePrefix },
352 DWORD i;
354 for (i = 0; i < sizeof(DefaultContainerData) / sizeof(DefaultContainerData[0]); i++)
356 WCHAR wszCachePath[MAX_PATH];
357 WCHAR wszMutexName[MAX_PATH];
358 int path_len, suffix_len;
360 if (FAILED(SHGetSpecialFolderPathW(NULL, wszCachePath, DefaultContainerData[i].nFolder, TRUE)))
362 ERR("Couldn't get path for default container %lu\n", i);
363 continue;
365 path_len = strlenW(wszCachePath);
366 suffix_len = strlenW(DefaultContainerData[i].shpath_suffix);
368 if (path_len + suffix_len + 2 > MAX_PATH)
370 ERR("Path too long\n");
371 continue;
374 wszCachePath[path_len] = '\\';
376 strcpyW(wszMutexName, wszCachePath);
378 if (suffix_len)
380 memcpy(wszCachePath + path_len + 1, DefaultContainerData[i].shpath_suffix, (suffix_len + 1) * sizeof(WCHAR));
381 wszCachePath[path_len + suffix_len + 1] = '\\';
382 wszCachePath[path_len + suffix_len + 2] = '\0';
385 URLCacheContainers_AddContainer(DefaultContainerData[i].cache_prefix, wszCachePath, wszMutexName);
389 void URLCacheContainers_DeleteAll()
391 while(!list_empty(&UrlContainers))
392 URLCacheContainer_DeleteContainer(
393 LIST_ENTRY(list_head(&UrlContainers), URLCACHECONTAINER, entry)
397 static BOOL URLCacheContainers_FindContainerW(LPCWSTR lpwszUrl, URLCACHECONTAINER ** ppContainer)
399 struct list * cursor;
401 TRACE("searching for prefix for URL: %s\n", debugstr_w(lpwszUrl));
403 LIST_FOR_EACH(cursor, &UrlContainers)
405 URLCACHECONTAINER * pContainer = LIST_ENTRY(cursor, URLCACHECONTAINER, entry);
406 int prefix_len = strlenW(pContainer->cache_prefix);
407 if (!strncmpW(pContainer->cache_prefix, lpwszUrl, prefix_len))
409 TRACE("found container with prefx %s for URL %s\n", debugstr_w(pContainer->cache_prefix), debugstr_w(lpwszUrl));
410 *ppContainer = pContainer;
411 return TRUE;
414 ERR("no container found\n");
415 SetLastError(ERROR_FILE_NOT_FOUND);
416 return FALSE;
419 static BOOL URLCacheContainers_FindContainerA(LPCSTR lpszUrl, URLCACHECONTAINER ** ppContainer)
421 BOOL ret;
422 LPWSTR lpwszUrl;
423 int url_len = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0);
424 if (url_len && (lpwszUrl = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(WCHAR))))
426 MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, lpwszUrl, url_len);
427 ret = URLCacheContainers_FindContainerW(lpwszUrl, ppContainer);
428 HeapFree(GetProcessHeap(), 0, lpwszUrl);
429 return ret;
431 return FALSE;
434 /***********************************************************************
435 * URLCacheContainer_LockIndex (Internal)
438 static LPURLCACHE_HEADER URLCacheContainer_LockIndex(URLCACHECONTAINER * pContainer)
440 BYTE index;
441 LPVOID pIndexData;
442 URLCACHE_HEADER * pHeader;
444 /* acquire mutex */
445 WaitForSingleObject(pContainer->hMutex, INFINITE);
447 pIndexData = MapViewOfFile(pContainer->hMapping, FILE_MAP_WRITE, 0, 0, 0);
449 if (!pIndexData)
451 ReleaseMutex(pContainer->hMutex);
452 ERR("Couldn't MapViewOfFile. Error: %ld\n", GetLastError());
453 return FALSE;
455 pHeader = (URLCACHE_HEADER *)pIndexData;
457 /* file has grown - we need to remap to prevent us getting
458 * access violations when we try and access beyond the end
459 * of the memory mapped file */
460 if (pHeader->dwFileSize != pContainer->file_size)
462 URLCacheContainer_CloseIndex(pContainer);
463 if (!URLCacheContainer_OpenIndex(pContainer))
465 ReleaseMutex(pContainer->hMutex);
466 return FALSE;
468 pIndexData = MapViewOfFile(pContainer->hMapping, FILE_MAP_WRITE, 0, 0, 0);
470 if (!pIndexData)
472 ReleaseMutex(pContainer->hMutex);
473 ERR("Couldn't MapViewOfFile. Error: %ld\n", GetLastError());
474 return FALSE;
476 pHeader = (URLCACHE_HEADER *)pIndexData;
479 TRACE("Signature: %s, file size: %ld bytes\n", pHeader->szSignature, pHeader->dwFileSize);
481 for (index = 0; index < pHeader->DirectoryCount; index++)
483 TRACE("Directory[%d] = \"%.8s\"\n", index, pHeader->directory_data[index].filename);
486 return pHeader;
489 /***********************************************************************
490 * URLCacheContainer_UnlockIndex (Internal)
493 static BOOL URLCacheContainer_UnlockIndex(URLCACHECONTAINER * pContainer, LPURLCACHE_HEADER pHeader)
495 /* release mutex */
496 ReleaseMutex(pContainer->hMutex);
497 return UnmapViewOfFile(pHeader);
501 #ifndef CHAR_BIT
502 #define CHAR_BIT (8 * sizeof(CHAR))
503 #endif
505 /***********************************************************************
506 * URLCache_Allocation_BlockIsFree (Internal)
508 * Is the specified block number free?
510 * RETURNS
511 * zero if free
512 * non-zero otherwise
515 static inline BYTE URLCache_Allocation_BlockIsFree(BYTE * AllocationTable, DWORD dwBlockNumber)
517 BYTE mask = 1 << (dwBlockNumber % CHAR_BIT);
518 return (AllocationTable[dwBlockNumber / CHAR_BIT] & mask) == 0;
521 /***********************************************************************
522 * URLCache_Allocation_BlockFree (Internal)
524 * Marks the specified block as free
526 * RETURNS
527 * nothing
530 static inline void URLCache_Allocation_BlockFree(BYTE * AllocationTable, DWORD dwBlockNumber)
532 BYTE mask = ~(1 << (dwBlockNumber % CHAR_BIT));
533 AllocationTable[dwBlockNumber / CHAR_BIT] &= mask;
536 /***********************************************************************
537 * URLCache_Allocation_BlockAllocate (Internal)
539 * Marks the specified block as allocated
541 * RETURNS
542 * nothing
545 static inline void URLCache_Allocation_BlockAllocate(BYTE * AllocationTable, DWORD dwBlockNumber)
547 BYTE mask = 1 << (dwBlockNumber % CHAR_BIT);
548 AllocationTable[dwBlockNumber / CHAR_BIT] |= mask;
551 /***********************************************************************
552 * URLCache_FindFirstFreeEntry (Internal)
554 * Finds and allocates the first block of free space big enough and
555 * sets ppEntry to point to it.
557 * RETURNS
558 * TRUE if it had enough space
559 * FALSE if it couldn't find enough space
562 static BOOL URLCache_FindFirstFreeEntry(URLCACHE_HEADER * pHeader, DWORD dwBlocksNeeded, CACHEFILE_ENTRY ** ppEntry)
564 LPBYTE AllocationTable = (LPBYTE)pHeader + ALLOCATION_TABLE_OFFSET;
565 DWORD dwBlockNumber;
566 DWORD dwFreeCounter;
567 for (dwBlockNumber = 0; dwBlockNumber < pHeader->dwIndexCapacityInBlocks; dwBlockNumber++)
569 for (dwFreeCounter = 0;
570 dwFreeCounter < dwBlocksNeeded &&
571 dwFreeCounter + dwBlockNumber < pHeader->dwIndexCapacityInBlocks &&
572 URLCache_Allocation_BlockIsFree(AllocationTable, dwBlockNumber + dwFreeCounter);
573 dwFreeCounter++)
574 TRACE("Found free block at no. %ld (0x%lx)\n", dwBlockNumber, ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
576 if (dwFreeCounter == dwBlocksNeeded)
578 DWORD index;
579 TRACE("Found free blocks starting at no. %ld (0x%lx)\n", dwBlockNumber, ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
580 for (index = 0; index < dwBlocksNeeded; index++)
581 URLCache_Allocation_BlockAllocate(AllocationTable, dwBlockNumber + index);
582 *ppEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
583 (*ppEntry)->dwBlocksUsed = dwBlocksNeeded;
584 return TRUE;
587 FIXME("Grow file\n");
588 return FALSE;
591 /***********************************************************************
592 * URLCache_DeleteEntry (Internal)
594 * Deletes the specified entry and frees the space allocated to it
596 * RETURNS
597 * TRUE if it succeeded
598 * FALSE if it failed
601 static BOOL URLCache_DeleteEntry(CACHEFILE_ENTRY * pEntry)
603 ZeroMemory(pEntry, pEntry->dwBlocksUsed * BLOCKSIZE);
604 return TRUE;
607 /***********************************************************************
608 * URLCache_LocalFileNameToPathW (Internal)
610 * Copies the full path to the specified buffer given the local file
611 * name and the index of the directory it is in. Always sets value in
612 * lpBufferSize to the required buffer size (in bytes).
614 * RETURNS
615 * TRUE if the buffer was big enough
616 * FALSE if the buffer was too small
619 static BOOL URLCache_LocalFileNameToPathW(
620 const URLCACHECONTAINER * pContainer,
621 LPCURLCACHE_HEADER pHeader,
622 LPCSTR szLocalFileName,
623 BYTE Directory,
624 LPWSTR wszPath,
625 LPLONG lpBufferSize)
627 LONG nRequired;
628 int path_len = strlenW(pContainer->path);
629 int file_name_len = MultiByteToWideChar(CP_ACP, 0, szLocalFileName, -1, NULL, 0);
630 if (Directory >= pHeader->DirectoryCount)
632 *lpBufferSize = 0;
633 return FALSE;
636 nRequired = (path_len + DIR_LENGTH + file_name_len + 1) * sizeof(WCHAR);
637 if (nRequired < *lpBufferSize)
639 int dir_len;
641 memcpy(wszPath, pContainer->path, path_len * sizeof(WCHAR));
642 dir_len = MultiByteToWideChar(CP_ACP, 0, pHeader->directory_data[Directory].filename, DIR_LENGTH, wszPath + path_len, DIR_LENGTH);
643 wszPath[dir_len + path_len] = '\\';
644 MultiByteToWideChar(CP_ACP, 0, szLocalFileName, -1, wszPath + dir_len + path_len + 1, file_name_len);
645 *lpBufferSize = nRequired;
646 return TRUE;
648 *lpBufferSize = nRequired;
649 return FALSE;
652 /***********************************************************************
653 * URLCache_LocalFileNameToPathA (Internal)
655 * Copies the full path to the specified buffer given the local file
656 * name and the index of the directory it is in. Always sets value in
657 * lpBufferSize to the required buffer size.
659 * RETURNS
660 * TRUE if the buffer was big enough
661 * FALSE if the buffer was too small
664 static BOOL URLCache_LocalFileNameToPathA(
665 const URLCACHECONTAINER * pContainer,
666 LPCURLCACHE_HEADER pHeader,
667 LPCSTR szLocalFileName,
668 BYTE Directory,
669 LPSTR szPath,
670 LPLONG lpBufferSize)
672 LONG nRequired;
673 int path_len, file_name_len, dir_len;
675 if (Directory >= pHeader->DirectoryCount)
677 *lpBufferSize = 0;
678 return FALSE;
681 path_len = WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, NULL, 0, NULL, NULL);
682 file_name_len = strlen(szLocalFileName);
683 dir_len = DIR_LENGTH;
685 nRequired = (path_len + dir_len + 1 + file_name_len) * sizeof(WCHAR);
686 if (nRequired < *lpBufferSize)
688 WideCharToMultiByte(CP_ACP, 0, pContainer->path, -1, szPath, -1, NULL, NULL);
689 memcpy(szPath+path_len, pHeader->directory_data[Directory].filename, dir_len);
690 szPath[path_len + dir_len] = '\\';
691 memcpy(szPath + path_len + dir_len + 1, szLocalFileName, file_name_len);
692 *lpBufferSize = nRequired;
693 return TRUE;
695 *lpBufferSize = nRequired;
696 return FALSE;
699 /***********************************************************************
700 * URLCache_CopyEntry (Internal)
702 * Copies an entry from the cache index file to the Win32 structure
704 * RETURNS
705 * TRUE if the buffer was big enough
706 * FALSE if the buffer was too small
709 static BOOL URLCache_CopyEntry(
710 URLCACHECONTAINER * pContainer,
711 LPCURLCACHE_HEADER pHeader,
712 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
713 LPDWORD lpdwBufferSize,
714 URL_CACHEFILE_ENTRY * pUrlEntry,
715 BOOL bUnicode)
717 int lenUrl;
718 DWORD dwRequiredSize = sizeof(*lpCacheEntryInfo);
720 if (*lpdwBufferSize >= dwRequiredSize)
722 lpCacheEntryInfo->lpHeaderInfo = NULL;
723 lpCacheEntryInfo->lpszFileExtension = NULL;
724 lpCacheEntryInfo->lpszLocalFileName = NULL;
725 lpCacheEntryInfo->lpszSourceUrlName = NULL;
726 lpCacheEntryInfo->CacheEntryType = pUrlEntry->CacheEntryType;
727 lpCacheEntryInfo->u.dwExemptDelta = pUrlEntry->dwExemptDelta;
728 lpCacheEntryInfo->dwHeaderInfoSize = pUrlEntry->dwHeaderInfoSize;
729 lpCacheEntryInfo->dwHitRate = pUrlEntry->dwHitRate;
730 lpCacheEntryInfo->dwSizeHigh = pUrlEntry->dwSizeHigh;
731 lpCacheEntryInfo->dwSizeLow = pUrlEntry->dwSizeLow;
732 lpCacheEntryInfo->dwStructSize = sizeof(*lpCacheEntryInfo);
733 lpCacheEntryInfo->dwUseCount = pUrlEntry->dwUseCount;
734 DosDateTimeToFileTime(pUrlEntry->wExpiredDate, pUrlEntry->wExpiredTime, &lpCacheEntryInfo->ExpireTime);
735 lpCacheEntryInfo->LastAccessTime.dwHighDateTime = pUrlEntry->LastAccessTime.dwHighDateTime;
736 lpCacheEntryInfo->LastAccessTime.dwLowDateTime = pUrlEntry->LastAccessTime.dwLowDateTime;
737 lpCacheEntryInfo->LastModifiedTime.dwHighDateTime = pUrlEntry->LastModifiedTime.dwHighDateTime;
738 lpCacheEntryInfo->LastModifiedTime.dwLowDateTime = pUrlEntry->LastModifiedTime.dwLowDateTime;
739 DosDateTimeToFileTime(pUrlEntry->wLastSyncDate, pUrlEntry->wLastSyncTime, &lpCacheEntryInfo->LastSyncTime);
742 if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
743 ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
744 dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
745 if (bUnicode)
746 lenUrl = MultiByteToWideChar(CP_ACP, 0, pUrlEntry->szSourceUrlName, -1, NULL, 0);
747 else
748 lenUrl = strlen(pUrlEntry->szSourceUrlName);
749 dwRequiredSize += lenUrl + 1;
751 /* FIXME: is source url optional? */
752 if (*lpdwBufferSize >= dwRequiredSize)
754 lpCacheEntryInfo->lpszSourceUrlName = (LPSTR)lpCacheEntryInfo + dwRequiredSize - lenUrl - 1;
755 if (bUnicode)
756 MultiByteToWideChar(CP_ACP, 0, pUrlEntry->szSourceUrlName, -1, (LPWSTR)lpCacheEntryInfo->lpszSourceUrlName, lenUrl + 1);
757 else
758 memcpy(lpCacheEntryInfo->lpszSourceUrlName, pUrlEntry->szSourceUrlName, (lenUrl + 1) * sizeof(CHAR));
761 if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
762 ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
763 dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
765 if (pUrlEntry->dwOffsetLocalName)
767 LONG nLocalFilePathSize;
768 LPSTR lpszLocalFileName;
769 lpszLocalFileName = (LPSTR)lpCacheEntryInfo + dwRequiredSize;
770 nLocalFilePathSize = *lpdwBufferSize - dwRequiredSize;
771 if ((bUnicode && URLCache_LocalFileNameToPathW(pContainer, pHeader, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetLocalName, pUrlEntry->CacheDir, (LPWSTR)lpszLocalFileName, &nLocalFilePathSize)) ||
772 URLCache_LocalFileNameToPathA(pContainer, pHeader, (LPCSTR)pUrlEntry + pUrlEntry->dwOffsetLocalName, pUrlEntry->CacheDir, lpszLocalFileName, &nLocalFilePathSize))
774 lpCacheEntryInfo->lpszLocalFileName = lpszLocalFileName;
776 dwRequiredSize += nLocalFilePathSize;
778 if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
779 ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
780 dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
782 dwRequiredSize += pUrlEntry->dwHeaderInfoSize + 1;
784 if (*lpdwBufferSize >= dwRequiredSize)
786 lpCacheEntryInfo->lpHeaderInfo = (LPBYTE)lpCacheEntryInfo + dwRequiredSize - pUrlEntry->dwHeaderInfoSize - 1;
787 memcpy(lpCacheEntryInfo->lpHeaderInfo, (LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo, pUrlEntry->dwHeaderInfoSize);
788 ((LPBYTE)lpCacheEntryInfo)[dwRequiredSize - 1] = '\0';
790 if ((dwRequiredSize % 4) && (dwRequiredSize < *lpdwBufferSize))
791 ZeroMemory((LPBYTE)lpCacheEntryInfo + dwRequiredSize, 4 - (dwRequiredSize % 4));
792 dwRequiredSize = DWORD_ALIGN(dwRequiredSize);
794 if (dwRequiredSize > *lpdwBufferSize)
796 *lpdwBufferSize = dwRequiredSize;
797 SetLastError(ERROR_INSUFFICIENT_BUFFER);
798 return FALSE;
800 *lpdwBufferSize = dwRequiredSize;
801 return TRUE;
805 /***********************************************************************
806 * URLCache_SetEntryInfo (Internal)
808 * Helper for SetUrlCacheEntryInfo{A,W}. Sets fields in URL entry
809 * according the the flags set by dwFieldControl.
811 * RETURNS
812 * TRUE if the buffer was big enough
813 * FALSE if the buffer was too small
816 static BOOL URLCache_SetEntryInfo(URL_CACHEFILE_ENTRY * pUrlEntry, const INTERNET_CACHE_ENTRY_INFOW * lpCacheEntryInfo, DWORD dwFieldControl)
818 if (dwFieldControl & CACHE_ENTRY_ACCTIME_FC)
819 pUrlEntry->LastAccessTime = lpCacheEntryInfo->LastAccessTime;
820 if (dwFieldControl & CACHE_ENTRY_ATTRIBUTE_FC)
821 pUrlEntry->CacheEntryType = lpCacheEntryInfo->CacheEntryType;
822 if (dwFieldControl & CACHE_ENTRY_EXEMPT_DELTA_FC)
823 pUrlEntry->dwExemptDelta = lpCacheEntryInfo->u.dwExemptDelta;
824 if (dwFieldControl & CACHE_ENTRY_EXPTIME_FC)
825 FIXME("CACHE_ENTRY_EXPTIME_FC unimplemented\n");
826 if (dwFieldControl & CACHE_ENTRY_HEADERINFO_FC)
827 FIXME("CACHE_ENTRY_HEADERINFO_FC unimplemented\n");
828 if (dwFieldControl & CACHE_ENTRY_HITRATE_FC)
829 pUrlEntry->dwHitRate = lpCacheEntryInfo->dwHitRate;
830 if (dwFieldControl & CACHE_ENTRY_MODTIME_FC)
831 pUrlEntry->LastModifiedTime = lpCacheEntryInfo->LastModifiedTime;
832 if (dwFieldControl & CACHE_ENTRY_SYNCTIME_FC)
833 FileTimeToDosDateTime(&lpCacheEntryInfo->LastAccessTime, &pUrlEntry->wLastSyncDate, &pUrlEntry->wLastSyncTime);
835 return TRUE;
838 /***********************************************************************
839 * URLCache_HashKey (Internal)
841 * Returns the hash key for a given string
843 * RETURNS
844 * hash key for the string
847 static DWORD URLCache_HashKey(LPCSTR lpszKey)
849 /* NOTE: this uses the same lookup table as SHLWAPI.UrlHash{A,W}
850 * but the algorithm and result are not the same!
852 static const unsigned char lookupTable[256] =
854 0x01, 0x0E, 0x6E, 0x19, 0x61, 0xAE, 0x84, 0x77,
855 0x8A, 0xAA, 0x7D, 0x76, 0x1B, 0xE9, 0x8C, 0x33,
856 0x57, 0xC5, 0xB1, 0x6B, 0xEA, 0xA9, 0x38, 0x44,
857 0x1E, 0x07, 0xAD, 0x49, 0xBC, 0x28, 0x24, 0x41,
858 0x31, 0xD5, 0x68, 0xBE, 0x39, 0xD3, 0x94, 0xDF,
859 0x30, 0x73, 0x0F, 0x02, 0x43, 0xBA, 0xD2, 0x1C,
860 0x0C, 0xB5, 0x67, 0x46, 0x16, 0x3A, 0x4B, 0x4E,
861 0xB7, 0xA7, 0xEE, 0x9D, 0x7C, 0x93, 0xAC, 0x90,
862 0xB0, 0xA1, 0x8D, 0x56, 0x3C, 0x42, 0x80, 0x53,
863 0x9C, 0xF1, 0x4F, 0x2E, 0xA8, 0xC6, 0x29, 0xFE,
864 0xB2, 0x55, 0xFD, 0xED, 0xFA, 0x9A, 0x85, 0x58,
865 0x23, 0xCE, 0x5F, 0x74, 0xFC, 0xC0, 0x36, 0xDD,
866 0x66, 0xDA, 0xFF, 0xF0, 0x52, 0x6A, 0x9E, 0xC9,
867 0x3D, 0x03, 0x59, 0x09, 0x2A, 0x9B, 0x9F, 0x5D,
868 0xA6, 0x50, 0x32, 0x22, 0xAF, 0xC3, 0x64, 0x63,
869 0x1A, 0x96, 0x10, 0x91, 0x04, 0x21, 0x08, 0xBD,
870 0x79, 0x40, 0x4D, 0x48, 0xD0, 0xF5, 0x82, 0x7A,
871 0x8F, 0x37, 0x69, 0x86, 0x1D, 0xA4, 0xB9, 0xC2,
872 0xC1, 0xEF, 0x65, 0xF2, 0x05, 0xAB, 0x7E, 0x0B,
873 0x4A, 0x3B, 0x89, 0xE4, 0x6C, 0xBF, 0xE8, 0x8B,
874 0x06, 0x18, 0x51, 0x14, 0x7F, 0x11, 0x5B, 0x5C,
875 0xFB, 0x97, 0xE1, 0xCF, 0x15, 0x62, 0x71, 0x70,
876 0x54, 0xE2, 0x12, 0xD6, 0xC7, 0xBB, 0x0D, 0x20,
877 0x5E, 0xDC, 0xE0, 0xD4, 0xF7, 0xCC, 0xC4, 0x2B,
878 0xF9, 0xEC, 0x2D, 0xF4, 0x6F, 0xB6, 0x99, 0x88,
879 0x81, 0x5A, 0xD9, 0xCA, 0x13, 0xA5, 0xE7, 0x47,
880 0xE6, 0x8E, 0x60, 0xE3, 0x3E, 0xB3, 0xF6, 0x72,
881 0xA2, 0x35, 0xA0, 0xD7, 0xCD, 0xB4, 0x2F, 0x6D,
882 0x2C, 0x26, 0x1F, 0x95, 0x87, 0x00, 0xD8, 0x34,
883 0x3F, 0x17, 0x25, 0x45, 0x27, 0x75, 0x92, 0xB8,
884 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB, 0x0A,
885 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1
887 BYTE key[4];
888 DWORD i;
889 int subscript[sizeof(key) / sizeof(key[0])];
891 subscript[0] = *lpszKey;
892 subscript[1] = (char)(*lpszKey + 1);
893 subscript[2] = (char)(*lpszKey + 2);
894 subscript[3] = (char)(*lpszKey + 3);
896 for (i = 0; i < sizeof(key) / sizeof(key[0]); i++)
897 key[i] = lookupTable[i];
899 for (lpszKey++; *lpszKey && ((lpszKey[0] != '/') || (lpszKey[1] != 0)); lpszKey++)
901 for (i = 0; i < sizeof(key) / sizeof(key[0]); i++)
902 key[i] = lookupTable[*lpszKey ^ key[i]];
905 return *(DWORD *)key;
908 static inline HASH_CACHEFILE_ENTRY * URLCache_HashEntryFromOffset(LPCURLCACHE_HEADER pHeader, DWORD dwOffset)
910 return (HASH_CACHEFILE_ENTRY *)((LPBYTE)pHeader + dwOffset);
913 static BOOL URLCache_FindHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, struct _HASH_ENTRY ** ppHashEntry)
915 /* structure of hash table:
916 * 448 entries divided into 64 blocks
917 * each block therefore contains a chain of 7 key/offset pairs
918 * how position in table is calculated:
919 * 1. the url is hashed in helper function
920 * 2. the key % 64 * 8 is the offset
921 * 3. the key in the hash table is the hash key aligned to 64
923 * note:
924 * there can be multiple hash tables in the file and the offset to
925 * the next one is stored in the header of the hash table
927 DWORD key = URLCache_HashKey(lpszUrl);
928 DWORD offset = (key % HASHTABLE_NUM_ENTRIES) * sizeof(struct _HASH_ENTRY);
929 HASH_CACHEFILE_ENTRY * pHashEntry;
930 DWORD dwHashTableNumber = 0;
932 key = (DWORD)(key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES;
934 for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable);
935 ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize);
936 pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHashEntry->dwAddressNext))
938 int i;
939 if (pHashEntry->dwHashTableNumber != dwHashTableNumber++)
941 ERR("Error: not right hash table number (%ld) expected %ld\n", pHashEntry->dwHashTableNumber, dwHashTableNumber);
942 continue;
944 /* make sure that it is in fact a hash entry */
945 if (pHashEntry->CacheFileEntry.dwSignature != HASH_SIGNATURE)
947 ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->CacheFileEntry.dwSignature);
948 continue;
951 for (i = 0; i < HASHTABLE_BLOCKSIZE; i++)
953 struct _HASH_ENTRY * pHashElement = &pHashEntry->HashTable[offset + i];
954 if (key == (DWORD)(pHashElement->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES)
956 /* FIXME: we should make sure that this is the right element
957 * before returning and claiming that it is. We can do this
958 * by doing a simple compare between the URL we were given
959 * and the URL stored in the entry. However, this assumes
960 * we know the format of all the entries stored in the
961 * hash table */
962 *ppHashEntry = pHashElement;
963 return TRUE;
967 return FALSE;
970 /***********************************************************************
971 * URLCache_FindEntryInHash (Internal)
973 * Searches all the hash tables in the index for the given URL and
974 * returns the entry, if it was found, in ppEntry
976 * RETURNS
977 * TRUE if the entry was found
978 * FALSE if the entry could not be found
981 static BOOL URLCache_FindEntryInHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, CACHEFILE_ENTRY ** ppEntry)
983 struct _HASH_ENTRY * pHashEntry;
984 if (URLCache_FindHash(pHeader, lpszUrl, &pHashEntry))
986 *ppEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
987 return TRUE;
989 return FALSE;
992 /***********************************************************************
993 * URLCache_HashEntrySetUse (Internal)
995 * Searches all the hash tables in the index for the given URL and
996 * sets the use count (stored or'ed with key)
998 * RETURNS
999 * TRUE if the entry was found
1000 * FALSE if the entry could not be found
1003 static BOOL URLCache_HashEntrySetUse(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, DWORD dwUseCount)
1005 struct _HASH_ENTRY * pHashEntry;
1006 if (URLCache_FindHash(pHeader, lpszUrl, &pHashEntry))
1008 pHashEntry->dwHashKey = dwUseCount | (DWORD)(pHashEntry->dwHashKey / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES;
1009 return TRUE;
1011 return FALSE;
1014 /***********************************************************************
1015 * URLCache_DeleteEntryFromHash (Internal)
1017 * Searches all the hash tables in the index for the given URL and
1018 * then if found deletes the entry.
1020 * RETURNS
1021 * TRUE if the entry was found
1022 * FALSE if the entry could not be found
1025 static BOOL URLCache_DeleteEntryFromHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl)
1027 struct _HASH_ENTRY * pHashEntry;
1028 if (URLCache_FindHash(pHeader, lpszUrl, &pHashEntry))
1030 pHashEntry->dwHashKey = HASHTABLE_FREE;
1031 pHashEntry->dwOffsetEntry = HASHTABLE_FREE;
1032 return TRUE;
1034 return FALSE;
1037 /***********************************************************************
1038 * URLCache_AddEntryToHash (Internal)
1040 * Searches all the hash tables for a free slot based on the offset
1041 * generated from the hash key. If a free slot is found, the offset and
1042 * key are entered into the hash table.
1044 * RETURNS
1045 * TRUE if the entry was added
1046 * FALSE if the entry could not be added
1049 static BOOL URLCache_AddEntryToHash(LPCURLCACHE_HEADER pHeader, LPCSTR lpszUrl, DWORD dwOffsetEntry)
1051 /* see URLCache_FindEntryInHash for structure of hash tables */
1053 DWORD key = URLCache_HashKey(lpszUrl);
1054 DWORD offset = (key % HASHTABLE_NUM_ENTRIES) * sizeof(struct _HASH_ENTRY);
1055 HASH_CACHEFILE_ENTRY * pHashEntry;
1056 DWORD dwHashTableNumber = 0;
1058 key = (DWORD)(key / HASHTABLE_NUM_ENTRIES) * HASHTABLE_NUM_ENTRIES;
1060 for (pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHeader->dwOffsetFirstHashTable);
1061 ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) >= ENTRY_START_OFFSET) && ((DWORD)((LPBYTE)pHashEntry - (LPBYTE)pHeader) < pHeader->dwFileSize);
1062 pHashEntry = URLCache_HashEntryFromOffset(pHeader, pHashEntry->dwAddressNext))
1064 int i;
1065 if (pHashEntry->dwHashTableNumber != dwHashTableNumber++)
1067 ERR("not right hash table number (%ld) expected %ld\n", pHashEntry->dwHashTableNumber, dwHashTableNumber);
1068 break;
1070 /* make sure that it is in fact a hash entry */
1071 if (pHashEntry->CacheFileEntry.dwSignature != HASH_SIGNATURE)
1073 ERR("not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR)&pHashEntry->CacheFileEntry.dwSignature);
1074 break;
1077 for (i = 0; i < HASHTABLE_BLOCKSIZE; i++)
1079 struct _HASH_ENTRY * pHashElement = &pHashEntry->HashTable[offset + i];
1080 if (pHashElement->dwHashKey == HASHTABLE_FREE) /* if the slot is free */
1082 pHashElement->dwHashKey = key;
1083 pHashElement->dwOffsetEntry = dwOffsetEntry;
1084 return TRUE;
1088 FIXME("need to create another hash table\n");
1089 return FALSE;
1092 /***********************************************************************
1093 * GetUrlCacheEntryInfoExA (WININET.@)
1096 BOOL WINAPI GetUrlCacheEntryInfoExA(
1097 LPCSTR lpszUrl,
1098 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1099 LPDWORD lpdwCacheEntryInfoBufSize,
1100 LPSTR lpszReserved,
1101 LPDWORD lpdwReserved,
1102 LPVOID lpReserved,
1103 DWORD dwFlags)
1105 TRACE("(%s, %p, %p, %p, %p, %p, %lx)\n",
1106 debugstr_a(lpszUrl),
1107 lpCacheEntryInfo,
1108 lpdwCacheEntryInfoBufSize,
1109 lpszReserved,
1110 lpdwReserved,
1111 lpReserved,
1112 dwFlags);
1114 if ((lpszReserved != NULL) ||
1115 (lpdwReserved != NULL) ||
1116 (lpReserved != NULL))
1118 ERR("Reserved value was not 0\n");
1119 SetLastError(ERROR_INVALID_PARAMETER);
1120 return FALSE;
1122 if (dwFlags != 0)
1123 FIXME("Undocumented flag(s): %lx\n", dwFlags);
1124 return GetUrlCacheEntryInfoA(lpszUrl, lpCacheEntryInfo, lpdwCacheEntryInfoBufSize);
1127 /***********************************************************************
1128 * GetUrlCacheEntryInfoA (WININET.@)
1131 BOOL WINAPI GetUrlCacheEntryInfoA(
1132 IN LPCSTR lpszUrlName,
1133 IN LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1134 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize
1137 LPURLCACHE_HEADER pHeader;
1138 CACHEFILE_ENTRY * pEntry;
1139 URL_CACHEFILE_ENTRY * pUrlEntry;
1140 URLCACHECONTAINER * pContainer;
1142 TRACE("(%s, %p, %p)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo, lpdwCacheEntryInfoBufferSize);
1144 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1145 return FALSE;
1147 if (!URLCacheContainer_OpenIndex(pContainer))
1148 return FALSE;
1150 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1151 return FALSE;
1153 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1155 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1156 WARN("entry %s not found!\n", debugstr_a(lpszUrlName));
1157 SetLastError(ERROR_FILE_NOT_FOUND);
1158 return FALSE;
1161 if (pEntry->dwSignature != URL_SIGNATURE)
1163 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1164 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1165 SetLastError(ERROR_FILE_NOT_FOUND);
1166 return FALSE;
1169 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1170 TRACE("Found URL: %s\n", debugstr_a(pUrlEntry->szSourceUrlName));
1171 if (pUrlEntry->dwOffsetHeaderInfo)
1172 TRACE("Header info: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo));
1174 if (!URLCache_CopyEntry(
1175 pContainer,
1176 pHeader,
1177 lpCacheEntryInfo,
1178 lpdwCacheEntryInfoBufferSize,
1179 pUrlEntry,
1180 FALSE /* ANSI */))
1182 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1183 return FALSE;
1185 TRACE("Local File Name: %s\n", debugstr_a(lpCacheEntryInfo->lpszLocalFileName));
1187 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1189 return TRUE;
1192 /***********************************************************************
1193 * GetUrlCacheEntryInfoW (WININET.@)
1196 BOOL WINAPI GetUrlCacheEntryInfoW(LPCWSTR lpszUrl,
1197 LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
1198 LPDWORD lpdwCacheEntryInfoBufferSize)
1200 LPURLCACHE_HEADER pHeader;
1201 CACHEFILE_ENTRY * pEntry;
1202 URL_CACHEFILE_ENTRY * pUrlEntry;
1203 URLCACHECONTAINER * pContainer;
1204 LPSTR lpszUrlA;
1205 int url_len;
1207 TRACE("(%s, %p, %p)\n", debugstr_w(lpszUrl), lpCacheEntryInfo, lpdwCacheEntryInfoBufferSize);
1209 url_len = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
1210 lpszUrlA = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(CHAR));
1211 if (!lpszUrlA)
1213 SetLastError(ERROR_OUTOFMEMORY);
1214 return FALSE;
1216 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, lpszUrlA, url_len, NULL, NULL);
1218 if (!URLCacheContainers_FindContainerW(lpszUrl, &pContainer))
1220 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1221 return FALSE;
1224 if (!URLCacheContainer_OpenIndex(pContainer))
1226 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1227 return FALSE;
1230 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1232 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1233 return FALSE;
1236 if (!URLCache_FindEntryInHash(pHeader, lpszUrlA, &pEntry))
1238 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1239 WARN("entry %s not found!\n", debugstr_a(lpszUrlA));
1240 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1241 SetLastError(ERROR_FILE_NOT_FOUND);
1242 return FALSE;
1244 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1246 if (pEntry->dwSignature != URL_SIGNATURE)
1248 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1249 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1250 SetLastError(ERROR_FILE_NOT_FOUND);
1251 return FALSE;
1254 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1255 TRACE("Found URL: %s\n", debugstr_a(pUrlEntry->szSourceUrlName));
1256 TRACE("Header info: %s\n", debugstr_a((LPSTR)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo));
1258 if (!URLCache_CopyEntry(
1259 pContainer,
1260 pHeader,
1261 (LPINTERNET_CACHE_ENTRY_INFOA)lpCacheEntryInfo,
1262 lpdwCacheEntryInfoBufferSize,
1263 pUrlEntry,
1264 TRUE /* UNICODE */))
1266 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1267 return FALSE;
1269 TRACE("Local File Name: %s\n", debugstr_w(lpCacheEntryInfo->lpszLocalFileName));
1271 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1273 return TRUE;
1276 /***********************************************************************
1277 * GetUrlCacheEntryInfoExW (WININET.@)
1280 BOOL WINAPI GetUrlCacheEntryInfoExW(
1281 LPCWSTR lpszUrl,
1282 LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
1283 LPDWORD lpdwCacheEntryInfoBufSize,
1284 LPWSTR lpszReserved,
1285 LPDWORD lpdwReserved,
1286 LPVOID lpReserved,
1287 DWORD dwFlags)
1289 TRACE("(%s, %p, %p, %p, %p, %p, %lx)\n",
1290 debugstr_w(lpszUrl),
1291 lpCacheEntryInfo,
1292 lpdwCacheEntryInfoBufSize,
1293 lpszReserved,
1294 lpdwReserved,
1295 lpReserved,
1296 dwFlags);
1298 if ((lpszReserved != NULL) ||
1299 (lpdwReserved != NULL) ||
1300 (lpReserved != NULL))
1302 ERR("Reserved value was not 0\n");
1303 SetLastError(ERROR_INVALID_PARAMETER);
1304 return FALSE;
1306 if (dwFlags != 0)
1307 FIXME("Undocumented flag(s): %lx\n", dwFlags);
1308 return GetUrlCacheEntryInfoW(lpszUrl, lpCacheEntryInfo, lpdwCacheEntryInfoBufSize);
1311 /***********************************************************************
1312 * SetUrlCacheEntryInfoA (WININET.@)
1314 BOOL WINAPI SetUrlCacheEntryInfoA(
1315 LPCSTR lpszUrlName,
1316 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1317 DWORD dwFieldControl)
1319 LPURLCACHE_HEADER pHeader;
1320 CACHEFILE_ENTRY * pEntry;
1321 URLCACHECONTAINER * pContainer;
1323 TRACE("(%s, %p, 0x%08lx)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo, dwFieldControl);
1325 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1326 return FALSE;
1328 if (!URLCacheContainer_OpenIndex(pContainer))
1329 return FALSE;
1331 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1332 return FALSE;
1334 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1336 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1337 WARN("entry %s not found!\n", debugstr_a(lpszUrlName));
1338 SetLastError(ERROR_FILE_NOT_FOUND);
1339 return FALSE;
1342 if (pEntry->dwSignature != URL_SIGNATURE)
1344 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1345 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1346 SetLastError(ERROR_FILE_NOT_FOUND);
1347 return FALSE;
1350 URLCache_SetEntryInfo(
1351 (URL_CACHEFILE_ENTRY *)pEntry,
1352 (const INTERNET_CACHE_ENTRY_INFOW *)lpCacheEntryInfo,
1353 dwFieldControl);
1355 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1357 return TRUE;
1360 /***********************************************************************
1361 * SetUrlCacheEntryInfoW (WININET.@)
1363 BOOL WINAPI SetUrlCacheEntryInfoW(LPCWSTR lpszUrl, LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo, DWORD dwFieldControl)
1365 LPURLCACHE_HEADER pHeader;
1366 CACHEFILE_ENTRY * pEntry;
1367 URLCACHECONTAINER * pContainer;
1368 LPSTR lpszUrlA;
1369 int url_len;
1371 TRACE("(%s, %p, 0x%08lx)\n", debugstr_w(lpszUrl), lpCacheEntryInfo, dwFieldControl);
1373 url_len = WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, NULL, 0, NULL, NULL);
1374 lpszUrlA = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(CHAR));
1375 if (!lpszUrlA)
1377 SetLastError(ERROR_OUTOFMEMORY);
1378 return FALSE;
1380 WideCharToMultiByte(CP_ACP, 0, lpszUrl, -1, lpszUrlA, url_len, NULL, NULL);
1382 if (!URLCacheContainers_FindContainerW(lpszUrl, &pContainer))
1384 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1385 return FALSE;
1388 if (!URLCacheContainer_OpenIndex(pContainer))
1390 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1391 return FALSE;
1394 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1396 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1397 return FALSE;
1400 if (!URLCache_FindEntryInHash(pHeader, lpszUrlA, &pEntry))
1402 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1403 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1404 WARN("entry %s not found!\n", debugstr_a(lpszUrlA));
1405 SetLastError(ERROR_FILE_NOT_FOUND);
1406 return FALSE;
1408 HeapFree(GetProcessHeap(), 0, lpszUrlA);
1410 if (pEntry->dwSignature != URL_SIGNATURE)
1412 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1413 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1414 SetLastError(ERROR_FILE_NOT_FOUND);
1415 return FALSE;
1418 URLCache_SetEntryInfo(
1419 (URL_CACHEFILE_ENTRY *)pEntry,
1420 lpCacheEntryInfo,
1421 dwFieldControl);
1423 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1425 return TRUE;
1428 /***********************************************************************
1429 * RetrieveUrlCacheEntryFileA (WININET.@)
1432 BOOL WINAPI RetrieveUrlCacheEntryFileA(
1433 IN LPCSTR lpszUrlName,
1434 OUT LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
1435 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
1436 IN DWORD dwReserved
1439 LPURLCACHE_HEADER pHeader;
1440 CACHEFILE_ENTRY * pEntry;
1441 URL_CACHEFILE_ENTRY * pUrlEntry;
1442 URLCACHECONTAINER * pContainer;
1444 TRACE("(%s, %p, %p, 0x%08lx)\n",
1445 debugstr_a(lpszUrlName),
1446 lpCacheEntryInfo,
1447 lpdwCacheEntryInfoBufferSize,
1448 dwReserved);
1450 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1451 return FALSE;
1453 if (!URLCacheContainer_OpenIndex(pContainer))
1454 return FALSE;
1456 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1457 return FALSE;
1459 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1461 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1462 TRACE("entry %s not found!\n", lpszUrlName);
1463 SetLastError(ERROR_FILE_NOT_FOUND);
1464 return FALSE;
1467 if (pEntry->dwSignature != URL_SIGNATURE)
1469 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1470 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1471 SetLastError(ERROR_FILE_NOT_FOUND);
1472 return FALSE;
1475 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1476 TRACE("Found URL: %s\n", pUrlEntry->szSourceUrlName);
1477 TRACE("Header info: %s\n", (LPBYTE)pUrlEntry + pUrlEntry->dwOffsetHeaderInfo);
1479 pUrlEntry->dwHitRate++;
1480 pUrlEntry->dwUseCount++;
1481 URLCache_HashEntrySetUse(pHeader, lpszUrlName, pUrlEntry->dwUseCount);
1483 if (!URLCache_CopyEntry(pContainer, pHeader, lpCacheEntryInfo, lpdwCacheEntryInfoBufferSize, pUrlEntry, FALSE))
1485 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1486 return FALSE;
1488 TRACE("Local File Name: %s\n", lpCacheEntryInfo->lpszLocalFileName);
1490 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1492 return TRUE;
1495 /***********************************************************************
1496 * RetrieveUrlCacheEntryFileW (WININET.@)
1499 BOOL WINAPI RetrieveUrlCacheEntryFileW(
1500 IN LPCWSTR lpszUrlName,
1501 OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
1502 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
1503 IN DWORD dwReserved
1506 TRACE("(%s, %p, %p, 0x%08lx)\n",
1507 debugstr_w(lpszUrlName),
1508 lpCacheEntryInfo,
1509 lpdwCacheEntryInfoBufferSize,
1510 dwReserved);
1512 return FALSE;
1515 /***********************************************************************
1516 * UnlockUrlCacheEntryFileA (WININET.@)
1519 BOOL WINAPI UnlockUrlCacheEntryFileA(
1520 IN LPCSTR lpszUrlName,
1521 IN DWORD dwReserved
1524 LPURLCACHE_HEADER pHeader;
1525 CACHEFILE_ENTRY * pEntry;
1526 URL_CACHEFILE_ENTRY * pUrlEntry;
1527 URLCACHECONTAINER * pContainer;
1529 TRACE("(%s, 0x%08lx)\n", debugstr_a(lpszUrlName), dwReserved);
1531 if (dwReserved)
1533 ERR("dwReserved != 0\n");
1534 SetLastError(ERROR_INVALID_PARAMETER);
1535 return FALSE;
1538 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
1539 return FALSE;
1541 if (!URLCacheContainer_OpenIndex(pContainer))
1542 return FALSE;
1544 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1545 return FALSE;
1547 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
1549 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1550 TRACE("entry %s not found!\n", lpszUrlName);
1551 SetLastError(ERROR_FILE_NOT_FOUND);
1552 return FALSE;
1555 if (pEntry->dwSignature != URL_SIGNATURE)
1557 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1558 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR)&pEntry->dwSignature, sizeof(DWORD)));
1559 SetLastError(ERROR_FILE_NOT_FOUND);
1560 return FALSE;
1563 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1565 if (pUrlEntry->dwUseCount == 0)
1567 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1568 return FALSE;
1570 pUrlEntry->dwUseCount--;
1571 URLCache_HashEntrySetUse(pHeader, lpszUrlName, pUrlEntry->dwUseCount);
1573 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1575 return TRUE;
1578 /***********************************************************************
1579 * UnlockUrlCacheEntryFileW (WININET.@)
1582 BOOL WINAPI UnlockUrlCacheEntryFileW( LPCWSTR lpszUrlName, DWORD dwReserved )
1584 FIXME("(%s, 0x%08lx)\n", debugstr_w(lpszUrlName), dwReserved);
1585 return TRUE;
1588 /***********************************************************************
1589 * CreateUrlCacheEntryA (WININET.@)
1592 BOOL WINAPI CreateUrlCacheEntryA(
1593 IN LPCSTR lpszUrlName,
1594 IN DWORD dwExpectedFileSize,
1595 IN LPCSTR lpszFileExtension,
1596 OUT LPSTR lpszFileName,
1597 IN DWORD dwReserved
1600 DWORD len;
1601 WCHAR *url_name;
1602 WCHAR *file_extension;
1603 WCHAR file_name[MAX_PATH];
1604 BOOL bSuccess = FALSE;
1605 DWORD dwError = 0;
1607 if ((len = MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, NULL, 0)) != 0 &&
1608 (url_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0)
1610 MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, url_name, len);
1611 if ((len = MultiByteToWideChar(CP_ACP, 0, lpszFileExtension, -1, NULL, 0)) != 0 &&
1612 (file_extension = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0)
1614 MultiByteToWideChar(CP_ACP, 0, lpszFileExtension, -1, file_extension, len);
1615 if (CreateUrlCacheEntryW(url_name, dwExpectedFileSize, file_extension, file_name, dwReserved))
1617 if (WideCharToMultiByte(CP_ACP, 0, file_name, -1, lpszFileName, MAX_PATH, NULL, NULL) < MAX_PATH)
1619 bSuccess = TRUE;
1621 else
1623 dwError = GetLastError();
1626 else
1628 dwError = GetLastError();
1630 HeapFree(GetProcessHeap(), 0, file_extension);
1632 else
1634 dwError = GetLastError();
1636 HeapFree(GetProcessHeap(), 0, url_name);
1637 if (!bSuccess)
1638 SetLastError(dwError);
1640 return bSuccess;
1642 /***********************************************************************
1643 * CreateUrlCacheEntryW (WININET.@)
1646 BOOL WINAPI CreateUrlCacheEntryW(
1647 IN LPCWSTR lpszUrlName,
1648 IN DWORD dwExpectedFileSize,
1649 IN LPCWSTR lpszFileExtension,
1650 OUT LPWSTR lpszFileName,
1651 IN DWORD dwReserved
1654 URLCACHECONTAINER * pContainer;
1655 LPURLCACHE_HEADER pHeader;
1656 CHAR szFile[MAX_PATH];
1657 WCHAR szExtension[MAX_PATH];
1658 LPCWSTR lpszUrlPart;
1659 LPCWSTR lpszUrlEnd;
1660 LPCWSTR lpszFileNameExtension;
1661 LPWSTR lpszFileNameNoPath;
1662 int i;
1663 int countnoextension;
1664 BYTE CacheDir;
1665 LONG lBufferSize;
1666 BOOL bFound = FALSE;
1667 int count;
1668 static WCHAR szWWW[] = {'w','w','w',0};
1670 TRACE("(%s, 0x%08lx, %s, %p, 0x%08lx)\n",
1671 debugstr_w(lpszUrlName),
1672 dwExpectedFileSize,
1673 debugstr_w(lpszFileExtension),
1674 lpszFileName,
1675 dwReserved);
1677 if (dwReserved)
1679 ERR("dwReserved != 0\n");
1680 SetLastError(ERROR_INVALID_PARAMETER);
1681 return FALSE;
1684 for (lpszUrlEnd = lpszUrlName; *lpszUrlEnd; lpszUrlEnd++)
1687 if (((lpszUrlEnd - lpszUrlName) > 1) && (*(lpszUrlEnd - 1) == '/' || *(lpszUrlEnd - 1) == '\\'))
1688 lpszUrlEnd--;
1690 for (lpszUrlPart = lpszUrlEnd;
1691 (lpszUrlPart >= lpszUrlName);
1692 lpszUrlPart--)
1694 if ((*lpszUrlPart == '/' || *lpszUrlPart == '\\') && ((lpszUrlEnd - lpszUrlPart) > 1))
1696 bFound = TRUE;
1697 lpszUrlPart++;
1698 break;
1701 if (!lstrcmpW(lpszUrlPart, szWWW))
1703 lpszUrlPart += lstrlenW(szWWW);
1706 count = lpszUrlEnd - lpszUrlPart;
1708 if (bFound && (count < MAX_PATH))
1710 int len = WideCharToMultiByte(CP_ACP, 0, lpszUrlPart, count, szFile, sizeof(szFile) - 1, NULL, NULL);
1711 if (!len)
1712 return FALSE;
1713 szFile[len] = '\0';
1714 /* FIXME: get rid of illegal characters like \, / and : */
1716 else
1718 FIXME("need to generate a random filename\n");
1721 TRACE("File name: %s\n", debugstr_a(szFile));
1723 if (!URLCacheContainers_FindContainerW(lpszUrlName, &pContainer))
1724 return FALSE;
1726 if (!URLCacheContainer_OpenIndex(pContainer))
1727 return FALSE;
1729 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1730 return FALSE;
1732 CacheDir = (BYTE)(rand() % pHeader->DirectoryCount);
1734 lBufferSize = MAX_PATH * sizeof(CHAR);
1735 URLCache_LocalFileNameToPathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize);
1737 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1739 for (lpszFileNameNoPath = lpszFileName + lBufferSize / sizeof(CHAR) - 2;
1740 lpszFileNameNoPath >= lpszFileName;
1741 --lpszFileNameNoPath)
1743 if (*lpszFileNameNoPath == '/' || *lpszFileNameNoPath == '\\')
1744 break;
1747 countnoextension = lstrlenW(lpszFileNameNoPath);
1748 lpszFileNameExtension = PathFindExtensionW(lpszFileNameNoPath);
1749 if (lpszFileNameExtension)
1750 countnoextension -= lstrlenW(lpszFileNameExtension);
1751 *szExtension = '\0';
1753 if (lpszFileExtension)
1755 szExtension[0] = '.';
1756 lstrcpyW(szExtension+1, lpszFileExtension);
1759 for (i = 0; i < 255; i++)
1761 static WCHAR szFormat[] = {'[','%','u',']','%','s',0};
1762 HANDLE hFile;
1763 wsprintfW(lpszFileNameNoPath + countnoextension, szFormat, i, szExtension);
1764 TRACE("Trying: %s\n", debugstr_w(lpszFileName));
1765 hFile = CreateFileW(lpszFileName, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
1766 if (hFile != INVALID_HANDLE_VALUE)
1768 CloseHandle(hFile);
1769 return TRUE;
1773 return FALSE;
1777 /***********************************************************************
1778 * CommitUrlCacheEntryInternal (Compensates for an MS bug)
1780 * The bug we are compensating for is that some drongo at Microsoft
1781 * used lpHeaderInfo to pass binary data to CommitUrlCacheEntryA.
1782 * As a consequence, CommitUrlCacheEntryA has been effectively
1783 * redefined as LPBYTE rather than LPCSTR. But CommitUrlCacheEntryW
1784 * is still defined as LPCWSTR. The result (other than madness) is
1785 * that we always need to store lpHeaderInfo in CP_ACP rather than
1786 * in UTF16, and we need to avoid converting lpHeaderInfo in
1787 * CommitUrlCacheEntryA to UTF16 and then back to CP_ACP, since the
1788 * result will lose data for arbitrary binary data.
1791 static BOOL WINAPI CommitUrlCacheEntryInternal(
1792 IN LPCWSTR lpszUrlName,
1793 IN LPCWSTR lpszLocalFileName,
1794 IN FILETIME ExpireTime,
1795 IN FILETIME LastModifiedTime,
1796 IN DWORD CacheEntryType,
1797 IN LPBYTE lpHeaderInfo,
1798 IN DWORD dwHeaderSize,
1799 IN LPCWSTR lpszFileExtension,
1800 IN LPCWSTR lpszOriginalUrl
1803 URLCACHECONTAINER * pContainer;
1804 LPURLCACHE_HEADER pHeader;
1805 CACHEFILE_ENTRY * pEntry;
1806 URL_CACHEFILE_ENTRY * pUrlEntry;
1807 DWORD dwBytesNeeded = sizeof(*pUrlEntry) - sizeof(pUrlEntry->szSourceUrlName);
1808 DWORD dwOffsetLocalFileName = 0;
1809 DWORD dwOffsetHeader = 0;
1810 DWORD dwFileSizeLow = 0;
1811 DWORD dwFileSizeHigh = 0;
1812 BYTE cDirectory = 0;
1813 char achFile[MAX_PATH];
1814 char achUrl[MAX_PATH];
1815 char *pchLocalFileName = 0;
1817 TRACE("(%s, %s, ..., ..., %lx, %p, %ld, %s, %s)\n",
1818 debugstr_w(lpszUrlName),
1819 debugstr_w(lpszLocalFileName),
1820 CacheEntryType,
1821 lpHeaderInfo,
1822 dwHeaderSize,
1823 debugstr_w(lpszFileExtension),
1824 debugstr_w(lpszOriginalUrl));
1826 if (lpszOriginalUrl)
1827 WARN(": lpszOriginalUrl ignored\n");
1829 if (lpszLocalFileName)
1831 HANDLE hFile;
1833 hFile = CreateFileW(lpszLocalFileName, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL);
1834 if (hFile == INVALID_HANDLE_VALUE)
1836 ERR("couldn't open file %s (error is %ld)\n", debugstr_w(lpszLocalFileName), GetLastError());
1837 return FALSE;
1840 /* Get file size */
1841 dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh);
1842 if ((dwFileSizeLow == INVALID_FILE_SIZE) && (GetLastError() != NO_ERROR))
1844 ERR("couldn't get file size (error is %ld)\n", GetLastError());
1845 CloseHandle(hFile);
1846 return FALSE;
1849 CloseHandle(hFile);
1852 if (!URLCacheContainers_FindContainerW(lpszUrlName, &pContainer))
1853 return FALSE;
1855 if (!URLCacheContainer_OpenIndex(pContainer))
1856 return FALSE;
1858 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
1859 return FALSE;
1861 WideCharToMultiByte(CP_ACP, 0, lpszUrlName, -1, achUrl, -1, NULL, NULL);
1863 if (URLCache_FindEntryInHash(pHeader, achUrl, &pEntry))
1865 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1866 FIXME("entry already in cache - don't know what to do!\n");
1868 * SetLastError(ERROR_FILE_NOT_FOUND);
1869 * return FALSE;
1871 return TRUE;
1874 if (lpszLocalFileName)
1876 BOOL bFound = FALSE;
1878 if (strncmpW(lpszLocalFileName, pContainer->path, lstrlenW(pContainer->path)))
1880 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1881 ERR("path %s must begin with cache content path %s\n", debugstr_w(lpszLocalFileName), debugstr_w(pContainer->path));
1882 SetLastError(ERROR_INVALID_PARAMETER);
1883 return FALSE;
1886 /* skip container path prefix */
1887 lpszLocalFileName += lstrlenW(pContainer->path);
1889 WideCharToMultiByte(CP_ACP, 0, lpszLocalFileName, -1, achFile, -1, NULL, NULL);
1890 pchLocalFileName = achFile;
1892 for (cDirectory = 0; cDirectory < pHeader->DirectoryCount; cDirectory++)
1894 if (!strncmp(pHeader->directory_data[cDirectory].filename, pchLocalFileName, DIR_LENGTH))
1896 bFound = TRUE;
1897 break;
1901 if (!bFound)
1903 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1904 ERR("cache directory not found in path %s\n", debugstr_w(lpszLocalFileName));
1905 SetLastError(ERROR_INVALID_PARAMETER);
1906 return FALSE;
1909 lpszLocalFileName += (DIR_LENGTH + 1); /* "1234WXYZ\" */
1912 dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(achUrl) + 1);
1913 if (lpszLocalFileName)
1915 dwOffsetLocalFileName = dwBytesNeeded;
1916 dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + strlen(pchLocalFileName) + 1);
1918 if (lpHeaderInfo)
1920 dwOffsetHeader = dwBytesNeeded;
1921 dwBytesNeeded = DWORD_ALIGN(dwBytesNeeded + dwHeaderSize);
1924 /* round up to next block */
1925 if (dwBytesNeeded % BLOCKSIZE)
1927 dwBytesNeeded -= dwBytesNeeded % BLOCKSIZE;
1928 dwBytesNeeded += BLOCKSIZE;
1931 if (!URLCache_FindFirstFreeEntry(pHeader, dwBytesNeeded / BLOCKSIZE, &pEntry))
1933 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1934 ERR("no free entries\n");
1935 return FALSE;
1938 /* FindFirstFreeEntry fills in blocks used */
1939 pUrlEntry = (URL_CACHEFILE_ENTRY *)pEntry;
1940 pUrlEntry->CacheFileEntry.dwSignature = URL_SIGNATURE;
1941 pUrlEntry->CacheDir = cDirectory;
1942 pUrlEntry->CacheEntryType = CacheEntryType;
1943 pUrlEntry->dwHeaderInfoSize = dwHeaderSize;
1944 pUrlEntry->dwExemptDelta = 0;
1945 pUrlEntry->dwHitRate = 0;
1946 pUrlEntry->dwOffsetHeaderInfo = dwOffsetHeader;
1947 pUrlEntry->dwOffsetLocalName = dwOffsetLocalFileName;
1948 pUrlEntry->dwOffsetUrl = sizeof(*pUrlEntry) - sizeof(pUrlEntry->szSourceUrlName);
1949 pUrlEntry->dwSizeHigh = 0;
1950 pUrlEntry->dwSizeLow = dwFileSizeLow;
1951 pUrlEntry->dwSizeHigh = dwFileSizeHigh;
1952 pUrlEntry->dwUseCount = 0;
1953 GetSystemTimeAsFileTime(&pUrlEntry->LastAccessTime);
1954 pUrlEntry->LastModifiedTime = LastModifiedTime;
1955 FileTimeToDosDateTime(&pUrlEntry->LastAccessTime, &pUrlEntry->wLastSyncDate, &pUrlEntry->wLastSyncTime);
1956 FileTimeToDosDateTime(&ExpireTime, &pUrlEntry->wExpiredDate, &pUrlEntry->wExpiredTime);
1957 pUrlEntry->wUnknownDate = pUrlEntry->wLastSyncDate;
1958 pUrlEntry->wUnknownTime = pUrlEntry->wLastSyncTime;
1960 /*** Unknowns ***/
1961 pUrlEntry->dwUnknown1 = 0;
1962 pUrlEntry->dwUnknown2 = 0;
1963 pUrlEntry->dwUnknown3 = 0x60;
1964 pUrlEntry->Unknown4 = 0;
1965 pUrlEntry->wUnknown5 = 0x1010;
1966 pUrlEntry->dwUnknown6 = 0;
1967 pUrlEntry->dwUnknown7 = 0;
1968 pUrlEntry->dwUnknown8 = 0;
1971 strcpy(pUrlEntry->szSourceUrlName, achUrl);
1972 if (dwOffsetLocalFileName)
1973 strcpy((LPSTR)((LPBYTE)pUrlEntry + dwOffsetLocalFileName), pchLocalFileName);
1974 if (dwOffsetHeader)
1975 memcpy((LPBYTE)pUrlEntry + dwOffsetHeader, lpHeaderInfo, dwHeaderSize);
1977 if (!URLCache_AddEntryToHash(pHeader, achUrl, (DWORD)((LPBYTE)pUrlEntry - (LPBYTE)pHeader)))
1979 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1980 return FALSE;
1983 URLCacheContainer_UnlockIndex(pContainer, pHeader);
1985 return TRUE;
1988 /***********************************************************************
1989 * CommitUrlCacheEntryA (WININET.@)
1992 BOOL WINAPI CommitUrlCacheEntryA(
1993 IN LPCSTR lpszUrlName,
1994 IN LPCSTR lpszLocalFileName,
1995 IN FILETIME ExpireTime,
1996 IN FILETIME LastModifiedTime,
1997 IN DWORD CacheEntryType,
1998 IN LPBYTE lpHeaderInfo,
1999 IN DWORD dwHeaderSize,
2000 IN LPCSTR lpszFileExtension,
2001 IN LPCSTR lpszOriginalUrl
2004 DWORD len;
2005 WCHAR *url_name;
2006 WCHAR *local_file_name;
2007 WCHAR *original_url = NULL;
2008 BOOL bSuccess = FALSE;
2009 DWORD dwError = 0;
2011 TRACE("(%s, %s, ..., ..., %lx, %p, %ld, %s, %s)\n",
2012 debugstr_a(lpszUrlName),
2013 debugstr_a(lpszLocalFileName),
2014 CacheEntryType,
2015 lpHeaderInfo,
2016 dwHeaderSize,
2017 debugstr_a(lpszFileExtension),
2018 debugstr_a(lpszOriginalUrl));
2020 if (lpszFileExtension != 0)
2022 SetLastError(ERROR_INVALID_PARAMETER);
2023 return FALSE;
2025 if ((len = MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, NULL, 0)) != 0 &&
2026 (url_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0)
2028 MultiByteToWideChar(CP_ACP, 0, lpszUrlName, -1, url_name, len);
2029 if ((len = MultiByteToWideChar(CP_ACP, 0, lpszLocalFileName, -1, NULL, 0)) != 0 &&
2030 (local_file_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0)
2032 MultiByteToWideChar(CP_ACP, 0, lpszLocalFileName, -1, local_file_name, len);
2033 if (!lpszOriginalUrl ||
2034 ((len = MultiByteToWideChar(CP_ACP, 0, lpszOriginalUrl, -1, NULL, 0)) != 0 &&
2035 (original_url = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))) != 0))
2037 if (original_url)
2038 MultiByteToWideChar(CP_ACP, 0, lpszOriginalUrl, -1, original_url, len);
2039 if (CommitUrlCacheEntryInternal(url_name, local_file_name, ExpireTime, LastModifiedTime,
2040 CacheEntryType, lpHeaderInfo, dwHeaderSize,
2041 NULL, original_url))
2043 bSuccess = TRUE;
2045 else
2047 dwError = GetLastError();
2049 if (original_url)
2050 HeapFree(GetProcessHeap(), 0, original_url);
2052 else
2054 dwError = GetLastError();
2056 HeapFree(GetProcessHeap(), 0, local_file_name);
2058 else
2060 dwError = GetLastError();
2062 HeapFree(GetProcessHeap(), 0, url_name);
2063 if (!bSuccess)
2064 SetLastError(dwError);
2066 return bSuccess;
2069 /***********************************************************************
2070 * CommitUrlCacheEntryW (WININET.@)
2073 BOOL WINAPI CommitUrlCacheEntryW(
2074 IN LPCWSTR lpszUrlName,
2075 IN LPCWSTR lpszLocalFileName,
2076 IN FILETIME ExpireTime,
2077 IN FILETIME LastModifiedTime,
2078 IN DWORD CacheEntryType,
2079 IN LPWSTR lpHeaderInfo,
2080 IN DWORD dwHeaderSize,
2081 IN LPCWSTR lpszFileExtension,
2082 IN LPCWSTR lpszOriginalUrl
2085 DWORD dwError = 0;
2086 BOOL bSuccess = FALSE;
2087 DWORD len = 0;
2088 CHAR *header_info = NULL;
2090 TRACE("(%s, %s, ..., ..., %lx, %p, %ld, %s, %s)\n",
2091 debugstr_w(lpszUrlName),
2092 debugstr_w(lpszLocalFileName),
2093 CacheEntryType,
2094 lpHeaderInfo,
2095 dwHeaderSize,
2096 debugstr_w(lpszFileExtension),
2097 debugstr_w(lpszOriginalUrl));
2099 if (!lpHeaderInfo ||
2100 ((len = WideCharToMultiByte(CP_ACP, 0, lpHeaderInfo, -1, NULL, 0, NULL, NULL)) != 0 &&
2101 (header_info = HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR) * len)) != 0))
2103 if (header_info)
2104 WideCharToMultiByte(CP_ACP, 0, lpHeaderInfo, -1, header_info, len, NULL, NULL);
2105 if (CommitUrlCacheEntryInternal(lpszUrlName, lpszLocalFileName, ExpireTime, LastModifiedTime,
2106 CacheEntryType, header_info, len, lpszFileExtension, lpszOriginalUrl))
2108 bSuccess = TRUE;
2110 else
2112 dwError = GetLastError();
2114 if (header_info)
2116 HeapFree(GetProcessHeap(), 0, header_info);
2117 if (!bSuccess)
2118 SetLastError(dwError);
2121 return bSuccess;
2124 /***********************************************************************
2125 * ReadUrlCacheEntryStream (WININET.@)
2128 BOOL WINAPI ReadUrlCacheEntryStream(
2129 IN HANDLE hUrlCacheStream,
2130 IN DWORD dwLocation,
2131 IN OUT LPVOID lpBuffer,
2132 IN OUT LPDWORD lpdwLen,
2133 IN DWORD dwReserved
2136 /* Get handle to file from 'stream' */
2137 STREAM_HANDLE * pStream = (STREAM_HANDLE *)hUrlCacheStream;
2139 if (dwReserved != 0)
2141 ERR("dwReserved != 0\n");
2142 SetLastError(ERROR_INVALID_PARAMETER);
2143 return FALSE;
2146 if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->lpszUrl, INTERNET_MAX_URL_LENGTH))
2148 SetLastError(ERROR_INVALID_HANDLE);
2149 return FALSE;
2152 if (SetFilePointer(pStream->hFile, dwLocation, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
2153 return FALSE;
2154 return ReadFile(pStream->hFile, lpBuffer, *lpdwLen, lpdwLen, NULL);
2157 /***********************************************************************
2158 * RetrieveUrlCacheEntryStreamA (WININET.@)
2161 HANDLE WINAPI RetrieveUrlCacheEntryStreamA(
2162 IN LPCSTR lpszUrlName,
2163 OUT LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo,
2164 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
2165 IN BOOL fRandomRead,
2166 IN DWORD dwReserved
2169 /* NOTE: this is not the same as the way that the native
2170 * version allocates 'stream' handles. I did it this way
2171 * as it is much easier and no applications should depend
2172 * on this behaviour. (Native version appears to allocate
2173 * indices into a table)
2175 STREAM_HANDLE * pStream;
2176 HANDLE hFile;
2178 TRACE( "(%s, %p, %p, %x, 0x%08lx)\n", debugstr_a(lpszUrlName), lpCacheEntryInfo,
2179 lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved );
2181 if (!RetrieveUrlCacheEntryFileA(lpszUrlName,
2182 lpCacheEntryInfo,
2183 lpdwCacheEntryInfoBufferSize,
2184 dwReserved))
2186 return NULL;
2189 hFile = CreateFileA(lpCacheEntryInfo->lpszLocalFileName,
2190 GENERIC_READ,
2191 FILE_SHARE_READ,
2192 NULL,
2193 OPEN_EXISTING,
2194 fRandomRead ? FILE_FLAG_RANDOM_ACCESS : 0,
2195 NULL);
2196 if (hFile == INVALID_HANDLE_VALUE)
2197 return FALSE;
2199 /* allocate handle storage space */
2200 pStream = HeapAlloc(GetProcessHeap(), 0, sizeof(STREAM_HANDLE) + strlen(lpszUrlName) * sizeof(CHAR));
2201 if (!pStream)
2203 CloseHandle(hFile);
2204 SetLastError(ERROR_OUTOFMEMORY);
2205 return FALSE;
2208 pStream->hFile = hFile;
2209 strcpy(pStream->lpszUrl, lpszUrlName);
2210 return (HANDLE)pStream;
2213 /***********************************************************************
2214 * RetrieveUrlCacheEntryStreamW (WININET.@)
2217 HANDLE WINAPI RetrieveUrlCacheEntryStreamW(
2218 IN LPCWSTR lpszUrlName,
2219 OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
2220 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize,
2221 IN BOOL fRandomRead,
2222 IN DWORD dwReserved
2225 FIXME( "(%s, %p, %p, %x, 0x%08lx)\n", debugstr_w(lpszUrlName), lpCacheEntryInfo,
2226 lpdwCacheEntryInfoBufferSize, fRandomRead, dwReserved );
2227 return NULL;
2230 /***********************************************************************
2231 * UnlockUrlCacheEntryStream (WININET.@)
2234 BOOL WINAPI UnlockUrlCacheEntryStream(
2235 IN HANDLE hUrlCacheStream,
2236 IN DWORD dwReserved
2239 STREAM_HANDLE * pStream = (STREAM_HANDLE *)hUrlCacheStream;
2241 if (dwReserved != 0)
2243 ERR("dwReserved != 0\n");
2244 SetLastError(ERROR_INVALID_PARAMETER);
2245 return FALSE;
2248 if (IsBadReadPtr(pStream, sizeof(*pStream)) || IsBadStringPtrA(pStream->lpszUrl, INTERNET_MAX_URL_LENGTH))
2250 SetLastError(ERROR_INVALID_HANDLE);
2251 return FALSE;
2254 if (!UnlockUrlCacheEntryFileA(pStream->lpszUrl, 0))
2255 return FALSE;
2257 /* close file handle */
2258 CloseHandle(pStream->hFile);
2260 /* free allocated space */
2261 HeapFree(GetProcessHeap(), 0, pStream);
2263 return TRUE;
2267 /***********************************************************************
2268 * DeleteUrlCacheEntryA (WININET.@)
2271 BOOL WINAPI DeleteUrlCacheEntryA(LPCSTR lpszUrlName)
2273 URLCACHECONTAINER * pContainer;
2274 LPURLCACHE_HEADER pHeader;
2275 CACHEFILE_ENTRY * pEntry;
2276 DWORD dwStartBlock;
2277 DWORD dwBlock;
2278 BYTE * AllocationTable;
2280 TRACE("(%s)\n", debugstr_a(lpszUrlName));
2282 if (!URLCacheContainers_FindContainerA(lpszUrlName, &pContainer))
2283 return FALSE;
2285 if (!URLCacheContainer_OpenIndex(pContainer))
2286 return FALSE;
2288 if (!(pHeader = URLCacheContainer_LockIndex(pContainer)))
2289 return FALSE;
2291 if (!URLCache_FindEntryInHash(pHeader, lpszUrlName, &pEntry))
2293 URLCacheContainer_UnlockIndex(pContainer, pHeader);
2294 TRACE("entry %s not found!\n", lpszUrlName);
2295 SetLastError(ERROR_FILE_NOT_FOUND);
2296 return FALSE;
2299 AllocationTable = (LPBYTE)pHeader + ALLOCATION_TABLE_OFFSET;
2301 /* update allocation table */
2302 dwStartBlock = ((DWORD)pEntry - (DWORD)pHeader) / BLOCKSIZE;
2303 for (dwBlock = dwStartBlock; dwBlock < dwStartBlock + pEntry->dwBlocksUsed; dwBlock++)
2304 URLCache_Allocation_BlockFree(AllocationTable, dwBlock);
2306 URLCache_DeleteEntry(pEntry);
2308 URLCache_DeleteEntryFromHash(pHeader, lpszUrlName);
2310 URLCacheContainer_UnlockIndex(pContainer, pHeader);
2312 return TRUE;
2315 /***********************************************************************
2316 * DeleteUrlCacheEntryW (WININET.@)
2319 BOOL WINAPI DeleteUrlCacheEntryW(LPCWSTR lpszUrlName)
2321 FIXME("(%s) stub\n", debugstr_w(lpszUrlName));
2322 return TRUE;
2325 BOOL WINAPI DeleteUrlCacheContainerA(DWORD d1, DWORD d2)
2327 FIXME("(0x%08lx, 0x%08lx) stub\n", d1, d2);
2328 return TRUE;
2331 BOOL WINAPI DeleteUrlCacheContainerW(DWORD d1, DWORD d2)
2333 FIXME("(0x%08lx, 0x%08lx) stub\n", d1, d2);
2334 return TRUE;
2337 /***********************************************************************
2338 * CreateCacheContainerA (WININET.@)
2340 BOOL WINAPI CreateUrlCacheContainerA(DWORD d1, DWORD d2, DWORD d3, DWORD d4,
2341 DWORD d5, DWORD d6, DWORD d7, DWORD d8)
2343 FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx) stub\n",
2344 d1, d2, d3, d4, d5, d6, d7, d8);
2345 return TRUE;
2348 /***********************************************************************
2349 * CreateCacheContainerW (WININET.@)
2351 BOOL WINAPI CreateUrlCacheContainerW(DWORD d1, DWORD d2, DWORD d3, DWORD d4,
2352 DWORD d5, DWORD d6, DWORD d7, DWORD d8)
2354 FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx) stub\n",
2355 d1, d2, d3, d4, d5, d6, d7, d8);
2356 return TRUE;
2359 /***********************************************************************
2360 * FindCloseUrlCache (WININET.@)
2362 BOOL WINAPI FindCloseUrlCache(HANDLE hEnumHandle)
2364 FIXME("(%p) stub\n", hEnumHandle);
2365 return TRUE;
2368 /***********************************************************************
2369 * FindFirstUrlCacheContainerA (WININET.@)
2371 HANDLE WINAPI FindFirstUrlCacheContainerA( LPVOID p1, LPVOID p2, LPVOID p3, DWORD d1 )
2373 FIXME("(%p, %p, %p, 0x%08lx) stub\n", p1, p2, p3, d1 );
2374 return NULL;
2377 /***********************************************************************
2378 * FindFirstUrlCacheContainerW (WININET.@)
2380 HANDLE WINAPI FindFirstUrlCacheContainerW( LPVOID p1, LPVOID p2, LPVOID p3, DWORD d1 )
2382 FIXME("(%p, %p, %p, 0x%08lx) stub\n", p1, p2, p3, d1 );
2383 return NULL;
2386 /***********************************************************************
2387 * FindNextUrlCacheContainerA (WININET.@)
2389 BOOL WINAPI FindNextUrlCacheContainerA( HANDLE handle, LPVOID p1, LPVOID p2 )
2391 FIXME("(%p, %p, %p) stub\n", handle, p1, p2 );
2392 return FALSE;
2395 /***********************************************************************
2396 * FindNextUrlCacheContainerW (WININET.@)
2398 BOOL WINAPI FindNextUrlCacheContainerW( HANDLE handle, LPVOID p1, LPVOID p2 )
2400 FIXME("(%p, %p, %p) stub\n", handle, p1, p2 );
2401 return FALSE;
2404 HANDLE WINAPI FindFirstUrlCacheEntryExA(
2405 LPCSTR lpszUrlSearchPattern,
2406 DWORD dwFlags,
2407 DWORD dwFilter,
2408 GROUPID GroupId,
2409 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,
2410 LPDWORD lpdwFirstCacheEntryInfoBufferSize,
2411 LPVOID lpReserved,
2412 LPDWORD pcbReserved2,
2413 LPVOID lpReserved3
2416 FIXME("(%s, 0x%08lx, 0x%08lx, 0x%08lx%08lx, %p, %p, %p, %p, %p) stub\n", debugstr_a(lpszUrlSearchPattern),
2417 dwFlags, dwFilter, (ULONG)(GroupId >> 32), (ULONG)GroupId, lpFirstCacheEntryInfo,
2418 lpdwFirstCacheEntryInfoBufferSize, lpReserved, pcbReserved2,lpReserved3);
2419 SetLastError(ERROR_FILE_NOT_FOUND);
2420 return NULL;
2423 HANDLE WINAPI FindFirstUrlCacheEntryExW(
2424 LPCWSTR lpszUrlSearchPattern,
2425 DWORD dwFlags,
2426 DWORD dwFilter,
2427 GROUPID GroupId,
2428 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,
2429 LPDWORD lpdwFirstCacheEntryInfoBufferSize,
2430 LPVOID lpReserved,
2431 LPDWORD pcbReserved2,
2432 LPVOID lpReserved3
2435 FIXME("(%s, 0x%08lx, 0x%08lx, 0x%08lx%08lx, %p, %p, %p, %p, %p) stub\n", debugstr_w(lpszUrlSearchPattern),
2436 dwFlags, dwFilter, (ULONG)(GroupId >> 32), (ULONG)GroupId, lpFirstCacheEntryInfo,
2437 lpdwFirstCacheEntryInfoBufferSize, lpReserved, pcbReserved2,lpReserved3);
2438 SetLastError(ERROR_FILE_NOT_FOUND);
2439 return NULL;
2442 /***********************************************************************
2443 * FindFirstUrlCacheEntryA (WININET.@)
2446 INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern,
2447 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize)
2449 FIXME("(%s, %p, %p): stub\n", debugstr_a(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize);
2450 SetLastError(ERROR_FILE_NOT_FOUND);
2451 return 0;
2454 /***********************************************************************
2455 * FindFirstUrlCacheEntryW (WININET.@)
2458 INTERNETAPI HANDLE WINAPI FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern,
2459 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo, LPDWORD lpdwFirstCacheEntryInfoBufferSize)
2461 FIXME("(%s, %p, %p): stub\n", debugstr_w(lpszUrlSearchPattern), lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize);
2462 return 0;
2465 HANDLE WINAPI FindFirstUrlCacheGroup( DWORD dwFlags, DWORD dwFilter, LPVOID lpSearchCondition,
2466 DWORD dwSearchCondition, GROUPID* lpGroupId, LPVOID lpReserved )
2468 FIXME("(0x%08lx, 0x%08lx, %p, 0x%08lx, %p, %p) stub\n", dwFlags, dwFilter, lpSearchCondition,
2469 dwSearchCondition, lpGroupId, lpReserved);
2470 return NULL;
2473 BOOL WINAPI FindNextUrlCacheEntryA(
2474 HANDLE hEnumHandle,
2475 LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo,
2476 LPDWORD lpdwNextCacheEntryInfoBufferSize
2479 FIXME("(%p, %p, %p) stub\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize);
2480 return FALSE;
2483 BOOL WINAPI FindNextUrlCacheEntryW(
2484 HANDLE hEnumHandle,
2485 LPINTERNET_CACHE_ENTRY_INFOW lpNextCacheEntryInfo,
2486 LPDWORD lpdwNextCacheEntryInfoBufferSize
2489 FIXME("(%p, %p, %p) stub\n", hEnumHandle, lpNextCacheEntryInfo, lpdwNextCacheEntryInfoBufferSize);
2490 return FALSE;
2493 BOOL WINAPI FindNextUrlCacheEntryExA(
2494 HANDLE hEnumHandle,
2495 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo,
2496 LPDWORD lpdwFirstCacheEntryInfoBufferSize,
2497 LPVOID lpReserved,
2498 LPDWORD pcbReserved2,
2499 LPVOID lpReserved3
2502 FIXME("(%p, %p, %p, %p, %p, %p) stub\n", hEnumHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize,
2503 lpReserved, pcbReserved2, lpReserved3);
2504 return FALSE;
2507 BOOL WINAPI FindNextUrlCacheEntryExW(
2508 HANDLE hEnumHandle,
2509 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,
2510 LPDWORD lpdwFirstCacheEntryInfoBufferSize,
2511 LPVOID lpReserved,
2512 LPDWORD pcbReserved2,
2513 LPVOID lpReserved3
2516 FIXME("(%p, %p, %p, %p, %p, %p) stub\n", hEnumHandle, lpFirstCacheEntryInfo, lpdwFirstCacheEntryInfoBufferSize,
2517 lpReserved, pcbReserved2, lpReserved3);
2518 return FALSE;
2521 BOOL WINAPI FindNextUrlCacheGroup( HANDLE hFind, GROUPID* lpGroupId, LPVOID lpReserved )
2523 FIXME("(%p, %p, %p) stub\n", hFind, lpGroupId, lpReserved);
2524 return FALSE;
2527 /***********************************************************************
2528 * CreateUrlCacheGroup (WININET.@)
2531 INTERNETAPI GROUPID WINAPI CreateUrlCacheGroup(DWORD dwFlags, LPVOID lpReserved)
2533 FIXME("(0x%08lx, %p): stub\n", dwFlags, lpReserved);
2534 return FALSE;
2537 /***********************************************************************
2538 * DeleteUrlCacheGroup (WININET.@)
2541 BOOL WINAPI DeleteUrlCacheGroup(GROUPID GroupId, DWORD dwFlags, LPVOID lpReserved)
2543 FIXME("(0x%08lx%08lx, 0x%08lx, %p) stub\n",
2544 (ULONG)(GroupId >> 32), (ULONG)GroupId, dwFlags, lpReserved);
2545 return FALSE;
2548 /***********************************************************************
2549 * SetUrlCacheEntryGroupA (WININET.@)
2552 BOOL WINAPI SetUrlCacheEntryGroupA(LPCSTR lpszUrlName, DWORD dwFlags,
2553 GROUPID GroupId, LPBYTE pbGroupAttributes, DWORD cbGroupAttributes,
2554 LPVOID lpReserved)
2556 FIXME("(%s, 0x%08lx, 0x%08lx%08lx, %p, 0x%08lx, %p) stub\n",
2557 debugstr_a(lpszUrlName), dwFlags, (ULONG)(GroupId >> 32), (ULONG)GroupId,
2558 pbGroupAttributes, cbGroupAttributes, lpReserved);
2559 SetLastError(ERROR_FILE_NOT_FOUND);
2560 return FALSE;
2563 /***********************************************************************
2564 * SetUrlCacheEntryGroupW (WININET.@)
2567 BOOL WINAPI SetUrlCacheEntryGroupW(LPCWSTR lpszUrlName, DWORD dwFlags,
2568 GROUPID GroupId, LPBYTE pbGroupAttributes, DWORD cbGroupAttributes,
2569 LPVOID lpReserved)
2571 FIXME("(%s, 0x%08lx, 0x%08lx%08lx, %p, 0x%08lx, %p) stub\n",
2572 debugstr_w(lpszUrlName), dwFlags, (ULONG)(GroupId >> 32), (ULONG)GroupId,
2573 pbGroupAttributes, cbGroupAttributes, lpReserved);
2574 SetLastError(ERROR_FILE_NOT_FOUND);
2575 return FALSE;
2578 /***********************************************************************
2579 * GetUrlCacheConfigInfoW (WININET.@)
2581 BOOL WINAPI GetUrlCacheConfigInfoW(LPDWORD CacheInfo, LPDWORD size, DWORD bitmask)
2583 FIXME("(%p, %p, %lx)\n", CacheInfo, size, bitmask);
2584 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
2585 return FALSE;
2588 /***********************************************************************
2589 * GetUrlCacheConfigInfoA (WININET.@)
2591 * CacheInfo is some CACHE_CONFIG_INFO structure, with no MS info found by google
2593 BOOL WINAPI GetUrlCacheConfigInfoA(LPDWORD CacheInfo, LPDWORD size, DWORD bitmask)
2595 FIXME("(%p, %p, %lx)\n", CacheInfo, size, bitmask);
2596 INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
2597 return FALSE;
2600 BOOL WINAPI GetUrlCacheGroupAttributeA( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
2601 LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo,
2602 LPDWORD lpdwGroupInfo, LPVOID lpReserved )
2604 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p, %p) stub\n",
2605 (ULONG)(gid >> 32), (ULONG)gid, dwFlags, dwAttributes, lpGroupInfo,
2606 lpdwGroupInfo, lpReserved);
2607 return FALSE;
2610 BOOL WINAPI GetUrlCacheGroupAttributeW( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
2611 LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,
2612 LPDWORD lpdwGroupInfo, LPVOID lpReserved )
2614 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p, %p) stub\n",
2615 (ULONG)(gid >> 32), (ULONG)gid, dwFlags, dwAttributes, lpGroupInfo,
2616 lpdwGroupInfo, lpReserved);
2617 return FALSE;
2620 BOOL WINAPI SetUrlCacheGroupAttributeA( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
2621 LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo, LPVOID lpReserved )
2623 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p) stub\n",
2624 (ULONG)(gid >> 32), (ULONG)gid, dwFlags, dwAttributes, lpGroupInfo, lpReserved);
2625 return TRUE;
2628 BOOL WINAPI SetUrlCacheGroupAttributeW( GROUPID gid, DWORD dwFlags, DWORD dwAttributes,
2629 LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo, LPVOID lpReserved )
2631 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p) stub\n",
2632 (ULONG)(gid >> 32), (ULONG)gid, dwFlags, dwAttributes, lpGroupInfo, lpReserved);
2633 return TRUE;
2636 BOOL WINAPI SetUrlCacheConfigInfoA( LPDWORD lpCacheConfigInfo, DWORD dwFieldControl )
2638 FIXME("(%p, 0x%08lx) stub\n", lpCacheConfigInfo, dwFieldControl);
2639 return TRUE;
2642 BOOL WINAPI SetUrlCacheConfigInfoW( LPDWORD lpCacheConfigInfo, DWORD dwFieldControl )
2644 FIXME("(%p, 0x%08lx) stub\n", lpCacheConfigInfo, dwFieldControl);
2645 return TRUE;
2648 /***********************************************************************
2649 * DeleteIE3Cache (WININET.@)
2651 * Deletes the files used by the IE3 URL caching system.
2653 * PARAMS
2654 * hWnd [I] A dummy window.
2655 * hInst [I] Instance of process calling the function.
2656 * lpszCmdLine [I] Options used by function.
2657 * nCmdShow [I] The nCmdShow value to use when showing windows created, if any.
2659 * RETURNS
2660 * nothing
2662 void WINAPI DeleteIE3Cache(HWND hWnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nCmdShow)
2664 FIXME("(%p, %p, %s, %d)\n", hWnd, hInst, debugstr_a(lpszCmdLine), nCmdShow);