2 * Wininet - Url Cache functions
4 * Copyright 2001,2002 CodeWeavers
5 * Copyright 2003 Robert Shearman
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
27 #include "wine/port.h"
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
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
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
77 DWORD dwSignature
; /* e.g. "URL " */
78 /* CHAR szSignature[4];
80 DWORD dwBlocksUsed
; /* number of 128byte blocks used by this 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
;
126 typedef struct _HASH_CACHEFILE_ENTRY
128 CACHEFILE_ENTRY CacheFileEntry
;
130 DWORD dwHashTableNumber
;
131 struct _HASH_ENTRY HashTable
[HASHTABLE_SIZE
];
132 } HASH_CACHEFILE_ENTRY
;
134 typedef struct _DIRECTORY_DATA
137 char filename
[DIR_LENGTH
];
140 typedef struct _URLCACHE_HEADER
142 char szSignature
[28];
144 DWORD dwOffsetFirstHashTable
;
145 DWORD dwIndexCapacityInBlocks
;
146 DWORD dwBlocksInUse
; /* is this right? */
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? */
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
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 */
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 '!')
192 static void URLCache_PathToObjectName(LPWSTR lpszPath
, WCHAR replace
)
194 for (; *lpszPath
; lpszPath
++)
196 if (*lpszPath
== '\\')
201 /***********************************************************************
202 * URLCacheContainer_OpenIndex (Internal)
204 * Opens the index file and saves mapping handle in hCacheIndexMapping
211 static BOOL
URLCacheContainer_OpenIndex(URLCACHECONTAINER
* pContainer
)
214 WCHAR wszFilePath
[MAX_PATH
];
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
)
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");
233 dwFileSize
= GetFileSize(hFile
, NULL
);
234 if (dwFileSize
== INVALID_FILE_SIZE
)
239 FIXME("need to create cache index file\n");
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
);
249 if (!pContainer
->hMapping
)
251 ERR("Couldn't create file mapping (error is %ld)\n", GetLastError());
258 /***********************************************************************
259 * URLCacheContainer_CloseIndex (Internal)
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
);
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
);
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
);
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
);
317 list_add_head(&UrlContainers
, &pContainer
->entry
);
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};
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
},
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
);
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");
374 wszCachePath
[path_len
] = '\\';
376 strcpyW(wszMutexName
, wszCachePath
);
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
;
414 ERR("no container found\n");
415 SetLastError(ERROR_FILE_NOT_FOUND
);
419 static BOOL
URLCacheContainers_FindContainerA(LPCSTR lpszUrl
, URLCACHECONTAINER
** ppContainer
)
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
);
434 /***********************************************************************
435 * URLCacheContainer_LockIndex (Internal)
438 static LPURLCACHE_HEADER
URLCacheContainer_LockIndex(URLCACHECONTAINER
* pContainer
)
442 URLCACHE_HEADER
* pHeader
;
445 WaitForSingleObject(pContainer
->hMutex
, INFINITE
);
447 pIndexData
= MapViewOfFile(pContainer
->hMapping
, FILE_MAP_WRITE
, 0, 0, 0);
451 ReleaseMutex(pContainer
->hMutex
);
452 ERR("Couldn't MapViewOfFile. Error: %ld\n", GetLastError());
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
);
468 pIndexData
= MapViewOfFile(pContainer
->hMapping
, FILE_MAP_WRITE
, 0, 0, 0);
472 ReleaseMutex(pContainer
->hMutex
);
473 ERR("Couldn't MapViewOfFile. Error: %ld\n", GetLastError());
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
);
489 /***********************************************************************
490 * URLCacheContainer_UnlockIndex (Internal)
493 static BOOL
URLCacheContainer_UnlockIndex(URLCACHECONTAINER
* pContainer
, LPURLCACHE_HEADER pHeader
)
496 ReleaseMutex(pContainer
->hMutex
);
497 return UnmapViewOfFile(pHeader
);
502 #define CHAR_BIT (8 * sizeof(CHAR))
505 /***********************************************************************
506 * URLCache_Allocation_BlockIsFree (Internal)
508 * Is the specified block number free?
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
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
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.
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
;
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
);
574 TRACE("Found free block at no. %ld (0x%lx)\n", dwBlockNumber
, ENTRY_START_OFFSET
+ dwBlockNumber
* BLOCKSIZE
);
576 if (dwFreeCounter
== dwBlocksNeeded
)
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
;
587 FIXME("Grow file\n");
591 /***********************************************************************
592 * URLCache_DeleteEntry (Internal)
594 * Deletes the specified entry and frees the space allocated to it
597 * TRUE if it succeeded
601 static BOOL
URLCache_DeleteEntry(CACHEFILE_ENTRY
* pEntry
)
603 ZeroMemory(pEntry
, pEntry
->dwBlocksUsed
* BLOCKSIZE
);
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).
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
,
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
)
636 nRequired
= (path_len
+ DIR_LENGTH
+ file_name_len
+ 1) * sizeof(WCHAR
);
637 if (nRequired
< *lpBufferSize
)
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
;
648 *lpBufferSize
= nRequired
;
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.
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
,
673 int path_len
= WideCharToMultiByte(CP_ACP
, 0, pContainer
->path
, -1, NULL
, 0, NULL
, NULL
);
674 int file_name_len
= strlen(szLocalFileName
);
675 int dir_len
= DIR_LENGTH
;
676 if (Directory
>= pHeader
->DirectoryCount
)
682 nRequired
= (path_len
+ dir_len
+ file_name_len
+ 1) * sizeof(WCHAR
);
683 if (nRequired
< *lpBufferSize
)
685 WideCharToMultiByte(CP_ACP
, 0, pContainer
->path
, -1, szPath
, -1, NULL
, NULL
);
686 strncpy(szPath
, pHeader
->directory_data
[Directory
].filename
, DIR_LENGTH
);
687 szPath
[dir_len
+ path_len
] = '\\';
688 strcpy(szPath
+ dir_len
+ path_len
+ 1, szLocalFileName
);
689 *lpBufferSize
= nRequired
;
692 *lpBufferSize
= nRequired
;
696 /***********************************************************************
697 * URLCache_CopyEntry (Internal)
699 * Copies an entry from the cache index file to the Win32 structure
702 * TRUE if the buffer was big enough
703 * FALSE if the buffer was too small
706 static BOOL
URLCache_CopyEntry(
707 URLCACHECONTAINER
* pContainer
,
708 LPCURLCACHE_HEADER pHeader
,
709 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo
,
710 LPDWORD lpdwBufferSize
,
711 URL_CACHEFILE_ENTRY
* pUrlEntry
,
715 DWORD dwRequiredSize
= sizeof(*lpCacheEntryInfo
);
717 if (*lpdwBufferSize
>= dwRequiredSize
)
719 lpCacheEntryInfo
->lpHeaderInfo
= NULL
;
720 lpCacheEntryInfo
->lpszFileExtension
= NULL
;
721 lpCacheEntryInfo
->lpszLocalFileName
= NULL
;
722 lpCacheEntryInfo
->lpszSourceUrlName
= NULL
;
723 lpCacheEntryInfo
->CacheEntryType
= pUrlEntry
->CacheEntryType
;
724 lpCacheEntryInfo
->u
.dwExemptDelta
= pUrlEntry
->dwExemptDelta
;
725 lpCacheEntryInfo
->dwHeaderInfoSize
= pUrlEntry
->dwHeaderInfoSize
;
726 lpCacheEntryInfo
->dwHitRate
= pUrlEntry
->dwHitRate
;
727 lpCacheEntryInfo
->dwSizeHigh
= pUrlEntry
->dwSizeHigh
;
728 lpCacheEntryInfo
->dwSizeLow
= pUrlEntry
->dwSizeLow
;
729 lpCacheEntryInfo
->dwStructSize
= sizeof(*lpCacheEntryInfo
);
730 lpCacheEntryInfo
->dwUseCount
= pUrlEntry
->dwUseCount
;
731 DosDateTimeToFileTime(pUrlEntry
->wExpiredDate
, pUrlEntry
->wExpiredTime
, &lpCacheEntryInfo
->ExpireTime
);
732 lpCacheEntryInfo
->LastAccessTime
.dwHighDateTime
= pUrlEntry
->LastAccessTime
.dwHighDateTime
;
733 lpCacheEntryInfo
->LastAccessTime
.dwLowDateTime
= pUrlEntry
->LastAccessTime
.dwLowDateTime
;
734 lpCacheEntryInfo
->LastModifiedTime
.dwHighDateTime
= pUrlEntry
->LastModifiedTime
.dwHighDateTime
;
735 lpCacheEntryInfo
->LastModifiedTime
.dwLowDateTime
= pUrlEntry
->LastModifiedTime
.dwLowDateTime
;
736 DosDateTimeToFileTime(pUrlEntry
->wLastSyncDate
, pUrlEntry
->wLastSyncTime
, &lpCacheEntryInfo
->LastSyncTime
);
739 if ((dwRequiredSize
% 4) && (dwRequiredSize
< *lpdwBufferSize
))
740 ZeroMemory((LPBYTE
)lpCacheEntryInfo
+ dwRequiredSize
, 4 - (dwRequiredSize
% 4));
741 dwRequiredSize
= DWORD_ALIGN(dwRequiredSize
);
743 lenUrl
= MultiByteToWideChar(CP_ACP
, 0, pUrlEntry
->szSourceUrlName
, -1, NULL
, 0);
745 lenUrl
= strlen(pUrlEntry
->szSourceUrlName
);
746 dwRequiredSize
+= lenUrl
+ 1;
748 /* FIXME: is source url optional? */
749 if (*lpdwBufferSize
>= dwRequiredSize
)
751 lpCacheEntryInfo
->lpszSourceUrlName
= (LPSTR
)lpCacheEntryInfo
+ dwRequiredSize
- lenUrl
- 1;
753 MultiByteToWideChar(CP_ACP
, 0, pUrlEntry
->szSourceUrlName
, -1, (LPWSTR
)lpCacheEntryInfo
->lpszSourceUrlName
, lenUrl
+ 1);
755 memcpy(lpCacheEntryInfo
->lpszSourceUrlName
, pUrlEntry
->szSourceUrlName
, (lenUrl
+ 1) * sizeof(CHAR
));
758 if ((dwRequiredSize
% 4) && (dwRequiredSize
< *lpdwBufferSize
))
759 ZeroMemory((LPBYTE
)lpCacheEntryInfo
+ dwRequiredSize
, 4 - (dwRequiredSize
% 4));
760 dwRequiredSize
= DWORD_ALIGN(dwRequiredSize
);
762 if (pUrlEntry
->dwOffsetLocalName
)
764 LONG nLocalFilePathSize
;
765 LPSTR lpszLocalFileName
;
766 lpszLocalFileName
= (LPSTR
)lpCacheEntryInfo
+ dwRequiredSize
;
767 nLocalFilePathSize
= *lpdwBufferSize
- dwRequiredSize
;
768 if ((bUnicode
&& URLCache_LocalFileNameToPathW(pContainer
, pHeader
, (LPCSTR
)pUrlEntry
+ pUrlEntry
->dwOffsetLocalName
, pUrlEntry
->CacheDir
, (LPWSTR
)lpszLocalFileName
, &nLocalFilePathSize
)) ||
769 URLCache_LocalFileNameToPathA(pContainer
, pHeader
, (LPCSTR
)pUrlEntry
+ pUrlEntry
->dwOffsetLocalName
, pUrlEntry
->CacheDir
, lpszLocalFileName
, &nLocalFilePathSize
))
771 lpCacheEntryInfo
->lpszLocalFileName
= lpszLocalFileName
;
773 dwRequiredSize
+= nLocalFilePathSize
;
775 if ((dwRequiredSize
% 4) && (dwRequiredSize
< *lpdwBufferSize
))
776 ZeroMemory((LPBYTE
)lpCacheEntryInfo
+ dwRequiredSize
, 4 - (dwRequiredSize
% 4));
777 dwRequiredSize
= DWORD_ALIGN(dwRequiredSize
);
779 dwRequiredSize
+= pUrlEntry
->dwHeaderInfoSize
+ 1;
781 if (*lpdwBufferSize
>= dwRequiredSize
)
783 lpCacheEntryInfo
->lpHeaderInfo
= (LPBYTE
)lpCacheEntryInfo
+ dwRequiredSize
- pUrlEntry
->dwHeaderInfoSize
- 1;
784 memcpy(lpCacheEntryInfo
->lpHeaderInfo
, (LPSTR
)pUrlEntry
+ pUrlEntry
->dwOffsetHeaderInfo
, pUrlEntry
->dwHeaderInfoSize
);
785 ((LPBYTE
)lpCacheEntryInfo
)[dwRequiredSize
- 1] = '\0';
787 if ((dwRequiredSize
% 4) && (dwRequiredSize
< *lpdwBufferSize
))
788 ZeroMemory((LPBYTE
)lpCacheEntryInfo
+ dwRequiredSize
, 4 - (dwRequiredSize
% 4));
789 dwRequiredSize
= DWORD_ALIGN(dwRequiredSize
);
791 if (dwRequiredSize
> *lpdwBufferSize
)
793 *lpdwBufferSize
= dwRequiredSize
;
794 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
797 *lpdwBufferSize
= dwRequiredSize
;
802 /***********************************************************************
803 * URLCache_SetEntryInfo (Internal)
805 * Helper for SetUrlCacheEntryInfo{A,W}. Sets fields in URL entry
806 * according the the flags set by dwFieldControl.
809 * TRUE if the buffer was big enough
810 * FALSE if the buffer was too small
813 static BOOL
URLCache_SetEntryInfo(URL_CACHEFILE_ENTRY
* pUrlEntry
, const INTERNET_CACHE_ENTRY_INFOW
* lpCacheEntryInfo
, DWORD dwFieldControl
)
815 if (dwFieldControl
& CACHE_ENTRY_ACCTIME_FC
)
816 pUrlEntry
->LastAccessTime
= lpCacheEntryInfo
->LastAccessTime
;
817 if (dwFieldControl
& CACHE_ENTRY_ATTRIBUTE_FC
)
818 pUrlEntry
->CacheEntryType
= lpCacheEntryInfo
->CacheEntryType
;
819 if (dwFieldControl
& CACHE_ENTRY_EXEMPT_DELTA_FC
)
820 pUrlEntry
->dwExemptDelta
= lpCacheEntryInfo
->u
.dwExemptDelta
;
821 if (dwFieldControl
& CACHE_ENTRY_EXPTIME_FC
)
822 FIXME("CACHE_ENTRY_EXPTIME_FC unimplemented\n");
823 if (dwFieldControl
& CACHE_ENTRY_HEADERINFO_FC
)
824 FIXME("CACHE_ENTRY_HEADERINFO_FC unimplemented\n");
825 if (dwFieldControl
& CACHE_ENTRY_HITRATE_FC
)
826 pUrlEntry
->dwHitRate
= lpCacheEntryInfo
->dwHitRate
;
827 if (dwFieldControl
& CACHE_ENTRY_MODTIME_FC
)
828 pUrlEntry
->LastModifiedTime
= lpCacheEntryInfo
->LastModifiedTime
;
829 if (dwFieldControl
& CACHE_ENTRY_SYNCTIME_FC
)
830 FileTimeToDosDateTime(&lpCacheEntryInfo
->LastAccessTime
, &pUrlEntry
->wLastSyncDate
, &pUrlEntry
->wLastSyncTime
);
835 /***********************************************************************
836 * URLCache_HashKey (Internal)
838 * Returns the hash key for a given string
841 * hash key for the string
844 static DWORD
URLCache_HashKey(LPCSTR lpszKey
)
846 /* NOTE: this uses the same lookup table as SHLWAPI.UrlHash{A,W}
847 * but the algorithm and result are not the same!
849 static const unsigned char lookupTable
[256] =
851 0x01, 0x0E, 0x6E, 0x19, 0x61, 0xAE, 0x84, 0x77,
852 0x8A, 0xAA, 0x7D, 0x76, 0x1B, 0xE9, 0x8C, 0x33,
853 0x57, 0xC5, 0xB1, 0x6B, 0xEA, 0xA9, 0x38, 0x44,
854 0x1E, 0x07, 0xAD, 0x49, 0xBC, 0x28, 0x24, 0x41,
855 0x31, 0xD5, 0x68, 0xBE, 0x39, 0xD3, 0x94, 0xDF,
856 0x30, 0x73, 0x0F, 0x02, 0x43, 0xBA, 0xD2, 0x1C,
857 0x0C, 0xB5, 0x67, 0x46, 0x16, 0x3A, 0x4B, 0x4E,
858 0xB7, 0xA7, 0xEE, 0x9D, 0x7C, 0x93, 0xAC, 0x90,
859 0xB0, 0xA1, 0x8D, 0x56, 0x3C, 0x42, 0x80, 0x53,
860 0x9C, 0xF1, 0x4F, 0x2E, 0xA8, 0xC6, 0x29, 0xFE,
861 0xB2, 0x55, 0xFD, 0xED, 0xFA, 0x9A, 0x85, 0x58,
862 0x23, 0xCE, 0x5F, 0x74, 0xFC, 0xC0, 0x36, 0xDD,
863 0x66, 0xDA, 0xFF, 0xF0, 0x52, 0x6A, 0x9E, 0xC9,
864 0x3D, 0x03, 0x59, 0x09, 0x2A, 0x9B, 0x9F, 0x5D,
865 0xA6, 0x50, 0x32, 0x22, 0xAF, 0xC3, 0x64, 0x63,
866 0x1A, 0x96, 0x10, 0x91, 0x04, 0x21, 0x08, 0xBD,
867 0x79, 0x40, 0x4D, 0x48, 0xD0, 0xF5, 0x82, 0x7A,
868 0x8F, 0x37, 0x69, 0x86, 0x1D, 0xA4, 0xB9, 0xC2,
869 0xC1, 0xEF, 0x65, 0xF2, 0x05, 0xAB, 0x7E, 0x0B,
870 0x4A, 0x3B, 0x89, 0xE4, 0x6C, 0xBF, 0xE8, 0x8B,
871 0x06, 0x18, 0x51, 0x14, 0x7F, 0x11, 0x5B, 0x5C,
872 0xFB, 0x97, 0xE1, 0xCF, 0x15, 0x62, 0x71, 0x70,
873 0x54, 0xE2, 0x12, 0xD6, 0xC7, 0xBB, 0x0D, 0x20,
874 0x5E, 0xDC, 0xE0, 0xD4, 0xF7, 0xCC, 0xC4, 0x2B,
875 0xF9, 0xEC, 0x2D, 0xF4, 0x6F, 0xB6, 0x99, 0x88,
876 0x81, 0x5A, 0xD9, 0xCA, 0x13, 0xA5, 0xE7, 0x47,
877 0xE6, 0x8E, 0x60, 0xE3, 0x3E, 0xB3, 0xF6, 0x72,
878 0xA2, 0x35, 0xA0, 0xD7, 0xCD, 0xB4, 0x2F, 0x6D,
879 0x2C, 0x26, 0x1F, 0x95, 0x87, 0x00, 0xD8, 0x34,
880 0x3F, 0x17, 0x25, 0x45, 0x27, 0x75, 0x92, 0xB8,
881 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB, 0x0A,
882 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1
886 int subscript
[sizeof(key
) / sizeof(key
[0])];
888 subscript
[0] = *lpszKey
;
889 subscript
[1] = (char)(*lpszKey
+ 1);
890 subscript
[2] = (char)(*lpszKey
+ 2);
891 subscript
[3] = (char)(*lpszKey
+ 3);
893 for (i
= 0; i
< sizeof(key
) / sizeof(key
[0]); i
++)
894 key
[i
] = lookupTable
[i
];
896 for (lpszKey
++; *lpszKey
&& ((lpszKey
[0] != '/') || (lpszKey
[1] != 0)); lpszKey
++)
898 for (i
= 0; i
< sizeof(key
) / sizeof(key
[0]); i
++)
899 key
[i
] = lookupTable
[*lpszKey
^ key
[i
]];
902 return *(DWORD
*)key
;
905 static inline HASH_CACHEFILE_ENTRY
* URLCache_HashEntryFromOffset(LPCURLCACHE_HEADER pHeader
, DWORD dwOffset
)
907 return (HASH_CACHEFILE_ENTRY
*)((LPBYTE
)pHeader
+ dwOffset
);
910 static BOOL
URLCache_FindHash(LPCURLCACHE_HEADER pHeader
, LPCSTR lpszUrl
, struct _HASH_ENTRY
** ppHashEntry
)
912 /* structure of hash table:
913 * 448 entries divided into 64 blocks
914 * each block therefore contains a chain of 7 key/offset pairs
915 * how position in table is calculated:
916 * 1. the url is hashed in helper function
917 * 2. the key % 64 * 8 is the offset
918 * 3. the key in the hash table is the hash key aligned to 64
921 * there can be multiple hash tables in the file and the offset to
922 * the next one is stored in the header of the hash table
924 DWORD key
= URLCache_HashKey(lpszUrl
);
925 DWORD offset
= (key
% HASHTABLE_NUM_ENTRIES
) * sizeof(struct _HASH_ENTRY
);
926 HASH_CACHEFILE_ENTRY
* pHashEntry
;
927 DWORD dwHashTableNumber
= 0;
929 key
= (DWORD
)(key
/ HASHTABLE_NUM_ENTRIES
) * HASHTABLE_NUM_ENTRIES
;
931 for (pHashEntry
= URLCache_HashEntryFromOffset(pHeader
, pHeader
->dwOffsetFirstHashTable
);
932 ((DWORD
)((LPBYTE
)pHashEntry
- (LPBYTE
)pHeader
) >= ENTRY_START_OFFSET
) && ((DWORD
)((LPBYTE
)pHashEntry
- (LPBYTE
)pHeader
) < pHeader
->dwFileSize
);
933 pHashEntry
= URLCache_HashEntryFromOffset(pHeader
, pHashEntry
->dwAddressNext
))
936 if (pHashEntry
->dwHashTableNumber
!= dwHashTableNumber
++)
938 ERR("Error: not right hash table number (%ld) expected %ld\n", pHashEntry
->dwHashTableNumber
, dwHashTableNumber
);
941 /* make sure that it is in fact a hash entry */
942 if (pHashEntry
->CacheFileEntry
.dwSignature
!= HASH_SIGNATURE
)
944 ERR("Error: not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR
)&pHashEntry
->CacheFileEntry
.dwSignature
);
948 for (i
= 0; i
< HASHTABLE_BLOCKSIZE
; i
++)
950 struct _HASH_ENTRY
* pHashElement
= &pHashEntry
->HashTable
[offset
+ i
];
951 if (key
== (DWORD
)(pHashElement
->dwHashKey
/ HASHTABLE_NUM_ENTRIES
) * HASHTABLE_NUM_ENTRIES
)
953 /* FIXME: we should make sure that this is the right element
954 * before returning and claiming that it is. We can do this
955 * by doing a simple compare between the URL we were given
956 * and the URL stored in the entry. However, this assumes
957 * we know the format of all the entries stored in the
959 *ppHashEntry
= pHashElement
;
967 /***********************************************************************
968 * URLCache_FindEntryInHash (Internal)
970 * Searches all the hash tables in the index for the given URL and
971 * returns the entry, if it was found, in ppEntry
974 * TRUE if the entry was found
975 * FALSE if the entry could not be found
978 static BOOL
URLCache_FindEntryInHash(LPCURLCACHE_HEADER pHeader
, LPCSTR lpszUrl
, CACHEFILE_ENTRY
** ppEntry
)
980 struct _HASH_ENTRY
* pHashEntry
;
981 if (URLCache_FindHash(pHeader
, lpszUrl
, &pHashEntry
))
983 *ppEntry
= (CACHEFILE_ENTRY
*)((LPBYTE
)pHeader
+ pHashEntry
->dwOffsetEntry
);
989 /***********************************************************************
990 * URLCache_HashEntrySetUse (Internal)
992 * Searches all the hash tables in the index for the given URL and
993 * sets the use count (stored or'ed with key)
996 * TRUE if the entry was found
997 * FALSE if the entry could not be found
1000 static BOOL
URLCache_HashEntrySetUse(LPCURLCACHE_HEADER pHeader
, LPCSTR lpszUrl
, DWORD dwUseCount
)
1002 struct _HASH_ENTRY
* pHashEntry
;
1003 if (URLCache_FindHash(pHeader
, lpszUrl
, &pHashEntry
))
1005 pHashEntry
->dwHashKey
= dwUseCount
| (DWORD
)(pHashEntry
->dwHashKey
/ HASHTABLE_NUM_ENTRIES
) * HASHTABLE_NUM_ENTRIES
;
1011 /***********************************************************************
1012 * URLCache_DeleteEntryFromHash (Internal)
1014 * Searches all the hash tables in the index for the given URL and
1015 * then if found deletes the entry.
1018 * TRUE if the entry was found
1019 * FALSE if the entry could not be found
1022 static BOOL
URLCache_DeleteEntryFromHash(LPCURLCACHE_HEADER pHeader
, LPCSTR lpszUrl
)
1024 struct _HASH_ENTRY
* pHashEntry
;
1025 if (URLCache_FindHash(pHeader
, lpszUrl
, &pHashEntry
))
1027 pHashEntry
->dwHashKey
= HASHTABLE_FREE
;
1028 pHashEntry
->dwOffsetEntry
= HASHTABLE_FREE
;
1034 /***********************************************************************
1035 * URLCache_AddEntryToHash (Internal)
1037 * Searches all the hash tables for a free slot based on the offset
1038 * generated from the hash key. If a free slot is found, the offset and
1039 * key are entered into the hash table.
1042 * TRUE if the entry was added
1043 * FALSE if the entry could not be added
1046 static BOOL
URLCache_AddEntryToHash(LPCURLCACHE_HEADER pHeader
, LPCSTR lpszUrl
, DWORD dwOffsetEntry
)
1048 /* see URLCache_FindEntryInHash for structure of hash tables */
1050 DWORD key
= URLCache_HashKey(lpszUrl
);
1051 DWORD offset
= (key
% HASHTABLE_NUM_ENTRIES
) * sizeof(struct _HASH_ENTRY
);
1052 HASH_CACHEFILE_ENTRY
* pHashEntry
;
1053 DWORD dwHashTableNumber
= 0;
1055 key
= (DWORD
)(key
/ HASHTABLE_NUM_ENTRIES
) * HASHTABLE_NUM_ENTRIES
;
1057 for (pHashEntry
= URLCache_HashEntryFromOffset(pHeader
, pHeader
->dwOffsetFirstHashTable
);
1058 ((DWORD
)((LPBYTE
)pHashEntry
- (LPBYTE
)pHeader
) >= ENTRY_START_OFFSET
) && ((DWORD
)((LPBYTE
)pHashEntry
- (LPBYTE
)pHeader
) < pHeader
->dwFileSize
);
1059 pHashEntry
= URLCache_HashEntryFromOffset(pHeader
, pHashEntry
->dwAddressNext
))
1062 if (pHashEntry
->dwHashTableNumber
!= dwHashTableNumber
++)
1064 ERR("not right hash table number (%ld) expected %ld\n", pHashEntry
->dwHashTableNumber
, dwHashTableNumber
);
1067 /* make sure that it is in fact a hash entry */
1068 if (pHashEntry
->CacheFileEntry
.dwSignature
!= HASH_SIGNATURE
)
1070 ERR("not right signature (\"%.4s\") - expected \"HASH\"\n", (LPCSTR
)&pHashEntry
->CacheFileEntry
.dwSignature
);
1074 for (i
= 0; i
< HASHTABLE_BLOCKSIZE
; i
++)
1076 struct _HASH_ENTRY
* pHashElement
= &pHashEntry
->HashTable
[offset
+ i
];
1077 if (pHashElement
->dwHashKey
== HASHTABLE_FREE
) /* if the slot is free */
1079 pHashElement
->dwHashKey
= key
;
1080 pHashElement
->dwOffsetEntry
= dwOffsetEntry
;
1085 FIXME("need to create another hash table\n");
1089 /***********************************************************************
1090 * GetUrlCacheEntryInfoExA (WININET.@)
1093 BOOL WINAPI
GetUrlCacheEntryInfoExA(
1095 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo
,
1096 LPDWORD lpdwCacheEntryInfoBufSize
,
1098 LPDWORD lpdwReserved
,
1102 TRACE("(%s, %p, %p, %p, %p, %p, %lx)\n",
1103 debugstr_a(lpszUrl
),
1105 lpdwCacheEntryInfoBufSize
,
1111 if ((lpszReserved
!= NULL
) ||
1112 (lpdwReserved
!= NULL
) ||
1113 (lpReserved
!= NULL
))
1115 ERR("Reserved value was not 0\n");
1116 SetLastError(ERROR_INVALID_PARAMETER
);
1120 FIXME("Undocumented flag(s): %lx\n", dwFlags
);
1121 return GetUrlCacheEntryInfoA(lpszUrl
, lpCacheEntryInfo
, lpdwCacheEntryInfoBufSize
);
1124 /***********************************************************************
1125 * GetUrlCacheEntryInfoA (WININET.@)
1128 BOOL WINAPI
GetUrlCacheEntryInfoA(
1129 IN LPCSTR lpszUrlName
,
1130 IN LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo
,
1131 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize
1134 LPURLCACHE_HEADER pHeader
;
1135 CACHEFILE_ENTRY
* pEntry
;
1136 URL_CACHEFILE_ENTRY
* pUrlEntry
;
1137 URLCACHECONTAINER
* pContainer
;
1139 TRACE("(%s, %p, %p)\n", debugstr_a(lpszUrlName
), lpCacheEntryInfo
, lpdwCacheEntryInfoBufferSize
);
1141 if (!URLCacheContainers_FindContainerA(lpszUrlName
, &pContainer
))
1144 if (!URLCacheContainer_OpenIndex(pContainer
))
1147 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
1150 if (!URLCache_FindEntryInHash(pHeader
, lpszUrlName
, &pEntry
))
1152 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1153 WARN("entry %s not found!\n", debugstr_a(lpszUrlName
));
1154 SetLastError(ERROR_FILE_NOT_FOUND
);
1158 if (pEntry
->dwSignature
!= URL_SIGNATURE
)
1160 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1161 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR
)&pEntry
->dwSignature
, sizeof(DWORD
)));
1162 SetLastError(ERROR_FILE_NOT_FOUND
);
1166 pUrlEntry
= (URL_CACHEFILE_ENTRY
*)pEntry
;
1167 TRACE("Found URL: %s\n", debugstr_a(pUrlEntry
->szSourceUrlName
));
1168 if (pUrlEntry
->dwOffsetHeaderInfo
)
1169 TRACE("Header info: %s\n", debugstr_a((LPSTR
)pUrlEntry
+ pUrlEntry
->dwOffsetHeaderInfo
));
1171 if (!URLCache_CopyEntry(
1175 lpdwCacheEntryInfoBufferSize
,
1179 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1182 TRACE("Local File Name: %s\n", debugstr_a(lpCacheEntryInfo
->lpszLocalFileName
));
1184 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1189 /***********************************************************************
1190 * GetUrlCacheEntryInfoW (WININET.@)
1193 BOOL WINAPI
GetUrlCacheEntryInfoW(LPCWSTR lpszUrl
,
1194 LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo
,
1195 LPDWORD lpdwCacheEntryInfoBufferSize
)
1197 LPURLCACHE_HEADER pHeader
;
1198 CACHEFILE_ENTRY
* pEntry
;
1199 URL_CACHEFILE_ENTRY
* pUrlEntry
;
1200 URLCACHECONTAINER
* pContainer
;
1204 TRACE("(%s, %p, %p)\n", debugstr_w(lpszUrl
), lpCacheEntryInfo
, lpdwCacheEntryInfoBufferSize
);
1206 url_len
= WideCharToMultiByte(CP_ACP
, 0, lpszUrl
, -1, NULL
, 0, NULL
, NULL
);
1207 lpszUrlA
= HeapAlloc(GetProcessHeap(), 0, url_len
* sizeof(CHAR
));
1210 SetLastError(ERROR_OUTOFMEMORY
);
1213 WideCharToMultiByte(CP_ACP
, 0, lpszUrl
, -1, lpszUrlA
, url_len
, NULL
, NULL
);
1215 if (!URLCacheContainers_FindContainerW(lpszUrl
, &pContainer
))
1217 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1221 if (!URLCacheContainer_OpenIndex(pContainer
))
1223 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1227 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
1229 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1233 if (!URLCache_FindEntryInHash(pHeader
, lpszUrlA
, &pEntry
))
1235 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1236 WARN("entry %s not found!\n", debugstr_a(lpszUrlA
));
1237 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1238 SetLastError(ERROR_FILE_NOT_FOUND
);
1241 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1243 if (pEntry
->dwSignature
!= URL_SIGNATURE
)
1245 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1246 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR
)&pEntry
->dwSignature
, sizeof(DWORD
)));
1247 SetLastError(ERROR_FILE_NOT_FOUND
);
1251 pUrlEntry
= (URL_CACHEFILE_ENTRY
*)pEntry
;
1252 TRACE("Found URL: %s\n", debugstr_a(pUrlEntry
->szSourceUrlName
));
1253 TRACE("Header info: %s\n", debugstr_a((LPSTR
)pUrlEntry
+ pUrlEntry
->dwOffsetHeaderInfo
));
1255 if (!URLCache_CopyEntry(
1258 (LPINTERNET_CACHE_ENTRY_INFOA
)lpCacheEntryInfo
,
1259 lpdwCacheEntryInfoBufferSize
,
1261 TRUE
/* UNICODE */))
1263 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1266 TRACE("Local File Name: %s\n", debugstr_w(lpCacheEntryInfo
->lpszLocalFileName
));
1268 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1273 /***********************************************************************
1274 * GetUrlCacheEntryInfoExW (WININET.@)
1277 BOOL WINAPI
GetUrlCacheEntryInfoExW(
1279 LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo
,
1280 LPDWORD lpdwCacheEntryInfoBufSize
,
1281 LPWSTR lpszReserved
,
1282 LPDWORD lpdwReserved
,
1286 TRACE("(%s, %p, %p, %p, %p, %p, %lx)\n",
1287 debugstr_w(lpszUrl
),
1289 lpdwCacheEntryInfoBufSize
,
1295 if ((lpszReserved
!= NULL
) ||
1296 (lpdwReserved
!= NULL
) ||
1297 (lpReserved
!= NULL
))
1299 ERR("Reserved value was not 0\n");
1300 SetLastError(ERROR_INVALID_PARAMETER
);
1304 FIXME("Undocumented flag(s): %lx\n", dwFlags
);
1305 return GetUrlCacheEntryInfoW(lpszUrl
, lpCacheEntryInfo
, lpdwCacheEntryInfoBufSize
);
1308 /***********************************************************************
1309 * SetUrlCacheEntryInfoA (WININET.@)
1311 BOOL WINAPI
SetUrlCacheEntryInfoA(
1313 LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo
,
1314 DWORD dwFieldControl
)
1316 LPURLCACHE_HEADER pHeader
;
1317 CACHEFILE_ENTRY
* pEntry
;
1318 URLCACHECONTAINER
* pContainer
;
1320 TRACE("(%s, %p, 0x%08lx)\n", debugstr_a(lpszUrlName
), lpCacheEntryInfo
, dwFieldControl
);
1322 if (!URLCacheContainers_FindContainerA(lpszUrlName
, &pContainer
))
1325 if (!URLCacheContainer_OpenIndex(pContainer
))
1328 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
1331 if (!URLCache_FindEntryInHash(pHeader
, lpszUrlName
, &pEntry
))
1333 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1334 WARN("entry %s not found!\n", debugstr_a(lpszUrlName
));
1335 SetLastError(ERROR_FILE_NOT_FOUND
);
1339 if (pEntry
->dwSignature
!= URL_SIGNATURE
)
1341 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1342 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR
)&pEntry
->dwSignature
, sizeof(DWORD
)));
1343 SetLastError(ERROR_FILE_NOT_FOUND
);
1347 URLCache_SetEntryInfo(
1348 (URL_CACHEFILE_ENTRY
*)pEntry
,
1349 (const INTERNET_CACHE_ENTRY_INFOW
*)lpCacheEntryInfo
,
1352 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1357 /***********************************************************************
1358 * SetUrlCacheEntryInfoW (WININET.@)
1360 BOOL WINAPI
SetUrlCacheEntryInfoW(LPCWSTR lpszUrl
, LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo
, DWORD dwFieldControl
)
1362 LPURLCACHE_HEADER pHeader
;
1363 CACHEFILE_ENTRY
* pEntry
;
1364 URLCACHECONTAINER
* pContainer
;
1368 TRACE("(%s, %p, 0x%08lx)\n", debugstr_w(lpszUrl
), lpCacheEntryInfo
, dwFieldControl
);
1370 url_len
= WideCharToMultiByte(CP_ACP
, 0, lpszUrl
, -1, NULL
, 0, NULL
, NULL
);
1371 lpszUrlA
= HeapAlloc(GetProcessHeap(), 0, url_len
* sizeof(CHAR
));
1374 SetLastError(ERROR_OUTOFMEMORY
);
1377 WideCharToMultiByte(CP_ACP
, 0, lpszUrl
, -1, lpszUrlA
, url_len
, NULL
, NULL
);
1379 if (!URLCacheContainers_FindContainerW(lpszUrl
, &pContainer
))
1381 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1385 if (!URLCacheContainer_OpenIndex(pContainer
))
1387 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1391 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
1393 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1397 if (!URLCache_FindEntryInHash(pHeader
, lpszUrlA
, &pEntry
))
1399 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1400 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1401 WARN("entry %s not found!\n", debugstr_a(lpszUrlA
));
1402 SetLastError(ERROR_FILE_NOT_FOUND
);
1405 HeapFree(GetProcessHeap(), 0, lpszUrlA
);
1407 if (pEntry
->dwSignature
!= URL_SIGNATURE
)
1409 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1410 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR
)&pEntry
->dwSignature
, sizeof(DWORD
)));
1411 SetLastError(ERROR_FILE_NOT_FOUND
);
1415 URLCache_SetEntryInfo(
1416 (URL_CACHEFILE_ENTRY
*)pEntry
,
1420 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1425 /***********************************************************************
1426 * RetrieveUrlCacheEntryFileA (WININET.@)
1429 BOOL WINAPI
RetrieveUrlCacheEntryFileA(
1430 IN LPCSTR lpszUrlName
,
1431 OUT LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo
,
1432 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize
,
1436 LPURLCACHE_HEADER pHeader
;
1437 CACHEFILE_ENTRY
* pEntry
;
1438 URL_CACHEFILE_ENTRY
* pUrlEntry
;
1439 URLCACHECONTAINER
* pContainer
;
1441 TRACE("(%s, %p, %p, 0x%08lx)\n",
1442 debugstr_a(lpszUrlName
),
1444 lpdwCacheEntryInfoBufferSize
,
1447 if (!URLCacheContainers_FindContainerA(lpszUrlName
, &pContainer
))
1450 if (!URLCacheContainer_OpenIndex(pContainer
))
1453 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
1456 if (!URLCache_FindEntryInHash(pHeader
, lpszUrlName
, &pEntry
))
1458 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1459 TRACE("entry %s not found!\n", lpszUrlName
);
1460 SetLastError(ERROR_FILE_NOT_FOUND
);
1464 if (pEntry
->dwSignature
!= URL_SIGNATURE
)
1466 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1467 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR
)&pEntry
->dwSignature
, sizeof(DWORD
)));
1468 SetLastError(ERROR_FILE_NOT_FOUND
);
1472 pUrlEntry
= (URL_CACHEFILE_ENTRY
*)pEntry
;
1473 TRACE("Found URL: %s\n", pUrlEntry
->szSourceUrlName
);
1474 TRACE("Header info: %s\n", (LPBYTE
)pUrlEntry
+ pUrlEntry
->dwOffsetHeaderInfo
);
1476 pUrlEntry
->dwHitRate
++;
1477 pUrlEntry
->dwUseCount
++;
1478 URLCache_HashEntrySetUse(pHeader
, lpszUrlName
, pUrlEntry
->dwUseCount
);
1480 if (!URLCache_CopyEntry(pContainer
, pHeader
, lpCacheEntryInfo
, lpdwCacheEntryInfoBufferSize
, pUrlEntry
, FALSE
))
1482 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1485 TRACE("Local File Name: %s\n", lpCacheEntryInfo
->lpszLocalFileName
);
1487 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1492 /***********************************************************************
1493 * RetrieveUrlCacheEntryFileW (WININET.@)
1496 BOOL WINAPI
RetrieveUrlCacheEntryFileW(
1497 IN LPCWSTR lpszUrlName
,
1498 OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo
,
1499 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize
,
1503 TRACE("(%s, %p, %p, 0x%08lx)\n",
1504 debugstr_w(lpszUrlName
),
1506 lpdwCacheEntryInfoBufferSize
,
1512 /***********************************************************************
1513 * UnlockUrlCacheEntryFileA (WININET.@)
1516 BOOL WINAPI
UnlockUrlCacheEntryFileA(
1517 IN LPCSTR lpszUrlName
,
1521 LPURLCACHE_HEADER pHeader
;
1522 CACHEFILE_ENTRY
* pEntry
;
1523 URL_CACHEFILE_ENTRY
* pUrlEntry
;
1524 URLCACHECONTAINER
* pContainer
;
1526 TRACE("(%s, 0x%08lx)\n", debugstr_a(lpszUrlName
), dwReserved
);
1530 ERR("dwReserved != 0\n");
1531 SetLastError(ERROR_INVALID_PARAMETER
);
1535 if (!URLCacheContainers_FindContainerA(lpszUrlName
, &pContainer
))
1538 if (!URLCacheContainer_OpenIndex(pContainer
))
1541 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
1544 if (!URLCache_FindEntryInHash(pHeader
, lpszUrlName
, &pEntry
))
1546 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1547 TRACE("entry %s not found!\n", lpszUrlName
);
1548 SetLastError(ERROR_FILE_NOT_FOUND
);
1552 if (pEntry
->dwSignature
!= URL_SIGNATURE
)
1554 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1555 FIXME("Trying to retrieve entry of unknown format %s\n", debugstr_an((LPSTR
)&pEntry
->dwSignature
, sizeof(DWORD
)));
1556 SetLastError(ERROR_FILE_NOT_FOUND
);
1560 pUrlEntry
= (URL_CACHEFILE_ENTRY
*)pEntry
;
1562 if (pUrlEntry
->dwUseCount
== 0)
1564 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1567 pUrlEntry
->dwUseCount
--;
1568 URLCache_HashEntrySetUse(pHeader
, lpszUrlName
, pUrlEntry
->dwUseCount
);
1570 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1575 /***********************************************************************
1576 * UnlockUrlCacheEntryFileW (WININET.@)
1579 BOOL WINAPI
UnlockUrlCacheEntryFileW( LPCWSTR lpszUrlName
, DWORD dwReserved
)
1581 FIXME("(%s, 0x%08lx)\n", debugstr_w(lpszUrlName
), dwReserved
);
1585 /***********************************************************************
1586 * CreateUrlCacheEntryA (WININET.@)
1589 BOOL WINAPI
CreateUrlCacheEntryA(
1590 IN LPCSTR lpszUrlName
,
1591 IN DWORD dwExpectedFileSize
,
1592 IN LPCSTR lpszFileExtension
,
1593 OUT LPSTR lpszFileName
,
1599 WCHAR
*file_extension
;
1600 WCHAR file_name
[MAX_PATH
];
1601 BOOL bSuccess
= FALSE
;
1604 if ((len
= MultiByteToWideChar(CP_ACP
, 0, lpszUrlName
, -1, NULL
, 0)) != 0 &&
1605 (url_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))) != 0)
1607 MultiByteToWideChar(CP_ACP
, 0, lpszUrlName
, -1, url_name
, len
);
1608 if ((len
= MultiByteToWideChar(CP_ACP
, 0, lpszFileExtension
, -1, NULL
, 0)) != 0 &&
1609 (file_extension
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))) != 0)
1611 MultiByteToWideChar(CP_ACP
, 0, lpszFileExtension
, -1, file_extension
, len
);
1612 if (CreateUrlCacheEntryW(url_name
, dwExpectedFileSize
, file_extension
, file_name
, dwReserved
))
1614 if (WideCharToMultiByte(CP_ACP
, 0, file_name
, -1, lpszFileName
, MAX_PATH
, NULL
, NULL
) < MAX_PATH
)
1620 dwError
= GetLastError();
1625 dwError
= GetLastError();
1627 HeapFree(GetProcessHeap(), 0, file_extension
);
1631 dwError
= GetLastError();
1633 HeapFree(GetProcessHeap(), 0, url_name
);
1635 SetLastError(dwError
);
1639 /***********************************************************************
1640 * CreateUrlCacheEntryW (WININET.@)
1643 BOOL WINAPI
CreateUrlCacheEntryW(
1644 IN LPCWSTR lpszUrlName
,
1645 IN DWORD dwExpectedFileSize
,
1646 IN LPCWSTR lpszFileExtension
,
1647 OUT LPWSTR lpszFileName
,
1651 URLCACHECONTAINER
* pContainer
;
1652 LPURLCACHE_HEADER pHeader
;
1653 CHAR szFile
[MAX_PATH
];
1654 WCHAR szExtension
[MAX_PATH
];
1655 LPCWSTR lpszUrlPart
;
1657 LPCWSTR lpszFileNameExtension
;
1658 LPWSTR lpszFileNameNoPath
;
1660 int countnoextension
;
1663 BOOL bFound
= FALSE
;
1665 static WCHAR szWWW
[] = {'w','w','w',0};
1667 TRACE("(%s, 0x%08lx, %s, %p, 0x%08lx)\n",
1668 debugstr_w(lpszUrlName
),
1670 debugstr_w(lpszFileExtension
),
1676 ERR("dwReserved != 0\n");
1677 SetLastError(ERROR_INVALID_PARAMETER
);
1681 for (lpszUrlEnd
= lpszUrlName
; *lpszUrlEnd
; lpszUrlEnd
++)
1684 if (((lpszUrlEnd
- lpszUrlName
) > 1) && (*(lpszUrlEnd
- 1) == '/' || *(lpszUrlEnd
- 1) == '\\'))
1687 for (lpszUrlPart
= lpszUrlEnd
;
1688 (lpszUrlPart
>= lpszUrlName
);
1691 if ((*lpszUrlPart
== '/' || *lpszUrlPart
== '\\') && ((lpszUrlEnd
- lpszUrlPart
) > 1))
1698 if (!lstrcmpW(lpszUrlPart
, szWWW
))
1700 lpszUrlPart
+= lstrlenW(szWWW
);
1703 count
= lpszUrlEnd
- lpszUrlPart
;
1705 if (bFound
&& (count
< MAX_PATH
))
1707 int len
= WideCharToMultiByte(CP_ACP
, 0, lpszUrlPart
, count
, szFile
, sizeof(szFile
) - 1, NULL
, NULL
);
1711 /* FIXME: get rid of illegal characters like \, / and : */
1715 FIXME("need to generate a random filename\n");
1718 TRACE("File name: %s\n", debugstr_a(szFile
));
1720 if (!URLCacheContainers_FindContainerW(lpszUrlName
, &pContainer
))
1723 if (!URLCacheContainer_OpenIndex(pContainer
))
1726 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
1729 CacheDir
= (BYTE
)(rand() % pHeader
->DirectoryCount
);
1731 lBufferSize
= MAX_PATH
* sizeof(CHAR
);
1732 URLCache_LocalFileNameToPathW(pContainer
, pHeader
, szFile
, CacheDir
, lpszFileName
, &lBufferSize
);
1734 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1736 for (lpszFileNameNoPath
= lpszFileName
+ lBufferSize
/ sizeof(CHAR
) - 2;
1737 lpszFileNameNoPath
>= lpszFileName
;
1738 --lpszFileNameNoPath
)
1740 if (*lpszFileNameNoPath
== '/' || *lpszFileNameNoPath
== '\\')
1744 countnoextension
= lstrlenW(lpszFileNameNoPath
);
1745 lpszFileNameExtension
= PathFindExtensionW(lpszFileNameNoPath
);
1746 if (lpszFileNameExtension
)
1747 countnoextension
-= lstrlenW(lpszFileNameExtension
);
1748 *szExtension
= '\0';
1750 if (lpszFileExtension
)
1752 szExtension
[0] = '.';
1753 lstrcpyW(szExtension
+1, lpszFileExtension
);
1756 for (i
= 0; i
< 255; i
++)
1758 static WCHAR szFormat
[] = {'[','%','u',']','%','s',0};
1760 wsprintfW(lpszFileNameNoPath
+ countnoextension
, szFormat
, i
, szExtension
);
1761 TRACE("Trying: %s\n", debugstr_w(lpszFileName
));
1762 hFile
= CreateFileW(lpszFileName
, GENERIC_READ
, 0, NULL
, CREATE_NEW
, 0, NULL
);
1763 if (hFile
!= INVALID_HANDLE_VALUE
)
1774 /***********************************************************************
1775 * CommitUrlCacheEntryInternal (Compensates for an MS bug)
1777 * The bug we are compensating for is that some drongo at Microsoft
1778 * used lpHeaderInfo to pass binary data to CommitUrlCacheEntryA.
1779 * As a consequence, CommitUrlCacheEntryA has been effectively
1780 * redefined as LPBYTE rather than LPCSTR. But CommitUrlCacheEntryW
1781 * is still defined as LPCWSTR. The result (other than madness) is
1782 * that we always need to store lpHeaderInfo in CP_ACP rather than
1783 * in UTF16, and we need to avoid converting lpHeaderInfo in
1784 * CommitUrlCacheEntryA to UTF16 and then back to CP_ACP, since the
1785 * result will lose data for arbitrary binary data.
1788 static BOOL WINAPI
CommitUrlCacheEntryInternal(
1789 IN LPCWSTR lpszUrlName
,
1790 IN LPCWSTR lpszLocalFileName
,
1791 IN FILETIME ExpireTime
,
1792 IN FILETIME LastModifiedTime
,
1793 IN DWORD CacheEntryType
,
1794 IN LPBYTE lpHeaderInfo
,
1795 IN DWORD dwHeaderSize
,
1796 IN LPCWSTR lpszFileExtension
,
1797 IN LPCWSTR lpszOriginalUrl
1800 URLCACHECONTAINER
* pContainer
;
1801 LPURLCACHE_HEADER pHeader
;
1802 CACHEFILE_ENTRY
* pEntry
;
1803 URL_CACHEFILE_ENTRY
* pUrlEntry
;
1804 DWORD dwBytesNeeded
= sizeof(*pUrlEntry
) - sizeof(pUrlEntry
->szSourceUrlName
);
1805 DWORD dwOffsetLocalFileName
= 0;
1806 DWORD dwOffsetHeader
= 0;
1807 DWORD dwFileSizeLow
= 0;
1808 DWORD dwFileSizeHigh
= 0;
1809 BYTE cDirectory
= 0;
1810 char achFile
[MAX_PATH
];
1811 char achUrl
[MAX_PATH
];
1812 char *pchLocalFileName
= 0;
1814 TRACE("(%s, %s, ..., ..., %lx, %p, %ld, %s, %s)\n",
1815 debugstr_w(lpszUrlName
),
1816 debugstr_w(lpszLocalFileName
),
1820 debugstr_w(lpszFileExtension
),
1821 debugstr_w(lpszOriginalUrl
));
1823 if (lpszOriginalUrl
)
1824 WARN(": lpszOriginalUrl ignored\n");
1826 if (lpszLocalFileName
)
1830 hFile
= CreateFileW(lpszLocalFileName
, FILE_READ_ATTRIBUTES
, FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
, NULL
, OPEN_EXISTING
, 0, NULL
);
1831 if (hFile
== INVALID_HANDLE_VALUE
)
1833 ERR("couldn't open file %s (error is %ld)\n", debugstr_w(lpszLocalFileName
), GetLastError());
1838 dwFileSizeLow
= GetFileSize(hFile
, &dwFileSizeHigh
);
1839 if ((dwFileSizeLow
== INVALID_FILE_SIZE
) && (GetLastError() != NO_ERROR
))
1841 ERR("couldn't get file size (error is %ld)\n", GetLastError());
1849 if (!URLCacheContainers_FindContainerW(lpszUrlName
, &pContainer
))
1852 if (!URLCacheContainer_OpenIndex(pContainer
))
1855 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
1858 WideCharToMultiByte(CP_ACP
, 0, lpszUrlName
, -1, achUrl
, -1, NULL
, NULL
);
1860 if (URLCache_FindEntryInHash(pHeader
, achUrl
, &pEntry
))
1862 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1863 FIXME("entry already in cache - don't know what to do!\n");
1865 * SetLastError(ERROR_FILE_NOT_FOUND);
1871 if (lpszLocalFileName
)
1873 BOOL bFound
= FALSE
;
1875 if (strncmpW(lpszLocalFileName
, pContainer
->path
, lstrlenW(pContainer
->path
)))
1877 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1878 ERR("path %s must begin with cache content path %s\n", debugstr_w(lpszLocalFileName
), debugstr_w(pContainer
->path
));
1879 SetLastError(ERROR_INVALID_PARAMETER
);
1883 /* skip container path prefix */
1884 lpszLocalFileName
+= lstrlenW(pContainer
->path
);
1886 WideCharToMultiByte(CP_ACP
, 0, lpszLocalFileName
, -1, achFile
, -1, NULL
, NULL
);
1887 pchLocalFileName
= achFile
;
1889 for (cDirectory
= 0; cDirectory
< pHeader
->DirectoryCount
; cDirectory
++)
1891 if (!strncmp(pHeader
->directory_data
[cDirectory
].filename
, pchLocalFileName
, DIR_LENGTH
))
1900 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1901 ERR("cache directory not found in path %s\n", debugstr_w(lpszLocalFileName
));
1902 SetLastError(ERROR_INVALID_PARAMETER
);
1906 lpszLocalFileName
+= (DIR_LENGTH
+ 1); /* "1234WXYZ\" */
1909 dwBytesNeeded
= DWORD_ALIGN(dwBytesNeeded
+ strlen(achUrl
) + 1);
1910 if (lpszLocalFileName
)
1912 dwOffsetLocalFileName
= dwBytesNeeded
;
1913 dwBytesNeeded
= DWORD_ALIGN(dwBytesNeeded
+ strlen(pchLocalFileName
) + 1);
1917 dwOffsetHeader
= dwBytesNeeded
;
1918 dwBytesNeeded
= DWORD_ALIGN(dwBytesNeeded
+ dwHeaderSize
);
1921 /* round up to next block */
1922 if (dwBytesNeeded
% BLOCKSIZE
)
1924 dwBytesNeeded
-= dwBytesNeeded
% BLOCKSIZE
;
1925 dwBytesNeeded
+= BLOCKSIZE
;
1928 if (!URLCache_FindFirstFreeEntry(pHeader
, dwBytesNeeded
/ BLOCKSIZE
, &pEntry
))
1930 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1931 ERR("no free entries\n");
1935 /* FindFirstFreeEntry fills in blocks used */
1936 pUrlEntry
= (URL_CACHEFILE_ENTRY
*)pEntry
;
1937 pUrlEntry
->CacheFileEntry
.dwSignature
= URL_SIGNATURE
;
1938 pUrlEntry
->CacheDir
= cDirectory
;
1939 pUrlEntry
->CacheEntryType
= CacheEntryType
;
1940 pUrlEntry
->dwHeaderInfoSize
= dwHeaderSize
;
1941 pUrlEntry
->dwExemptDelta
= 0;
1942 pUrlEntry
->dwHitRate
= 0;
1943 pUrlEntry
->dwOffsetHeaderInfo
= dwOffsetHeader
;
1944 pUrlEntry
->dwOffsetLocalName
= dwOffsetLocalFileName
;
1945 pUrlEntry
->dwOffsetUrl
= sizeof(*pUrlEntry
) - sizeof(pUrlEntry
->szSourceUrlName
);
1946 pUrlEntry
->dwSizeHigh
= 0;
1947 pUrlEntry
->dwSizeLow
= dwFileSizeLow
;
1948 pUrlEntry
->dwSizeHigh
= dwFileSizeHigh
;
1949 pUrlEntry
->dwUseCount
= 0;
1950 GetSystemTimeAsFileTime(&pUrlEntry
->LastAccessTime
);
1951 pUrlEntry
->LastModifiedTime
= LastModifiedTime
;
1952 FileTimeToDosDateTime(&pUrlEntry
->LastAccessTime
, &pUrlEntry
->wLastSyncDate
, &pUrlEntry
->wLastSyncTime
);
1953 FileTimeToDosDateTime(&ExpireTime
, &pUrlEntry
->wExpiredDate
, &pUrlEntry
->wExpiredTime
);
1954 pUrlEntry
->wUnknownDate
= pUrlEntry
->wLastSyncDate
;
1955 pUrlEntry
->wUnknownTime
= pUrlEntry
->wLastSyncTime
;
1958 pUrlEntry
->dwUnknown1
= 0;
1959 pUrlEntry
->dwUnknown2
= 0;
1960 pUrlEntry
->dwUnknown3
= 0x60;
1961 pUrlEntry
->Unknown4
= 0;
1962 pUrlEntry
->wUnknown5
= 0x1010;
1963 pUrlEntry
->dwUnknown6
= 0;
1964 pUrlEntry
->dwUnknown7
= 0;
1965 pUrlEntry
->dwUnknown8
= 0;
1968 strcpy(pUrlEntry
->szSourceUrlName
, achUrl
);
1969 if (dwOffsetLocalFileName
)
1970 strcpy((LPSTR
)((LPBYTE
)pUrlEntry
+ dwOffsetLocalFileName
), pchLocalFileName
);
1972 memcpy((LPBYTE
)pUrlEntry
+ dwOffsetHeader
, lpHeaderInfo
, dwHeaderSize
);
1974 if (!URLCache_AddEntryToHash(pHeader
, achUrl
, (DWORD
)((LPBYTE
)pUrlEntry
- (LPBYTE
)pHeader
)))
1976 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1980 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
1985 /***********************************************************************
1986 * CommitUrlCacheEntryA (WININET.@)
1989 BOOL WINAPI
CommitUrlCacheEntryA(
1990 IN LPCSTR lpszUrlName
,
1991 IN LPCSTR lpszLocalFileName
,
1992 IN FILETIME ExpireTime
,
1993 IN FILETIME LastModifiedTime
,
1994 IN DWORD CacheEntryType
,
1995 IN LPBYTE lpHeaderInfo
,
1996 IN DWORD dwHeaderSize
,
1997 IN LPCSTR lpszFileExtension
,
1998 IN LPCSTR lpszOriginalUrl
2003 WCHAR
*local_file_name
;
2004 WCHAR
*original_url
= NULL
;
2005 BOOL bSuccess
= FALSE
;
2008 TRACE("(%s, %s, ..., ..., %lx, %p, %ld, %s, %s)\n",
2009 debugstr_a(lpszUrlName
),
2010 debugstr_a(lpszLocalFileName
),
2014 debugstr_a(lpszFileExtension
),
2015 debugstr_a(lpszOriginalUrl
));
2017 if (lpszFileExtension
!= 0)
2019 SetLastError(ERROR_INVALID_PARAMETER
);
2022 if ((len
= MultiByteToWideChar(CP_ACP
, 0, lpszUrlName
, -1, NULL
, 0)) != 0 &&
2023 (url_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))) != 0)
2025 MultiByteToWideChar(CP_ACP
, 0, lpszUrlName
, -1, url_name
, len
);
2026 if ((len
= MultiByteToWideChar(CP_ACP
, 0, lpszLocalFileName
, -1, NULL
, 0)) != 0 &&
2027 (local_file_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))) != 0)
2029 MultiByteToWideChar(CP_ACP
, 0, lpszLocalFileName
, -1, local_file_name
, len
);
2030 if (!lpszOriginalUrl
||
2031 ((len
= MultiByteToWideChar(CP_ACP
, 0, lpszOriginalUrl
, -1, NULL
, 0)) != 0 &&
2032 (original_url
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
))) != 0))
2035 MultiByteToWideChar(CP_ACP
, 0, lpszOriginalUrl
, -1, original_url
, len
);
2036 if (CommitUrlCacheEntryInternal(url_name
, local_file_name
, ExpireTime
, LastModifiedTime
,
2037 CacheEntryType
, lpHeaderInfo
, dwHeaderSize
,
2038 NULL
, original_url
))
2044 dwError
= GetLastError();
2047 HeapFree(GetProcessHeap(), 0, original_url
);
2051 dwError
= GetLastError();
2053 HeapFree(GetProcessHeap(), 0, local_file_name
);
2057 dwError
= GetLastError();
2059 HeapFree(GetProcessHeap(), 0, url_name
);
2061 SetLastError(dwError
);
2066 /***********************************************************************
2067 * CommitUrlCacheEntryW (WININET.@)
2070 BOOL WINAPI
CommitUrlCacheEntryW(
2071 IN LPCWSTR lpszUrlName
,
2072 IN LPCWSTR lpszLocalFileName
,
2073 IN FILETIME ExpireTime
,
2074 IN FILETIME LastModifiedTime
,
2075 IN DWORD CacheEntryType
,
2076 IN LPWSTR lpHeaderInfo
,
2077 IN DWORD dwHeaderSize
,
2078 IN LPCWSTR lpszFileExtension
,
2079 IN LPCWSTR lpszOriginalUrl
2083 BOOL bSuccess
= FALSE
;
2085 CHAR
*header_info
= NULL
;
2087 TRACE("(%s, %s, ..., ..., %lx, %p, %ld, %s, %s)\n",
2088 debugstr_w(lpszUrlName
),
2089 debugstr_w(lpszLocalFileName
),
2093 debugstr_w(lpszFileExtension
),
2094 debugstr_w(lpszOriginalUrl
));
2096 if (!lpHeaderInfo
||
2097 ((len
= WideCharToMultiByte(CP_ACP
, 0, lpHeaderInfo
, -1, NULL
, 0, NULL
, NULL
)) != 0 &&
2098 (header_info
= HeapAlloc(GetProcessHeap(), 0, sizeof(CHAR
) * len
)) != 0))
2101 WideCharToMultiByte(CP_ACP
, 0, lpHeaderInfo
, -1, header_info
, len
, NULL
, NULL
);
2102 if (CommitUrlCacheEntryInternal(lpszUrlName
, lpszLocalFileName
, ExpireTime
, LastModifiedTime
,
2103 CacheEntryType
, header_info
, len
, lpszFileExtension
, lpszOriginalUrl
))
2109 dwError
= GetLastError();
2113 HeapFree(GetProcessHeap(), 0, header_info
);
2115 SetLastError(dwError
);
2121 /***********************************************************************
2122 * ReadUrlCacheEntryStream (WININET.@)
2125 BOOL WINAPI
ReadUrlCacheEntryStream(
2126 IN HANDLE hUrlCacheStream
,
2127 IN DWORD dwLocation
,
2128 IN OUT LPVOID lpBuffer
,
2129 IN OUT LPDWORD lpdwLen
,
2133 /* Get handle to file from 'stream' */
2134 STREAM_HANDLE
* pStream
= (STREAM_HANDLE
*)hUrlCacheStream
;
2136 if (dwReserved
!= 0)
2138 ERR("dwReserved != 0\n");
2139 SetLastError(ERROR_INVALID_PARAMETER
);
2143 if (IsBadReadPtr(pStream
, sizeof(*pStream
)) || IsBadStringPtrA(pStream
->lpszUrl
, INTERNET_MAX_URL_LENGTH
))
2145 SetLastError(ERROR_INVALID_HANDLE
);
2149 if (SetFilePointer(pStream
->hFile
, dwLocation
, NULL
, FILE_CURRENT
) == INVALID_SET_FILE_POINTER
)
2151 return ReadFile(pStream
->hFile
, lpBuffer
, *lpdwLen
, lpdwLen
, NULL
);
2154 /***********************************************************************
2155 * RetrieveUrlCacheEntryStreamA (WININET.@)
2158 HANDLE WINAPI
RetrieveUrlCacheEntryStreamA(
2159 IN LPCSTR lpszUrlName
,
2160 OUT LPINTERNET_CACHE_ENTRY_INFOA lpCacheEntryInfo
,
2161 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize
,
2162 IN BOOL fRandomRead
,
2166 /* NOTE: this is not the same as the way that the native
2167 * version allocates 'stream' handles. I did it this way
2168 * as it is much easier and no applications should depend
2169 * on this behaviour. (Native version appears to allocate
2170 * indices into a table)
2172 STREAM_HANDLE
* pStream
;
2175 TRACE( "(%s, %p, %p, %x, 0x%08lx)\n", debugstr_a(lpszUrlName
), lpCacheEntryInfo
,
2176 lpdwCacheEntryInfoBufferSize
, fRandomRead
, dwReserved
);
2178 if (!RetrieveUrlCacheEntryFileA(lpszUrlName
,
2180 lpdwCacheEntryInfoBufferSize
,
2186 hFile
= CreateFileA(lpCacheEntryInfo
->lpszLocalFileName
,
2191 fRandomRead
? FILE_FLAG_RANDOM_ACCESS
: 0,
2193 if (hFile
== INVALID_HANDLE_VALUE
)
2196 /* allocate handle storage space */
2197 pStream
= HeapAlloc(GetProcessHeap(), 0, sizeof(STREAM_HANDLE
) + strlen(lpszUrlName
) * sizeof(CHAR
));
2201 SetLastError(ERROR_OUTOFMEMORY
);
2205 pStream
->hFile
= hFile
;
2206 strcpy(pStream
->lpszUrl
, lpszUrlName
);
2207 return (HANDLE
)pStream
;
2210 /***********************************************************************
2211 * RetrieveUrlCacheEntryStreamW (WININET.@)
2214 HANDLE WINAPI
RetrieveUrlCacheEntryStreamW(
2215 IN LPCWSTR lpszUrlName
,
2216 OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo
,
2217 IN OUT LPDWORD lpdwCacheEntryInfoBufferSize
,
2218 IN BOOL fRandomRead
,
2222 FIXME( "(%s, %p, %p, %x, 0x%08lx)\n", debugstr_w(lpszUrlName
), lpCacheEntryInfo
,
2223 lpdwCacheEntryInfoBufferSize
, fRandomRead
, dwReserved
);
2227 /***********************************************************************
2228 * UnlockUrlCacheEntryStream (WININET.@)
2231 BOOL WINAPI
UnlockUrlCacheEntryStream(
2232 IN HANDLE hUrlCacheStream
,
2236 STREAM_HANDLE
* pStream
= (STREAM_HANDLE
*)hUrlCacheStream
;
2238 if (dwReserved
!= 0)
2240 ERR("dwReserved != 0\n");
2241 SetLastError(ERROR_INVALID_PARAMETER
);
2245 if (IsBadReadPtr(pStream
, sizeof(*pStream
)) || IsBadStringPtrA(pStream
->lpszUrl
, INTERNET_MAX_URL_LENGTH
))
2247 SetLastError(ERROR_INVALID_HANDLE
);
2251 if (!UnlockUrlCacheEntryFileA(pStream
->lpszUrl
, 0))
2254 /* close file handle */
2255 CloseHandle(pStream
->hFile
);
2257 /* free allocated space */
2258 HeapFree(GetProcessHeap(), 0, pStream
);
2264 /***********************************************************************
2265 * DeleteUrlCacheEntryA (WININET.@)
2268 BOOL WINAPI
DeleteUrlCacheEntryA(LPCSTR lpszUrlName
)
2270 URLCACHECONTAINER
* pContainer
;
2271 LPURLCACHE_HEADER pHeader
;
2272 CACHEFILE_ENTRY
* pEntry
;
2275 BYTE
* AllocationTable
;
2277 TRACE("(%s)\n", debugstr_a(lpszUrlName
));
2279 if (!URLCacheContainers_FindContainerA(lpszUrlName
, &pContainer
))
2282 if (!URLCacheContainer_OpenIndex(pContainer
))
2285 if (!(pHeader
= URLCacheContainer_LockIndex(pContainer
)))
2288 if (!URLCache_FindEntryInHash(pHeader
, lpszUrlName
, &pEntry
))
2290 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
2291 TRACE("entry %s not found!\n", lpszUrlName
);
2292 SetLastError(ERROR_FILE_NOT_FOUND
);
2296 AllocationTable
= (LPBYTE
)pHeader
+ ALLOCATION_TABLE_OFFSET
;
2298 /* update allocation table */
2299 dwStartBlock
= ((DWORD
)pEntry
- (DWORD
)pHeader
) / BLOCKSIZE
;
2300 for (dwBlock
= dwStartBlock
; dwBlock
< dwStartBlock
+ pEntry
->dwBlocksUsed
; dwBlock
++)
2301 URLCache_Allocation_BlockFree(AllocationTable
, dwBlock
);
2303 URLCache_DeleteEntry(pEntry
);
2305 URLCache_DeleteEntryFromHash(pHeader
, lpszUrlName
);
2307 URLCacheContainer_UnlockIndex(pContainer
, pHeader
);
2312 /***********************************************************************
2313 * DeleteUrlCacheEntryW (WININET.@)
2316 BOOL WINAPI
DeleteUrlCacheEntryW(LPCWSTR lpszUrlName
)
2318 FIXME("(%s) stub\n", debugstr_w(lpszUrlName
));
2322 BOOL WINAPI
DeleteUrlCacheContainerA(DWORD d1
, DWORD d2
)
2324 FIXME("(0x%08lx, 0x%08lx) stub\n", d1
, d2
);
2328 BOOL WINAPI
DeleteUrlCacheContainerW(DWORD d1
, DWORD d2
)
2330 FIXME("(0x%08lx, 0x%08lx) stub\n", d1
, d2
);
2334 /***********************************************************************
2335 * CreateCacheContainerA (WININET.@)
2337 BOOL WINAPI
CreateUrlCacheContainerA(DWORD d1
, DWORD d2
, DWORD d3
, DWORD d4
,
2338 DWORD d5
, DWORD d6
, DWORD d7
, DWORD d8
)
2340 FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx) stub\n",
2341 d1
, d2
, d3
, d4
, d5
, d6
, d7
, d8
);
2345 /***********************************************************************
2346 * CreateCacheContainerW (WININET.@)
2348 BOOL WINAPI
CreateUrlCacheContainerW(DWORD d1
, DWORD d2
, DWORD d3
, DWORD d4
,
2349 DWORD d5
, DWORD d6
, DWORD d7
, DWORD d8
)
2351 FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx) stub\n",
2352 d1
, d2
, d3
, d4
, d5
, d6
, d7
, d8
);
2356 /***********************************************************************
2357 * FindCloseUrlCache (WININET.@)
2359 BOOL WINAPI
FindCloseUrlCache(HANDLE hEnumHandle
)
2361 FIXME("(%p) stub\n", hEnumHandle
);
2365 /***********************************************************************
2366 * FindFirstUrlCacheContainerA (WININET.@)
2368 HANDLE WINAPI
FindFirstUrlCacheContainerA( LPVOID p1
, LPVOID p2
, LPVOID p3
, DWORD d1
)
2370 FIXME("(%p, %p, %p, 0x%08lx) stub\n", p1
, p2
, p3
, d1
);
2374 /***********************************************************************
2375 * FindFirstUrlCacheContainerW (WININET.@)
2377 HANDLE WINAPI
FindFirstUrlCacheContainerW( LPVOID p1
, LPVOID p2
, LPVOID p3
, DWORD d1
)
2379 FIXME("(%p, %p, %p, 0x%08lx) stub\n", p1
, p2
, p3
, d1
);
2383 /***********************************************************************
2384 * FindNextUrlCacheContainerA (WININET.@)
2386 BOOL WINAPI
FindNextUrlCacheContainerA( HANDLE handle
, LPVOID p1
, LPVOID p2
)
2388 FIXME("(%p, %p, %p) stub\n", handle
, p1
, p2
);
2392 /***********************************************************************
2393 * FindNextUrlCacheContainerW (WININET.@)
2395 BOOL WINAPI
FindNextUrlCacheContainerW( HANDLE handle
, LPVOID p1
, LPVOID p2
)
2397 FIXME("(%p, %p, %p) stub\n", handle
, p1
, p2
);
2401 HANDLE WINAPI
FindFirstUrlCacheEntryExA(
2402 LPCSTR lpszUrlSearchPattern
,
2406 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo
,
2407 LPDWORD lpdwFirstCacheEntryInfoBufferSize
,
2409 LPDWORD pcbReserved2
,
2413 FIXME("(%s, 0x%08lx, 0x%08lx, 0x%08lx%08lx, %p, %p, %p, %p, %p) stub\n", debugstr_a(lpszUrlSearchPattern
),
2414 dwFlags
, dwFilter
, (ULONG
)(GroupId
>> 32), (ULONG
)GroupId
, lpFirstCacheEntryInfo
,
2415 lpdwFirstCacheEntryInfoBufferSize
, lpReserved
, pcbReserved2
,lpReserved3
);
2416 SetLastError(ERROR_FILE_NOT_FOUND
);
2420 HANDLE WINAPI
FindFirstUrlCacheEntryExW(
2421 LPCWSTR lpszUrlSearchPattern
,
2425 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo
,
2426 LPDWORD lpdwFirstCacheEntryInfoBufferSize
,
2428 LPDWORD pcbReserved2
,
2432 FIXME("(%s, 0x%08lx, 0x%08lx, 0x%08lx%08lx, %p, %p, %p, %p, %p) stub\n", debugstr_w(lpszUrlSearchPattern
),
2433 dwFlags
, dwFilter
, (ULONG
)(GroupId
>> 32), (ULONG
)GroupId
, lpFirstCacheEntryInfo
,
2434 lpdwFirstCacheEntryInfoBufferSize
, lpReserved
, pcbReserved2
,lpReserved3
);
2435 SetLastError(ERROR_FILE_NOT_FOUND
);
2439 /***********************************************************************
2440 * FindFirstUrlCacheEntryA (WININET.@)
2443 INTERNETAPI HANDLE WINAPI
FindFirstUrlCacheEntryA(LPCSTR lpszUrlSearchPattern
,
2444 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo
, LPDWORD lpdwFirstCacheEntryInfoBufferSize
)
2446 FIXME("(%s, %p, %p): stub\n", debugstr_a(lpszUrlSearchPattern
), lpFirstCacheEntryInfo
, lpdwFirstCacheEntryInfoBufferSize
);
2447 SetLastError(ERROR_FILE_NOT_FOUND
);
2451 /***********************************************************************
2452 * FindFirstUrlCacheEntryW (WININET.@)
2455 INTERNETAPI HANDLE WINAPI
FindFirstUrlCacheEntryW(LPCWSTR lpszUrlSearchPattern
,
2456 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo
, LPDWORD lpdwFirstCacheEntryInfoBufferSize
)
2458 FIXME("(%s, %p, %p): stub\n", debugstr_w(lpszUrlSearchPattern
), lpFirstCacheEntryInfo
, lpdwFirstCacheEntryInfoBufferSize
);
2462 HANDLE WINAPI
FindFirstUrlCacheGroup( DWORD dwFlags
, DWORD dwFilter
, LPVOID lpSearchCondition
,
2463 DWORD dwSearchCondition
, GROUPID
* lpGroupId
, LPVOID lpReserved
)
2465 FIXME("(0x%08lx, 0x%08lx, %p, 0x%08lx, %p, %p) stub\n", dwFlags
, dwFilter
, lpSearchCondition
,
2466 dwSearchCondition
, lpGroupId
, lpReserved
);
2470 BOOL WINAPI
FindNextUrlCacheEntryA(
2472 LPINTERNET_CACHE_ENTRY_INFOA lpNextCacheEntryInfo
,
2473 LPDWORD lpdwNextCacheEntryInfoBufferSize
2476 FIXME("(%p, %p, %p) stub\n", hEnumHandle
, lpNextCacheEntryInfo
, lpdwNextCacheEntryInfoBufferSize
);
2480 BOOL WINAPI
FindNextUrlCacheEntryW(
2482 LPINTERNET_CACHE_ENTRY_INFOW lpNextCacheEntryInfo
,
2483 LPDWORD lpdwNextCacheEntryInfoBufferSize
2486 FIXME("(%p, %p, %p) stub\n", hEnumHandle
, lpNextCacheEntryInfo
, lpdwNextCacheEntryInfoBufferSize
);
2490 BOOL WINAPI
FindNextUrlCacheEntryExA(
2492 LPINTERNET_CACHE_ENTRY_INFOA lpFirstCacheEntryInfo
,
2493 LPDWORD lpdwFirstCacheEntryInfoBufferSize
,
2495 LPDWORD pcbReserved2
,
2499 FIXME("(%p, %p, %p, %p, %p, %p) stub\n", hEnumHandle
, lpFirstCacheEntryInfo
, lpdwFirstCacheEntryInfoBufferSize
,
2500 lpReserved
, pcbReserved2
, lpReserved3
);
2504 BOOL WINAPI
FindNextUrlCacheEntryExW(
2506 LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo
,
2507 LPDWORD lpdwFirstCacheEntryInfoBufferSize
,
2509 LPDWORD pcbReserved2
,
2513 FIXME("(%p, %p, %p, %p, %p, %p) stub\n", hEnumHandle
, lpFirstCacheEntryInfo
, lpdwFirstCacheEntryInfoBufferSize
,
2514 lpReserved
, pcbReserved2
, lpReserved3
);
2518 BOOL WINAPI
FindNextUrlCacheGroup( HANDLE hFind
, GROUPID
* lpGroupId
, LPVOID lpReserved
)
2520 FIXME("(%p, %p, %p) stub\n", hFind
, lpGroupId
, lpReserved
);
2524 /***********************************************************************
2525 * CreateUrlCacheGroup (WININET.@)
2528 INTERNETAPI GROUPID WINAPI
CreateUrlCacheGroup(DWORD dwFlags
, LPVOID lpReserved
)
2530 FIXME("(0x%08lx, %p): stub\n", dwFlags
, lpReserved
);
2534 /***********************************************************************
2535 * DeleteUrlCacheGroup (WININET.@)
2538 BOOL WINAPI
DeleteUrlCacheGroup(GROUPID GroupId
, DWORD dwFlags
, LPVOID lpReserved
)
2540 FIXME("(0x%08lx%08lx, 0x%08lx, %p) stub\n",
2541 (ULONG
)(GroupId
>> 32), (ULONG
)GroupId
, dwFlags
, lpReserved
);
2545 /***********************************************************************
2546 * SetUrlCacheEntryGroupA (WININET.@)
2549 BOOL WINAPI
SetUrlCacheEntryGroupA(LPCSTR lpszUrlName
, DWORD dwFlags
,
2550 GROUPID GroupId
, LPBYTE pbGroupAttributes
, DWORD cbGroupAttributes
,
2553 FIXME("(%s, 0x%08lx, 0x%08lx%08lx, %p, 0x%08lx, %p) stub\n",
2554 debugstr_a(lpszUrlName
), dwFlags
, (ULONG
)(GroupId
>> 32), (ULONG
)GroupId
,
2555 pbGroupAttributes
, cbGroupAttributes
, lpReserved
);
2556 SetLastError(ERROR_FILE_NOT_FOUND
);
2560 /***********************************************************************
2561 * SetUrlCacheEntryGroupW (WININET.@)
2564 BOOL WINAPI
SetUrlCacheEntryGroupW(LPCWSTR lpszUrlName
, DWORD dwFlags
,
2565 GROUPID GroupId
, LPBYTE pbGroupAttributes
, DWORD cbGroupAttributes
,
2568 FIXME("(%s, 0x%08lx, 0x%08lx%08lx, %p, 0x%08lx, %p) stub\n",
2569 debugstr_w(lpszUrlName
), dwFlags
, (ULONG
)(GroupId
>> 32), (ULONG
)GroupId
,
2570 pbGroupAttributes
, cbGroupAttributes
, lpReserved
);
2571 SetLastError(ERROR_FILE_NOT_FOUND
);
2575 /***********************************************************************
2576 * GetUrlCacheConfigInfoW (WININET.@)
2578 BOOL WINAPI
GetUrlCacheConfigInfoW(LPDWORD CacheInfo
, LPDWORD size
, DWORD bitmask
)
2580 FIXME("(%p, %p, %lx)\n", CacheInfo
, size
, bitmask
);
2581 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
2585 /***********************************************************************
2586 * GetUrlCacheConfigInfoA (WININET.@)
2588 * CacheInfo is some CACHE_CONFIG_INFO structure, with no MS info found by google
2590 BOOL WINAPI
GetUrlCacheConfigInfoA(LPDWORD CacheInfo
, LPDWORD size
, DWORD bitmask
)
2592 FIXME("(%p, %p, %lx)\n", CacheInfo
, size
, bitmask
);
2593 INTERNET_SetLastError(ERROR_INVALID_PARAMETER
);
2597 BOOL WINAPI
GetUrlCacheGroupAttributeA( GROUPID gid
, DWORD dwFlags
, DWORD dwAttributes
,
2598 LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo
,
2599 LPDWORD lpdwGroupInfo
, LPVOID lpReserved
)
2601 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p, %p) stub\n",
2602 (ULONG
)(gid
>> 32), (ULONG
)gid
, dwFlags
, dwAttributes
, lpGroupInfo
,
2603 lpdwGroupInfo
, lpReserved
);
2607 BOOL WINAPI
GetUrlCacheGroupAttributeW( GROUPID gid
, DWORD dwFlags
, DWORD dwAttributes
,
2608 LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo
,
2609 LPDWORD lpdwGroupInfo
, LPVOID lpReserved
)
2611 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p, %p) stub\n",
2612 (ULONG
)(gid
>> 32), (ULONG
)gid
, dwFlags
, dwAttributes
, lpGroupInfo
,
2613 lpdwGroupInfo
, lpReserved
);
2617 BOOL WINAPI
SetUrlCacheGroupAttributeA( GROUPID gid
, DWORD dwFlags
, DWORD dwAttributes
,
2618 LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo
, LPVOID lpReserved
)
2620 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p) stub\n",
2621 (ULONG
)(gid
>> 32), (ULONG
)gid
, dwFlags
, dwAttributes
, lpGroupInfo
, lpReserved
);
2625 BOOL WINAPI
SetUrlCacheGroupAttributeW( GROUPID gid
, DWORD dwFlags
, DWORD dwAttributes
,
2626 LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo
, LPVOID lpReserved
)
2628 FIXME("(0x%08lx%08lx, 0x%08lx, 0x%08lx, %p, %p) stub\n",
2629 (ULONG
)(gid
>> 32), (ULONG
)gid
, dwFlags
, dwAttributes
, lpGroupInfo
, lpReserved
);
2633 BOOL WINAPI
SetUrlCacheConfigInfoA( LPDWORD lpCacheConfigInfo
, DWORD dwFieldControl
)
2635 FIXME("(%p, 0x%08lx) stub\n", lpCacheConfigInfo
, dwFieldControl
);
2639 BOOL WINAPI
SetUrlCacheConfigInfoW( LPDWORD lpCacheConfigInfo
, DWORD dwFieldControl
)
2641 FIXME("(%p, 0x%08lx) stub\n", lpCacheConfigInfo
, dwFieldControl
);
2645 /***********************************************************************
2646 * DeleteIE3Cache (WININET.@)
2648 * Deletes the files used by the IE3 URL caching system.
2651 * hWnd [I] A dummy window.
2652 * hInst [I] Instance of process calling the function.
2653 * lpszCmdLine [I] Options used by function.
2654 * nCmdShow [I] The nCmdShow value to use when showing windows created, if any.
2659 void WINAPI
DeleteIE3Cache(HWND hWnd
, HINSTANCE hInst
, LPSTR lpszCmdLine
, int nCmdShow
)
2661 FIXME("(%p, %p, %s, %d)\n", hWnd
, hInst
, debugstr_a(lpszCmdLine
), nCmdShow
);